Merge "BUG-1281: introduce XML event stream writer"
authorTony Tkacik <ttkacik@cisco.com>
Fri, 11 Jul 2014 10:03:55 +0000 (10:03 +0000)
committerGerrit Code Review <gerrit@opendaylight.org>
Fri, 11 Jul 2014 10:03:55 +0000 (10:03 +0000)
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/codec/xml/InstanceIdentifierForXmlCodec.java
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/codec/xml/RandomPrefix.java [new file with mode: 0644]
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/codec/xml/XmlDocumentUtils.java
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/codec/xml/XmlStreamUtils.java [new file with mode: 0644]
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/codec/xml/XmlUtils.java [new file with mode: 0644]
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/SchemaUtils.java

index 440e68da86f426215a9464e5fbfb3b94ca37ccc0..6051b2681388aeb09fbf3213cba99d5ec33c259d 100644 (file)
@@ -13,19 +13,16 @@ import com.google.common.base.Splitter;
 import java.net.URI;
 import java.net.URISyntaxException;
 import java.util.ArrayList;
-import java.util.Collection;
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
-import java.util.concurrent.ThreadLocalRandom;
+import java.util.Map.Entry;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifierWithPredicates;
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeWithValue;
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
 import org.opendaylight.yangtools.yang.model.api.Module;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
@@ -65,32 +62,17 @@ public final class InstanceIdentifierForXmlCodec {
         return InstanceIdentifier.create(result);
     }
 
-    public static Element serialize(final InstanceIdentifier data, final Element element) {
-        Preconditions.checkNotNull(data, "Variable should contain instance of instance identifier and can't be null");
+    public static Element serialize(final InstanceIdentifier id, final Element element) {
+        Preconditions.checkNotNull(id, "Variable should contain instance of instance identifier and can't be null");
         Preconditions.checkNotNull(element, "DOM element can't be null");
-        Map<String, String> prefixes = new HashMap<>();
-        StringBuilder textContent = new StringBuilder();
-        for (PathArgument pathArgument : data.getPathArguments()) {
-            textContent.append('/');
-            writeIdentifierWithNamespacePrefix(element, textContent, pathArgument.getNodeType(), prefixes);
-            if (pathArgument instanceof NodeIdentifierWithPredicates) {
-                Map<QName, Object> predicates = ((NodeIdentifierWithPredicates) pathArgument).getKeyValues();
-
-                for (QName keyValue : predicates.keySet()) {
-                    String predicateValue = String.valueOf(predicates.get(keyValue));
-                    textContent.append('[');
-                    writeIdentifierWithNamespacePrefix(element, textContent, keyValue, prefixes);
-                    textContent.append("='");
-                    textContent.append(predicateValue);
-                    textContent.append("']");
-                }
-            } else if (pathArgument instanceof NodeWithValue) {
-                textContent.append("[.='");
-                textContent.append(((NodeWithValue) pathArgument).getValue());
-                textContent.append("']");
-            }
+
+        final RandomPrefix prefixes = new RandomPrefix();
+        final String str = XmlUtils.encodeIdentifier(prefixes, id);
+
+        for (Entry<URI, String> e: prefixes.getPrefixes()) {
+            element.setAttribute("xmlns:" + e.getValue(), e.getKey().toString());
         }
-        element.setTextContent(textContent.toString());
+        element.setTextContent(str);
         return element;
     }
 
@@ -198,39 +180,4 @@ public final class InstanceIdentifierForXmlCodec {
             return null;
         }
     }
-
-    private static void writeIdentifierWithNamespacePrefix(final Element element, final StringBuilder textContent, final QName qName,
-            final Map<String, String> prefixes) {
-        String namespace = qName.getNamespace().toString();
-        String prefix = prefixes.get(namespace);
-        if (prefix == null) {
-            prefix = qName.getPrefix();
-            if (prefix == null || prefix.isEmpty() || prefixes.containsValue(prefix)) {
-                prefix = generateNewPrefix(prefixes.values());
-            }
-        }
-
-        element.setAttribute("xmlns:" + prefix, namespace.toString());
-        textContent.append(prefix);
-        prefixes.put(namespace, prefix);
-
-        textContent.append(':');
-        textContent.append(qName.getLocalName());
-    }
-
-    private static String generateNewPrefix(final Collection<String> prefixes) {
-        String result;
-
-        final ThreadLocalRandom random = ThreadLocalRandom.current();
-        do {
-            StringBuilder sb = new StringBuilder();
-            for (int i = 0; i < 4; i++) {
-                sb.append('a' + random.nextInt(25));
-            }
-
-            result = sb.toString();
-        } while (prefixes.contains(result));
-
-        return result;
-    }
 }
diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/codec/xml/RandomPrefix.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/codec/xml/RandomPrefix.java
new file mode 100644 (file)
index 0000000..8292894
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.yangtools.yang.data.impl.codec.xml;
+
+import java.net.URI;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.concurrent.ThreadLocalRandom;
+
+import org.opendaylight.yangtools.yang.common.QName;
+
+final class RandomPrefix {
+    final Map<URI, String> prefixes = new HashMap<>();
+
+    Iterable<Entry<URI, String>> getPrefixes() {
+        return prefixes.entrySet();
+    }
+
+    String encodeQName(final QName qname) {
+        String prefix = prefixes.get(qname.getNamespace());
+        if (prefix == null) {
+            prefix = qname.getPrefix();
+            if (prefix == null || prefix.isEmpty() || prefixes.containsValue(prefix)) {
+                final ThreadLocalRandom random = ThreadLocalRandom.current();
+                do {
+                    final StringBuilder sb = new StringBuilder();
+                    for (int i = 0; i < 4; i++) {
+                        sb.append('a' + random.nextInt(25));
+                    }
+
+                    prefix = sb.toString();
+                } while (prefixes.containsValue(prefix));
+            }
+
+            prefixes.put(qname.getNamespace(), prefix);
+        }
+
+        return prefix + ':' + qname.getLocalName();
+    }
+}
\ No newline at end of file
index e011d3ec83bb13b85434c3c2261f061490fe7b57..666492df6b5621c7f81159e1a4e6648f7ebb12ef 100644 (file)
@@ -37,9 +37,8 @@ import org.opendaylight.yangtools.yang.data.api.SimpleNode;
 import org.opendaylight.yangtools.yang.data.impl.ImmutableCompositeNode;
 import org.opendaylight.yangtools.yang.data.impl.SimpleNodeTOImpl;
 import org.opendaylight.yangtools.yang.data.impl.codec.TypeDefinitionAwareCodec;
+import org.opendaylight.yangtools.yang.data.impl.schema.SchemaUtils;
 import org.opendaylight.yangtools.yang.data.impl.util.CompositeNodeBuilder;
-import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode;
-import org.opendaylight.yangtools.yang.model.api.ChoiceNode;
 import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
@@ -80,7 +79,6 @@ public class XmlDocumentUtils {
     }
 
     private static final XmlCodecProvider DEFAULT_XML_VALUE_CODEC_PROVIDER = new XmlCodecProvider() {
-
         @Override
         public TypeDefinitionAwareCodec<Object, ? extends TypeDefinition<?>> codecFor(final TypeDefinition<?> baseType) {
             return TypeDefinitionAwareCodec.from(baseType);
@@ -177,12 +175,11 @@ public class XmlDocumentUtils {
             for (Node<?> child : ((CompositeNode) data).getValue()) {
                 DataSchemaNode childSchema = null;
                 if (schema instanceof DataNodeContainer) {
-                    childSchema = findFirstSchema(child.getNodeType(), ((DataNodeContainer) schema).getChildNodes()).orNull();
+                    childSchema = SchemaUtils.findFirstSchema(child.getNodeType(), ((DataNodeContainer) schema).getChildNodes()).orNull();
                     if (logger.isDebugEnabled()) {
                         if (childSchema == null) {
-                            logger.debug("Probably the data node \""
-                                    + ((child == null) ? "" : child.getNodeType().getLocalName())
-                                    + "\" is not conform to schema");
+                            logger.debug("Probably the data node \"{}\" does not conform to schema",
+                                    child == null ? "" : child.getNodeType().getLocalName());
                         }
                     }
                 }
@@ -219,7 +216,7 @@ public class XmlDocumentUtils {
     }
 
     public static void writeValueByType(final Element element, final TypeDefinition<?> type, final XmlCodecProvider codecProvider, final Object nodeValue) {
-        TypeDefinition<?> baseType = resolveBaseTypeFrom(type);
+        TypeDefinition<?> baseType = XmlUtils.resolveBaseTypeFrom(type);
         if (baseType instanceof IdentityrefTypeDefinition) {
             if (nodeValue instanceof QName) {
                 QName value = (QName) nodeValue;
@@ -268,14 +265,6 @@ public class XmlDocumentUtils {
         }
     }
 
-    public final static TypeDefinition<?> resolveBaseTypeFrom(final TypeDefinition<?> type) {
-        TypeDefinition<?> superType = type;
-        while (superType.getBaseType() != null) {
-            superType = superType.getBaseType();
-        }
-        return superType;
-    }
-
     public static Node<?> toDomNode(final Element xmlElement, final Optional<DataSchemaNode> schema,
             final Optional<XmlCodecProvider> codecProvider) {
         if (schema.isPresent()) {
@@ -367,8 +356,8 @@ public class XmlDocumentUtils {
     public static Optional<ModifyAction> getModifyOperationFromAttributes(final Element xmlElement) {
         Attr attributeNodeNS = xmlElement.getAttributeNodeNS(OPERATION_ATTRIBUTE_QNAME.getNamespace().toString(), OPERATION_ATTRIBUTE_QNAME.getLocalName());
         if(attributeNodeNS == null) {
-                       return Optional.absent();
-               }
+            return Optional.absent();
+        }
 
         ModifyAction action = ModifyAction.fromXmlValue(attributeNodeNS.getValue());
         Preconditions.checkArgument(action.isOnElementPermitted(), "Unexpected operation %s on %s", action, xmlElement);
@@ -381,24 +370,6 @@ public class XmlDocumentUtils {
         checkState(qName.getLocalName().equals(xmlElement.getLocalName()));
     }
 
-    public static final Optional<DataSchemaNode> findFirstSchema(final QName qname, final Set<DataSchemaNode> dataSchemaNode) {
-        if (dataSchemaNode != null && !dataSchemaNode.isEmpty() && qname != null) {
-            for (DataSchemaNode dsn : dataSchemaNode) {
-                if (qname.isEqualWithoutRevision(dsn.getQName())) {
-                    return Optional.<DataSchemaNode> of(dsn);
-                } else if (dsn instanceof ChoiceNode) {
-                    for (ChoiceCaseNode choiceCase : ((ChoiceNode) dsn).getCases()) {
-                        Optional<DataSchemaNode> foundDsn = findFirstSchema(qname, choiceCase.getChildNodes());
-                        if (foundDsn != null && foundDsn.isPresent()) {
-                            return foundDsn;
-                        }
-                    }
-                }
-            }
-        }
-        return Optional.absent();
-    }
-
     public static Node<?> toDomNode(final Document doc) {
         return toDomNode(doc.getDocumentElement());
     }
@@ -436,7 +407,7 @@ public class XmlDocumentUtils {
             public Optional<Node<?>> apply(final ElementWithSchemaContext input) {
                 if (context.isPresent()) {
                     QName partialQName = qNameFromElement(input.getElement());
-                    Optional<DataSchemaNode> schemaNode = findFirstSchema(partialQName, context.get());
+                    Optional<DataSchemaNode> schemaNode = SchemaUtils.findFirstSchema(partialQName, context.get());
                     if (schemaNode.isPresent()) {
                         return Optional.<Node<?>> fromNullable(//
                                 toNodeWithSchema(input.getElement(), schemaNode.get(), DEFAULT_XML_VALUE_CODEC_PROVIDER,input.getSchemaContext()));
diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/codec/xml/XmlStreamUtils.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/codec/xml/XmlStreamUtils.java
new file mode 100644 (file)
index 0000000..6491391
--- /dev/null
@@ -0,0 +1,160 @@
+package org.opendaylight.yangtools.yang.data.impl.codec.xml;
+
+import com.google.common.base.Preconditions;
+
+import java.net.URI;
+import java.util.Map.Entry;
+
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamWriter;
+
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.AttributesContainer;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.Node;
+import org.opendaylight.yangtools.yang.data.api.SimpleNode;
+import org.opendaylight.yangtools.yang.data.impl.codec.TypeDefinitionAwareCodec;
+import org.opendaylight.yangtools.yang.data.impl.schema.SchemaUtils;
+import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.SchemaNode;
+import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
+import org.opendaylight.yangtools.yang.model.api.type.IdentityrefTypeDefinition;
+import org.opendaylight.yangtools.yang.model.api.type.InstanceIdentifierTypeDefinition;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class XmlStreamUtils {
+    private static final Logger LOG = LoggerFactory.getLogger(XmlStreamUtils.class);
+
+    public static void writeDataDocument(final XMLStreamWriter writer, final CompositeNode data, final SchemaNode schema, final XmlCodecProvider codecProvider) throws XMLStreamException {
+        //        final Boolean repairing = (Boolean) writer.getProperty(XMLOutputFactory.IS_REPAIRING_NAMESPACES);
+        //        Preconditions.checkArgument(repairing == true, "XML Stream Writer has to be repairing namespaces");
+
+        writer.writeStartDocument();
+        writeData(writer, data, schema, codecProvider);
+        writer.writeEndDocument();
+        writer.flush();
+    }
+
+    public static void writeDataDocument(final XMLStreamWriter writer, final CompositeNode data, final XmlCodecProvider codecProvider) throws XMLStreamException {
+        writeDataDocument(writer, data, null, codecProvider);
+    }
+
+    public static void write(final XMLStreamWriter writer, final InstanceIdentifier id) throws XMLStreamException {
+        Preconditions.checkNotNull(writer, "Writer may not be null");
+        Preconditions.checkNotNull(id, "Variable should contain instance of instance identifier and can't be null");
+
+        final RandomPrefix prefixes = new RandomPrefix();
+        final String str = XmlUtils.encodeIdentifier(prefixes, id);
+
+        for (Entry<URI, String> e: prefixes.getPrefixes()) {
+            writer.writeNamespace(e.getValue(), e.getKey().toString());
+        }
+        writer.writeCharacters(str);
+    }
+
+    public static void writeData(final XMLStreamWriter writer, final Node<?> data, final SchemaNode schema, final XmlCodecProvider codecProvider) throws XMLStreamException {
+        final QName qname = data.getNodeType();
+        final String pfx = qname.getPrefix() != null ? qname.getPrefix() : "";
+        final String ns;
+        if (qname.getNamespace() != null) {
+            ns = qname.getNamespace().toString();
+        } else {
+            ns = "";
+        }
+
+        writer.writeStartElement(pfx, qname.getLocalName(), ns);
+        if (data instanceof AttributesContainer && ((AttributesContainer) data).getAttributes() != null) {
+            for (Entry<QName, String> attribute : ((AttributesContainer) data).getAttributes().entrySet()) {
+                writer.writeAttribute(attribute.getKey().getNamespace().toString(), attribute.getKey().getLocalName(), attribute.getValue());
+            }
+        }
+
+        if (data instanceof SimpleNode<?>) {
+            // Simple node
+            if (schema instanceof LeafListSchemaNode) {
+                writeValue(writer, ((LeafListSchemaNode) schema).getType(), codecProvider, data.getValue());
+            } else if (schema instanceof LeafSchemaNode) {
+                writeValue(writer, ((LeafSchemaNode) schema).getType(), codecProvider, data.getValue());
+            } else {
+                Object value = data.getValue();
+                if (value != null) {
+                    writer.writeCharacters(String.valueOf(value));
+                }
+            }
+        } else {
+            // CompositeNode
+            for (Node<?> child : ((CompositeNode) data).getValue()) {
+                DataSchemaNode childSchema = null;
+                if (schema instanceof DataNodeContainer) {
+                    childSchema = SchemaUtils.findFirstSchema(child.getNodeType(), ((DataNodeContainer) schema).getChildNodes()).orNull();
+                    if (LOG.isDebugEnabled()) {
+                        if (childSchema == null) {
+                            LOG.debug("Probably the data node \"{}\" does not conform to schema", child == null ? "" : child.getNodeType().getLocalName());
+                        }
+                    }
+                }
+
+                writeData(writer, child, childSchema, codecProvider);
+            }
+        }
+
+        writer.writeEndElement();
+    }
+
+    public static void writeValue(final XMLStreamWriter writer, final TypeDefinition<?> type, final XmlCodecProvider codecProvider, final Object nodeValue) throws XMLStreamException {
+        TypeDefinition<?> baseType = XmlUtils.resolveBaseTypeFrom(type);
+        if (baseType instanceof IdentityrefTypeDefinition) {
+            if (nodeValue instanceof QName) {
+                QName value = (QName) nodeValue;
+                String prefix = "x";
+                if (value.getPrefix() != null && !value.getPrefix().isEmpty()) {
+                    prefix = value.getPrefix();
+                }
+
+                writer.writeNamespace(prefix, value.getNamespace().toString());
+                writer.writeCharacters(prefix + ':' + value.getLocalName());
+            } else {
+                Object value = nodeValue;
+                LOG.debug("Value of {}:{} is not instance of QName but is {}", baseType.getQName().getNamespace(),
+                        baseType.getQName().getLocalName(), value != null ? value.getClass() : "null");
+                if (value != null) {
+                    writer.writeCharacters(String.valueOf(value));
+                }
+            }
+        } else if (baseType instanceof InstanceIdentifierTypeDefinition) {
+            if (nodeValue instanceof InstanceIdentifier) {
+                write(writer, (InstanceIdentifier)nodeValue);
+            } else {
+                Object value = nodeValue;
+                LOG.debug("Value of {}:{} is not instance of InstanceIdentifier but is {}", baseType.getQName()
+                        .getNamespace(), //
+                        baseType.getQName().getLocalName(), value != null ? value.getClass() : "null");
+                if (value != null) {
+                    writer.writeCharacters(String.valueOf(value));
+                }
+            }
+        } else {
+            if (nodeValue != null) {
+                final TypeDefinitionAwareCodec<Object, ?> codec = codecProvider.codecFor(baseType);
+                String text;
+                if (codec != null) {
+                    try {
+                        text = codec.serialize(nodeValue);
+                    } catch (ClassCastException e) {
+                        LOG.error("Provided node value {} did not have type {} required by mapping. Using stream instead.", nodeValue, baseType, e);
+                        text = String.valueOf(nodeValue);
+                    }
+                } else {
+                    LOG.error("Failed to find codec for {}, falling back to using stream", baseType);
+                    text = String.valueOf(nodeValue);
+                }
+                writer.writeCharacters(text);
+            }
+        }
+    }
+}
diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/codec/xml/XmlUtils.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/codec/xml/XmlUtils.java
new file mode 100644 (file)
index 0000000..dbdb6ff
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.yangtools.yang.data.impl.codec.xml;
+
+import java.util.Map;
+
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifierWithPredicates;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeWithValue;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
+import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
+
+/**
+ * Common XML-related utility methods, which are not specific to a particular
+ * JAXP API.
+ */
+final class XmlUtils {
+
+    private XmlUtils() {
+
+    }
+
+    public static TypeDefinition<?> resolveBaseTypeFrom(final TypeDefinition<?> type) {
+        TypeDefinition<?> superType = type;
+        while (superType.getBaseType() != null) {
+            superType = superType.getBaseType();
+        }
+        return superType;
+    }
+
+    static String encodeIdentifier(final RandomPrefix prefixes, final InstanceIdentifier id) {
+        StringBuilder textContent = new StringBuilder();
+        for (PathArgument pathArgument : id.getPathArguments()) {
+            textContent.append('/');
+            textContent.append(prefixes.encodeQName(pathArgument.getNodeType()));
+            if (pathArgument instanceof NodeIdentifierWithPredicates) {
+                Map<QName, Object> predicates = ((NodeIdentifierWithPredicates) pathArgument).getKeyValues();
+
+                for (QName keyValue : predicates.keySet()) {
+                    String predicateValue = String.valueOf(predicates.get(keyValue));
+                    textContent.append('[');
+                    textContent.append(prefixes.encodeQName(keyValue));
+                    textContent.append("='");
+                    textContent.append(predicateValue);
+                    textContent.append("']");
+                }
+            } else if (pathArgument instanceof NodeWithValue) {
+                textContent.append("[.='");
+                textContent.append(((NodeWithValue) pathArgument).getValue());
+                textContent.append("']");
+            }
+        }
+
+        return textContent.toString();
+    }
+}
index 345ab7618d2d6980b36dc9e24942117f3bfd2028..fe5892a3f61cb5e906ff939fd52b59fe6de90a3d 100644 (file)
@@ -14,39 +14,66 @@ import com.google.common.base.Preconditions;
 import com.google.common.collect.Collections2;
 import com.google.common.collect.Maps;
 import com.google.common.collect.Sets;
+
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.schema.AugmentationNode;
 import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild;
-import org.opendaylight.yangtools.yang.data.impl.codec.xml.XmlDocumentUtils;
-import org.opendaylight.yangtools.yang.model.api.*;
-import java.util.*;
+import org.opendaylight.yangtools.yang.model.api.AugmentationSchema;
+import org.opendaylight.yangtools.yang.model.api.AugmentationTarget;
+import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode;
+import org.opendaylight.yangtools.yang.model.api.ChoiceNode;
+import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
 
 public final class SchemaUtils {
 
     private SchemaUtils() {
     }
 
-    public static DataSchemaNode findSchemaForChild(DataNodeContainer schema, QName qname) {
+    public static final Optional<DataSchemaNode> findFirstSchema(final QName qname, final Set<DataSchemaNode> dataSchemaNode) {
+        if (dataSchemaNode != null && !dataSchemaNode.isEmpty() && qname != null) {
+            for (DataSchemaNode dsn : dataSchemaNode) {
+                if (qname.isEqualWithoutRevision(dsn.getQName())) {
+                    return Optional.<DataSchemaNode> of(dsn);
+                } else if (dsn instanceof ChoiceNode) {
+                    for (ChoiceCaseNode choiceCase : ((ChoiceNode) dsn).getCases()) {
+                        Optional<DataSchemaNode> foundDsn = findFirstSchema(qname, choiceCase.getChildNodes());
+                        if (foundDsn != null && foundDsn.isPresent()) {
+                            return foundDsn;
+                        }
+                    }
+                }
+            }
+        }
+        return Optional.absent();
+    }
+
+    public static DataSchemaNode findSchemaForChild(final DataNodeContainer schema, final QName qname) {
         Set<DataSchemaNode> childNodes = schema.getChildNodes();
         return findSchemaForChild(schema, qname, childNodes);
     }
 
-    public static DataSchemaNode findSchemaForChild(DataNodeContainer schema, QName qname, Set<DataSchemaNode> childNodes) {
-        Optional<DataSchemaNode> childSchema = XmlDocumentUtils.findFirstSchema(qname, childNodes);
+    public static DataSchemaNode findSchemaForChild(final DataNodeContainer schema, final QName qname, final Set<DataSchemaNode> childNodes) {
+        Optional<DataSchemaNode> childSchema = findFirstSchema(qname, childNodes);
         Preconditions.checkState(childSchema.isPresent(),
                 "Unknown child(ren) node(s) detected, identified by: %s, in: %s", qname, schema);
         return childSchema.get();
     }
 
-    public static AugmentationSchema findSchemaForAugment(AugmentationTarget schema, Set<QName> qNames) {
+    public static AugmentationSchema findSchemaForAugment(final AugmentationTarget schema, final Set<QName> qNames) {
         Optional<AugmentationSchema> schemaForAugment = findAugment(schema, qNames);
         Preconditions.checkState(schemaForAugment.isPresent(), "Unknown augmentation node detected, identified by: %s, in: %s",
                 qNames, schema);
         return schemaForAugment.get();
     }
 
-    public static AugmentationSchema findSchemaForAugment(ChoiceNode schema, Set<QName> qNames) {
+    public static AugmentationSchema findSchemaForAugment(final ChoiceNode schema, final Set<QName> qNames) {
         Optional<AugmentationSchema> schemaForAugment = Optional.absent();
 
         for (ChoiceCaseNode choiceCaseNode : schema.getCases()) {
@@ -61,12 +88,12 @@ public final class SchemaUtils {
         return schemaForAugment.get();
     }
 
-    private static Optional<AugmentationSchema> findAugment(AugmentationTarget schema, Set<QName> qNames) {
+    private static Optional<AugmentationSchema> findAugment(final AugmentationTarget schema, final Set<QName> qNames) {
         for (AugmentationSchema augment : schema.getAvailableAugmentations()) {
 
             HashSet<QName> qNamesFromAugment = Sets.newHashSet(Collections2.transform(augment.getChildNodes(), new Function<DataSchemaNode, QName>() {
                 @Override
-                public QName apply(DataSchemaNode input) {
+                public QName apply(final DataSchemaNode input) {
                     return input.getQName();
                 }
             }));
@@ -79,10 +106,9 @@ public final class SchemaUtils {
         return Optional.absent();
     }
 
-    public static DataSchemaNode findSchemaForChild(ChoiceNode schema, QName childPartialQName) {
+    public static DataSchemaNode findSchemaForChild(final ChoiceNode schema, final QName childPartialQName) {
         for (ChoiceCaseNode choiceCaseNode : schema.getCases()) {
-            Optional<DataSchemaNode> childSchema = XmlDocumentUtils.findFirstSchema(childPartialQName,
-                    choiceCaseNode.getChildNodes());
+            Optional<DataSchemaNode> childSchema = findFirstSchema(childPartialQName, choiceCaseNode.getChildNodes());
             if (childSchema.isPresent()) {
                 return childSchema.get();
             }
@@ -98,13 +124,13 @@ public final class SchemaUtils {
      *
      * @return Map with all child nodes, to their most top augmentation
      */
-    public static Map<QName, ChoiceNode> mapChildElementsFromChoices(DataNodeContainer schema) {
+    public static Map<QName, ChoiceNode> mapChildElementsFromChoices(final DataNodeContainer schema) {
         Set<DataSchemaNode> childNodes = schema.getChildNodes();
 
         return mapChildElementsFromChoices(schema, childNodes);
     }
 
-    private static Map<QName, ChoiceNode> mapChildElementsFromChoices(DataNodeContainer schema, Set<DataSchemaNode> childNodes) {
+    private static Map<QName, ChoiceNode> mapChildElementsFromChoices(final DataNodeContainer schema, final Set<DataSchemaNode> childNodes) {
         Map<QName, ChoiceNode> mappedChoices = Maps.newLinkedHashMap();
 
         for (final DataSchemaNode childSchema : childNodes) {
@@ -126,7 +152,7 @@ public final class SchemaUtils {
         return mappedChoices;
     }
 
-    private static boolean isFromAugment(DataNodeContainer schema, DataSchemaNode childSchema) {
+    private static boolean isFromAugment(final DataNodeContainer schema, final DataSchemaNode childSchema) {
         if(schema instanceof AugmentationTarget == false) {
             return false;
         }
@@ -145,7 +171,7 @@ public final class SchemaUtils {
      *
      * @return Map with all child nodes, to their most top augmentation
      */
-    public static Map<QName, AugmentationSchema> mapChildElementsFromAugments(AugmentationTarget schema) {
+    public static Map<QName, AugmentationSchema> mapChildElementsFromAugments(final AugmentationTarget schema) {
 
         Map<QName, AugmentationSchema> childNodesToAugmentation = Maps.newLinkedHashMap();
 
@@ -163,8 +189,9 @@ public final class SchemaUtils {
 
             for (DataSchemaNode child : ((DataNodeContainer) schema).getChildNodes()) {
                 // If is not augmented child, continue
-                if (augments.containsKey(child.getQName()) == false)
+                if (augments.containsKey(child.getQName()) == false) {
                     continue;
+                }
 
                 AugmentationSchema mostTopAugmentation = augments.get(child.getQName());
 
@@ -206,7 +233,7 @@ public final class SchemaUtils {
      *
      * In case of choice, augment and cases, step in.
      */
-    public static Set<QName> getChildNodesRecursive(DataNodeContainer nodeContainer) {
+    public static Set<QName> getChildNodesRecursive(final DataNodeContainer nodeContainer) {
         Set<QName> allChildNodes = Sets.newHashSet();
 
         for (DataSchemaNode childSchema : nodeContainer.getChildNodes()) {
@@ -232,7 +259,7 @@ public final class SchemaUtils {
      * Schema of child node from augment is incomplete, therefore its useless for xml <-> normalizedNode translation.
      *
      */
-    public static Set<DataSchemaNode> getRealSchemasForAugment(AugmentationTarget targetSchema, AugmentationSchema augmentSchema) {
+    public static Set<DataSchemaNode> getRealSchemasForAugment(final AugmentationTarget targetSchema, final AugmentationSchema augmentSchema) {
         if(targetSchema.getAvailableAugmentations().contains(augmentSchema) == false) {
             return Collections.emptySet();
         }
@@ -240,7 +267,7 @@ public final class SchemaUtils {
         Set<DataSchemaNode> realChildNodes = Sets.newHashSet();
 
         if(targetSchema instanceof DataNodeContainer) {
-              realChildNodes = getRealSchemasForAugment((DataNodeContainer)targetSchema, augmentSchema);
+            realChildNodes = getRealSchemasForAugment((DataNodeContainer)targetSchema, augmentSchema);
         } else if(targetSchema instanceof ChoiceNode) {
             for (DataSchemaNode dataSchemaNode : augmentSchema.getChildNodes()) {
                 for (ChoiceCaseNode choiceCaseNode : ((ChoiceNode) targetSchema).getCases()) {
@@ -254,8 +281,8 @@ public final class SchemaUtils {
         return realChildNodes;
     }
 
-    public static Set<DataSchemaNode> getRealSchemasForAugment(DataNodeContainer targetSchema,
-            AugmentationSchema augmentSchema) {
+    public static Set<DataSchemaNode> getRealSchemasForAugment(final DataNodeContainer targetSchema,
+            final AugmentationSchema augmentSchema) {
         Set<DataSchemaNode> realChildNodes = Sets.newHashSet();
         for (DataSchemaNode dataSchemaNode : augmentSchema.getChildNodes()) {
             DataSchemaNode realChild = targetSchema.getDataChildByName(dataSchemaNode.getQName());
@@ -264,7 +291,7 @@ public final class SchemaUtils {
         return realChildNodes;
     }
 
-    public static Optional<ChoiceCaseNode> detectCase(ChoiceNode schema, DataContainerChild<?, ?> child) {
+    public static Optional<ChoiceCaseNode> detectCase(final ChoiceNode schema, final DataContainerChild<?, ?> child) {
         for (ChoiceCaseNode choiceCaseNode : schema.getCases()) {
             if (child instanceof AugmentationNode
                     && belongsToCaseAugment(choiceCaseNode,
@@ -278,7 +305,7 @@ public final class SchemaUtils {
         return Optional.absent();
     }
 
-    public static boolean belongsToCaseAugment(ChoiceCaseNode caseNode, InstanceIdentifier.AugmentationIdentifier childToProcess) {
+    public static boolean belongsToCaseAugment(final ChoiceCaseNode caseNode, final InstanceIdentifier.AugmentationIdentifier childToProcess) {
         for (AugmentationSchema augmentationSchema : caseNode.getAvailableAugmentations()) {
 
             Set<QName> currentAugmentChildNodes = Sets.newHashSet();
@@ -294,11 +321,11 @@ public final class SchemaUtils {
         return false;
     }
 
-    public static InstanceIdentifier.AugmentationIdentifier getNodeIdentifierForAugmentation(AugmentationSchema schema) {
+    public static InstanceIdentifier.AugmentationIdentifier getNodeIdentifierForAugmentation(final AugmentationSchema schema) {
         return new InstanceIdentifier.AugmentationIdentifier(getChildQNames(schema));
     }
 
-    public static Set<QName> getChildQNames(AugmentationSchema schema) {
+    public static Set<QName> getChildQNames(final AugmentationSchema schema) {
         Set<QName> qnames = Sets.newHashSet();
 
         for (DataSchemaNode dataSchemaNode : schema.getChildNodes()) {