Define legacy unprefixed XML attribute namespace 62/81362/5
authorRobert Varga <robert.varga@pantheon.tech>
Wed, 3 Apr 2019 19:52:08 +0000 (21:52 +0200)
committerRobert Varga <robert.varga@pantheon.tech>
Wed, 3 Apr 2019 22:25:33 +0000 (00:25 +0200)
Since we are switching from pass-through XML attributes to a proper
definition of RFC7952 metadata, we need a conduit to handle legacy
unprefixed attributes until they can be properly bound to their
metadata (or similar, like RFC6241) definition.

This patch adds the namespace and language to support such attributes.

JIRA: YANGTOOLS-961
Change-Id: Ie5763f77faad0a4c480d081ba06ac0f9df420b20
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
yang/rfc7952-data-api/src/main/java/org/opendaylight/yangtools/rfc7952/data/api/NormalizedMetadata.java
yang/yang-data-codec-xml/pom.xml
yang/yang-data-codec-xml/src/main/java/org/opendaylight/yangtools/yang/data/codec/xml/XmlParserStream.java

index 6edd0210fece864f67da118f93e4da871572915c..8509899f5d00ff0b10bfc412d4e099db737bd6a0 100644 (file)
@@ -9,11 +9,13 @@ package org.opendaylight.yangtools.rfc7952.data.api;
 
 import com.google.common.annotations.Beta;
 import com.google.common.collect.ImmutableMap;
+import java.net.URI;
 import java.util.Map;
 import org.eclipse.jdt.annotation.NonNull;
 import org.opendaylight.yangtools.concepts.Identifiable;
 import org.opendaylight.yangtools.concepts.Immutable;
 import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.common.QNameModule;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
 import org.opendaylight.yangtools.yang.data.api.schema.LeafSetNode;
 import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
@@ -34,10 +36,30 @@ import org.opendaylight.yangtools.yang.data.api.schema.UnkeyedListNode;
  */
 @Beta
 public interface NormalizedMetadata extends Identifiable<PathArgument>, Immutable {
+    /**
+     * {@link QNameModule} for use with legacy XML attributes.
+     * @deprecated The use on this namespace is discouraged and users are strongly encouraged to proper RFC7952 metadata
+     *             annotations.
+     */
+    @Deprecated
+    QNameModule LEGACY_ATTRIBUTE_NAMESPACE = QNameModule.create(URI.create("")).intern();
+
     /**
      * Return the set of annotations defined in this metadata node. Values are expected to be effectively-immutable
      * scalar types, like {@link String}s, {@link Number}s and similar. The map must also be effectively-immutable.
      *
+     * <p>
+     * Due to backwards compatibility reasons, keys may include QNames with empty URI (as exposed via
+     * {@link #LEGACY_ATTRIBUTE_NAMESPACE}) as their QNameModule. These indicate an unqualified XML attribute and their
+     * value can be assumed to be a String. Furthermore, this extends to qualified attributes, which uses the proper
+     * namespace, but will not bind to a proper module revision -- these need to be reconciled with a particular
+     * SchemaContext and are expected to either be fully decoded, or contain a String value. Handling of such
+     * annotations is at the discretion of the user encountering it: preferred way of handling is to either filter or
+     * normalize them to proper QNames/values when encountered.
+     *
+     * <p>
+     * This caveat will be removed in a future version.
+     *
      * @return The set of annotations attached to the corresponding data node.
      */
     @NonNull Map<QName, Object> getAnnotations();
index 20e9af443db6c7861bea78266caabbf505e2b4d4..4d5c6e7424c7ff06ddaeac7b30e852385a02b0a2 100644 (file)
             <groupId>org.opendaylight.yangtools</groupId>
             <artifactId>yang-data-api</artifactId>
         </dependency>
+        <dependency>
+            <groupId>org.opendaylight.yangtools</groupId>
+            <artifactId>rfc7952-data-api</artifactId>
+        </dependency>
         <dependency>
             <groupId>org.opendaylight.yangtools</groupId>
             <artifactId>yang-data-impl</artifactId>
index 68039422c69653697463423be72f81eb2a0e7f23..fab6da9581c2d1da6901ce990624798ac4b5dab0 100644 (file)
@@ -13,6 +13,7 @@ import static com.google.common.base.Verify.verify;
 import static java.util.Objects.requireNonNull;
 
 import com.google.common.annotations.Beta;
+import com.google.common.base.Strings;
 import com.google.common.collect.ImmutableMap;
 import java.io.Closeable;
 import java.io.Flushable;
@@ -40,7 +41,9 @@ import javax.xml.transform.dom.DOMResult;
 import javax.xml.transform.dom.DOMSource;
 import javax.xml.transform.stax.StAXSource;
 import org.opendaylight.yangtools.odlext.model.api.YangModeledAnyXmlSchemaNode;
+import org.opendaylight.yangtools.rfc7952.data.api.NormalizedMetadata;
 import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.common.QNameModule;
 import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeStreamWriter;
 import org.opendaylight.yangtools.yang.data.util.AbstractNodeDataWithSchema;
 import org.opendaylight.yangtools.yang.data.util.AnyXmlNodeDataWithSchema;
@@ -242,18 +245,22 @@ public final class XmlParserStream implements Closeable, Flushable {
         final Map<QName, String> attributes = new LinkedHashMap<>();
 
         for (int attrIndex = 0; attrIndex < in.getAttributeCount(); attrIndex++) {
-            String attributeNS = in.getAttributeNamespace(attrIndex);
-
-            if (attributeNS == null) {
-                attributeNS = "";
-            }
+            final String attributeNS = in.getAttributeNamespace(attrIndex);
 
             // Skip namespace definitions
             if (XMLConstants.XMLNS_ATTRIBUTE_NS_URI.equals(attributeNS)) {
                 continue;
             }
 
-            final QName qName = QName.create(URI.create(attributeNS), in.getAttributeLocalName(attrIndex));
+            final QNameModule namespace;
+            if (!Strings.isNullOrEmpty(attributeNS)) {
+                // FIXME: bind the namespace to a module, if available
+                namespace = QNameModule.create(URI.create(attributeNS));
+            } else {
+                namespace = NormalizedMetadata.LEGACY_ATTRIBUTE_NAMESPACE;
+            }
+
+            final QName qName = QName.create(namespace, in.getAttributeLocalName(attrIndex));
             attributes.put(qName, in.getAttributeValue(attrIndex));
         }