Bug 3874: Support of yang modeled AnyXML - JSON deserialization
[yangtools.git] / yang / yang-data-codec-gson / src / main / java / org / opendaylight / yangtools / yang / data / codec / gson / CompositeNodeDataWithSchema.java
index ee2541d8e651888fd4062db56828e0046b3a8168..4d40db27f78c2b48cf7611659e46610619156b9d 100644 (file)
@@ -7,11 +7,8 @@
  */
 package org.opendaylight.yangtools.yang.data.codec.gson;
 
-import com.google.common.base.Function;
 import com.google.common.base.Preconditions;
 import com.google.common.collect.ArrayListMultimap;
-import com.google.common.collect.Collections2;
-import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.Multimap;
 import java.io.IOException;
 import java.util.ArrayList;
@@ -19,31 +16,23 @@ import java.util.Collection;
 import java.util.Deque;
 import java.util.List;
 import java.util.Map.Entry;
-import javax.annotation.Nonnull;
-import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.AugmentationIdentifier;
-import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeStreamWriter;
+import org.opendaylight.yangtools.yang.data.api.schema.stream.SchemaAwareNormalizedNodeStreamWriter;
+import org.opendaylight.yangtools.yang.data.impl.schema.SchemaUtils;
 import org.opendaylight.yangtools.yang.model.api.AnyXmlSchemaNode;
 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.ChoiceSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
 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.ListSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.YangModeledAnyXmlSchemaNode;
 
 /**
  * A node which is composed of multiple simpler nodes.
  */
 class CompositeNodeDataWithSchema extends AbstractNodeDataWithSchema {
-    private static final Function<DataSchemaNode, QName> QNAME_FUNCTION = new Function<DataSchemaNode, QName>() {
-        @Override
-        public QName apply(@Nonnull final DataSchemaNode input) {
-            return input.getQName();
-        }
-    };
 
     /**
      * nodes which were added to schema via augmentation and are present in data input
@@ -71,9 +60,9 @@ class CompositeNodeDataWithSchema extends AbstractNodeDataWithSchema {
 
         // The choice/case mess, reuse what we already popped
         final DataSchemaNode choiceCandidate = schema;
-        Preconditions.checkArgument(choiceCandidate instanceof ChoiceNode,
+        Preconditions.checkArgument(choiceCandidate instanceof ChoiceSchemaNode,
             "Expected node of type ChoiceNode but was %s", choiceCandidate.getClass().getSimpleName());
-        final ChoiceNode choiceNode = (ChoiceNode) choiceCandidate;
+        final ChoiceSchemaNode choiceNode = (ChoiceSchemaNode) choiceCandidate;
 
         final DataSchemaNode caseCandidate = schemas.pop();
         Preconditions.checkArgument(caseCandidate instanceof ChoiceCaseNode,
@@ -82,7 +71,7 @@ class CompositeNodeDataWithSchema extends AbstractNodeDataWithSchema {
 
         AugmentationSchema augSchema = null;
         if (choiceCandidate.isAugmenting()) {
-            augSchema = findCorrespondingAugment(getSchema(), choiceCandidate);
+            augSchema = SchemaUtils.findCorrespondingAugment(getSchema(), choiceCandidate);
         }
 
         // looking for existing choice
@@ -96,7 +85,7 @@ class CompositeNodeDataWithSchema extends AbstractNodeDataWithSchema {
         CompositeNodeDataWithSchema caseNodeDataWithSchema = findChoice(childNodes, choiceCandidate, caseCandidate);
         if (caseNodeDataWithSchema == null) {
             ChoiceNodeDataWithSchema choiceNodeDataWithSchema = new ChoiceNodeDataWithSchema(choiceNode);
-            addChild(choiceNodeDataWithSchema);
+            childNodes.add(choiceNodeDataWithSchema);
             caseNodeDataWithSchema = choiceNodeDataWithSchema.addCompositeChild(caseNode);
         }
 
@@ -108,6 +97,10 @@ class CompositeNodeDataWithSchema extends AbstractNodeDataWithSchema {
         if (schema instanceof LeafSchemaNode) {
             newChild = new LeafNodeDataWithSchema(schema);
         } else if (schema instanceof AnyXmlSchemaNode) {
+            // YangModeledAnyXmlSchemaNode is handled by addCompositeChild method.
+            if (schema instanceof YangModeledAnyXmlSchemaNode) {
+                return null;
+            }
             newChild = new AnyXmlNodeDataWithSchema(schema);
         } else {
             return null;
@@ -115,7 +108,7 @@ class CompositeNodeDataWithSchema extends AbstractNodeDataWithSchema {
 
         AugmentationSchema augSchema = null;
         if (schema.isAugmenting()) {
-            augSchema = findCorrespondingAugment(getSchema(), schema);
+            augSchema = SchemaUtils.findCorrespondingAugment(getSchema(), schema);
         }
         if (augSchema != null) {
             augmentationsToChild.put(augSchema, newChild);
@@ -125,8 +118,8 @@ class CompositeNodeDataWithSchema extends AbstractNodeDataWithSchema {
         return newChild;
     }
 
-    private CaseNodeDataWithSchema findChoice(final Collection<AbstractNodeDataWithSchema> childNodes, final DataSchemaNode choiceCandidate,
-            final DataSchemaNode caseCandidate) {
+    private static CaseNodeDataWithSchema findChoice(final Collection<AbstractNodeDataWithSchema> childNodes,
+            final DataSchemaNode choiceCandidate, final DataSchemaNode caseCandidate) {
         if (childNodes != null) {
             for (AbstractNodeDataWithSchema nodeDataWithSchema : childNodes) {
                 if (nodeDataWithSchema instanceof ChoiceNodeDataWithSchema
@@ -145,22 +138,26 @@ class CompositeNodeDataWithSchema extends AbstractNodeDataWithSchema {
     }
 
     AbstractNodeDataWithSchema addCompositeChild(final DataSchemaNode schema) {
-        CompositeNodeDataWithSchema newChild;
+        final CompositeNodeDataWithSchema newChild;
+
         if (schema instanceof ListSchemaNode) {
             newChild = new ListNodeDataWithSchema(schema);
         } else if (schema instanceof LeafListSchemaNode) {
             newChild = new LeafListNodeDataWithSchema(schema);
         } else if (schema instanceof ContainerSchemaNode) {
             newChild = new ContainerNodeDataWithSchema(schema);
+        } else if (schema instanceof YangModeledAnyXmlSchemaNode) {
+            newChild = new YangModeledAnyXmlNodeDataWithSchema((YangModeledAnyXmlSchemaNode)schema);
         } else {
             newChild = new CompositeNodeDataWithSchema(schema);
         }
+
         addCompositeChild(newChild);
         return newChild;
     }
 
     void addCompositeChild(final CompositeNodeDataWithSchema newChild) {
-        AugmentationSchema augSchema = findCorrespondingAugment(getSchema(), newChild.getSchema());
+        AugmentationSchema augSchema = SchemaUtils.findCorrespondingAugment(getSchema(), newChild.getSchema());
         if (augSchema != null) {
             augmentationsToChild.put(augSchema, newChild);
         } else {
@@ -185,31 +182,16 @@ class CompositeNodeDataWithSchema extends AbstractNodeDataWithSchema {
         return children.size();
     }
 
-    /**
-     * Tries to find in {@code parent} which is dealed as augmentation target node with QName as {@code child}. If such
-     * node is found then it is returned, else null.
-     */
-    AugmentationSchema findCorrespondingAugment(final DataSchemaNode parent, final DataSchemaNode child) {
-        if (parent instanceof AugmentationTarget && !((parent instanceof ChoiceCaseNode) || (parent instanceof ChoiceNode))) {
-            for (AugmentationSchema augmentation : ((AugmentationTarget) parent).getAvailableAugmentations()) {
-                DataSchemaNode childInAugmentation = augmentation.getDataChildByName(child.getQName());
-                if (childInAugmentation != null) {
-                    return augmentation;
-                }
-            }
-        }
-        return null;
-    }
-
     @Override
-    public void write(final NormalizedNodeStreamWriter writer) throws IOException {
+    public void write(final SchemaAwareNormalizedNodeStreamWriter writer) throws IOException {
         for (AbstractNodeDataWithSchema child : children) {
             child.write(writer);
         }
         for (Entry<AugmentationSchema, Collection<AbstractNodeDataWithSchema>> augmentationToChild : augmentationsToChild.asMap().entrySet()) {
             final Collection<AbstractNodeDataWithSchema> childsFromAgumentation = augmentationToChild.getValue();
             if (!childsFromAgumentation.isEmpty()) {
-                writer.startAugmentationNode(toAugmentationIdentifier(augmentationToChild.getKey()));
+                // FIXME: can we get the augmentation schema?
+                writer.startAugmentationNode(SchemaUtils.getNodeIdentifierForAugmentation(augmentationToChild.getKey()));
 
                 for (AbstractNodeDataWithSchema nodeDataWithSchema : childsFromAgumentation) {
                     nodeDataWithSchema.write(writer);
@@ -219,9 +201,4 @@ class CompositeNodeDataWithSchema extends AbstractNodeDataWithSchema {
             }
         }
     }
-
-    private static AugmentationIdentifier toAugmentationIdentifier(final AugmentationSchema schema) {
-        final Collection<QName> qnames = Collections2.transform(schema.getChildNodes(), QNAME_FUNCTION);
-        return new AugmentationIdentifier(ImmutableSet.copyOf(qnames));
-    }
 }