Fix xml->CompositeNode transformation for rpc replies for rpcs with no output
[yangtools.git] / yang / yang-data-util / src / main / java / org / opendaylight / yangtools / yang / data / util / AbstractNamespaceCodec.java
1 /*
2  * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8 package org.opendaylight.yangtools.yang.data.util;
9
10 import com.google.common.base.Preconditions;
11 import com.google.common.base.Splitter;
12
13 import java.net.URI;
14 import java.util.Iterator;
15
16 import javax.annotation.Nonnull;
17 import javax.annotation.Nullable;
18
19 import org.opendaylight.yangtools.yang.common.QName;
20
21 abstract class AbstractNamespaceCodec {
22     private static final Splitter COLON_SPLITTER = Splitter.on(':');
23
24     /**
25      * Return string prefix for a particular namespace, allocating a new one if necessary.
26      *
27      * @param namespace Namespace to map
28      * @return Allocated unique prefix, or null if the prefix cannot be mapped.
29      */
30     protected abstract @Nullable String prefixForNamespace(final @Nonnull URI namespace);
31
32     /**
33      * Create a QName for a prefix and local name.
34      *
35      * @param prefix Prefix for namespace
36      * @param localName local name
37      * @return QName
38      * @throws IllegalArgumentException if the prefix cannot be resolved
39      */
40     protected abstract @Nullable QName createQName(final @Nonnull String prefix, final @Nonnull String localName);
41
42     private static String getIdAndPrefixAsStr(final String pathPart) {
43         int predicateStartIndex = pathPart.indexOf('[');
44         return predicateStartIndex == -1 ? pathPart : pathPart.substring(0, predicateStartIndex);
45     }
46
47     protected final StringBuilder appendQName(final StringBuilder sb, final QName qname) {
48         final String prefix = prefixForNamespace(qname.getNamespace());
49         Preconditions.checkArgument(prefix != null, "Failed to map QName {}", qname);
50         sb.append(prefix);
51         sb.append(':');
52         sb.append(qname.getLocalName());
53         return sb;
54     }
55
56     protected final QName parseQName(final String str) {
57         final String xPathPartTrimmed = getIdAndPrefixAsStr(str).trim();
58         final Iterator<String> it = COLON_SPLITTER.split(xPathPartTrimmed).iterator();
59
60         // Empty string
61         if (!it.hasNext()) {
62             return null;
63         }
64
65         final String prefix = it.next().trim();
66         if (prefix.isEmpty()) {
67             return null;
68         }
69
70         // it is not "prefix:value"
71         if (!it.hasNext()) {
72             return null;
73         }
74
75         final String identifier = it.next().trim();
76         if (identifier.isEmpty()) {
77             return null;
78         }
79
80         return createQName(prefix, identifier);
81     }
82 }