Abstract infrastructure for normalized nodes translation. 94/5594/23
authorMaros Marsalek <mmarsale@cisco.com>
Wed, 19 Mar 2014 10:31:56 +0000 (11:31 +0100)
committerRobert Varga <rovarga@cisco.com>
Thu, 20 Mar 2014 19:38:07 +0000 (20:38 +0100)
With implementation for dom <-> normalized nodes.

Change-Id: Ic2c08d2955177bc335d6493d64076a77d2cc7d62
Signed-off-by: Maros Marsalek <mmarsale@cisco.com>
Signed-off-by: Jozef Gloncak <jgloncak@cisco.com>
Signed-off-by: Ladislav Borak <lborak@cisco.com>
Signed-off-by: Robert Varga <rovarga@cisco.com>
67 files changed:
pom.xml
yang/yang-data-api/src/main/java/org/opendaylight/yangtools/yang/data/api/InstanceIdentifier.java
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/codec/TypeDefinitionAwareCodec.java
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/schema/builder/impl/ImmutableAugmentationNodeSchemaAwareBuilder.java
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/impl/ImmutableChoiceNodeBuilder.java
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/impl/ImmutableChoiceNodeSchemaAwareBuilder.java
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/impl/ImmutableLeafNodeBuilder.java
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/impl/ImmutableLeafSetEntryNodeBuilder.java
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/impl/ImmutableLeafSetNodeBuilder.java
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/impl/ImmutableMapEntryNodeBuilder.java
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/impl/ImmutableMapEntryNodeSchemaAwareBuilder.java
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/impl/ImmutableMapNodeBuilder.java
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/impl/valid/DataNodeContainerValidator.java
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/nodes/AbstractImmutableDataContainerNode.java
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/nodes/AbstractImmutableNormalizedNode.java
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/FromNormalizedNodeSerializer.java [new file with mode: 0644]
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/ToNormalizedNodeParser.java [new file with mode: 0644]
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/AugmentationSchemaProxy.java [new file with mode: 0644]
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/SchemaUtils.java [new file with mode: 0644]
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/parser/AugmentationNodeBaseParser.java [new file with mode: 0644]
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/parser/BaseDispatcherParser.java [new file with mode: 0644]
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/parser/ChoiceNodeBaseParser.java [new file with mode: 0644]
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/parser/ContainerNodeBaseParser.java [new file with mode: 0644]
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/parser/LeafNodeBaseParser.java [new file with mode: 0644]
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/parser/LeafSetEntryNodeBaseParser.java [new file with mode: 0644]
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/parser/LeafSetNodeBaseParser.java [new file with mode: 0644]
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/parser/MapEntryNodeBaseParser.java [new file with mode: 0644]
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/parser/MapNodeBaseParser.java [new file with mode: 0644]
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/parser/NodeParserDispatcher.java [new file with mode: 0644]
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/serializer/AugmentationNodeBaseSerializer.java [new file with mode: 0644]
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/serializer/BaseDispatcherSerializer.java [new file with mode: 0644]
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/serializer/ChoiceNodeBaseSerializer.java [new file with mode: 0644]
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/serializer/ContainerNodeBaseSerializer.java [new file with mode: 0644]
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/serializer/LeafNodeBaseSerializer.java [new file with mode: 0644]
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/serializer/LeafSetEntryNodeBaseSerializer.java [new file with mode: 0644]
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/serializer/LeafSetNodeBaseSerializer.java [new file with mode: 0644]
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/serializer/MapEntryNodeBaseSerializer.java [new file with mode: 0644]
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/serializer/MapNodeBaseSerializer.java [new file with mode: 0644]
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/serializer/NodeSerializerDispatcher.java [new file with mode: 0644]
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/DomUtils.java [new file with mode: 0644]
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/parser/AugmentationNodeDomParser.java [new file with mode: 0644]
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/parser/ChoiceNodeDomParser.java [new file with mode: 0644]
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/parser/ContainerNodeDomParser.java [new file with mode: 0644]
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/parser/DomNodeDispatcher.java [new file with mode: 0644]
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/parser/LeafNodeDomParser.java [new file with mode: 0644]
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/parser/LeafSetEntryNodeDomParser.java [new file with mode: 0644]
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/parser/LeafSetNodeDomParser.java [new file with mode: 0644]
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/parser/MapEntryNodeDomParser.java [new file with mode: 0644]
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/parser/MapNodeDomParser.java [new file with mode: 0644]
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/serializer/AugmentationNodeDomSerializer.java [new file with mode: 0644]
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/serializer/ChoiceNodeDomSerializer.java [new file with mode: 0644]
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/serializer/ContainerNodeDomSerializer.java [new file with mode: 0644]
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/serializer/DomNodeSerializerDispatcher.java [new file with mode: 0644]
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/serializer/LeafNodeDomSerializer.java [new file with mode: 0644]
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/serializer/LeafSetEntryNodeDomSerializer.java [new file with mode: 0644]
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/serializer/LeafSetNodeDomSerializer.java [new file with mode: 0644]
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/serializer/MapEntryNodeDomSerializer.java [new file with mode: 0644]
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/serializer/MapNodeDomSerializer.java [new file with mode: 0644]
yang/yang-data-impl/src/test/java/org/opendaylight/yangtools/yang/data/impl/schema/NormalizedDataBuilderTest.java
yang/yang-data-impl/src/test/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/serializer/NormalizedNodeXmlTranslationTest.java [new file with mode: 0644]
yang/yang-data-impl/src/test/resources/org/opendaylight/yangtools/yang/data/impl/schema/augment_choice_hell.yang [new file with mode: 0644]
yang/yang-data-impl/src/test/resources/org/opendaylight/yangtools/yang/data/impl/schema/augment_choice_hell_ok.xml [new file with mode: 0644]
yang/yang-data-impl/src/test/resources/org/opendaylight/yangtools/yang/data/impl/schema/augment_choice_hell_ok2.xml [new file with mode: 0644]
yang/yang-data-impl/src/test/resources/org/opendaylight/yangtools/yang/data/impl/schema/simple.xml
yang/yang-data-impl/src/test/resources/org/opendaylight/yangtools/yang/data/impl/schema/simple2.xml [new file with mode: 0644]
yang/yang-data-impl/src/test/resources/org/opendaylight/yangtools/yang/data/impl/schema/test.yang

diff --git a/pom.xml b/pom.xml
index 37399eff88b7163690ef34c9e5152d53196ad46c..68cc427b04b8c501c4eeff0e193858fd3947ecbc 100644 (file)
--- a/pom.xml
+++ b/pom.xml
@@ -29,7 +29,7 @@
 
         <!-- Build Plugin Versions -->
         <maven.bundle.version>2.4.0</maven.bundle.version>
-        <maven.jar.version>2.4</maven.jar.version>
+        <maven.jar.version>2.3.2</maven.jar.version>
         <maven.javadoc.version>2.9.1</maven.javadoc.version>
         <maven.release.version>2.4.2</maven.release.version>
         <maven.source.version>2.2.1</maven.source.version>
index f3a6c3800fe6d5fdd2c765ca204ce73602a245ce..174ae31000d90a9be813dd204adf9166f5cc5949 100644 (file)
@@ -354,6 +354,33 @@ public class InstanceIdentifier implements Path<InstanceIdentifier>, Immutable,
             return childNames;
         }
 
+        @Override
+        public String toString() {
+            final StringBuffer sb = new StringBuffer("AugmentationIdentifier{");
+            sb.append("childNames=").append(childNames);
+            sb.append('}');
+            return sb.toString();
+        }
+
+        @Override
+        public boolean equals(Object o) {
+            if (this == o) return true;
+            if (!(o instanceof AugmentationIdentifier)) return false;
+
+            AugmentationIdentifier that = (AugmentationIdentifier) o;
+
+            if (childNames != null ? !childNames.equals(that.childNames) : that.childNames != null) return false;
+            if (nodeType != null ? !nodeType.equals(that.nodeType) : that.nodeType != null) return false;
+
+            return true;
+        }
+
+        @Override
+        public int hashCode() {
+            int result = nodeType != null ? nodeType.hashCode() : 0;
+            result = 31 * result + (childNames != null ? childNames.hashCode() : 0);
+            return result;
+        }
     }
 
     private static class BuilderImpl implements InstanceIdentifierBuilder {
index a1fa857775319ca249d50484604bf22d16703b23..8cb399584d0343b27b5a745c08d9d42ead4cd35b 100644 (file)
@@ -58,23 +58,23 @@ import com.google.common.collect.ImmutableSet;
 import com.google.common.io.BaseEncoding;
 
 public abstract class TypeDefinitionAwareCodec<J, T extends TypeDefinition<T>> implements DataStringCodec<J> {
-    
+
     private static final Pattern intPattern = Pattern.compile("[+-]?[1-9][0-9]*$");
     private static final Pattern hexPattern = Pattern.compile("[+-]?0[xX][0-9a-fA-F]+");
     private static final Pattern octalPattern = Pattern.compile("[+-]?0[1-7][0-7]*$");
-    
+
     private final Optional<T> typeDefinition;
     private final Class<J> inputClass;
-    
+
     private static final int provideBase(final String integer) {
         if (integer == null) {
             throw new IllegalArgumentException("String representing integer number cannot be NULL!");
         }
-        
+
         if ((integer.length() == 1) && (integer.charAt(0) == '0')) {
             return 10;
         }
-        
+
         final Matcher intMatcher = intPattern.matcher(integer);
         if (intMatcher.matches()) {
             return 10;
@@ -87,7 +87,7 @@ public abstract class TypeDefinitionAwareCodec<J, T extends TypeDefinition<T>> i
                 if (octMatcher.matches()) {
                     return 8;
                 } else {
-                    throw new NumberFormatException("Incorrect lexical representation of Integer value!"
+                    throw new NumberFormatException("Incorrect lexical representation of Integer value: " + integer
                             + "The Integer value can be defined as Integer Number, Hexadecimal Number or"
                             + "Octal Number. The sign vlues are allowed. "
                             + "Spaces between digits are NOT allowed!");
@@ -95,7 +95,7 @@ public abstract class TypeDefinitionAwareCodec<J, T extends TypeDefinition<T>> i
             }
         }
     }
-    
+
     private static String normalizeHexadecimal(final String hexInt) {
         if (hexInt == null) {
             throw new IllegalArgumentException(
@@ -111,7 +111,7 @@ public abstract class TypeDefinitionAwareCodec<J, T extends TypeDefinition<T>> i
         }
         return normalizedString;
     }
-    
+
     public static final BinaryCodecStringImpl BINARY_DEFAULT_CODEC = new BinaryCodecStringImpl(
             Optional.<BinaryTypeDefinition> absent());
 
index 9f034543d7c659ff7dcc8999bf0914c341c03a7f..7345d3dded5ae16c61256750213fa988ebafb76e 100644 (file)
@@ -23,13 +23,16 @@ import javax.xml.parsers.DocumentBuilder;
 import javax.xml.parsers.DocumentBuilderFactory;
 import javax.xml.parsers.ParserConfigurationException;
 
-import com.google.common.collect.Maps;
 import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.data.api.*;
+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.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.data.api.ModifyAction;
 import org.opendaylight.yangtools.yang.data.api.Node;
+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;
@@ -49,7 +52,10 @@ 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;
-import org.w3c.dom.*;
+import org.w3c.dom.Attr;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
 
 import com.google.common.base.Function;
 import com.google.common.base.Objects;
index 1f07eb555302dc14e1d6b7803bc26e559e5df269..33638de640eac8d4ab02b3b859e75a7788dcce6f 100644 (file)
@@ -18,7 +18,6 @@ import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.valid.DataN
 import org.opendaylight.yangtools.yang.model.api.AugmentationSchema;
 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
 
-import com.google.common.base.Preconditions;
 import com.google.common.collect.Sets;
 
 public class ImmutableAugmentationNodeSchemaAwareBuilder extends ImmutableAugmentationNodeBuilder {
index a5c2d031805e35014197b518f43b8b6817b57bc0..f1ad8d05592ee0fd3757e21bfb8cf3875776243f 100644 (file)
@@ -36,6 +36,5 @@ public class ImmutableChoiceNodeBuilder extends AbstractImmutableDataContainerNo
                             final Map<InstanceIdentifier.PathArgument, DataContainerChild<? extends InstanceIdentifier.PathArgument, ?>> children) {
             super(ImmutableMap.copyOf(children), nodeIdentifier);
         }
-
     }
 }
index ab73930b402f09104d906d21e71f2149e7101db5..312361bb4180b76f6b56195bf0892362a65770ef 100644 (file)
@@ -7,15 +7,14 @@
  */
 package org.opendaylight.yangtools.yang.data.impl.schema.builder.impl;
 
+import com.google.common.base.Supplier;
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode;
 import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild;
 import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeBuilder;
 import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.valid.DataNodeContainerValidator;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.SchemaUtils;
 import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode;
-import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
-
-import com.google.common.base.Preconditions;
 
 public class ImmutableChoiceNodeSchemaAwareBuilder extends ImmutableChoiceNodeBuilder {
 
@@ -35,9 +34,15 @@ public class ImmutableChoiceNodeSchemaAwareBuilder extends ImmutableChoiceNodeBu
     }
 
     @Override
-    public DataContainerNodeBuilder<InstanceIdentifier.NodeIdentifier, ChoiceNode> withChild(DataContainerChild<?, ?> child) {
+    public DataContainerNodeBuilder<InstanceIdentifier.NodeIdentifier, ChoiceNode> withChild(final DataContainerChild<?, ?> child) {
         if(detectedCase == null) {
-            detectedCase = detectCase(child);
+            detectedCase = SchemaUtils.detectCase(schema, child).or(new Supplier<ChoiceCaseNode>() {
+                @Override
+                public ChoiceCaseNode get() {
+                    throw new IllegalArgumentException(String.format("Unknown child node: %s, for choice: %s", child.getNodeType(),
+                            schema.getQName()));
+                }
+            });
             validator = new DataNodeContainerValidator(detectedCase);
         }
 
@@ -52,19 +57,6 @@ public class ImmutableChoiceNodeSchemaAwareBuilder extends ImmutableChoiceNodeBu
         return super.build();
     }
 
-    private ChoiceCaseNode detectCase(DataContainerChild<?, ?> child) {
-        for (ChoiceCaseNode choiceCaseNode : schema.getCases()) {
-            for (DataSchemaNode childFromCase : choiceCaseNode.getChildNodes()) {
-                if (childFromCase.getQName().equals(child.getNodeType())) {
-                    return choiceCaseNode;
-                }
-            }
-        }
-
-        throw new IllegalArgumentException(String.format("Unknown child node: %s, for choice: %s", child.getNodeType(),
-                schema.getQName()));
-    }
-
     public static DataContainerNodeBuilder<InstanceIdentifier.NodeIdentifier, ChoiceNode> create(org.opendaylight.yangtools.yang.model.api.ChoiceNode schema) {
         return new ImmutableChoiceNodeSchemaAwareBuilder(schema);
     }
index f466ed3929edf8bfc3a5c072c69d36b9f8f8c510..60335eb30dd45029e48c4acfad81ea9bbef7076d 100644 (file)
@@ -32,13 +32,5 @@ public class ImmutableLeafNodeBuilder<T> extends AbstractImmutableNormalizedNode
             super(nodeIdentifier, value);
         }
 
-        @Override
-        public String toString() {
-            final StringBuffer sb = new StringBuffer("ImmutableLeafNode{");
-            sb.append("nodeIdentifier=").append(nodeIdentifier);
-            sb.append(", value=").append(value);
-            sb.append('}');
-            return sb.toString();
-        }
     }
 }
index 77d23d80a31b1422974102c995b11fbd9408e146..2c4e4e89b906e9f7b79fdccbae272024690f78a8 100644 (file)
@@ -33,13 +33,5 @@ public class ImmutableLeafSetEntryNodeBuilder<T> extends AbstractImmutableNormal
                     "Node identifier contains different value: %s than value itself: %s", nodeIdentifier, value);
         }
 
-        @Override
-        public String toString() {
-            final StringBuffer sb = new StringBuffer("ImmutableLeafSetEntryNode{");
-            sb.append("nodeIdentifier=").append(nodeIdentifier);
-            sb.append(", value=").append(value);
-            sb.append('}');
-            return sb.toString();
-        }
     }
 }
index f3dd9d0c9b1fb73a004e60f5af19263b8aa53195..4cb2d8ee22532a31398aff258030e9ada2cb28ee 100644 (file)
@@ -21,6 +21,7 @@ import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNo
 import org.opendaylight.yangtools.yang.data.impl.schema.nodes.AbstractImmutableNormalizedNode;
 
 import com.google.common.base.Optional;
+import com.google.common.collect.ImmutableList;
 import com.google.common.collect.Maps;
 
 public class ImmutableLeafSetNodeBuilder<T> implements ListNodeBuilder<T, LeafSetEntryNode<T>> {
@@ -73,7 +74,7 @@ public class ImmutableLeafSetNodeBuilder<T> implements ListNodeBuilder<T, LeafSe
 
         ImmutableLeafSetNode(final InstanceIdentifier.NodeIdentifier nodeIdentifier,
                 final Map<InstanceIdentifier.NodeWithValue, LeafSetEntryNode<T>> children) {
-            super(nodeIdentifier, children.values());
+            super(nodeIdentifier, ImmutableList.copyOf(children.values()));
             this.mappedChildren = children;
         }
 
@@ -82,14 +83,6 @@ public class ImmutableLeafSetNodeBuilder<T> implements ListNodeBuilder<T, LeafSe
             return Optional.fromNullable(mappedChildren.get(child));
         }
 
-        @Override
-        public String toString() {
-            final StringBuffer sb = new StringBuffer("ImmutableLeafSetNode{");
-            sb.append("nodeIdentifier=").append(nodeIdentifier);
-            sb.append(", children=").append(value);
-            sb.append('}');
-            return sb.toString();
-        }
     }
 
     @Override
index 896ff642d098f453e5b490571b513c743d656c6a..816cfaba52f29728bdd48491da433f53991d0737 100644 (file)
@@ -39,14 +39,24 @@ public class ImmutableMapEntryNodeBuilder
     @Override
     public DataContainerNodeBuilder<InstanceIdentifier.NodeIdentifierWithPredicates, MapEntryNode> withValue(final List<DataContainerChild<? extends InstanceIdentifier.PathArgument, ?>> value) {
         for (DataContainerChild<? extends InstanceIdentifier.PathArgument, ?> childId : value) {
-            this.childrenQNamesToPaths.put(childId.getNodeType(), childId.getIdentifier());
+            InstanceIdentifier.PathArgument identifier = childId.getIdentifier();
+
+            // Augmentation nodes cannot be keys, and do not have to be present in childrenQNamesToPaths map
+            if(identifier instanceof InstanceIdentifier.AugmentationIdentifier) {
+                continue;
+            }
+
+            this.childrenQNamesToPaths.put(childId.getNodeType(), identifier);
         }
         return super.withValue(value);
     }
 
     @Override
     public DataContainerNodeBuilder<InstanceIdentifier.NodeIdentifierWithPredicates, MapEntryNode> withChild(final DataContainerChild<?, ?> child) {
-        childrenQNamesToPaths.put(child.getNodeType(), child.getIdentifier());
+        // Augmentation nodes cannot be keys, and do not have to be present in childrenQNamesToPaths map
+        if(child.getIdentifier() instanceof InstanceIdentifier.AugmentationIdentifier == false) {
+            childrenQNamesToPaths.put(child.getNodeType(), child.getIdentifier());
+        }
         return super.withChild(child);
     }
 
index 44959104390f0eaf8eca1a921d1503439b281b60..6fc9a86c8fa28c912ec1aedfe38f0dd7e4d50fda 100644 (file)
@@ -68,6 +68,7 @@ public final class ImmutableMapEntryNodeSchemaAwareBuilder extends ImmutableMapE
             keysToValues.put(key, valueForKey.getValue());
         }
 
+
         return new InstanceIdentifier.NodeIdentifierWithPredicates(schema.getQName(), keysToValues);
     }
 
index b149abca017b9e8a065acd5f019157559c08c473..a4b3a493d9c5435c66b015f0120d231255dff403 100644 (file)
@@ -18,6 +18,7 @@ import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.CollectionNo
 import org.opendaylight.yangtools.yang.data.impl.schema.nodes.AbstractImmutableNormalizedNode;
 
 import com.google.common.base.Optional;
+import com.google.common.collect.ImmutableList;
 import com.google.common.collect.Maps;
 
 public class ImmutableMapNodeBuilder
@@ -69,7 +70,7 @@ public class ImmutableMapNodeBuilder
 
         ImmutableMapNode(final InstanceIdentifier.NodeIdentifier nodeIdentifier,
                          final Map<InstanceIdentifier.NodeIdentifierWithPredicates, MapEntryNode> children) {
-            super(nodeIdentifier, children.values());
+            super(nodeIdentifier, ImmutableList.copyOf(children.values()));
             this.mappedChildren = children;
         }
 
@@ -78,13 +79,5 @@ public class ImmutableMapNodeBuilder
             return Optional.fromNullable(mappedChildren.get(child));
         }
 
-        @Override
-        public String toString() {
-            final StringBuffer sb = new StringBuffer("ImmutableMapNode{");
-            sb.append("nodeIdentifier=").append(nodeIdentifier);
-            sb.append(", children=").append(mappedChildren);
-            sb.append('}');
-            return sb.toString();
-        }
     }
 }
index 8e0c1d32b05df344586819ba8a4a0e2ec110a25c..f3d8f31478cfba2e46c624e8527d098ae71afb1e 100644 (file)
@@ -7,16 +7,15 @@
  */
 package org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.valid;
 
-import com.google.common.base.Optional;
-import com.google.common.base.Preconditions;
+import java.util.Collection;
+import java.util.Collections;
+
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableAugmentationNodeSchemaAwareBuilder;
-import org.opendaylight.yangtools.yang.model.api.AugmentationSchema;
-import org.opendaylight.yangtools.yang.model.api.AugmentationTarget;
-import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
+import org.opendaylight.yangtools.yang.model.api.*;
 
-import java.util.Collection;
-import java.util.Collections;
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
 
 /**
  * General validator for container like statements, e.g. container, list-entry, choice, augment
@@ -40,9 +39,17 @@ public class DataNodeContainerValidator {
                     return true;
                 }
             }
-            // check regular child node
+            // check regular child node (also in child cases)
+        } else if(schema.getDataChildByName(child.getNodeType()) == null) {
+            for (DataSchemaNode dataSchemaNode : schema.getChildNodes()) {
+                if(dataSchemaNode instanceof ChoiceCaseNode) {
+                    if(((ChoiceCaseNode) dataSchemaNode).getDataChildByName(child.getNodeType()) != null) {
+                        return true;
+                    }
+                }
+            }
         } else {
-            return schema.getDataChildByName(child.getNodeType()) != null;
+            return true;
         }
 
         return false;
@@ -61,12 +68,12 @@ public class DataNodeContainerValidator {
     // FIXME, need to compare Set of QNames(AugmentationIdentifier) with Set of DataSchemaNodes(AugmentationSchema)
     // throw away set is created just to compare
     // Or if augmentationSchemaNode had a QName, we would just compare a QName
-    private boolean equalAugments(AugmentationSchema augmentationSchema, InstanceIdentifier.AugmentationIdentifier identifier) {
+    public static boolean equalAugments(AugmentationSchema augmentationSchema, InstanceIdentifier.AugmentationIdentifier identifier) {
         return identifier.getPossibleChildNames().equals(ImmutableAugmentationNodeSchemaAwareBuilder.getChildQNames(augmentationSchema));
     }
 
     public void validateChild(InstanceIdentifier.PathArgument child) {
-        Preconditions.checkArgument(isKnownChild(child), "Unknown child node: %s, does not belong to: %s", child.getNodeType(), schema);
+        Preconditions.checkArgument(isKnownChild(child), "Unknown child node: %s, does not belong to: %s", child, schema);
 
         // FIXME make a cache for augmentation child sets in constructor
         Optional<AugmentationSchema> augmentChild = isAugmentChild(child);
index f914484831b120066529ed6696c8a58e5f099081..2cac25dbb8412d9060da31d2f07b7e889e2a1e4c 100644 (file)
@@ -15,6 +15,7 @@ import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild;
 import org.opendaylight.yangtools.yang.data.api.schema.DataContainerNode;
 
 import com.google.common.base.Optional;
+import com.google.common.collect.ImmutableList;
 
 public abstract class AbstractImmutableDataContainerNode<K extends PathArgument> //
         extends AbstractImmutableNormalizedNode<K, Iterable<DataContainerChild<? extends PathArgument, ?>>> //
@@ -22,9 +23,10 @@ public abstract class AbstractImmutableDataContainerNode<K extends PathArgument>
 
     protected final Map<PathArgument, DataContainerChild<? extends PathArgument, ?>> children;
 
+
     public AbstractImmutableDataContainerNode(
             final Map<PathArgument, DataContainerChild<? extends PathArgument, ?>> children, final K nodeIdentifier) {
-        super(nodeIdentifier, children.values());
+        super(nodeIdentifier, ImmutableList.copyOf(children.values()));
         this.children = children;
     }
 
@@ -33,12 +35,4 @@ public abstract class AbstractImmutableDataContainerNode<K extends PathArgument>
         return Optional.<DataContainerChild<? extends PathArgument, ?>> fromNullable(children.get(child));
     }
 
-    @Override
-    public String toString() {
-        final StringBuffer sb = new StringBuffer("ImmutableContainerNode{");
-        sb.append("nodeIdentifier=").append(nodeIdentifier);
-        sb.append(", children=").append(children);
-        sb.append('}');
-        return sb.toString();
-    }
 }
index ceb20124c81f709faf28cf6c647fac50be52e464..96ff9e5f22676d49143a753712d95e2ae9080807 100644 (file)
@@ -13,13 +13,14 @@ import org.opendaylight.yangtools.yang.data.api.CompositeNode;
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
 
+import com.google.common.base.Objects;
 import com.google.common.base.Preconditions;
 
 public abstract class AbstractImmutableNormalizedNode<K extends InstanceIdentifier.PathArgument,V>
         implements NormalizedNode<K, V>, Immutable {
 
     protected final K nodeIdentifier;
-    protected V value;
+    protected final V value;
 
     protected AbstractImmutableNormalizedNode(K nodeIdentifier, V value) {
         this.nodeIdentifier = Preconditions.checkNotNull(nodeIdentifier, "nodeIdentifier");
@@ -27,41 +28,49 @@ public abstract class AbstractImmutableNormalizedNode<K extends InstanceIdentifi
     }
 
     @Override
-    public QName getNodeType() {
+    public final QName getNodeType() {
         return getIdentifier().getNodeType();
     }
 
     @Override
-    public K getIdentifier() {
+    public final K getIdentifier() {
         return nodeIdentifier;
     }
 
     @Override
-    public CompositeNode getParent() {
+    public final CompositeNode getParent() {
         throw new UnsupportedOperationException("Deprecated");
     }
 
     @Override
-    public QName getKey() {
+    public final QName getKey() {
         return getNodeType();
     }
 
     @Override
-    public V getValue() {
+    public final V getValue() {
         return value;
     }
 
     @Override
-    public V setValue(V value) {
+    public final V setValue(V value) {
         throw new UnsupportedOperationException("Immutable");
     }
 
+    @Override
+    public final String toString() {
+        return Objects.toStringHelper(this)
+                .add("nodeIdentifier", nodeIdentifier)
+                .add("value", value)
+                .toString();
+    }
+
     @Override
     public boolean equals(Object o) {
         if (this == o) return true;
         if (!(o instanceof AbstractImmutableNormalizedNode)) return false;
 
-        AbstractImmutableNormalizedNode that = (AbstractImmutableNormalizedNode) o;
+        AbstractImmutableNormalizedNode<?, ?> that = (AbstractImmutableNormalizedNode<?, ?>) o;
 
         if (!nodeIdentifier.equals(that.nodeIdentifier)) return false;
         if (!value.equals(that.value)) return false;
diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/FromNormalizedNodeSerializer.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/FromNormalizedNodeSerializer.java
new file mode 100644 (file)
index 0000000..58d666e
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2013 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.schema.transform;
+
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+
+/**
+ *
+ * Generic serializer for normalized nodes. NormalizedNodes can be serialized
+ * e.g. to Dom APIs.
+ *
+ * @param <E>
+ *            type of resulting/serialized element from NormalizedNode
+ * @param <N>
+ *            type of NormalizedNode to be serialized
+ * @param <S>
+ *            schema belonging to the type N of NormalizedNode
+ */
+public interface FromNormalizedNodeSerializer<E, N extends NormalizedNode<?, ?>, S> {
+
+    /**
+     *
+     * Serialize one node of type N as a list of E elements. If the serialization
+     * process creates only one E element as a result e.g. container node, the
+     * result element is expected to be wrapped in a list.
+     *
+     * @param schema
+     * @param node
+     * @return Serialized N node as a list of E elements
+     */
+    Iterable<E> serialize(S schema, N node);
+}
diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/ToNormalizedNodeParser.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/ToNormalizedNodeParser.java
new file mode 100644 (file)
index 0000000..25cd330
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2013 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.schema.transform;
+
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+
+/**
+ *
+ * Generic parser for normalized nodes. NormalizedNodes can be parsed
+ * e.g. from Dom APIs.
+ *
+ * @param <E>
+ *            type of element to be parsed into NormalizedNode
+ * @param <N>
+ *            type of NormalizedNode to be the result of parsing
+ * @param <S>
+ *            schema belonging to the type N of NormalizedNode
+ */
+public interface ToNormalizedNodeParser<E, N extends NormalizedNode<?, ?>, S> {
+
+    /**
+     *
+     * Parse a list of E elements as a NormalizedNode of type N. If the parsing
+     * process expects only one E element as input e.g. container node, the
+     * input element will be wrapped in a list.
+     *
+     * @param xmlDom
+     * @param schema
+     * @return NormalizedNode as a result of parsing list of E elements with schema S
+     */
+    N parse(Iterable<E> xmlDom, S schema);
+
+
+}
diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/AugmentationSchemaProxy.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/AugmentationSchemaProxy.java
new file mode 100644 (file)
index 0000000..726c40c
--- /dev/null
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2013 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.schema.transform.base;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import com.google.common.collect.Maps;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.model.api.*;
+
+/**
+ * Proxy for AugmentationSchema. Child node schemas are replaced with actual schemas from parent.
+ */
+public final class AugmentationSchemaProxy implements AugmentationSchema {
+    private final AugmentationSchema delegate;
+    private final Set<DataSchemaNode> realChildSchemas;
+    private final Map<QName, DataSchemaNode> mappedChildSchemas;
+
+    public AugmentationSchemaProxy(AugmentationSchema augmentSchema, Set<DataSchemaNode> realChildSchemas) {
+        this.delegate = augmentSchema;
+        this.realChildSchemas = realChildSchemas;
+
+        this.mappedChildSchemas = Maps.newHashMap();
+        for (DataSchemaNode realChildSchema : realChildSchemas) {
+            mappedChildSchemas.put(realChildSchema.getQName(), realChildSchema);
+        }
+    }
+
+    @Override
+    public RevisionAwareXPath getWhenCondition() {
+        return delegate.getWhenCondition();
+    }
+
+    @Override
+    public String getDescription() {
+        return delegate.getDescription();
+    }
+
+    @Override
+    public String getReference() {
+        return delegate.getReference();
+    }
+
+    @Override
+    public Status getStatus() {
+        return delegate.getStatus();
+    }
+
+    @Override
+    public SchemaPath getTargetPath() {
+        return delegate.getTargetPath();
+    }
+
+    @Override
+    public List<UnknownSchemaNode> getUnknownSchemaNodes() {
+        return delegate.getUnknownSchemaNodes();
+    }
+
+    @Override
+    public Set<TypeDefinition<?>> getTypeDefinitions() {
+        return delegate.getTypeDefinitions();
+    }
+
+    @Override
+    public Set<DataSchemaNode> getChildNodes() {
+        return realChildSchemas;
+    }
+
+    @Override
+    public Set<GroupingDefinition> getGroupings() {
+        return delegate.getGroupings();
+    }
+
+    @Override
+    public DataSchemaNode getDataChildByName(QName name) {
+        if(mappedChildSchemas.containsKey(name)) {
+            return mappedChildSchemas.get(name);
+        }
+
+        throw new IllegalArgumentException("Unknown child: " + name + " in: " + delegate);
+    }
+
+    @Override
+    public DataSchemaNode getDataChildByName(String name) {
+        // Unused
+        throw new UnsupportedOperationException("Unable to retrieve child node by name");
+    }
+
+    @Override
+    public Set<UsesNode> getUses() {
+        return delegate.getUses();
+    }
+}
diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/SchemaUtils.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/SchemaUtils.java
new file mode 100644 (file)
index 0000000..60cb076
--- /dev/null
@@ -0,0 +1,291 @@
+/*
+ * Copyright (c) 2013 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.schema.transform.base;
+
+import com.google.common.base.Function;
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import com.google.common.base.Predicate;
+import com.google.common.collect.Collections2;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
+import org.opendaylight.yangtools.yang.common.QName;
+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.Collections;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+public final class SchemaUtils {
+
+    private SchemaUtils() {
+    }
+
+    public static DataSchemaNode findSchemaForChild(DataNodeContainer schema, 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);
+        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) {
+        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) {
+        Optional<AugmentationSchema> schemaForAugment = Optional.absent();
+
+        for (ChoiceCaseNode choiceCaseNode : schema.getCases()) {
+            schemaForAugment = findAugment(choiceCaseNode, qNames);
+            if(schemaForAugment.isPresent()) {
+                break;
+            }
+        }
+
+        Preconditions.checkState(schemaForAugment.isPresent(), "Unknown augmentation node detected, identified by: %s, in: %s",
+                qNames, schema);
+        return schemaForAugment.get();
+    }
+
+    private static Optional<AugmentationSchema> findAugment(AugmentationTarget schema, 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) {
+                    return input.getQName();
+                }
+            }));
+
+            if(qNamesFromAugment.equals(qNames)) {
+                return Optional.of(augment);
+            }
+        }
+
+        return Optional.absent();
+    }
+
+    public static DataSchemaNode findSchemaForChild(ChoiceNode schema, QName childPartialQName) {
+        for (ChoiceCaseNode choiceCaseNode : schema.getCases()) {
+            Optional<DataSchemaNode> childSchema = XmlDocumentUtils.findFirstSchema(childPartialQName,
+                    choiceCaseNode.getChildNodes());
+            if (childSchema.isPresent()) {
+                return childSchema.get();
+            }
+        }
+
+
+        throw new IllegalStateException(String.format("Unknown child(ren) node(s) detected, identified by: %s, in: %s",
+                childPartialQName, schema));
+    }
+
+    /**
+     * Recursively find all child nodes that come from choices in augment.
+     *
+     * @return Map with all child nodes, to their most top augmentation
+     */
+    public static Map<QName,ChoiceNode> mapChildElementsFromChoicesInAugment(AugmentationSchema schema, Set<DataSchemaNode> realChildSchemas) {
+        Map<QName, ChoiceNode> mappedChoices = Maps.newLinkedHashMap();
+
+        for (DataSchemaNode realChildSchema : realChildSchemas) {
+            if(realChildSchema instanceof ChoiceNode)
+                mappedChoices.putAll(mapChildElementsFromChoices(schema, realChildSchemas));
+        }
+
+        return mappedChoices;
+    }
+
+    /**
+     * Recursively find all child nodes that come from choices.
+     *
+     * @return Map with all child nodes, to their most top augmentation
+     */
+    public static Map<QName, ChoiceNode> mapChildElementsFromChoices(DataNodeContainer schema) {
+        Set<DataSchemaNode> childNodes = schema.getChildNodes();
+
+        return mapChildElementsFromChoices(schema, childNodes);
+    }
+
+    private static Map<QName, ChoiceNode> mapChildElementsFromChoices(DataNodeContainer schema, Set<DataSchemaNode> childNodes) {
+        Map<QName, ChoiceNode> mappedChoices = Maps.newLinkedHashMap();
+
+        for (final DataSchemaNode childSchema : childNodes) {
+            if(childSchema instanceof ChoiceNode) {
+                for (ChoiceCaseNode choiceCaseNode : ((ChoiceNode) childSchema).getCases()) {
+
+                    for (QName qName : getChildNodes(choiceCaseNode)) {
+                        mappedChoices.put(qName, (ChoiceNode) childSchema);
+                    }
+                }
+            }
+        }
+
+        // Remove augmented choices
+        // TODO ineffective, mapping augments one more time is not necessary, the map could be injected
+        if(schema instanceof AugmentationTarget) {
+            final Map<QName, AugmentationSchema> augments = mapChildElementsFromAugments((AugmentationTarget) schema);
+
+            return Maps.filterKeys(mappedChoices, new Predicate<QName>() {
+                @Override
+                public boolean apply(QName input) {
+                    return augments.containsKey(input) == false;
+                }
+            });
+        }
+
+        return mappedChoices;
+    }
+
+    /**
+     * Recursively find all child nodes that come from augmentations.
+     *
+     * @return Map with all child nodes, to their most top augmentation
+     */
+    public static Map<QName, AugmentationSchema> mapChildElementsFromAugments(AugmentationTarget schema) {
+
+        Map<QName, AugmentationSchema> childNodesToAugmentation = Maps.newLinkedHashMap();
+
+        // Find QNames of augmented child nodes
+        Map<QName, AugmentationSchema> augments = Maps.newHashMap();
+        for (final AugmentationSchema augmentationSchema : schema.getAvailableAugmentations()) {
+            for (DataSchemaNode dataSchemaNode : augmentationSchema.getChildNodes()) {
+                augments.put(dataSchemaNode.getQName(), augmentationSchema);
+            }
+        }
+
+        // Augmented nodes have to be looked up directly in augmentationTarget
+        // because nodes from augment do not contain nodes from other augmentations
+        if (schema instanceof DataNodeContainer) {
+
+            for (DataSchemaNode child : ((DataNodeContainer) schema).getChildNodes()) {
+                // If is not augmented child, continue
+                if (augments.containsKey(child.getQName()) == false)
+                    continue;
+
+                AugmentationSchema mostTopAugmentation = augments.get(child.getQName());
+
+                // recursively add all child nodes in case of augment, case and choice
+                if (child instanceof AugmentationSchema || child instanceof ChoiceCaseNode) {
+                    for (QName qName : getChildNodes((DataNodeContainer) child)) {
+                        childNodesToAugmentation.put(qName, mostTopAugmentation);
+                    }
+                } else if (child instanceof ChoiceNode) {
+                    for (ChoiceCaseNode choiceCaseNode : ((ChoiceNode) child).getCases()) {
+                        for (QName qName : getChildNodes(choiceCaseNode)) {
+                            childNodesToAugmentation.put(qName, mostTopAugmentation);
+                        }
+                    }
+                } else {
+                    childNodesToAugmentation.put(child.getQName(), mostTopAugmentation);
+                }
+            }
+        }
+
+        // Choice Node has to map child nodes from all its cases
+        if (schema instanceof ChoiceNode) {
+            for (ChoiceCaseNode choiceCaseNode : ((ChoiceNode) schema).getCases()) {
+                if (augments.containsKey(choiceCaseNode.getQName()) == false) {
+                    continue;
+                }
+
+                for (QName qName : getChildNodes(choiceCaseNode)) {
+                    childNodesToAugmentation.put(qName, augments.get(choiceCaseNode.getQName()));
+                }
+            }
+        }
+
+        return childNodesToAugmentation;
+    }
+
+    /**
+     * Recursively list all child nodes.
+     *
+     * In case of choice, augment and cases, step in.
+     */
+    public static Set<QName> getChildNodes(DataNodeContainer nodeContainer) {
+        Set<QName> allChildNodes = Sets.newHashSet();
+
+        for (DataSchemaNode childSchema : nodeContainer.getChildNodes()) {
+            if(childSchema instanceof ChoiceNode) {
+                for (ChoiceCaseNode choiceCaseNode : ((ChoiceNode) childSchema).getCases()) {
+                    allChildNodes.addAll(getChildNodes(choiceCaseNode));
+                }
+            } else if(childSchema instanceof AugmentationSchema || childSchema instanceof ChoiceCaseNode) {
+                allChildNodes.addAll(getChildNodes((DataNodeContainer) childSchema));
+            }
+            else {
+                allChildNodes.add(childSchema.getQName());
+            }
+        }
+
+        return allChildNodes;
+    }
+
+    /**
+     * Retrieves real schemas for augmented child node.
+     *
+     * Schema of the same child node from augment, and directly from target is not the same.
+     * Schema of child node from augment is incomplete, therefore its useless for xml <-> normalizedNode translation.
+     *
+     */
+    public static Set<DataSchemaNode> getRealSchemasForAugment(AugmentationTarget targetSchema, AugmentationSchema augmentSchema) {
+        if(targetSchema.getAvailableAugmentations().contains(augmentSchema) == false) {
+            return Collections.emptySet();
+        }
+
+        Set<DataSchemaNode> realChildNodes = Sets.newHashSet();
+
+        if(targetSchema instanceof DataNodeContainer) {
+              realChildNodes = getRealSchemasForAugment((DataNodeContainer)targetSchema, augmentSchema);
+        } else if(targetSchema instanceof ChoiceNode) {
+            for (DataSchemaNode dataSchemaNode : augmentSchema.getChildNodes()) {
+                for (ChoiceCaseNode choiceCaseNode : ((ChoiceNode) targetSchema).getCases()) {
+                    if(getChildNodes(choiceCaseNode).contains(dataSchemaNode.getQName())) {
+                        realChildNodes.add(choiceCaseNode.getDataChildByName(dataSchemaNode.getQName()));
+                    }
+                }
+            }
+        }
+
+        return realChildNodes;
+    }
+
+    public static Set<DataSchemaNode> getRealSchemasForAugment(DataNodeContainer targetSchema,
+            AugmentationSchema augmentSchema) {
+        Set<DataSchemaNode> realChildNodes = Sets.newHashSet();
+        for (DataSchemaNode dataSchemaNode : augmentSchema.getChildNodes()) {
+            DataSchemaNode realChild = ((DataNodeContainer) targetSchema).getDataChildByName(dataSchemaNode.getQName());
+            realChildNodes.add(realChild);
+        }
+
+        return realChildNodes;
+    }
+
+    public static Optional<ChoiceCaseNode> detectCase(ChoiceNode schema, DataContainerChild<?, ?> child) {
+        for (ChoiceCaseNode choiceCaseNode : schema.getCases()) {
+            for (DataSchemaNode childFromCase : choiceCaseNode.getChildNodes()) {
+                if (childFromCase.getQName().equals(child.getNodeType())) {
+                    return Optional.of(choiceCaseNode);
+                }
+            }
+        }
+
+        return Optional.absent();
+    }
+}
diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/parser/AugmentationNodeBaseParser.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/parser/AugmentationNodeBaseParser.java
new file mode 100644 (file)
index 0000000..804f28c
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2013 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.schema.transform.base.parser;
+
+import java.util.Collections;
+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.impl.schema.Builders;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.SchemaUtils;
+import org.opendaylight.yangtools.yang.model.api.AugmentationSchema;
+import org.opendaylight.yangtools.yang.model.api.ChoiceNode;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+
+/**
+ * Abstract(base) parser for AugmentationNode, parses elements of type E.
+ *
+ * @param <E> type of elements to be parsed
+ */
+public abstract class AugmentationNodeBaseParser<E> extends
+        BaseDispatcherParser<E,AugmentationNode, AugmentationSchema> {
+
+    @Override
+    protected final DataContainerNodeBuilder<InstanceIdentifier.AugmentationIdentifier, AugmentationNode> getBuilder(AugmentationSchema schema) {
+        return Builders.augmentationBuilder(schema);
+    }
+
+    @Override
+    protected final Set<DataSchemaNode> getRealSchemasForAugment(AugmentationSchema schema, AugmentationSchema augmentSchema) {
+        return SchemaUtils.getRealSchemasForAugment(schema, augmentSchema);
+    }
+
+
+    @Override
+    protected final DataSchemaNode getSchemaForChild(AugmentationSchema schema, QName childQName) {
+        return SchemaUtils.findSchemaForChild(schema, childQName);
+    }
+
+    @Override
+    protected final Map<QName, ChoiceNode> mapChildElementsFromChoices(AugmentationSchema schema) {
+        return SchemaUtils.mapChildElementsFromChoices(schema);
+    }
+
+    @Override
+    protected final Map<QName, AugmentationSchema> mapChildElementsFromAugments(AugmentationSchema schema) {
+        return Collections.emptyMap();
+    }
+}
diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/parser/BaseDispatcherParser.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/parser/BaseDispatcherParser.java
new file mode 100644 (file)
index 0000000..e24a1f7
--- /dev/null
@@ -0,0 +1,159 @@
+/*
+ * Copyright (c) 2013 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.schema.transform.base.parser;
+
+import java.util.List;
+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.DataContainerChild;
+import org.opendaylight.yangtools.yang.data.api.schema.DataContainerNode;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.ToNormalizedNodeParser;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.AugmentationSchemaProxy;
+import org.opendaylight.yangtools.yang.model.api.AugmentationSchema;
+import org.opendaylight.yangtools.yang.model.api.ChoiceNode;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.LinkedListMultimap;
+
+/**
+ * Abstract(base) Parser for DataContainerNodes e.g. ContainerNode, AugmentationNode.
+ */
+public abstract class BaseDispatcherParser<E, N extends DataContainerNode<?>, S>
+        implements ToNormalizedNodeParser<E, N, S> {
+
+    /**
+     *
+     * @param schema
+     * @return New(empty) instance of a builder to build node identified by schema.
+     */
+    protected abstract DataContainerNodeBuilder<?, N> getBuilder(S schema);
+
+    /**
+     *
+     * @param schema
+     * @param childQName QName of a child being parsed, QName does not continue revision date
+     * @return schema object for child identified by parent schema: schema and QName childQName
+     */
+    protected abstract DataSchemaNode getSchemaForChild(S schema, QName childQName);
+
+    /**
+     *
+     * @param xml
+     * @return map from QName to child elements. Multiple elements are allowed under QName.
+     */
+    protected abstract LinkedListMultimap<QName, E> mapChildElements(Iterable<E> xml);
+
+    /**
+     *
+     * @param schema
+     * @return map from QName to ChoiceNode schema of child nodes that are
+     *         contained within a choice statement under current schema.
+     */
+    protected abstract Map<QName, ChoiceNode> mapChildElementsFromChoices(S schema);
+
+    /**
+     *
+     * @param schema
+     * @return map from QName to child elements that are added by augmentation
+     *         that targets current schema.
+     */
+    protected abstract Map<QName, AugmentationSchema> mapChildElementsFromAugments(S schema);
+
+    /**
+     *
+     * @param schema
+     * @param augmentSchema
+     * @return Set of real schema objects that represent child nodes of an
+     *         augmentation. Augmentation schema child nodes, if further
+     *         augmented, do not contain further augmented, that are crucial for
+     *         parsing. The real schema object can be retrieved from parent schema: schema.
+     */
+    protected abstract Set<DataSchemaNode> getRealSchemasForAugment(S schema, AugmentationSchema augmentSchema);
+
+    /**
+     *
+     * @return dispatcher object to dispatch parsing of child elements, might be
+     *         the same instance if provided parsers are immutable.
+     */
+    protected abstract NodeParserDispatcher<E> getDispatcher();
+
+    @Override
+    public N parse(Iterable<E> element, S schema) {
+
+        checkAtLeastOneNode(schema, element);
+
+        DataContainerNodeBuilder<?, N> containerBuilder = getBuilder(schema);
+
+        // Map child nodes to QName
+        LinkedListMultimap<QName, E> mappedChildElements = mapChildElements(element);
+
+        // Map child nodes from Augments
+        Map<QName, AugmentationSchema> mappedAugmentChildNodes = mapChildElementsFromAugments(schema);
+        LinkedListMultimap<AugmentationSchema, E> augmentsToElements = LinkedListMultimap.create();
+
+        // Map child nodes from choices
+        Map<QName, ChoiceNode> mappedChoiceChildNodes = mapChildElementsFromChoices(schema);
+        LinkedListMultimap<ChoiceNode, E> choicesToElements = LinkedListMultimap.create();
+
+        // process Child nodes
+        for (QName childPartialQName : mappedChildElements.keySet()) {
+            DataSchemaNode childSchema = getSchemaForChild(schema, childPartialQName);
+            List<E> childrenForQName = mappedChildElements.get(childPartialQName);
+
+            // Augment
+            if (isMarkedAs(mappedAugmentChildNodes, childSchema.getQName())) {
+                AugmentationSchema augmentationSchema = mappedAugmentChildNodes.get(childSchema.getQName());
+                augmentsToElements.putAll(augmentationSchema, childrenForQName);
+                // Choices
+            } else if (isMarkedAs(mappedChoiceChildNodes, childSchema.getQName())) {
+                ChoiceNode choiceSchema = mappedChoiceChildNodes.get(childSchema.getQName());
+                choicesToElements.putAll(choiceSchema, childrenForQName);
+                // Regular child nodes
+            } else {
+                DataContainerChild<? extends InstanceIdentifier.PathArgument, ?> builtChildNode = getDispatcher()
+                        .dispatchChildElement(childSchema, childrenForQName);
+                containerBuilder.withChild(builtChildNode);
+            }
+        }
+
+        // TODO ordering is not preserved for choice and augment elements
+        for (ChoiceNode choiceSchema : choicesToElements.keySet()) {
+            containerBuilder.withChild(getDispatcher().dispatchChildElement(choiceSchema,
+                    choicesToElements.get(choiceSchema)));
+        }
+
+        for (AugmentationSchema augmentSchema : augmentsToElements.keySet()) {
+            Set<DataSchemaNode> realChildSchemas = getRealSchemasForAugment(schema, augmentSchema);
+            AugmentationSchemaProxy augSchemaProxy = new AugmentationSchemaProxy(augmentSchema, realChildSchemas);
+            containerBuilder.withChild(getDispatcher().dispatchChildElement(augSchemaProxy, augmentsToElements.get(augmentSchema)));
+        }
+
+        return containerBuilder.build();
+    }
+
+    private boolean isMarkedAs(Map<QName, ?> mappedAugmentChildNodes, QName qName) {
+        return mappedAugmentChildNodes.containsKey(qName);
+    }
+
+    protected void checkOnlyOneNode(S schema, Iterable<E> childNodes) {
+        final int size = Iterables.size(childNodes);
+        Preconditions.checkArgument(size == 1,
+                "Node detected multiple times, should be 1, identified by: %s, found: %s", schema, childNodes);
+    }
+
+    private void checkAtLeastOneNode(S schema, Iterable<E> childNodes) {
+        Preconditions.checkArgument(Iterables.isEmpty(childNodes) == false,
+                "Node detected 0 times, should be at least 1, identified by: %s, found: %s", schema, childNodes);
+    }
+}
diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/parser/ChoiceNodeBaseParser.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/parser/ChoiceNodeBaseParser.java
new file mode 100644 (file)
index 0000000..021efc0
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2013 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.schema.transform.base.parser;
+
+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.ChoiceNode;
+import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.SchemaUtils;
+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.DataSchemaNode;
+
+import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
+
+/**
+ * Abstract(base) parser for ChoiceNodes, parses elements of type E.
+ *
+ * @param <E> type of elements to be parsed
+ */
+public abstract class ChoiceNodeBaseParser<E> extends
+        BaseDispatcherParser<E, ChoiceNode, org.opendaylight.yangtools.yang.model.api.ChoiceNode> {
+
+    @Override
+    protected final DataContainerNodeBuilder<InstanceIdentifier.NodeIdentifier, ChoiceNode> getBuilder(
+            org.opendaylight.yangtools.yang.model.api.ChoiceNode schema) {
+        return Builders.choiceBuilder(schema);
+    }
+
+    @Override
+    protected final Set<DataSchemaNode> getRealSchemasForAugment(org.opendaylight.yangtools.yang.model.api.ChoiceNode schema,
+            AugmentationSchema augmentSchema) {
+        Set<DataSchemaNode> fromAllCases = Sets.newHashSet();
+
+        fromAllCases.addAll(SchemaUtils.getRealSchemasForAugment(schema, augmentSchema));
+
+        for (ChoiceCaseNode choiceCaseNode : schema.getCases()) {
+            fromAllCases.addAll(SchemaUtils.getRealSchemasForAugment((AugmentationTarget) choiceCaseNode, augmentSchema));
+        }
+
+        return fromAllCases;
+    }
+
+    @Override
+    protected final DataSchemaNode getSchemaForChild(org.opendaylight.yangtools.yang.model.api.ChoiceNode schema,
+            QName childQName) {
+        return SchemaUtils.findSchemaForChild(schema, childQName);
+    }
+
+    @Override
+    protected final Map<QName, org.opendaylight.yangtools.yang.model.api.ChoiceNode> mapChildElementsFromChoices(
+            org.opendaylight.yangtools.yang.model.api.ChoiceNode schema) {
+        Map<QName, org.opendaylight.yangtools.yang.model.api.ChoiceNode> mappedChoices = Maps.newLinkedHashMap();
+
+        for (ChoiceCaseNode choiceCaseNode : schema.getCases()) {
+            mappedChoices.putAll(SchemaUtils.mapChildElementsFromChoices(choiceCaseNode));
+        }
+
+        return mappedChoices;
+    }
+
+    @Override
+    protected final Map<QName, AugmentationSchema> mapChildElementsFromAugments(
+            org.opendaylight.yangtools.yang.model.api.ChoiceNode schema) {
+        Map<QName, AugmentationSchema> mappedAugments = Maps.newLinkedHashMap();
+
+        for (ChoiceCaseNode choiceCaseNode : schema.getCases()) {
+            mappedAugments.putAll(SchemaUtils.mapChildElementsFromAugments(choiceCaseNode));
+        }
+        return mappedAugments;
+    }
+
+}
diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/parser/ContainerNodeBaseParser.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/parser/ContainerNodeBaseParser.java
new file mode 100644 (file)
index 0000000..f2c3350
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2013 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.schema.transform.base.parser;
+
+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.ContainerNode;
+import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.SchemaUtils;
+import org.opendaylight.yangtools.yang.model.api.AugmentationSchema;
+import org.opendaylight.yangtools.yang.model.api.AugmentationTarget;
+import org.opendaylight.yangtools.yang.model.api.ChoiceNode;
+import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+
+/**
+ * Abstract(base) parser for ContainerNodes, parses elements of type E.
+ *
+ * @param <E> type of elements to be parsed
+ */
+public abstract class ContainerNodeBaseParser<E> extends
+        BaseDispatcherParser<E, ContainerNode, ContainerSchemaNode> {
+
+    @Override
+    protected final DataContainerNodeBuilder<InstanceIdentifier.NodeIdentifier, ContainerNode> getBuilder(
+            ContainerSchemaNode schema) {
+        return Builders.containerBuilder(schema);
+    }
+
+    @Override
+    public final ContainerNode parse(Iterable<E> elements, ContainerSchemaNode schema) {
+        checkOnlyOneNode(schema, elements);
+        return super.parse(elements, schema);
+    }
+
+    @Override
+    protected final Set<DataSchemaNode> getRealSchemasForAugment(ContainerSchemaNode schema, AugmentationSchema augmentSchema) {
+        return SchemaUtils.getRealSchemasForAugment((AugmentationTarget) schema, augmentSchema);
+    }
+
+    @Override
+    protected final DataSchemaNode getSchemaForChild(ContainerSchemaNode schema, QName childQName) {
+        return SchemaUtils.findSchemaForChild(schema, childQName);
+    }
+
+    @Override
+    protected final Map<QName, ChoiceNode> mapChildElementsFromChoices(ContainerSchemaNode schema) {
+        return SchemaUtils.mapChildElementsFromChoices(schema);
+    }
+
+    @Override
+    protected final Map<QName, AugmentationSchema> mapChildElementsFromAugments(ContainerSchemaNode schema) {
+        return SchemaUtils.mapChildElementsFromAugments(schema);
+    }
+
+}
diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/parser/LeafNodeBaseParser.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/parser/LeafNodeBaseParser.java
new file mode 100644 (file)
index 0000000..8daef7f
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2013 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.schema.transform.base.parser;
+
+import org.opendaylight.yangtools.yang.data.api.schema.LeafNode;
+import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.ToNormalizedNodeParser;
+import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Iterables;
+
+/**
+ * Abstract(base) parser for LeafNodes, parses elements of type E.
+ *
+ * @param <E> type of elements to be parsed
+ */
+public abstract class LeafNodeBaseParser<E> implements
+        ToNormalizedNodeParser<E, LeafNode<?>, LeafSchemaNode> {
+
+    @Override
+    public final LeafNode<?> parse(Iterable<E> elements, LeafSchemaNode schema) {
+        final int size = Iterables.size(elements);
+        Preconditions.checkArgument(size == 1, "Elements mapped to leaf node illegal count: %s", size);
+        Object value = parseLeaf(elements.iterator().next(), schema);
+        return Builders.leafBuilder(schema).withValue(value).build();
+    }
+
+    /**
+     *
+     * Parse the inner value of a LeafNode from element of type E.
+     *
+     * @param element to be parsed
+     * @param schema schema for leaf
+     * @return parsed element as an Object
+     */
+    protected abstract Object parseLeaf(E element, LeafSchemaNode schema);
+}
diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/parser/LeafSetEntryNodeBaseParser.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/parser/LeafSetEntryNodeBaseParser.java
new file mode 100644 (file)
index 0000000..68e2b39
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2013 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.schema.transform.base.parser;
+
+import org.opendaylight.yangtools.yang.data.api.schema.LeafSetEntryNode;
+import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.ToNormalizedNodeParser;
+import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Iterables;
+
+/**
+ * Abstract(base) parser for LeafSetEntryNodes, parses elements of type E.
+ *
+ * @param <E> type of elements to be parsed
+ */
+public abstract class LeafSetEntryNodeBaseParser<E> implements
+        ToNormalizedNodeParser<E, LeafSetEntryNode<?>, LeafListSchemaNode> {
+
+    @Override
+    public final LeafSetEntryNode<Object> parse(Iterable<E> elements, LeafListSchemaNode schema) {
+        final int size = Iterables.size(elements);
+        Preconditions.checkArgument(size == 1, "Xml elements mapped to leaf node illegal count: %s", size);
+        Object value = parseLeafListEntry(elements.iterator().next(),schema);
+        return Builders.leafSetEntryBuilder(schema).withValue(value).build();
+    }
+
+    /**
+     *
+     * Parse the inner value of a LeafSetEntryNode from element of type E.
+     *
+     * @param element to be parsed
+     * @param schema schema for leaf-list
+     * @return parsed element as an Object
+     */
+    protected abstract Object parseLeafListEntry(E element, LeafListSchemaNode schema);
+}
diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/parser/LeafSetNodeBaseParser.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/parser/LeafSetNodeBaseParser.java
new file mode 100644 (file)
index 0000000..37ff5c9
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2013 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.schema.transform.base.parser;
+
+import java.util.Collections;
+
+import org.opendaylight.yangtools.yang.data.api.schema.LeafSetEntryNode;
+import org.opendaylight.yangtools.yang.data.api.schema.LeafSetNode;
+import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.ListNodeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.ToNormalizedNodeParser;
+import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
+
+/**
+ * Abstract(base) parser for LeafSetNodes, parses elements of type E.
+ *
+ * @param <E> type of elements to be parsed
+ */
+public abstract class LeafSetNodeBaseParser<E> implements
+        ToNormalizedNodeParser<E, LeafSetNode<?>, LeafListSchemaNode> {
+
+    @Override
+    public final LeafSetNode<?> parse(Iterable<E> childNodes, LeafListSchemaNode schema) {
+
+        ListNodeBuilder<Object, LeafSetEntryNode<Object>> leafListBuilder = Builders.leafSetBuilder(schema);
+        for (E childNode : childNodes) {
+            LeafSetEntryNode<?> builtChild = getLeafSetEntryNodeBaseParser().parse(
+                    Collections.singletonList(childNode), schema);
+
+            // TODO: can we get rid of this cast/SuppressWarnings somehow?
+            @SuppressWarnings("unchecked")
+            final LeafSetEntryNode<Object> child = (LeafSetEntryNode<Object>) builtChild;
+            leafListBuilder.withChild(child);
+        }
+
+        return leafListBuilder.build();
+    }
+
+    /**
+     *
+     * @return parser for inner LeafSetEntryNodes used to parse every entry of LeafSetNode, might be the same instance in case its immutable
+     */
+    protected abstract ToNormalizedNodeParser<E, LeafSetEntryNode<?>, LeafListSchemaNode> getLeafSetEntryNodeBaseParser();
+}
diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/parser/MapEntryNodeBaseParser.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/parser/MapEntryNodeBaseParser.java
new file mode 100644 (file)
index 0000000..cc59d77
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2013 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.schema.transform.base.parser;
+
+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.MapEntryNode;
+import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.SchemaUtils;
+import org.opendaylight.yangtools.yang.model.api.AugmentationSchema;
+import org.opendaylight.yangtools.yang.model.api.AugmentationTarget;
+import org.opendaylight.yangtools.yang.model.api.ChoiceNode;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
+
+/**
+ * Abstract(base) parser for MapEntryNodes, parses elements of type E.
+ *
+ * @param <E> type of elements to be parsed
+ */
+public abstract class MapEntryNodeBaseParser<E> extends BaseDispatcherParser<E, MapEntryNode, ListSchemaNode> {
+
+    @Override
+    protected final DataContainerNodeBuilder<InstanceIdentifier.NodeIdentifierWithPredicates, MapEntryNode> getBuilder(
+            ListSchemaNode schema) {
+        return Builders.mapEntryBuilder(schema);
+    }
+
+    @Override
+    public final MapEntryNode parse(Iterable<E> elements, ListSchemaNode schema) {
+        checkOnlyOneNode(schema, elements);
+        return super.parse(elements, schema);
+    }
+
+    @Override
+    protected final Set<DataSchemaNode> getRealSchemasForAugment(ListSchemaNode schema, AugmentationSchema augmentSchema) {
+        return SchemaUtils.getRealSchemasForAugment((AugmentationTarget) schema, augmentSchema);
+    }
+
+    @Override
+    protected final DataSchemaNode getSchemaForChild(ListSchemaNode schema, QName childQName) {
+        return SchemaUtils.findSchemaForChild(schema, childQName);
+    }
+
+    @Override
+    protected final Map<QName, ChoiceNode> mapChildElementsFromChoices(ListSchemaNode schema) {
+        return SchemaUtils.mapChildElementsFromChoices(schema);
+    }
+
+    @Override
+    protected final Map<QName, AugmentationSchema> mapChildElementsFromAugments(ListSchemaNode schema) {
+        return SchemaUtils.mapChildElementsFromAugments(schema);
+    }
+}
diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/parser/MapNodeBaseParser.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/parser/MapNodeBaseParser.java
new file mode 100644 (file)
index 0000000..11ec82c
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2013 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.schema.transform.base.parser;
+
+import java.util.Collections;
+
+import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
+import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
+import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.CollectionNodeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.ToNormalizedNodeParser;
+import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
+
+/**
+ * Abstract(base) parser for MapNodes, parses elements of type E.
+ *
+ * @param <E> type of elements to be parsed
+ */
+public abstract class MapNodeBaseParser<E> implements ToNormalizedNodeParser<E, MapNode, ListSchemaNode> {
+
+    @Override
+    public final MapNode parse(Iterable<E> childNodes, ListSchemaNode schema) {
+        CollectionNodeBuilder<MapEntryNode, MapNode> listBuilder = Builders.mapBuilder(schema);
+
+        for (E childNode : childNodes) {
+            MapEntryNode listChild = getMapEntryNodeDomParser().parse(Collections.singletonList(childNode), schema);
+            listBuilder.withChild(listChild);
+        }
+
+        return listBuilder.build();
+    }
+
+    /**
+     *
+     * @return parser for inner MapEntryNodes used to parse every entry of MapNode, might be the same instance in case its immutable
+     */
+    protected abstract ToNormalizedNodeParser<E, MapEntryNode, ListSchemaNode> getMapEntryNodeDomParser();
+
+}
diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/parser/NodeParserDispatcher.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/parser/NodeParserDispatcher.java
new file mode 100644 (file)
index 0000000..e18db0d
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2013 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.schema.transform.base.parser;
+
+import java.util.List;
+
+import org.opendaylight.yangtools.yang.data.api.schema.AugmentationNode;
+import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
+import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild;
+import org.opendaylight.yangtools.yang.data.api.schema.LeafNode;
+import org.opendaylight.yangtools.yang.data.api.schema.LeafSetNode;
+import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.ToNormalizedNodeParser;
+import org.opendaylight.yangtools.yang.model.api.AugmentationSchema;
+import org.opendaylight.yangtools.yang.model.api.ChoiceNode;
+import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
+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 com.google.common.base.Preconditions;
+
+/**
+ *
+ * Dispatches the parsing process of elements according to schema and returns the parsed Node.
+ *
+ * @param <E> type of elements parsed
+ */
+public interface NodeParserDispatcher<E> {
+
+    DataContainerChild<?, ?> dispatchChildElement(Object schema, List<E> childNodes);
+
+    /**
+     * Abstract implementation that implements the dispatch conditions. Only requires parsers to be provided.
+     * The same instance of parser can be provided in case it is immutable.
+     */
+    public static abstract class BaseNodeParserDispatcher<E> implements NodeParserDispatcher<E> {
+
+        @Override
+        public final DataContainerChild<?, ?> dispatchChildElement(Object schema, List<E> childNodes) {
+            Preconditions.checkArgument(childNodes.isEmpty() == false);
+
+            if (schema instanceof ContainerSchemaNode) {
+                return getContainerNodeParser().parse(childNodes, (ContainerSchemaNode) schema);
+            } else if (schema instanceof LeafSchemaNode) {
+                return getLeafNodeParser().parse(childNodes, (LeafSchemaNode) schema);
+            } else if (schema instanceof LeafListSchemaNode) {
+                return getLeafSetNodeParser().parse(childNodes, (LeafListSchemaNode) schema);
+            } else if (schema instanceof ListSchemaNode) {
+                return getMapNodeParser().parse(childNodes, (ListSchemaNode) schema);
+            } else if (schema instanceof ChoiceNode) {
+                return getChoiceNodeParser().parse(childNodes, (ChoiceNode) schema);
+            } else if (schema instanceof AugmentationSchema) {
+                return getAugmentationNodeParser().parse(childNodes, (AugmentationSchema) schema);
+            }
+
+            throw new IllegalArgumentException("Unable to parse node, unknown schema type: " + schema.getClass());
+        }
+
+        protected abstract ToNormalizedNodeParser<E, ContainerNode, ContainerSchemaNode> getContainerNodeParser();
+
+        protected abstract ToNormalizedNodeParser<E, LeafNode<?>, LeafSchemaNode> getLeafNodeParser();
+
+        protected abstract ToNormalizedNodeParser<E, LeafSetNode<?>, LeafListSchemaNode> getLeafSetNodeParser();
+
+        protected abstract ToNormalizedNodeParser<E, MapNode, ListSchemaNode> getMapNodeParser();
+
+        protected abstract ToNormalizedNodeParser<E, org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode, ChoiceNode> getChoiceNodeParser();
+
+        protected abstract ToNormalizedNodeParser<E, AugmentationNode, AugmentationSchema> getAugmentationNodeParser();
+
+    }
+}
diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/serializer/AugmentationNodeBaseSerializer.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/serializer/AugmentationNodeBaseSerializer.java
new file mode 100644 (file)
index 0000000..35dd342
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2013 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.schema.transform.base.serializer;
+
+import java.util.Set;
+
+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.schema.transform.base.SchemaUtils;
+import org.opendaylight.yangtools.yang.model.api.AugmentationSchema;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+
+/**
+ * Abstract(base) serializer for AugmentationNode, serializes elements of type E.
+ *
+ * @param <E> type of serialized elements
+ */
+public abstract class AugmentationNodeBaseSerializer<E> extends
+        BaseDispatcherSerializer<E, AugmentationNode, AugmentationSchema> {
+
+    @Override
+    protected Set<DataSchemaNode> getRealSchemasForAugment(AugmentationSchema schema, AugmentationSchema augmentationSchema) {
+        return SchemaUtils.getRealSchemasForAugment(schema, augmentationSchema);
+    }
+
+    @Override
+    protected DataSchemaNode getSchemaForChild(AugmentationSchema schema,
+                                               DataContainerChild<? extends InstanceIdentifier.PathArgument, ?> childNode) {
+        return SchemaUtils.findSchemaForChild(schema, childNode.getNodeType());
+    }
+
+    @Override
+    protected AugmentationSchema getAugmentedCase(AugmentationSchema schema, AugmentationNode augmentationNode) {
+        throw new UnsupportedOperationException("");
+    }
+
+}
diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/serializer/BaseDispatcherSerializer.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/serializer/BaseDispatcherSerializer.java
new file mode 100644 (file)
index 0000000..053520d
--- /dev/null
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2013 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.schema.transform.base.serializer;
+
+import java.util.List;
+import java.util.Set;
+
+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.api.schema.DataContainerNode;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.FromNormalizedNodeSerializer;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.AugmentationSchemaProxy;
+import org.opendaylight.yangtools.yang.model.api.AugmentationSchema;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Lists;
+
+/**
+ * Abstract(base) Serializer for DataContainerNodes e.g. ContainerNode, AugmentationNode.
+ */
+public abstract class BaseDispatcherSerializer<E, N extends DataContainerNode<?>, S> implements
+        FromNormalizedNodeSerializer<E, N, S> {
+
+    /**
+     *
+     * @param schema
+     * @param augmentationSchema
+     * @return Set of real schema objects that represent child nodes of an
+     *         augmentation. Augmentation schema child nodes, if further
+     *         augmented, do not contain further augmented, that are crucial for
+     *         parsing. The real schema object can be retrieved from parent schema: schema.
+     */
+    protected abstract Set<DataSchemaNode> getRealSchemasForAugment(S schema, AugmentationSchema augmentationSchema);
+
+    /**
+     *
+     * @param schema
+     * @param childNode
+     * @return Schema object associated with child node identified as: childNode.
+     *         Schema should be retrieved from parent schema: schema.
+     */
+    protected abstract DataSchemaNode getSchemaForChild(S schema,
+            DataContainerChild<? extends InstanceIdentifier.PathArgument, ?> childNode);
+
+    /**
+     *
+     * @param schema
+     * @param augmentationNode
+     * @return Schema object associated with augmentation child node identified as: augmentationNode.
+     *         Schema should be retrieved from parent schema: schema.
+     */
+    protected abstract AugmentationSchema getAugmentedCase(S schema, AugmentationNode augmentationNode);
+
+    /**
+     *
+     * @return Dispatcher object to dispatch serialization of child elements, might be
+     *         the same instance if provided serializers are immutable.
+     */
+    protected abstract NodeSerializerDispatcher<E> getNodeDispatcher();
+
+    @Override
+    public Iterable<E> serialize(S schema, N node) {
+        List<Iterable<E>> choiceChildren = Lists.newArrayList();
+
+        for (DataContainerChild<? extends InstanceIdentifier.PathArgument, ?> choiceChild : node.getValue()) {
+
+            Object childSchema;
+
+            if (choiceChild instanceof AugmentationNode) {
+
+                AugmentationSchema augSchema = getAugmentedCase(schema, (AugmentationNode) choiceChild);
+                Set<DataSchemaNode> realChildSchemas = getRealSchemasForAugment(schema, augSchema);
+                childSchema = new AugmentationSchemaProxy(augSchema, realChildSchemas);
+
+            } else {
+                childSchema = getSchemaForChild(schema, choiceChild);
+            }
+
+            Iterable<E> childElements = getNodeDispatcher().dispatchChildElement(childSchema, choiceChild);
+            choiceChildren.add(Preconditions.checkNotNull(childElements));
+        }
+
+        return Iterables.concat(choiceChildren);
+    }
+}
\ No newline at end of file
diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/serializer/ChoiceNodeBaseSerializer.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/serializer/ChoiceNodeBaseSerializer.java
new file mode 100644 (file)
index 0000000..af779b6
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2013 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.schema.transform.base.serializer;
+
+import java.util.Set;
+
+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.ChoiceNode;
+import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.SchemaUtils;
+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.DataSchemaNode;
+
+import com.google.common.collect.Sets;
+
+/**
+ * Abstract(base) serializer for ChoiceNodes, serializes elements of type E.
+ *
+ * @param <E> type of serialized elements
+ */
+public abstract class ChoiceNodeBaseSerializer<E>
+        extends
+        BaseDispatcherSerializer<E, ChoiceNode, org.opendaylight.yangtools.yang.model.api.ChoiceNode> {
+
+    @Override
+    protected final DataSchemaNode getSchemaForChild(org.opendaylight.yangtools.yang.model.api.ChoiceNode schema,
+            DataContainerChild<? extends InstanceIdentifier.PathArgument, ?> childNode) {
+        return SchemaUtils.findSchemaForChild(schema, childNode.getNodeType());
+    }
+
+    @Override
+    protected final AugmentationSchema getAugmentedCase(org.opendaylight.yangtools.yang.model.api.ChoiceNode schema,
+            AugmentationNode augmentationNode) {
+        return SchemaUtils.findSchemaForAugment(schema, augmentationNode.getIdentifier().getPossibleChildNames());
+    }
+
+    @Override
+    protected final Set<DataSchemaNode> getRealSchemasForAugment(org.opendaylight.yangtools.yang.model.api.ChoiceNode schema, AugmentationSchema augmentationSchema) {
+        Set<DataSchemaNode> aggregatedSchemas = Sets.newHashSet();
+
+        aggregatedSchemas.addAll(SchemaUtils.getRealSchemasForAugment(schema, augmentationSchema));
+
+        for (ChoiceCaseNode choiceCaseNode : schema.getCases()) {
+            aggregatedSchemas.addAll(SchemaUtils.getRealSchemasForAugment((AugmentationTarget) choiceCaseNode, augmentationSchema));
+        }
+
+        return aggregatedSchemas;
+    }
+}
\ No newline at end of file
diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/serializer/ContainerNodeBaseSerializer.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/serializer/ContainerNodeBaseSerializer.java
new file mode 100644 (file)
index 0000000..6d0b9f9
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2013 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.schema.transform.base.serializer;
+
+import java.util.Set;
+
+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.ContainerNode;
+import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.SchemaUtils;
+import org.opendaylight.yangtools.yang.model.api.AugmentationSchema;
+import org.opendaylight.yangtools.yang.model.api.AugmentationTarget;
+import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+
+/**
+ * Abstract(base) serializer for ContainerNodes, serializes elements of type E.
+ *
+ * @param <E> type of serialized elements
+ */
+public abstract class ContainerNodeBaseSerializer<E> extends
+        BaseDispatcherSerializer<E, ContainerNode, ContainerSchemaNode> {
+
+    @Override
+    protected final DataSchemaNode getSchemaForChild(ContainerSchemaNode schema,
+            DataContainerChild<? extends InstanceIdentifier.PathArgument, ?> childNode) {
+        return SchemaUtils.findSchemaForChild(schema, childNode.getNodeType());
+    }
+
+    @Override
+    protected final AugmentationSchema getAugmentedCase(ContainerSchemaNode schema, AugmentationNode augmentationNode) {
+        return SchemaUtils.findSchemaForAugment(schema, augmentationNode.getIdentifier().getPossibleChildNames());
+    }
+
+    @Override
+    protected final Set<DataSchemaNode> getRealSchemasForAugment(ContainerSchemaNode schema, AugmentationSchema augmentationSchema) {
+        return SchemaUtils.getRealSchemasForAugment((AugmentationTarget) schema, augmentationSchema);
+    }
+}
diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/serializer/LeafNodeBaseSerializer.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/serializer/LeafNodeBaseSerializer.java
new file mode 100644 (file)
index 0000000..2e13766
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2013 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.schema.transform.base.serializer;
+
+import java.util.Collections;
+
+import org.opendaylight.yangtools.yang.data.api.schema.LeafNode;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.FromNormalizedNodeSerializer;
+import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
+
+/**
+ * Abstract(base) serializer for LeafNodes, serializes elements of type E.
+ *
+ * @param <E> type of serialized elements
+ */
+public abstract class LeafNodeBaseSerializer<E> implements
+        FromNormalizedNodeSerializer<E, LeafNode<?>, LeafSchemaNode> {
+
+    @Override
+    public final Iterable<E> serialize(LeafSchemaNode schema, LeafNode<?> node) {
+        return Collections.singletonList(serializeLeaf(schema, node));
+    }
+
+    /**
+     *
+     * Serialize the inner value of a LeafNode into element of type E.
+     *
+     * @param node to be serialized
+     * @param schema schema for leaf
+     * @return serialized inner value as an Element
+     */
+    protected abstract E serializeLeaf(LeafSchemaNode schema, LeafNode<?> node);
+}
diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/serializer/LeafSetEntryNodeBaseSerializer.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/serializer/LeafSetEntryNodeBaseSerializer.java
new file mode 100644 (file)
index 0000000..f690590
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2013 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.schema.transform.base.serializer;
+
+import java.util.Collections;
+
+import org.opendaylight.yangtools.yang.data.api.schema.LeafSetEntryNode;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.FromNormalizedNodeSerializer;
+import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
+
+/**
+ * Abstract(base) serializer for LeafSetEntryNodes, serializes elements of type E.
+ *
+ * @param <E> type of serialized elements
+ */
+public abstract class LeafSetEntryNodeBaseSerializer<E> implements
+        FromNormalizedNodeSerializer<E, LeafSetEntryNode<?>, LeafListSchemaNode> {
+
+    @Override
+    public final Iterable<E> serialize(LeafListSchemaNode schema, LeafSetEntryNode<?> node) {
+        return Collections.singletonList(serializeLeaf(schema, node));
+    }
+
+    /**
+     *
+     * Serialize the inner value of a LeafSetEntryNode into element of type E.
+     *
+     * @param node to be serialized
+     * @param schema schema for leaf-list
+     * @return serialized inner value as an Element
+     */
+    protected abstract E serializeLeaf(LeafListSchemaNode schema, LeafSetEntryNode<?> node);
+}
diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/serializer/LeafSetNodeBaseSerializer.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/serializer/LeafSetNodeBaseSerializer.java
new file mode 100644 (file)
index 0000000..302ffbb
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2013 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.schema.transform.base.serializer;
+
+import org.opendaylight.yangtools.yang.data.api.schema.LeafSetEntryNode;
+import org.opendaylight.yangtools.yang.data.api.schema.LeafSetNode;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.FromNormalizedNodeSerializer;
+import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
+
+import com.google.common.base.Function;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Iterables;
+
+/**
+ * Abstract(base) serializer for LeafSetNodes, serializes elements of type E.
+ *
+ * @param <E> type of serialized elements
+ */
+public abstract class LeafSetNodeBaseSerializer<E> implements
+        FromNormalizedNodeSerializer<E, LeafSetNode<?>, LeafListSchemaNode> {
+
+    @Override
+    public final Iterable<E> serialize(final LeafListSchemaNode schema, final LeafSetNode<?> node) {
+        return Iterables.concat(Iterables.transform(node.getValue(), new Function<LeafSetEntryNode<?>, Iterable<E>>() {
+            @Override
+            public Iterable<E> apply(final LeafSetEntryNode<?> input) {
+                final Iterable<E> serializedChild = getLeafSetEntryNodeSerializer().serialize(schema, input);
+                final int size = Iterables.size(serializedChild);
+                Preconditions.checkState(size == 1,
+                        "Unexpected count of elements for leaf-list entry serialized from: %s, should be 1, was: %s",
+                        input, size);
+                return serializedChild;
+            }
+        }));
+    }
+
+    /**
+     *
+     * @return serializer for inner LeafSetEntryNodes used to serialize every entry of LeafSetNode, might be the same instance in case its immutable
+     */
+    protected abstract FromNormalizedNodeSerializer<E, LeafSetEntryNode<?>, LeafListSchemaNode> getLeafSetEntryNodeSerializer();
+}
diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/serializer/MapEntryNodeBaseSerializer.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/serializer/MapEntryNodeBaseSerializer.java
new file mode 100644 (file)
index 0000000..2f7822a
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2013 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.schema.transform.base.serializer;
+
+import java.util.Set;
+
+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.api.schema.MapEntryNode;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.SchemaUtils;
+import org.opendaylight.yangtools.yang.model.api.AugmentationSchema;
+import org.opendaylight.yangtools.yang.model.api.AugmentationTarget;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
+
+/**
+ * Abstract(base) serializer for MapEntryNodes, serializes elements of type E.
+ *
+ * @param <E> type of serialized elements
+ */
+public abstract class MapEntryNodeBaseSerializer<E> extends
+        BaseDispatcherSerializer<E, MapEntryNode, ListSchemaNode> {
+
+    @Override
+    protected final DataSchemaNode getSchemaForChild(ListSchemaNode schema,
+                                               DataContainerChild<? extends InstanceIdentifier.PathArgument, ?> childNode) {
+        return SchemaUtils.findSchemaForChild(schema, childNode.getNodeType());
+    }
+
+    @Override
+    protected final AugmentationSchema getAugmentedCase(ListSchemaNode schema, AugmentationNode augmentationNode) {
+        return SchemaUtils.findSchemaForAugment(schema, augmentationNode.getIdentifier().getPossibleChildNames());
+    }
+
+    @Override
+    protected final Set<DataSchemaNode> getRealSchemasForAugment(ListSchemaNode schema, AugmentationSchema augmentationSchema) {
+        return SchemaUtils.getRealSchemasForAugment((AugmentationTarget) schema, augmentationSchema);
+    }
+
+}
diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/serializer/MapNodeBaseSerializer.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/serializer/MapNodeBaseSerializer.java
new file mode 100644 (file)
index 0000000..dba2c5d
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2013 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.schema.transform.base.serializer;
+
+import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
+import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.FromNormalizedNodeSerializer;
+import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
+
+import com.google.common.base.Function;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Iterables;
+
+/**
+ * Abstract(base) serializer for MapNodes, serializes elements of type E.
+ *
+ * @param <E> type of serialized elements
+ */
+public abstract class MapNodeBaseSerializer<E> implements FromNormalizedNodeSerializer<E, MapNode, ListSchemaNode> {
+
+    @Override
+    public final Iterable<E> serialize(final ListSchemaNode schema, final MapNode node) {
+        return Iterables.concat(Iterables.transform(node.getValue(), new Function<MapEntryNode, Iterable<E>>() {
+            @Override
+            public Iterable<E> apply(MapEntryNode input) {
+                final Iterable<E> serializedChild = getMapEntryNodeDomSerializer().serialize(schema, input);
+                final int size = Iterables.size(serializedChild);
+
+                Preconditions.checkState(size == 1,
+                        "Unexpected count of entries  for list serialized from: %s, should be 1, was: %s",
+                        input, size);
+                return serializedChild;
+            }
+        }));
+    }
+
+    /**
+     *
+     * @return serializer for inner MapEntryNodes used to serialize every entry of MapNode, might be the same instance in case its immutable
+     */
+    protected abstract FromNormalizedNodeSerializer<E, MapEntryNode, ListSchemaNode> getMapEntryNodeDomSerializer();
+}
diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/serializer/NodeSerializerDispatcher.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/serializer/NodeSerializerDispatcher.java
new file mode 100644 (file)
index 0000000..e19b625
--- /dev/null
@@ -0,0 +1,142 @@
+/*
+ * Copyright (c) 2013 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.schema.transform.base.serializer;
+
+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.ChoiceNode;
+import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
+import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild;
+import org.opendaylight.yangtools.yang.data.api.schema.LeafNode;
+import org.opendaylight.yangtools.yang.data.api.schema.LeafSetNode;
+import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
+import org.opendaylight.yangtools.yang.data.api.schema.MixinNode;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.FromNormalizedNodeSerializer;
+import org.opendaylight.yangtools.yang.model.api.AugmentationSchema;
+import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
+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 com.google.common.base.Preconditions;
+import com.google.common.collect.Iterables;
+
+/**
+ *
+ * Dispatches the serialization process of nodes according to schema and returns the serialized elements.
+ *
+ * @param <E> type of serialized elements
+ */
+public interface NodeSerializerDispatcher<E> {
+
+    Iterable<E> dispatchChildElement(Object childSchema,
+            DataContainerChild<? extends InstanceIdentifier.PathArgument, ?> dataContainerChild);
+
+    /**
+     * Abstract implementation that implements the dispatch conditions. Only requires serializers to be provided.
+     * The same instance of serializer can be provided in case it is immutable.
+     */
+    public static abstract class BaseNodeSerializerDispatcher<E> implements NodeSerializerDispatcher<E> {
+
+        @Override
+        public final Iterable<E> dispatchChildElement(Object childSchema,
+                DataContainerChild<? extends InstanceIdentifier.PathArgument, ?> dataContainerChild) {
+            if (dataContainerChild instanceof ContainerNode) {
+                return onContainerNode(childSchema, dataContainerChild);
+            } else if (dataContainerChild instanceof LeafNode<?>) {
+                return onLeafNode(childSchema, dataContainerChild);
+            } else if (dataContainerChild instanceof MixinNode) {
+                if (dataContainerChild instanceof LeafSetNode<?>) {
+                    return onLeafListNode(childSchema, dataContainerChild);
+                } else if (dataContainerChild instanceof MapNode) {
+                    return onListNode(childSchema, dataContainerChild);
+                } else if (dataContainerChild instanceof ChoiceNode) {
+                    return onChoiceNode(childSchema, dataContainerChild);
+                } else if (dataContainerChild instanceof AugmentationNode) {
+                    return onAugmentationSchema(childSchema, dataContainerChild);
+                }
+            }
+            throw new IllegalArgumentException("Unable to serialize " + childSchema);
+        }
+
+        private Iterable<E> onAugmentationSchema(Object childSchema,
+                DataContainerChild<? extends InstanceIdentifier.PathArgument, ?> dataContainerChild) {
+            checkSchemaCompatibility(childSchema, AugmentationSchema.class, dataContainerChild);
+            return getAugmentationNodeSerializer().serialize((AugmentationSchema) childSchema,
+                    (AugmentationNode) dataContainerChild);
+        }
+
+        private Iterable<E> onChoiceNode(Object childSchema,
+                DataContainerChild<? extends InstanceIdentifier.PathArgument, ?> dataContainerChild) {
+            checkSchemaCompatibility(childSchema, org.opendaylight.yangtools.yang.model.api.ChoiceNode.class,
+                    dataContainerChild);
+            return getChoiceNodeSerializer()
+                    .serialize((org.opendaylight.yangtools.yang.model.api.ChoiceNode) childSchema,
+                            (ChoiceNode) dataContainerChild);
+        }
+
+        private Iterable<E> onListNode(Object childSchema,
+                DataContainerChild<? extends InstanceIdentifier.PathArgument, ?> dataContainerChild) {
+            checkSchemaCompatibility(childSchema, ListSchemaNode.class, dataContainerChild);
+            return getMapNodeSerializer().serialize((ListSchemaNode) childSchema, (MapNode) dataContainerChild);
+        }
+
+        private Iterable<E> onLeafListNode(Object childSchema,
+                DataContainerChild<? extends InstanceIdentifier.PathArgument, ?> dataContainerChild) {
+            checkSchemaCompatibility(childSchema, LeafListSchemaNode.class, dataContainerChild);
+            return getLeafSetNodeSerializer().serialize((LeafListSchemaNode) childSchema,
+                    (LeafSetNode<?>) dataContainerChild);
+        }
+
+        private Iterable<E> onLeafNode(Object childSchema,
+                DataContainerChild<? extends InstanceIdentifier.PathArgument, ?> dataContainerChild) {
+            checkSchemaCompatibility(childSchema, LeafSchemaNode.class, dataContainerChild);
+            Iterable<E> elements = getLeafNodeSerializer().serialize((LeafSchemaNode) childSchema,
+                    (LeafNode<?>) dataContainerChild);
+            checkOnlyOneSerializedElement(elements, dataContainerChild);
+            return elements;
+        }
+
+        private static void checkOnlyOneSerializedElement(Iterable<?> elements,
+                DataContainerChild<? extends InstanceIdentifier.PathArgument, ?> dataContainerChild) {
+            final int size = Iterables.size(elements);
+            Preconditions.checkArgument(size == 1,
+                    "Unexpected count of elements for entry serialized from: %s, should be 1, was: %s",
+                    dataContainerChild, size);
+        }
+
+        private Iterable<E> onContainerNode(Object childSchema,
+                DataContainerChild<? extends InstanceIdentifier.PathArgument, ?> dataContainerChild) {
+            checkSchemaCompatibility(childSchema, ContainerSchemaNode.class, dataContainerChild);
+
+            Iterable<E> elements = getContainerNodeSerializer().serialize((ContainerSchemaNode) childSchema,
+                    (ContainerNode) dataContainerChild);
+            checkOnlyOneSerializedElement(elements, dataContainerChild);
+            return elements;
+        }
+
+        private static void checkSchemaCompatibility(Object childSchema, Class<?> containerSchemaNodeClass,
+                DataContainerChild<? extends InstanceIdentifier.PathArgument, ?> dataContainerChild) {
+            Preconditions.checkArgument(containerSchemaNodeClass.isAssignableFrom(childSchema.getClass()),
+                    "Incompatible schema: %s with node: %s, expected: %s", childSchema, dataContainerChild,
+                    containerSchemaNodeClass);
+        }
+
+        protected abstract FromNormalizedNodeSerializer<E, ContainerNode, ContainerSchemaNode> getContainerNodeSerializer();
+
+        protected abstract FromNormalizedNodeSerializer<E, LeafNode<?>, LeafSchemaNode> getLeafNodeSerializer();
+
+        protected abstract FromNormalizedNodeSerializer<E, LeafSetNode<?>, LeafListSchemaNode> getLeafSetNodeSerializer();
+
+        protected abstract FromNormalizedNodeSerializer<E, MapNode, ListSchemaNode> getMapNodeSerializer();
+
+        protected abstract FromNormalizedNodeSerializer<E, org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode, org.opendaylight.yangtools.yang.model.api.ChoiceNode> getChoiceNodeSerializer();
+
+        protected abstract FromNormalizedNodeSerializer<E, AugmentationNode, AugmentationSchema> getAugmentationNodeSerializer();
+    }
+}
diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/DomUtils.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/DomUtils.java
new file mode 100644 (file)
index 0000000..b8a893e
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2013 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.schema.transform.dom;
+
+import java.util.List;
+
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.impl.codec.TypeDefinitionAwareCodec;
+import org.opendaylight.yangtools.yang.data.impl.codec.xml.XmlCodecProvider;
+import org.opendaylight.yangtools.yang.data.impl.codec.xml.XmlDocumentUtils;
+import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
+import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
+
+import com.google.common.collect.LinkedListMultimap;
+import com.google.common.collect.Lists;
+
+public class DomUtils {
+
+    private DomUtils() {
+    }
+
+    private static final XmlCodecProvider DEFAULT_XML_VALUE_CODEC_PROVIDER = new XmlCodecProvider() {
+
+        @Override
+        public TypeDefinitionAwareCodec<Object, ? extends TypeDefinition<?>> codecFor(TypeDefinition<?> baseType) {
+            return TypeDefinitionAwareCodec.from(baseType);
+        }
+    };
+
+    public static XmlCodecProvider defaultValueCodecProvider() {
+        return DEFAULT_XML_VALUE_CODEC_PROVIDER;
+    }
+
+    public static Object parseXmlValue(Element xml, XmlCodecProvider codecProvider, TypeDefinition<?> type) {
+        TypeDefinitionAwareCodec<Object, ? extends TypeDefinition<?>> codec = codecProvider.codecFor(type);
+
+        String text = xml.getTextContent();
+        text = text.trim();
+
+        Object value;
+        if (codec != null) {
+            value = codec.deserialize(text);
+        } else {
+            value = text;
+        }
+
+        return value;
+    }
+
+    public static void serializeXmlValue(Element itemEl, TypeDefinition<? extends TypeDefinition<?>> type, XmlCodecProvider codecProvider, Object value) {
+        XmlDocumentUtils.writeValueByType(itemEl, type, codecProvider, value);
+    }
+
+    public static LinkedListMultimap<QName, Element> mapChildElementsForSingletonNode(Element node) {
+        List<Element> childNodesCollection = Lists.newArrayList();
+        NodeList childNodes = node.getChildNodes();
+        for (int i = 0; i < childNodes.getLength(); i++) {
+            if(childNodes.item(i) instanceof Element) {
+                childNodesCollection.add((Element) childNodes.item(i));
+            }
+        }
+
+        return mapChildElements(childNodesCollection);
+    }
+
+    public static LinkedListMultimap<QName, Element> mapChildElements(Iterable<Element> childNodesCollection) {
+        LinkedListMultimap<QName, Element> mappedChildElements = LinkedListMultimap.create();
+
+        for (Element element : childNodesCollection) {
+            QName childQName = XmlDocumentUtils.qNameFromElement(element);
+            mappedChildElements.put(childQName, element);
+        }
+
+        return mappedChildElements;
+    }
+
+
+}
diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/parser/AugmentationNodeDomParser.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/parser/AugmentationNodeDomParser.java
new file mode 100644 (file)
index 0000000..0b351f1
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2013 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.schema.transform.dom.parser;
+
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.impl.codec.xml.XmlCodecProvider;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.parser.AugmentationNodeBaseParser;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.parser.NodeParserDispatcher;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.dom.DomUtils;
+import org.w3c.dom.Element;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.LinkedListMultimap;
+
+public final class AugmentationNodeDomParser extends AugmentationNodeBaseParser<Element> {
+
+    private final XmlCodecProvider codecProvider;
+
+    public AugmentationNodeDomParser(XmlCodecProvider codecProvider) {
+        this.codecProvider = Preconditions.checkNotNull(codecProvider);
+    }
+
+    @Override
+    protected LinkedListMultimap<QName, Element> mapChildElements(Iterable<Element> elements) {
+        return DomUtils.mapChildElements(elements);
+    }
+
+    @Override
+    protected NodeParserDispatcher<Element> getDispatcher() {
+        return DomNodeDispatcher.getInstance(codecProvider);
+    }
+
+}
diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/parser/ChoiceNodeDomParser.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/parser/ChoiceNodeDomParser.java
new file mode 100644 (file)
index 0000000..5e07720
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2013 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.schema.transform.dom.parser;
+
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.impl.codec.xml.XmlCodecProvider;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.parser.ChoiceNodeBaseParser;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.parser.NodeParserDispatcher;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.dom.DomUtils;
+import org.w3c.dom.Element;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.LinkedListMultimap;
+
+public final class ChoiceNodeDomParser extends ChoiceNodeBaseParser<Element> {
+
+    private final XmlCodecProvider codecProvider;
+
+    public ChoiceNodeDomParser(XmlCodecProvider codecProvider) {
+        this.codecProvider = Preconditions.checkNotNull(codecProvider);
+    }
+
+    @Override
+    protected LinkedListMultimap<QName, Element> mapChildElements(Iterable<Element> xml) {
+        return DomUtils.mapChildElements(xml);
+    }
+
+    @Override
+    protected NodeParserDispatcher<Element> getDispatcher() {
+        return DomNodeDispatcher.getInstance(codecProvider);
+    }
+
+}
diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/parser/ContainerNodeDomParser.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/parser/ContainerNodeDomParser.java
new file mode 100644 (file)
index 0000000..cb31015
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2013 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.schema.transform.dom.parser;
+
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.impl.codec.xml.XmlCodecProvider;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.parser.ContainerNodeBaseParser;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.parser.NodeParserDispatcher;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.dom.DomUtils;
+import org.w3c.dom.Element;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.LinkedListMultimap;
+
+public final class ContainerNodeDomParser extends ContainerNodeBaseParser<Element> {
+
+    private final XmlCodecProvider codecProvider;
+
+    public ContainerNodeDomParser(XmlCodecProvider codecProvider) {
+        this.codecProvider = Preconditions.checkNotNull(codecProvider);
+    }
+
+    @Override
+    protected NodeParserDispatcher<Element> getDispatcher() {
+        return DomNodeDispatcher.getInstance(codecProvider);
+    }
+
+    @Override
+    protected LinkedListMultimap<QName, Element> mapChildElements(Iterable<Element> elements) {
+        return DomUtils.mapChildElementsForSingletonNode(elements.iterator().next());
+    }
+
+}
diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/parser/DomNodeDispatcher.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/parser/DomNodeDispatcher.java
new file mode 100644 (file)
index 0000000..ae725f5
--- /dev/null
@@ -0,0 +1,67 @@
+package org.opendaylight.yangtools.yang.data.impl.schema.transform.dom.parser;
+
+import org.opendaylight.yangtools.yang.data.api.schema.*;
+import org.opendaylight.yangtools.yang.data.impl.codec.xml.XmlCodecProvider;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.ToNormalizedNodeParser;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.parser.NodeParserDispatcher;
+import org.opendaylight.yangtools.yang.model.api.*;
+import org.opendaylight.yangtools.yang.model.api.ChoiceNode;
+import org.w3c.dom.Element;
+
+public class DomNodeDispatcher extends NodeParserDispatcher.BaseNodeParserDispatcher<Element> {
+
+        private final ContainerNodeDomParser containerNodeDomParser;
+        private final LeafNodeDomParser leafNodeDomParser;
+        private final LeafSetNodeDomParser leafSetNodeDomParser;
+        private final MapNodeDomParser mapNodeDomParser;
+        private final ChoiceNodeDomParser choiceNodeDomParser;
+        private final AugmentationNodeDomParser augmentationNodeDomParser;
+
+        private static DomNodeDispatcher instance = null;
+
+        private DomNodeDispatcher(XmlCodecProvider codecProvider) {
+            leafNodeDomParser = new LeafNodeDomParser(codecProvider);
+            containerNodeDomParser = new ContainerNodeDomParser(codecProvider);
+            leafSetNodeDomParser = new LeafSetNodeDomParser(new LeafSetEntryNodeDomParser(codecProvider));
+            mapNodeDomParser = new MapNodeDomParser(new MapEntryNodeDomParser(codecProvider));
+            choiceNodeDomParser = new ChoiceNodeDomParser(codecProvider);
+            augmentationNodeDomParser = new AugmentationNodeDomParser(codecProvider);
+        }
+
+        @Override
+        protected ToNormalizedNodeParser<Element, ContainerNode, ContainerSchemaNode> getContainerNodeParser() {
+            return containerNodeDomParser;
+        }
+
+        @Override
+        protected ToNormalizedNodeParser<Element, LeafNode<?>, LeafSchemaNode> getLeafNodeParser() {
+            return leafNodeDomParser;
+        }
+
+        @Override
+        protected ToNormalizedNodeParser<Element, LeafSetNode<?>, LeafListSchemaNode> getLeafSetNodeParser() {
+            return leafSetNodeDomParser;
+        }
+
+        @Override
+        protected ToNormalizedNodeParser<Element, MapNode, ListSchemaNode> getMapNodeParser() {
+            return mapNodeDomParser;
+        }
+
+        @Override
+        protected ToNormalizedNodeParser<Element, org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode, ChoiceNode> getChoiceNodeParser() {
+            return choiceNodeDomParser;
+        }
+
+        @Override
+        protected ToNormalizedNodeParser<Element, AugmentationNode, AugmentationSchema> getAugmentationNodeParser() {
+            return augmentationNodeDomParser;
+        }
+
+        public static NodeParserDispatcher<Element> getInstance(XmlCodecProvider codecProvider) {
+            if (instance == null) {
+                instance = new DomNodeDispatcher(codecProvider);
+            }
+            return instance;
+        }
+}
diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/parser/LeafNodeDomParser.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/parser/LeafNodeDomParser.java
new file mode 100644 (file)
index 0000000..723bc81
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2013 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.schema.transform.dom.parser;
+
+import com.google.common.base.Preconditions;
+import org.opendaylight.yangtools.yang.data.impl.codec.xml.XmlCodecProvider;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.parser.LeafNodeBaseParser;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.dom.DomUtils;
+import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
+import org.w3c.dom.Element;
+
+public class LeafNodeDomParser extends LeafNodeBaseParser<Element> {
+
+    private final XmlCodecProvider codecProvider;
+
+    public LeafNodeDomParser(XmlCodecProvider codecProvider) {
+        this.codecProvider = Preconditions.checkNotNull(codecProvider);
+    }
+
+    @Override
+    protected Object parseLeaf(Element xmlElement, LeafSchemaNode schema) {
+        return DomUtils.parseXmlValue(xmlElement, codecProvider, schema.getType());
+    }
+}
diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/parser/LeafSetEntryNodeDomParser.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/parser/LeafSetEntryNodeDomParser.java
new file mode 100644 (file)
index 0000000..b048049
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2013 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.schema.transform.dom.parser;
+
+import com.google.common.base.Preconditions;
+import org.opendaylight.yangtools.yang.data.impl.codec.xml.XmlCodecProvider;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.parser.LeafSetEntryNodeBaseParser;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.dom.DomUtils;
+import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
+import org.w3c.dom.Element;
+
+public class LeafSetEntryNodeDomParser extends LeafSetEntryNodeBaseParser<Element> {
+
+    private final XmlCodecProvider codecProvider;
+
+    public LeafSetEntryNodeDomParser(XmlCodecProvider codecProvider) {
+        this.codecProvider = Preconditions.checkNotNull(codecProvider);
+    }
+
+    @Override
+    protected Object parseLeafListEntry(Element xmlElement, LeafListSchemaNode schema) {
+        return DomUtils.parseXmlValue(xmlElement, codecProvider, schema.getType());
+    }
+}
diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/parser/LeafSetNodeDomParser.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/parser/LeafSetNodeDomParser.java
new file mode 100644 (file)
index 0000000..8a771aa
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2013 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.schema.transform.dom.parser;
+
+import org.opendaylight.yangtools.yang.data.api.schema.LeafSetEntryNode;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.ToNormalizedNodeParser;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.parser.LeafSetNodeBaseParser;
+import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
+import org.w3c.dom.Element;
+
+public class LeafSetNodeDomParser extends LeafSetNodeBaseParser<Element> {
+
+    private final LeafSetEntryNodeDomParser leafSetEntryNodeBaseParser;
+
+    public LeafSetNodeDomParser(LeafSetEntryNodeDomParser leafSetEntryNodeBaseParser) {
+        this.leafSetEntryNodeBaseParser = leafSetEntryNodeBaseParser;
+    }
+
+    @Override
+    protected ToNormalizedNodeParser<Element, LeafSetEntryNode<?>, LeafListSchemaNode> getLeafSetEntryNodeBaseParser() {
+        return leafSetEntryNodeBaseParser;
+    }
+}
diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/parser/MapEntryNodeDomParser.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/parser/MapEntryNodeDomParser.java
new file mode 100644 (file)
index 0000000..b521760
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2013 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.schema.transform.dom.parser;
+
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.impl.codec.xml.XmlCodecProvider;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.parser.MapEntryNodeBaseParser;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.parser.NodeParserDispatcher;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.dom.DomUtils;
+import org.w3c.dom.Element;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.LinkedListMultimap;
+
+public final class MapEntryNodeDomParser extends MapEntryNodeBaseParser<Element> {
+
+    private final XmlCodecProvider codecProvider;
+
+    public MapEntryNodeDomParser(XmlCodecProvider codecProvider) {
+        this.codecProvider = Preconditions.checkNotNull(codecProvider);
+    }
+
+    @Override
+    protected LinkedListMultimap<QName, Element> mapChildElements(Iterable<Element> elements) {
+        return DomUtils.mapChildElementsForSingletonNode(elements.iterator().next());
+    }
+
+    @Override
+    protected NodeParserDispatcher<Element> getDispatcher() {
+        return DomNodeDispatcher.getInstance(codecProvider);
+    }
+
+
+}
diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/parser/MapNodeDomParser.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/parser/MapNodeDomParser.java
new file mode 100644 (file)
index 0000000..1549269
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2013 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.schema.transform.dom.parser;
+
+import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.ToNormalizedNodeParser;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.parser.MapNodeBaseParser;
+import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
+import org.w3c.dom.Element;
+
+public final class MapNodeDomParser extends MapNodeBaseParser<Element> {
+
+    private final MapEntryNodeDomParser mapEntryParser;
+
+    public MapNodeDomParser(MapEntryNodeDomParser mapEntryParser) {
+        this.mapEntryParser = mapEntryParser;
+    }
+
+    @Override
+    protected ToNormalizedNodeParser<Element, MapEntryNode, ListSchemaNode> getMapEntryNodeDomParser() {
+        return mapEntryParser;
+    }
+}
diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/serializer/AugmentationNodeDomSerializer.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/serializer/AugmentationNodeDomSerializer.java
new file mode 100644 (file)
index 0000000..fbffc03
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2013 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.schema.transform.dom.serializer;
+
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.serializer.AugmentationNodeBaseSerializer;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.serializer.NodeSerializerDispatcher;
+import org.w3c.dom.Element;
+
+import com.google.common.base.Preconditions;
+
+public class AugmentationNodeDomSerializer extends
+        AugmentationNodeBaseSerializer<Element> {
+
+    private final NodeSerializerDispatcher<Element> dispatcher;
+
+    public AugmentationNodeDomSerializer(NodeSerializerDispatcher<Element> dispatcher) {
+        this.dispatcher = Preconditions.checkNotNull(dispatcher);
+    }
+
+    @Override
+    protected NodeSerializerDispatcher<Element> getNodeDispatcher() {
+        return dispatcher;
+    }
+}
diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/serializer/ChoiceNodeDomSerializer.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/serializer/ChoiceNodeDomSerializer.java
new file mode 100644 (file)
index 0000000..1db6a8b
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2013 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.schema.transform.dom.serializer;
+
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.serializer.ChoiceNodeBaseSerializer;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.serializer.NodeSerializerDispatcher;
+import org.w3c.dom.Element;
+
+import com.google.common.base.Preconditions;
+
+public class ChoiceNodeDomSerializer extends ChoiceNodeBaseSerializer<Element> {
+    private final NodeSerializerDispatcher<Element> dispatcher;
+
+    public ChoiceNodeDomSerializer(final NodeSerializerDispatcher<Element> dispatcher) {
+        this.dispatcher = Preconditions.checkNotNull(dispatcher);
+    }
+
+    @Override
+    protected NodeSerializerDispatcher<Element> getNodeDispatcher() {
+        return dispatcher;
+    }
+}
diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/serializer/ContainerNodeDomSerializer.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/serializer/ContainerNodeDomSerializer.java
new file mode 100644 (file)
index 0000000..c5641a0
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2013 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.schema.transform.dom.serializer;
+
+import java.util.Collections;
+
+import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
+import org.opendaylight.yangtools.yang.data.impl.codec.xml.XmlDocumentUtils;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.serializer.ContainerNodeBaseSerializer;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.serializer.NodeSerializerDispatcher;
+import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+import com.google.common.base.Preconditions;
+
+public class ContainerNodeDomSerializer extends
+        ContainerNodeBaseSerializer<Element> {
+
+    private final Document doc;
+    private final NodeSerializerDispatcher<Element> dispatcher;
+
+    public ContainerNodeDomSerializer(final Document doc, final NodeSerializerDispatcher<Element> dispatcher) {
+        this.doc = Preconditions.checkNotNull(doc);
+        this.dispatcher = Preconditions.checkNotNull(dispatcher);
+    }
+
+    @Override
+    public Iterable<Element> serialize(ContainerSchemaNode schema, ContainerNode containerNode) {
+        Element itemEl = XmlDocumentUtils.createElementFor(doc, containerNode);
+
+        for (Element element : super.serialize(schema, containerNode)) {
+            itemEl.appendChild(element);
+        }
+        return Collections.singletonList(itemEl);
+    }
+
+    @Override
+    protected NodeSerializerDispatcher<Element> getNodeDispatcher() {
+        return dispatcher;
+    }
+
+}
diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/serializer/DomNodeSerializerDispatcher.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/serializer/DomNodeSerializerDispatcher.java
new file mode 100644 (file)
index 0000000..9dee602
--- /dev/null
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2013 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.schema.transform.dom.serializer;
+
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutionException;
+
+import org.opendaylight.yangtools.yang.data.api.schema.AugmentationNode;
+import org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode;
+import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
+import org.opendaylight.yangtools.yang.data.api.schema.LeafNode;
+import org.opendaylight.yangtools.yang.data.api.schema.LeafSetNode;
+import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
+import org.opendaylight.yangtools.yang.data.impl.codec.xml.XmlCodecProvider;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.FromNormalizedNodeSerializer;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.serializer.NodeSerializerDispatcher;
+import org.opendaylight.yangtools.yang.model.api.AugmentationSchema;
+import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
+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.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+import com.google.common.cache.Cache;
+import com.google.common.cache.CacheBuilder;
+
+final class DomNodeSerializerDispatcher extends NodeSerializerDispatcher.BaseNodeSerializerDispatcher<Element> {
+    private static final Cache<Document, DomNodeSerializerDispatcher> dispatcherCache =
+            CacheBuilder.newBuilder().weakKeys().build();
+
+    private final FromNormalizedNodeSerializer<Element, ContainerNode, ContainerSchemaNode> containerSerializer;
+    private final FromNormalizedNodeSerializer<Element, ChoiceNode, org.opendaylight.yangtools.yang.model.api.ChoiceNode> choiceSerializer;
+    private final FromNormalizedNodeSerializer<Element, AugmentationNode, AugmentationSchema> augmentSerializer;
+    private final FromNormalizedNodeSerializer<Element, LeafNode<?>, LeafSchemaNode> leafNodeSerializer;
+    private final FromNormalizedNodeSerializer<Element, LeafSetNode<?>, LeafListSchemaNode> leafSetSerializer;
+    private final FromNormalizedNodeSerializer<Element, MapNode, ListSchemaNode> mapNodeSerializer;
+
+    DomNodeSerializerDispatcher(Document doc, XmlCodecProvider codecProvider) {
+        containerSerializer = new ContainerNodeDomSerializer(doc, this);
+        choiceSerializer = new ChoiceNodeDomSerializer(this);
+        augmentSerializer = new AugmentationNodeDomSerializer(this);
+        leafNodeSerializer = new LeafNodeDomSerializer(doc, codecProvider);
+        leafSetSerializer = new LeafSetNodeDomSerializer(new LeafSetEntryNodeDomSerializer(doc, codecProvider));
+        mapNodeSerializer = new MapNodeDomSerializer(new MapEntryNodeDomSerializer(doc, this));
+    }
+
+    // FIXME: Callers should really grow a proper (per-document) lifecycle and not rely on this
+    @Deprecated
+    static DomNodeSerializerDispatcher getInstance(final Document doc, final XmlCodecProvider codecProvider) {
+        // DOM does not allow to add elements to one document from another, so maintain a cache
+        // on a per-document case.
+        try {
+            return dispatcherCache.get(doc, new Callable<DomNodeSerializerDispatcher>() {
+                @Override
+                public DomNodeSerializerDispatcher call() {
+                    return new DomNodeSerializerDispatcher(doc, codecProvider);
+                }
+            });
+        } catch (ExecutionException e) {
+            throw new IllegalStateException("Failed to instantiated a dispatcher", e);
+        }
+    }
+
+    @Override
+    protected FromNormalizedNodeSerializer<Element, ContainerNode, ContainerSchemaNode> getContainerNodeSerializer() {
+        return containerSerializer;
+    }
+
+    @Override
+    protected FromNormalizedNodeSerializer<Element, LeafNode<?>, LeafSchemaNode> getLeafNodeSerializer() {
+        return leafNodeSerializer;
+    }
+
+    @Override
+    protected FromNormalizedNodeSerializer<Element, LeafSetNode<?>, LeafListSchemaNode> getLeafSetNodeSerializer() {
+        return leafSetSerializer;
+    }
+
+    @Override
+    protected FromNormalizedNodeSerializer<Element, MapNode, ListSchemaNode> getMapNodeSerializer() {
+        return mapNodeSerializer;
+    }
+
+    @Override
+    protected FromNormalizedNodeSerializer<Element, ChoiceNode, org.opendaylight.yangtools.yang.model.api.ChoiceNode> getChoiceNodeSerializer() {
+        return choiceSerializer;
+    }
+
+    @Override
+    protected FromNormalizedNodeSerializer<Element, AugmentationNode, AugmentationSchema> getAugmentationNodeSerializer() {
+        return augmentSerializer;
+    }
+}
diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/serializer/LeafNodeDomSerializer.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/serializer/LeafNodeDomSerializer.java
new file mode 100644 (file)
index 0000000..acdb7eb
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2013 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.schema.transform.dom.serializer;
+
+import com.google.common.base.Preconditions;
+import org.opendaylight.yangtools.yang.data.api.schema.LeafNode;
+import org.opendaylight.yangtools.yang.data.impl.codec.xml.XmlCodecProvider;
+import org.opendaylight.yangtools.yang.data.impl.codec.xml.XmlDocumentUtils;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.dom.DomUtils;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.serializer.LeafNodeBaseSerializer;
+import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+public class LeafNodeDomSerializer extends LeafNodeBaseSerializer<Element> {
+
+    private final Document doc;
+    private final XmlCodecProvider codecProvider;
+
+    public LeafNodeDomSerializer(Document doc, XmlCodecProvider codecProvider) {
+        this.doc = Preconditions.checkNotNull(doc);
+        this.codecProvider = Preconditions.checkNotNull(codecProvider);
+    }
+
+    @Override
+    protected Element serializeLeaf(LeafSchemaNode schema, LeafNode<?> node) {
+        Element itemEl = XmlDocumentUtils.createElementFor(doc, node);
+        DomUtils.serializeXmlValue(itemEl, schema.getType(), codecProvider, node.getValue());
+
+        return itemEl;
+    }
+}
diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/serializer/LeafSetEntryNodeDomSerializer.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/serializer/LeafSetEntryNodeDomSerializer.java
new file mode 100644 (file)
index 0000000..98908cc
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2013 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.schema.transform.dom.serializer;
+
+import com.google.common.base.Preconditions;
+import org.opendaylight.yangtools.yang.data.api.schema.LeafSetEntryNode;
+import org.opendaylight.yangtools.yang.data.impl.codec.xml.XmlCodecProvider;
+import org.opendaylight.yangtools.yang.data.impl.codec.xml.XmlDocumentUtils;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.dom.DomUtils;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.serializer.LeafSetEntryNodeBaseSerializer;
+import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+public class LeafSetEntryNodeDomSerializer extends
+        LeafSetEntryNodeBaseSerializer<Element> {
+
+    private final Document doc;
+    private final XmlCodecProvider codecProvider;
+
+    public LeafSetEntryNodeDomSerializer(Document doc, XmlCodecProvider codecProvider) {
+        this.doc = Preconditions.checkNotNull(doc);
+        this.codecProvider = Preconditions.checkNotNull(codecProvider);
+    }
+
+    @Override
+    protected Element serializeLeaf(LeafListSchemaNode schema, LeafSetEntryNode<?> node) {
+        Element itemEl = XmlDocumentUtils.createElementFor(doc, node);
+
+        DomUtils.serializeXmlValue(itemEl, schema.getType(), codecProvider, node.getValue());
+
+        return itemEl;
+    }
+}
diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/serializer/LeafSetNodeDomSerializer.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/serializer/LeafSetNodeDomSerializer.java
new file mode 100644 (file)
index 0000000..ae49d68
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2013 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.schema.transform.dom.serializer;
+
+import org.opendaylight.yangtools.yang.data.api.schema.LeafSetEntryNode;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.FromNormalizedNodeSerializer;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.serializer.LeafSetNodeBaseSerializer;
+import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
+import org.w3c.dom.Element;
+
+public class LeafSetNodeDomSerializer extends
+        LeafSetNodeBaseSerializer<Element> {
+
+    private final FromNormalizedNodeSerializer<Element, LeafSetEntryNode<?>, LeafListSchemaNode> leafSetEntryNodeSerializer;
+
+    public LeafSetNodeDomSerializer(LeafSetEntryNodeDomSerializer leafSetEntryNodeSerializer) {
+        this.leafSetEntryNodeSerializer = leafSetEntryNodeSerializer;
+    }
+
+    @Override
+    protected FromNormalizedNodeSerializer<Element, LeafSetEntryNode<?>, LeafListSchemaNode> getLeafSetEntryNodeSerializer() {
+        return leafSetEntryNodeSerializer;
+    }
+}
diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/serializer/MapEntryNodeDomSerializer.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/serializer/MapEntryNodeDomSerializer.java
new file mode 100644 (file)
index 0000000..5e65dd8
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2013 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.schema.transform.dom.serializer;
+
+import java.util.Collections;
+
+import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
+import org.opendaylight.yangtools.yang.data.impl.codec.xml.XmlDocumentUtils;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.serializer.MapEntryNodeBaseSerializer;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.serializer.NodeSerializerDispatcher;
+import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+import com.google.common.base.Preconditions;
+
+public class MapEntryNodeDomSerializer extends
+        MapEntryNodeBaseSerializer<Element> {
+
+    private final Document doc;
+    private final NodeSerializerDispatcher<Element> dispatcher;
+
+    public MapEntryNodeDomSerializer(final Document doc, final NodeSerializerDispatcher<Element> dispatcher) {
+        this.doc = Preconditions.checkNotNull(doc);
+        this.dispatcher = Preconditions.checkNotNull(dispatcher);
+    }
+
+    @Override
+    public Iterable<Element> serialize(ListSchemaNode schema, MapEntryNode node) {
+        Element itemEl = XmlDocumentUtils.createElementFor(doc, node);
+
+        for (Element element : super.serialize(schema, node)) {
+            itemEl.appendChild(element);
+        }
+
+        return Collections.singletonList(itemEl);
+    }
+
+    @Override
+    protected NodeSerializerDispatcher<Element> getNodeDispatcher() {
+        return dispatcher;
+    }
+}
diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/serializer/MapNodeDomSerializer.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/serializer/MapNodeDomSerializer.java
new file mode 100644 (file)
index 0000000..d1486f0
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2013 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.schema.transform.dom.serializer;
+
+import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.FromNormalizedNodeSerializer;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.serializer.MapNodeBaseSerializer;
+import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
+import org.w3c.dom.Element;
+
+public class MapNodeDomSerializer extends MapNodeBaseSerializer<Element> {
+
+    private final FromNormalizedNodeSerializer<Element, MapEntryNode, ListSchemaNode> mapEntrySerializer;
+
+    public MapNodeDomSerializer(MapEntryNodeDomSerializer mapEntrySerializer) {
+        this.mapEntrySerializer = mapEntrySerializer;
+    }
+
+    @Override
+    protected FromNormalizedNodeSerializer<Element, MapEntryNode, ListSchemaNode> getMapEntryNodeDomSerializer() {
+        return mapEntrySerializer;
+    }
+}
index 60b93cef801fa2333ac5d02f7ce684e1295b94fb..5cea3b84ddb26a93c274f47959853fdc4f20f9e5 100644 (file)
@@ -7,54 +7,57 @@
  */
 package org.opendaylight.yangtools.yang.data.impl.schema;
 
-import com.google.common.base.Function;
-import com.google.common.base.Preconditions;
-import com.google.common.collect.Collections2;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Sets;
+import java.io.InputStream;
+import java.net.URI;
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
-import org.opendaylight.yangtools.yang.data.api.schema.*;
+import org.opendaylight.yangtools.yang.data.api.schema.AugmentationNode;
+import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
+import org.opendaylight.yangtools.yang.data.api.schema.LeafNode;
+import org.opendaylight.yangtools.yang.data.api.schema.LeafSetNode;
+import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
+import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
 import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeBuilder;
 import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableChoiceNodeSchemaAwareBuilder;
 import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableMapNodeSchemaAwareBuilder;
-import org.opendaylight.yangtools.yang.model.api.*;
+import org.opendaylight.yangtools.yang.model.api.AugmentationSchema;
 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;
+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.Module;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl;
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-import org.xml.sax.SAXException;
-
-import javax.xml.parsers.DocumentBuilder;
-import javax.xml.parsers.DocumentBuilderFactory;
-import javax.xml.parsers.ParserConfigurationException;
-import javax.xml.transform.*;
-import javax.xml.transform.dom.DOMSource;
-import javax.xml.transform.stream.StreamResult;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.StringWriter;
-import java.net.URI;
-import java.util.Collections;
-import java.util.List;
-import java.util.Set;
+
+import com.google.common.base.Function;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Collections2;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
 
 public class NormalizedDataBuilderTest {
 
     private ContainerSchemaNode containerNode;
     private SchemaContext schema;
 
-    SchemaContext parseTestSchema() {
+    SchemaContext parseTestSchema(String... yangPath) {
         YangParserImpl yangParserImpl = new YangParserImpl();
-        Set<Module> modules = yangParserImpl.parseYangModelsFromStreams(getTestYangs());
+        Set<Module> modules = yangParserImpl.parseYangModelsFromStreams(getTestYangs(yangPath));
         return yangParserImpl.resolveSchemaContext(modules);
     }
 
-    List<InputStream> getTestYangs() {
+    List<InputStream> getTestYangs(String... yangPaths) {
 
-        return Lists.newArrayList(Collections2.transform(Lists.newArrayList("test.yang"),
+        return Lists.newArrayList(Collections2.transform(Lists.newArrayList(yangPaths),
                 new Function<String, InputStream>() {
                     @Override
                     public InputStream apply(String input) {
@@ -67,126 +70,125 @@ public class NormalizedDataBuilderTest {
 
     @Before
     public void setUp() throws Exception {
-        schema = parseTestSchema();
+        schema = parseTestSchema("test.yang");
         containerNode = (ContainerSchemaNode) getSchemaNode(schema, "test", "container");
     }
 
     @Test
     public void testSchemaUnaware() throws Exception {
         // Container
-        DataContainerNodeBuilder<InstanceIdentifier.NodeIdentifier, ContainerNode> builder = Builders.containerBuilder().withNodeIdentifier(
-                getNodeIdentifier("container"));
+        DataContainerNodeBuilder<InstanceIdentifier.NodeIdentifier, ContainerNode> builder = Builders
+                .containerBuilder().withNodeIdentifier(getNodeIdentifier("container"));
 
         // leaf
-        LeafNode<String> leafChild = Builders.<String>leafBuilder()
-                .withNodeIdentifier(getNodeIdentifier("leaf")).withValue("String").build();
+        LeafNode<String> leafChild = Builders.<String> leafBuilder().withNodeIdentifier(getNodeIdentifier("leaf"))
+                .withValue("String").build();
         builder.withChild(leafChild);
 
         // leafList
-        LeafSetNode<Integer> leafList = Builders.<Integer>leafSetBuilder()
+        LeafSetNode<Integer> leafList = Builders
+                .<Integer> leafSetBuilder()
                 .withNodeIdentifier(getNodeIdentifier("leaf"))
                 .withChildValue(1)
-                .withChild(Builders.<Integer>leafSetEntryBuilder().withNodeIdentifier(getNodeWithValueIdentifier("leaf", 3)).withValue(3).build())
+                .withChild(
+                        Builders.<Integer> leafSetEntryBuilder()
+                                .withNodeIdentifier(getNodeWithValueIdentifier("leaf", 3)).withValue(3).build())
                 .build();
         builder.withChild(leafList);
 
         // list
-        MapEntryNode listChild1 = Builders.mapEntryBuilder()
-                .withChild(
-                        Builders.<Integer>leafBuilder()
-                                .withNodeIdentifier(getNodeIdentifier("uint32InList")).withValue(1).build())
+        MapEntryNode listChild1 = Builders
+                .mapEntryBuilder()
                 .withChild(
-                        Builders.containerBuilder().withNodeIdentifier(
-                                getNodeIdentifier("containerInList"))
-                                .build())
+                        Builders.<Integer> leafBuilder().withNodeIdentifier(getNodeIdentifier("uint32InList"))
+                                .withValue(1).build())
+                .withChild(Builders.containerBuilder().withNodeIdentifier(getNodeIdentifier("containerInList")).build())
                 .withNodeIdentifier(
                         new InstanceIdentifier.NodeIdentifierWithPredicates(getNodeIdentifier("list").getNodeType(),
                                 Collections.singletonMap(getNodeIdentifier("uint32InList").getNodeType(), (Object) 1)))
                 .build();
 
-        MapNode list = Builders.mapBuilder().withChild(listChild1).withNodeIdentifier(getNodeIdentifier("list")).build();
+        MapNode list = Builders.mapBuilder().withChild(listChild1).withNodeIdentifier(getNodeIdentifier("list"))
+                .build();
         builder.withChild(list);
 
-        AugmentationNode augmentation = Builders.augmentationBuilder()
-                .withNodeIdentifier(new InstanceIdentifier.AugmentationIdentifier(null, Sets.newHashSet(getQName("augmentUint32"))))
+        AugmentationNode augmentation = Builders
+                .augmentationBuilder()
+                .withNodeIdentifier(
+                        new InstanceIdentifier.AugmentationIdentifier(null, Sets.newHashSet(getQName("augmentUint32"))))
                 .withChild(
-                        Builders.<Integer>leafBuilder().withNodeIdentifier(getNodeIdentifier("augmentUint32")).withValue(11).build())
-                .build();
+                        Builders.<Integer> leafBuilder().withNodeIdentifier(getNodeIdentifier("augmentUint32"))
+                                .withValue(11).build()).build();
 
         builder.withChild(augmentation);
 
-        // This works without schema (adding child from augment as a direct child)
-        builder.withChild(Builders.<Integer>leafBuilder().withNodeIdentifier(getNodeIdentifier("augmentUint32")).withValue(11).build());
-
-        System.out.println(builder.build());
+        // This works without schema (adding child from augment as a direct
+        // child)
+        builder.withChild(Builders.<Integer> leafBuilder().withNodeIdentifier(getNodeIdentifier("augmentUint32"))
+                .withValue(11).build());
     }
 
     @Test
     public void testSchemaAware() throws Exception {
-        DataContainerNodeBuilder<InstanceIdentifier.NodeIdentifier, ContainerNode> builder =  Builders.containerBuilder(containerNode);
+        DataContainerNodeBuilder<InstanceIdentifier.NodeIdentifier, ContainerNode> builder = Builders
+                .containerBuilder(containerNode);
 
         LeafSchemaNode schemaNode = (LeafSchemaNode) getSchemaNode(schema, "test", "uint32");
-        LeafNode<String> leafChild = Builders.<String>leafBuilder(schemaNode)
-                .withValue("String").build();
+        LeafNode<String> leafChild = Builders.<String> leafBuilder(schemaNode).withValue("String").build();
         builder.withChild(leafChild);
 
         LeafListSchemaNode leafListSchemaNode = (LeafListSchemaNode) getSchemaNode(schema, "test", "leafList");
-        LeafSetNode<Integer> leafList = Builders.<Integer>leafSetBuilder(leafListSchemaNode)
-                .withChildValue(1)
-                .withChild(Builders.<Integer>leafSetEntryBuilder(leafListSchemaNode).withValue(3).build())
-                .build();
+        LeafSetNode<Integer> leafList = Builders.<Integer> leafSetBuilder(leafListSchemaNode).withChildValue(1)
+                .withChild(Builders.<Integer> leafSetEntryBuilder(leafListSchemaNode).withValue(3).build()).build();
         builder.withChild(leafList);
 
         ListSchemaNode listSchema = (ListSchemaNode) getSchemaNode(schema, "test", "list");
         LeafSchemaNode uint32InListSchemaNode = (LeafSchemaNode) getSchemaNode(schema, "test", "uint32InList");
-        ContainerSchemaNode containerInListSchemaNode = (ContainerSchemaNode) getSchemaNode(schema, "test", "containerInList");
+        ContainerSchemaNode containerInListSchemaNode = (ContainerSchemaNode) getSchemaNode(schema, "test",
+                "containerInList");
 
         MapEntryNode listChild1 = Builders.mapEntryBuilder(listSchema)
-                .withChild(
-                        Builders.<Integer>leafBuilder(uint32InListSchemaNode).withValue(1).build())
-                .withChild(
-                        Builders.containerBuilder(containerInListSchemaNode).build())
-                .build();
+                .withChild(Builders.<Integer> leafBuilder(uint32InListSchemaNode).withValue(1).build())
+                .withChild(Builders.containerBuilder(containerInListSchemaNode).build()).build();
 
         MapNode list = ImmutableMapNodeSchemaAwareBuilder.create(listSchema).withChild(listChild1).build();
         builder.withChild(list);
 
         LeafSchemaNode augmentUint32SchemaNode = (LeafSchemaNode) getSchemaNode(schema, "test", "augmentUint32");
-        AugmentationSchema augmentationSchema = getAugmentationSchemaForChild(containerNode, augmentUint32SchemaNode.getQName());
+        AugmentationSchema augmentationSchema = getAugmentationSchemaForChild(containerNode,
+                augmentUint32SchemaNode.getQName());
 
-        AugmentationNode augmentation = Builders.augmentationBuilder(augmentationSchema).withChild(
-                Builders.<Integer>leafBuilder(augmentUint32SchemaNode).withValue(11).build())
-                .build();
+        AugmentationNode augmentation = Builders.augmentationBuilder(augmentationSchema)
+                .withChild(Builders.<Integer>leafBuilder(augmentUint32SchemaNode).withValue(11).build()).build();
 
         builder.withChild(augmentation);
 
         // This should fail with schema, since the leaf comes from augmentation
-//        builder.withChild(ImmutableLeafNodeSchemaAwareBuilder.<Integer>get(augmentUint32SchemaNode).withValue(11).build());
+        // builder.withChild(ImmutableLeafNodeSchemaAwareBuilder.<Integer>get(augmentUint32SchemaNode).withValue(11).build());
 
         LeafSchemaNode augumentString1SchemaNode = (LeafSchemaNode) getSchemaNode(schema, "test", "augmentString1");
         LeafSchemaNode augumentString2SchemaNode = (LeafSchemaNode) getSchemaNode(schema, "test", "augmentString2");
 
         ChoiceNode choice1SchemaNode = (ChoiceNode) getSchemaNode(schema, "test", "choice");
-        org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode choice = ImmutableChoiceNodeSchemaAwareBuilder.create(choice1SchemaNode)
-                .withChild(Builders.<String>leafBuilder(augumentString1SchemaNode).withValue("case1")
-                        .build())
-                        // This should fail, since child node belongs to different case
-//                .withChild(Builders.<String>leafBuilder(augumentString2SchemaNode).withValue("case2")
-//                        .build())
+        org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode choice = ImmutableChoiceNodeSchemaAwareBuilder
+                .create(choice1SchemaNode)
+                .withChild(Builders.<String> leafBuilder(augumentString1SchemaNode).withValue("case1").build())
+                // This should fail, since child node belongs to different case
+                // .withChild(Builders.<String>leafBuilder(augumentString2SchemaNode).withValue("case2")
+                // .build())
                 .build();
 
-;        builder.withChild(choice);
+        ;
+        builder.withChild(choice);
 
         // This should fail, child from case
-//        builder.withChild(Builders.<String>leafBuilder(augumentString1SchemaNode).withValue("case1")
-//                .build());
-
-        System.out.println(builder.build());
+        // builder.withChild(Builders.<String>leafBuilder(augumentString1SchemaNode).withValue("case1")
+        // .build());
     }
 
     private AugmentationSchema getAugmentationSchemaForChild(ContainerSchemaNode containerNode, QName qName) {
         for (AugmentationSchema augmentationSchema : containerNode.getAvailableAugmentations()) {
-            if(augmentationSchema.getDataChildByName(qName) != null) {
+            if (augmentationSchema.getDataChildByName(qName) != null) {
                 return augmentationSchema;
             }
         }
@@ -202,92 +204,37 @@ public class NormalizedDataBuilderTest {
         return new QName(URI.create(namespace), localName);
     }
 
-    private InstanceIdentifier.NodeWithValue getNodeWithValueIdentifier(QName q, Object value) {
-        return new InstanceIdentifier.NodeWithValue(q, value);
-    }
-
     private InstanceIdentifier.NodeIdentifier getNodeIdentifier(String localName) {
         return new InstanceIdentifier.NodeIdentifier(getQName(localName));
     }
 
-    private InstanceIdentifier.NodeIdentifier getNodeIdentifier(QName q) {
-        return new InstanceIdentifier.NodeIdentifier(q);
-    }
-
-    private Document loadDocument(String xmlPath) throws Exception {
-        InputStream resourceAsStream = getClass().getResourceAsStream(xmlPath);
-
-        Document currentConfigElement = readXmlToDocument(resourceAsStream);
-        Preconditions.checkNotNull(currentConfigElement);
-        return currentConfigElement;
-    }
-
-    private static final DocumentBuilderFactory BUILDERFACTORY;
-
-    static {
-        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
-        factory.setNamespaceAware(true);
-        factory.setCoalescing(true);
-        factory.setIgnoringElementContentWhitespace(true);
-        factory.setIgnoringComments(true);
-        BUILDERFACTORY = factory;
-    }
-
-    private Document readXmlToDocument(InputStream xmlContent) throws IOException, SAXException {
-        DocumentBuilder dBuilder;
-        try {
-            dBuilder = BUILDERFACTORY.newDocumentBuilder();
-        } catch (ParserConfigurationException e) {
-            throw new RuntimeException("Failed to parse XML document", e);
-        }
-        Document doc = dBuilder.parse(xmlContent);
-
-        doc.getDocumentElement().normalize();
-        return doc;
-    }
-
-    public static String toString(Element xml) {
-        try {
-            Transformer transformer = TransformerFactory.newInstance().newTransformer();
-            transformer.setOutputProperty(OutputKeys.INDENT, "yes");
-
-            StreamResult result = new StreamResult(new StringWriter());
-            DOMSource source = new DOMSource(xml);
-            transformer.transform(source, result);
-
-            return result.getWriter().toString();
-        } catch (IllegalArgumentException | TransformerFactoryConfigurationError | TransformerException e) {
-            throw new RuntimeException("Unable to serialize xml element " + xml, e);
-        }
-    }
-
-    DataSchemaNode getSchemaNode(SchemaContext context, String moduleName, String childNodeName) {
+    public static DataSchemaNode getSchemaNode(SchemaContext context, String moduleName, String childNodeName) {
         for (Module module : context.getModules()) {
             if (module.getName().equals(moduleName)) {
                 DataSchemaNode found = findChildNode(module.getChildNodes(), childNodeName);
-                Preconditions.checkState(found!=null, "Unable to find %s", childNodeName);
+                Preconditions.checkState(found != null, "Unable to find %s", childNodeName);
                 return found;
             }
         }
         throw new IllegalStateException("Unable to find child node " + childNodeName);
     }
 
-    DataSchemaNode findChildNode(Set<DataSchemaNode> children, String name) {
+    static DataSchemaNode findChildNode(Set<DataSchemaNode> children, String name) {
         List<DataNodeContainer> containers = Lists.newArrayList();
 
         for (DataSchemaNode dataSchemaNode : children) {
             if (dataSchemaNode.getQName().getLocalName().equals(name))
                 return dataSchemaNode;
-            if(dataSchemaNode instanceof DataNodeContainer) {
+            if (dataSchemaNode instanceof DataNodeContainer) {
                 containers.add((DataNodeContainer) dataSchemaNode);
-            } else if(dataSchemaNode instanceof ChoiceNode) {
+            } else if (dataSchemaNode instanceof ChoiceNode) {
                 containers.addAll(((ChoiceNode) dataSchemaNode).getCases());
             }
         }
 
         for (DataNodeContainer container : containers) {
             DataSchemaNode retVal = findChildNode(container.getChildNodes(), name);
-            if(retVal != null) {
+            if (retVal != null) {
                 return retVal;
             }
         }
diff --git a/yang/yang-data-impl/src/test/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/serializer/NormalizedNodeXmlTranslationTest.java b/yang/yang-data-impl/src/test/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/serializer/NormalizedNodeXmlTranslationTest.java
new file mode 100644 (file)
index 0000000..a229932
--- /dev/null
@@ -0,0 +1,252 @@
+/*
+ * Copyright (c) 2013 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.schema.transform.dom.serializer;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.StringWriter;
+import java.net.URI;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Date;
+import java.util.List;
+import java.util.Set;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.transform.OutputKeys;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.TransformerFactoryConfigurationError;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
+import org.opendaylight.yangtools.yang.data.impl.codec.xml.XmlDocumentUtils;
+import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
+import org.opendaylight.yangtools.yang.data.impl.schema.NormalizedDataBuilderTest;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.serializer.NodeSerializerDispatcher;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.dom.DomUtils;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.dom.parser.ContainerNodeDomParser;
+import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.Module;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.xml.sax.SAXException;
+
+import com.google.common.base.Function;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Collections2;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
+
+@RunWith(Parameterized.class)
+public class NormalizedNodeXmlTranslationTest {
+    private static final Logger logger = LoggerFactory.getLogger(NormalizedNodeXmlTranslationTest.class);
+
+    @Parameterized.Parameters()
+    public static Collection<Object[]> data() {
+        return Arrays.asList(new Object[][]{
+                {"augment_choice_hell.yang", "augment_choice_hell_ok.xml", augmentChoiceHell()},
+                {"augment_choice_hell.yang", "augment_choice_hell_ok2.xml", null},
+                {"test.yang", "simple.xml", null},
+                {"test.yang", "simple2.xml", null}
+        });
+    }
+
+    public static final String NAMESPACE = "urn:opendaylight:params:xml:ns:yang:controller:test";
+    private static Date revision;
+    static {
+        try {
+            revision = new SimpleDateFormat("yyyy-MM-dd").parse("2014-03-13");
+        } catch (ParseException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    private static ContainerNode augmentChoiceHell() {
+
+        DataContainerNodeBuilder<InstanceIdentifier.NodeIdentifier, ContainerNode> b = Builders.containerBuilder();
+        b.withNodeIdentifier(getNodeIdentifier("container"));
+
+        b.withChild(
+                Builders.choiceBuilder().withNodeIdentifier(getNodeIdentifier("ch2"))
+                        .withChild(Builders.leafBuilder().withNodeIdentifier(getNodeIdentifier("c2Leaf")).withValue("2").build())
+                        .withChild(
+                                Builders.choiceBuilder().withNodeIdentifier(getNodeIdentifier("c2DeepChoice"))
+                                        .withChild(Builders.leafBuilder().withNodeIdentifier(getNodeIdentifier("c2DeepChoiceCase1Leaf2")).withValue("2").build())
+                                        .build()
+                        )
+                        .build()
+        );
+
+        b.withChild(
+                Builders.choiceBuilder().withNodeIdentifier(getNodeIdentifier("ch3")).withChild(
+                        Builders.leafBuilder().withNodeIdentifier(getNodeIdentifier("c3Leaf")).withValue("3").build())
+                .build());
+
+        b.withChild(
+                Builders.augmentationBuilder().withNodeIdentifier(getAugmentIdentifier("augLeaf")).withChild(
+                        Builders.leafBuilder().withNodeIdentifier(getNodeIdentifier("augLeaf")).withValue("augment").build())
+                .build());
+
+        b.withChild(
+                Builders.augmentationBuilder().withNodeIdentifier(getAugmentIdentifier("ch")).withChild(
+                        Builders.choiceBuilder().withNodeIdentifier(getNodeIdentifier("ch"))
+                                .withChild(
+                                        Builders.leafBuilder().withNodeIdentifier(getNodeIdentifier("c1Leaf")).withValue("1").build())
+                                .withChild(
+                                        Builders.augmentationBuilder().withNodeIdentifier(getAugmentIdentifier("c1Leaf_AnotherAugment", "deepChoice"))
+                                                .withChild(
+                                                        Builders.leafBuilder().withNodeIdentifier(getNodeIdentifier("c1Leaf_AnotherAugment")).withValue("1").build())
+                                                .withChild(
+                                                        Builders.choiceBuilder().withNodeIdentifier(getNodeIdentifier("deepChoice"))
+                                                                .withChild(
+                                                                        Builders.leafBuilder().withNodeIdentifier(getNodeIdentifier("deepLeafc1")).withValue("1").build()
+                                                                ).build()
+                                                ).build()
+                                ).build()
+        ).build());
+
+        return b.build();
+    }
+
+    private static InstanceIdentifier.NodeIdentifier getNodeIdentifier(String localName) {
+        return new InstanceIdentifier.NodeIdentifier(new QName(URI.create(NAMESPACE), revision, localName));
+    }
+
+    public static InstanceIdentifier.AugmentationIdentifier getAugmentIdentifier(String... childNames) {
+        Set<QName> qn = Sets.newHashSet();
+
+        for (String childName : childNames) {
+            qn.add(getNodeIdentifier(childName).getNodeType());
+        }
+
+        return new InstanceIdentifier.AugmentationIdentifier(null, qn);
+    }
+
+    public NormalizedNodeXmlTranslationTest(String yangPath, String xmlPath, ContainerNode expectedNode) {
+        this.schema = parseTestSchema(yangPath);
+        this.xmlPath = xmlPath;
+        this.containerNode = (ContainerSchemaNode) NormalizedDataBuilderTest.getSchemaNode(schema, "test", "container");
+        this.expectedNode = expectedNode;
+    }
+
+    private final ContainerNode expectedNode;
+    private final ContainerSchemaNode containerNode;
+    private final SchemaContext schema;
+    private final String xmlPath;
+
+
+    SchemaContext parseTestSchema(String... yangPath) {
+        YangParserImpl yangParserImpl = new YangParserImpl();
+        Set<Module> modules = yangParserImpl.parseYangModelsFromStreams(getTestYangs(yangPath));
+        return yangParserImpl.resolveSchemaContext(modules);
+    }
+
+    List<InputStream> getTestYangs(String... yangPaths) {
+
+        return Lists.newArrayList(Collections2.transform(Lists.newArrayList(yangPaths),
+                new Function<String, InputStream>() {
+                    @Override
+                    public InputStream apply(String input) {
+                        InputStream resourceAsStream = NormalizedDataBuilderTest.class.getResourceAsStream(input);
+                        Preconditions.checkNotNull(resourceAsStream, "File %s was null", resourceAsStream);
+                        return resourceAsStream;
+                    }
+                }));
+    }
+
+    @Test
+    public void testTranslation() throws Exception {
+        Document doc = loadDocument(xmlPath);
+
+        ContainerNode built = new ContainerNodeDomParser(DomUtils.defaultValueCodecProvider()).parse(
+                Collections.singletonList(doc.getDocumentElement()), containerNode);
+
+        if (expectedNode != null)
+            junit.framework.Assert.assertEquals(expectedNode, built);
+
+        logger.info("{}", built);
+
+        final Document newDoc = XmlDocumentUtils.getDocument();
+        final NodeSerializerDispatcher<Element> dispatcher = new DomNodeSerializerDispatcher(newDoc, DomUtils.defaultValueCodecProvider());
+
+        Iterable<Element> els = new ContainerNodeDomSerializer(newDoc,
+                dispatcher).serialize(containerNode, built);
+
+        Element el = els.iterator().next();
+
+        Assert.assertEquals(toString(doc.getDocumentElement()).replaceAll("\\s*", ""),
+                toString(el).replaceAll("\\s*", ""));
+    }
+
+
+    private Document loadDocument(String xmlPath) throws Exception {
+        InputStream resourceAsStream = NormalizedDataBuilderTest.class.getResourceAsStream(xmlPath);
+
+        Document currentConfigElement = readXmlToDocument(resourceAsStream);
+        Preconditions.checkNotNull(currentConfigElement);
+        return currentConfigElement;
+    }
+
+    private static final DocumentBuilderFactory BUILDERFACTORY;
+
+    static {
+        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+        factory.setNamespaceAware(true);
+        factory.setCoalescing(true);
+        factory.setIgnoringElementContentWhitespace(true);
+        factory.setIgnoringComments(true);
+        BUILDERFACTORY = factory;
+    }
+
+    private Document readXmlToDocument(InputStream xmlContent) throws IOException, SAXException {
+        DocumentBuilder dBuilder;
+        try {
+            dBuilder = BUILDERFACTORY.newDocumentBuilder();
+        } catch (ParserConfigurationException e) {
+            throw new RuntimeException("Failed to parse XML document", e);
+        }
+        Document doc = dBuilder.parse(xmlContent);
+
+        doc.getDocumentElement().normalize();
+        return doc;
+    }
+
+    public static String toString(Element xml) {
+        try {
+            Transformer transformer = TransformerFactory.newInstance().newTransformer();
+            transformer.setOutputProperty(OutputKeys.INDENT, "yes");
+
+            StreamResult result = new StreamResult(new StringWriter());
+            DOMSource source = new DOMSource(xml);
+            transformer.transform(source, result);
+
+            return result.getWriter().toString();
+        } catch (IllegalArgumentException | TransformerFactoryConfigurationError | TransformerException e) {
+            throw new RuntimeException("Unable to serialize xml element " + xml, e);
+        }
+    }
+}
diff --git a/yang/yang-data-impl/src/test/resources/org/opendaylight/yangtools/yang/data/impl/schema/augment_choice_hell.yang b/yang/yang-data-impl/src/test/resources/org/opendaylight/yangtools/yang/data/impl/schema/augment_choice_hell.yang
new file mode 100644 (file)
index 0000000..c2a57f6
--- /dev/null
@@ -0,0 +1,109 @@
+// vi: set smarttab et sw=4 tabstop=4:
+module test {
+    yang-version 1;
+    namespace "urn:opendaylight:params:xml:ns:yang:controller:test";
+    prefix "test";
+
+    organization "Cisco Systems, Inc.";
+
+    revision "2014-3-13" {
+        description
+            "Initial revision";
+    }
+
+
+    container container {
+        choice ch2{}
+        choice ch3{
+            case c3 {
+                leaf c3Leaf {
+                    type string;
+                }
+            }
+        }
+    }
+
+    augment "/container/" {
+        leaf augLeaf {
+            type string;
+        }
+    }
+
+    augment "/container/" {
+        choice ch{}
+    }
+
+    augment "/container/ch/" {
+        case c1 {
+            leaf c1Leaf {
+                type string;
+            }
+        }
+
+        leaf c12 {
+            type string;
+        }
+    }
+    augment "/container/ch/c1/" {
+        leaf c1Leaf_AnotherAugment {
+            type string;
+        }
+
+        choice deepChoice{}
+    }
+
+    augment "/container/ch3/" {
+        case c32 {
+            leaf c32Leaf {
+                type string;
+            }
+        }
+
+        leaf c34LeafS {
+            type string;
+        }
+    }
+
+
+    augment "/container/ch/c1/deepChoice/" {
+        case deepCase1 {
+            leaf deepLeafc1 {
+                type string;
+            }
+        }
+        case deepCase2 {
+            leaf deepLeafc2 {
+                type string;
+            }
+        }
+    }
+
+    augment "/container/ch2/" {
+        case c2 {
+            leaf c2Leaf {
+                type string;
+            }
+
+            choice c2DeepChoice {
+                case c2DeepChoiceCase1 {
+                    leaf c2DeepChoiceCase1Leaf1 {
+                        type string;
+                    }
+                }
+                case c2DeepChoiceCase2 {
+                    leaf c2DeepChoiceCase1Leaf2 {
+                        type string;
+                    }
+                }
+            }
+        }
+    }
+
+    augment "/container/ch2/" {
+        leaf c22Leaf {
+            type string;
+        }
+    }
+
+
+}
\ No newline at end of file
diff --git a/yang/yang-data-impl/src/test/resources/org/opendaylight/yangtools/yang/data/impl/schema/augment_choice_hell_ok.xml b/yang/yang-data-impl/src/test/resources/org/opendaylight/yangtools/yang/data/impl/schema/augment_choice_hell_ok.xml
new file mode 100644 (file)
index 0000000..c5a581c
--- /dev/null
@@ -0,0 +1,15 @@
+<container xmlns="urn:opendaylight:params:xml:ns:yang:controller:test">
+
+    <c2Leaf>2</c2Leaf>
+    <c2DeepChoiceCase1Leaf2>2</c2DeepChoiceCase1Leaf2>
+    <!--<c2DeepChoiceCase1Leaf1>2</c2DeepChoiceCase1Leaf1>-->
+
+    <c3Leaf>3</c3Leaf>
+
+    <augLeaf>augment</augLeaf>
+
+    <c1Leaf>1</c1Leaf>
+    <c1Leaf_AnotherAugment>1</c1Leaf_AnotherAugment>
+    <deepLeafc1>1</deepLeafc1>
+    <!--<deepLeafc2>1</deepLeafc2>-->
+</container>
\ No newline at end of file
diff --git a/yang/yang-data-impl/src/test/resources/org/opendaylight/yangtools/yang/data/impl/schema/augment_choice_hell_ok2.xml b/yang/yang-data-impl/src/test/resources/org/opendaylight/yangtools/yang/data/impl/schema/augment_choice_hell_ok2.xml
new file mode 100644 (file)
index 0000000..8332d21
--- /dev/null
@@ -0,0 +1,12 @@
+<container xmlns="urn:opendaylight:params:xml:ns:yang:controller:test">
+
+    <c22Leaf>2</c22Leaf>
+
+    <c34LeafS>3</c34LeafS>
+
+    <augLeaf>augment</augLeaf>
+
+    <c1Leaf>1</c1Leaf>
+    <c1Leaf_AnotherAugment>1</c1Leaf_AnotherAugment>
+    <deepLeafc2>1</deepLeafc2>
+</container>
\ No newline at end of file
index 014688e567ac51a4d428c41230b842d51ed9fa48..579f79ae57db640decd728b5cecaa768e9b6b759 100644 (file)
@@ -12,6 +12,8 @@
             <uint32>32</uint32>
             <uint16>16</uint16>
         </containerInList>
+        <stringAugmentedToList>augmentInList</stringAugmentedToList>
+        <stringAugmentedToListInCase1>augmentInListCase1</stringAugmentedToListInCase1>
     </list>
     <list>
         <uint32InList>2</uint32InList>
             <uint32>32</uint32>
             <uint16>16</uint16>
         </containerInList>
+        <!--<stringAugmentedToListInCase1>augmentInListCase1</stringAugmentedToListInCase1>-->
+        <stringAugmentedToListInCase2>augmentInListCase2</stringAugmentedToListInCase2>
     </list>
     <list>
         <uint32InList>3</uint32InList>
     </list>
 
-    <augmentUint32>999</augmentUint32>
-
     <augmentString1>choice1Case1</augmentString1>
+    <!--<augmentString2>choice1Case1</augmentString2>-->
     <augmentInt1>41</augmentInt1>
+    <!--<stringInAugmentedCaseInAugmentedChoice>deep</stringInAugmentedCaseInAugmentedChoice>-->
+    <stringInAugmentedCaseInAugmentedChoiceFromAugment>deep</stringInAugmentedCaseInAugmentedChoiceFromAugment>
 
     <augmentContainer>
         <augmentStringInaugmentContainer>choice2Case1</augmentStringInaugmentContainer>
     </augmentContainer>
 
+    <augmentUint32>999</augmentUint32>
+
+
 
 </container>
\ No newline at end of file
diff --git a/yang/yang-data-impl/src/test/resources/org/opendaylight/yangtools/yang/data/impl/schema/simple2.xml b/yang/yang-data-impl/src/test/resources/org/opendaylight/yangtools/yang/data/impl/schema/simple2.xml
new file mode 100644 (file)
index 0000000..9bb8aff
--- /dev/null
@@ -0,0 +1,43 @@
+<container xmlns="urn:opendaylight:params:xml:ns:yang:controller:test">
+    <augmentString1>choice1Case1</augmentString1>
+    <!--<augmentString2>choice1Case1</augmentString2>-->
+    <augmentInt1>41</augmentInt1>
+    <!--<stringInAugmentedCaseInAugmentedChoice>deep</stringInAugmentedCaseInAugmentedChoice>-->
+    <stringInAugmentedCaseInAugmentedChoice2>deep</stringInAugmentedCaseInAugmentedChoice2>
+
+    <augmentedList>
+        <augmentStringInaugmentList>aug1</augmentStringInaugmentList>
+    </augmentedList>
+
+    <augmentedList>
+        <augmentStringInaugmentList>aug2</augmentStringInaugmentList>
+        <augmentedContainerInAugmentedListInAugmentedCase>
+            <leafInAugmentedContainerInAugmentedListInAugmentedCase>
+                66
+            </leafInAugmentedContainerInAugmentedListInAugmentedCase>
+        </augmentedContainerInAugmentedListInAugmentedCase>
+
+        <augmentedListInAugmentedListInAugmentedCase>
+            <leafInAugmentedListInAugmentedListInAugmentedCase>
+                661
+            </leafInAugmentedListInAugmentedListInAugmentedCase>
+            <leafInAugmentedListInAugmentedListInAugmentedCase>
+                662
+            </leafInAugmentedListInAugmentedListInAugmentedCase>
+        </augmentedListInAugmentedListInAugmentedCase>
+
+        <augmentedListInAugmentedListInAugmentedCase>
+            <leafInAugmentedListInAugmentedListInAugmentedCase>
+                6621
+            </leafInAugmentedListInAugmentedListInAugmentedCase>
+        </augmentedListInAugmentedListInAugmentedCase>
+    </augmentedList>
+
+    <augmentedList>
+        <augmentStringInaugmentList>aug3</augmentStringInaugmentList>
+        <augmentedContainerInAugmentedListInAugmentedCase/>
+
+        <augmentedListInAugmentedListInAugmentedCase/>
+    </augmentedList>
+
+</container>
\ No newline at end of file
index 4ad6e786259c47e91d38fc490ef6c767dfcf4634..ef9e8d67a7ff994afff9121ad590bb78d0c2437d 100644 (file)
@@ -72,7 +72,33 @@ module test {
             type string;
         }
 
-        uses listGroup;
+        uses listGroup {
+            augment "list/" {
+                leaf stringAugmentedToList{
+                    type string;
+                }
+
+                choice choiceInList {
+                    case caseInList1 {
+                        leaf stringAugmentedToListInCase1 {
+                            type string;
+                        }
+                    }
+                    case caseInList2 {
+                        leaf stringAugmentedToListInCase2 {
+                            type string;
+                        }
+                    }
+                }
+            }
+        }
+
+        list directList {
+            leaf stringInDirectList {
+                type string;
+            }
+        }
+
         uses innerContainerGrouping;
 
         choice choice{}
@@ -101,6 +127,12 @@ module test {
         }
     }
 
+    augment "/container/directList/" {
+        leaf augmentedString {
+            type uint32;
+        }
+    }
+
     augment "/container/choice/" {
         case test-identity-augment {
             when "/container/identityRef = 'test-identity'";
@@ -124,6 +156,32 @@ module test {
         }
     }
 
+    augment "/container/choice/test-identity-augment/" {
+
+        choice augmentedChoiceInCase {
+
+            case augmentedCaseInAugmentedChoice {
+                leaf stringInAugmentedCaseInAugmentedChoice {
+                    type string;
+                }
+            }
+
+            case augmentedCaseInAugmentedChoice2 {
+                leaf stringInAugmentedCaseInAugmentedChoice2 {
+                    type string;
+                }
+            }
+        }
+    }
+
+    augment "/container/choice/test-identity-augment/augmentedChoiceInCase/" {
+        case augmentedCaseInAugmentedChoiceFromAugment {
+            leaf stringInAugmentedCaseInAugmentedChoiceFromAugment {
+                type string;
+            }
+        }
+    }
+
     augment "/container/choice2/" {
         case test-identity-augment {
             when "/container/identityRef = 'test-identity'";
@@ -144,6 +202,21 @@ module test {
     }
 
 
+    augment "/container/choice2/test-identity-augment2/augmentedList/" {
+
+        container augmentedContainerInAugmentedListInAugmentedCase {
+            leaf-list leafInAugmentedContainerInAugmentedListInAugmentedCase {
+                type uint32;
+            }
+        }
+
+        list augmentedListInAugmentedListInAugmentedCase {
+            leaf-list leafInAugmentedListInAugmentedListInAugmentedCase {
+                    type uint32;
+                }
+        }
+    }
+
     identity test-identity {}
     identity test-identity2 {
         base test-identity;