Add XMLNamespace
[yangtools.git] / yang / yang-data-util / src / main / java / org / opendaylight / yangtools / yang / data / util / AbstractNamespaceCodec.java
index 620f46e20462592b1ddcfc7dcd23983629956640..89b0e415ea1e025d83f0a4b911c96ebe6153742a 100644 (file)
@@ -7,18 +7,18 @@
  */
 package org.opendaylight.yangtools.yang.data.util;
 
-import com.google.common.base.Preconditions;
-import com.google.common.base.Splitter;
+import static com.google.common.base.Preconditions.checkArgument;
 
-import java.net.URI;
+import com.google.common.base.Splitter;
 import java.util.Iterator;
-
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
-
+import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.jdt.annotation.Nullable;
+import org.opendaylight.yangtools.concepts.AbstractIllegalArgumentCodec;
 import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.common.QNameModule;
+import org.opendaylight.yangtools.yang.common.XMLNamespace;
 
-abstract class AbstractNamespaceCodec {
+abstract class AbstractNamespaceCodec<T> extends AbstractIllegalArgumentCodec<String, T> {
     private static final Splitter COLON_SPLITTER = Splitter.on(':');
 
     /**
@@ -27,7 +27,7 @@ abstract class AbstractNamespaceCodec {
      * @param namespace Namespace to map
      * @return Allocated unique prefix, or null if the prefix cannot be mapped.
      */
-    protected abstract @Nullable String prefixForNamespace(final @Nonnull URI namespace);
+    protected abstract @Nullable String prefixForNamespace(@NonNull XMLNamespace namespace);
 
     /**
      * Create a QName for a prefix and local name.
@@ -37,20 +37,31 @@ abstract class AbstractNamespaceCodec {
      * @return QName
      * @throws IllegalArgumentException if the prefix cannot be resolved
      */
-    protected abstract @Nullable QName createQName(final @Nonnull String prefix, final @Nonnull String localName);
+    protected abstract @Nullable QName createQName(@NonNull String prefix, @NonNull String localName);
 
     private static String getIdAndPrefixAsStr(final String pathPart) {
         int predicateStartIndex = pathPart.indexOf('[');
         return predicateStartIndex == -1 ? pathPart : pathPart.substring(0, predicateStartIndex);
     }
 
-    protected final StringBuilder appendQName(final StringBuilder sb, final QName qname) {
+    protected final @NonNull StringBuilder appendQName(final StringBuilder sb, final QName qname) {
         final String prefix = prefixForNamespace(qname.getNamespace());
-        Preconditions.checkArgument(prefix != null, "Failed to map QName {}", qname);
-        sb.append(prefix);
-        sb.append(':');
-        sb.append(qname.getLocalName());
-        return sb;
+        checkArgument(prefix != null, "Failed to map QName %s to prefix", qname);
+        return sb.append(prefix).append(':').append(qname.getLocalName());
+    }
+
+    /**
+     * Append a QName, potentially taking into account last QNameModule encountered in the serialized path.
+     *
+     * @param sb target StringBuilder
+     * @param qname QName to append
+     * @param lastModule last QNameModule encountered, may be null
+     * @return target StringBuilder
+     */
+    protected StringBuilder appendQName(final StringBuilder sb, final QName qname,
+            final @Nullable QNameModule lastModule) {
+        // Covers XML and uncompressed JSON codec
+        return appendQName(sb, qname);
     }
 
     protected final QName parseQName(final String str) {
@@ -62,17 +73,22 @@ abstract class AbstractNamespaceCodec {
             return null;
         }
 
-        final String prefix = it.next().trim();
-        if (prefix.isEmpty()) {
-            return null;
-        }
 
-        // it is not "prefix:value"
-        if (!it.hasNext()) {
+        final String first = it.next().trim();
+        if (first.isEmpty()) {
             return null;
         }
 
-        final String identifier = it.next().trim();
+        final String identifier;
+        final String prefix;
+        if (it.hasNext()) {
+            // It is "prefix:value"
+            prefix = first;
+            identifier = it.next().trim();
+        } else {
+            prefix = "";
+            identifier = first;
+        }
         if (identifier.isEmpty()) {
             return null;
         }