Add hooking into NormalizedNodeParsers. 25/19225/2
authorTomas Cere <tcere@cisco.com>
Tue, 28 Apr 2015 12:35:13 +0000 (14:35 +0200)
committerTomas Cere <tcere@cisco.com>
Tue, 28 Apr 2015 15:23:02 +0000 (15:23 +0000)
Makes it possible to add a ParsingStrategy into the parsers,
to allow for callbacks/custom processing while parsing.
DefaultParsingStrategy has the same behaviour as the already present parsers.

Change-Id: I5998af4befaf31d3af3f4cf5e2f46ddc32b1e05b
Signed-off-by: Tomas Cere <tcere@cisco.com>
Signed-off-by: Maros Marsalek <mmarsale@cisco.com>
28 files changed:
code-generator/binding-generator-impl/src/main/java/org/opendaylight/yangtools/sal/binding/generator/impl/BindingGeneratorImpl.java
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/ToNormalizedNodeParser.java
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/parser/AugmentationNodeBaseParser.java
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/parser/BaseDispatcherParser.java
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/parser/ChoiceNodeBaseParser.java
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/parser/ContainerNodeBaseParser.java
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/parser/ExtensibleParser.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
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/parser/LeafSetEntryNodeBaseParser.java
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/parser/LeafSetNodeBaseParser.java
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/parser/ListEntryNodeBaseParser.java
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/parser/ListNodeBaseParser.java
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/parser/MapNodeBaseParser.java
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/parser/OrderedListNodeBaseParser.java
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/parser/UnkeyedListNodeBaseParser.java
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/parser/AugmentationNodeDomParser.java
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/parser/ChoiceNodeDomParser.java
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/parser/ContainerNodeDomParser.java
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/parser/DomToNormalizedNodeParserFactory.java
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/parser/LeafNodeDomParser.java
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/parser/LeafSetEntryNodeDomParser.java
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/parser/ListEntryNodeDomParser.java
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/parser/MapEntryNodeDomParser.java
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/parser/MapNodeDomParser.java
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/parser/OrderedListNodeDomParser.java
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/parser/UnkeyedListEntryNodeDomParser.java
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/parser/UnkeyedListNodeDomParser.java
yang/yang-data-operations/src/test/java/org/opendaylight/yangtools/yang/data/operations/YangDataOperationsTest.java

index 66f3bc042408f6a475a772aa41ef78541aabbbab..15b818e43ddbb9754eb159349c8ed63ca3831ce4 100644 (file)
@@ -38,6 +38,7 @@ import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import org.opendaylight.yangtools.sal.binding.generator.impl.YangTemplate;
 import org.opendaylight.yangtools.binding.generator.util.BindingGeneratorUtil;
 import org.opendaylight.yangtools.binding.generator.util.BindingTypes;
 import org.opendaylight.yangtools.binding.generator.util.ReferencedTypeImpl;
index a300cc07d41f88b83daa6d3dcbdc386ba353132d..04c4ed8f7388e34db8a588237e9a37ae85b86718 100644 (file)
@@ -7,6 +7,7 @@
  */
 package org.opendaylight.yangtools.yang.data.impl.schema.transform;
 
+import javax.annotation.Nullable;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
 
 /**
@@ -33,5 +34,6 @@ public interface ToNormalizedNodeParser<E, N extends NormalizedNode<?, ?>, S> {
      * @param schema
      * @return NormalizedNode as a result of parsing list of E elements with schema S
      */
+    @Nullable
     N parse(Iterable<E> xmlDom, S schema);
 }
index 7c3938fe088d92bc3bb6076bfa039cb9720e8102..bd7853a5dd028ea337c840f50f491e1a971f0056 100644 (file)
@@ -26,7 +26,13 @@ import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
  * @param <E> type of elements to be parsed
  */
 public abstract class AugmentationNodeBaseParser<E> extends
-        BaseDispatcherParser<E,AugmentationNode, AugmentationSchema> {
+        BaseDispatcherParser<E, YangInstanceIdentifier.AugmentationIdentifier, AugmentationNode, AugmentationSchema> {
+
+    public AugmentationNodeBaseParser(final BuildingStrategy<YangInstanceIdentifier.AugmentationIdentifier, AugmentationNode> buildingStrategy) {
+        super(buildingStrategy);
+    }
+
+    public AugmentationNodeBaseParser() {}
 
     @Override
     protected final DataContainerNodeBuilder<YangInstanceIdentifier.AugmentationIdentifier, AugmentationNode> getBuilder(final AugmentationSchema schema) {
index a594e5d763a8dbe51c8a33fd03d808b97d605d97..503da680311dad4ea10cf38eb124dc3c54a5d96c 100644 (file)
@@ -14,30 +14,42 @@ import java.util.Collections;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import javax.annotation.Nullable;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 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.AttributesBuilder;
 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.builder.api.NormalizedNodeBuilder;
 import org.opendaylight.yangtools.yang.model.api.AugmentationSchema;
 import org.opendaylight.yangtools.yang.model.api.ChoiceSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
 import org.opendaylight.yangtools.yang.model.util.EffectiveAugmentationSchema;
 
 /**
  * Abstract(base) Parser for DataContainerNodes e.g. ContainerNode, AugmentationNode.
  */
-public abstract class BaseDispatcherParser<E, N extends DataContainerNode<?>, S>
-        implements ToNormalizedNodeParser<E, N, S> {
+public abstract class BaseDispatcherParser<E, P extends YangInstanceIdentifier.PathArgument, N extends DataContainerNode<P>, S>
+        implements ExtensibleParser<P, E, N, S> {
+
+    private final BuildingStrategy<P, N> buildingStrategy;
+
+    public BaseDispatcherParser(final BuildingStrategy<P, N> buildingStrategy) {
+        this.buildingStrategy = buildingStrategy;
+    }
+
+    public BaseDispatcherParser() {
+        this.buildingStrategy = new SimpleBuildingStrategy<>();
+    }
 
     /**
      *
      * @param schema
      * @return New(empty) instance of a builder to build node identified by schema.
      */
-    protected abstract DataContainerNodeBuilder<?, N> getBuilder(S schema);
+    protected abstract DataContainerNodeBuilder<P, N> getBuilder(S schema);
 
     /**
      *
@@ -88,12 +100,19 @@ public abstract class BaseDispatcherParser<E, N extends DataContainerNode<?>, S>
      */
     protected abstract NodeParserDispatcher<E> getDispatcher();
 
+    /**
+     * can return null only if you override ParsingStrategy and explicitely return null
+     * @param elements
+     * @param schema
+     * @return
+     */
+    @Nullable
     @Override
     public N parse(final Iterable<E> elements, final S schema) {
 
         checkAtLeastOneNode(schema, elements);
 
-        DataContainerNodeBuilder<?, N> containerBuilder = getBuilder(schema);
+        DataContainerNodeBuilder<P, N> containerBuilder = getBuilder(schema);
 
         // Map child nodes to QName
         LinkedListMultimap<QName, E> mappedChildElements = mapChildElements(elements);
@@ -106,6 +125,36 @@ public abstract class BaseDispatcherParser<E, N extends DataContainerNode<?>, S>
         Map<QName, ChoiceSchemaNode> mappedChoiceChildNodes = mapChildElementsFromChoices(schema);
         LinkedListMultimap<ChoiceSchemaNode, E> choicesToElements = LinkedListMultimap.create();
 
+        Map<QName, String> attributes = getAttributes(elements.iterator().next());
+        if (containerBuilder instanceof AttributesBuilder) {
+            final int size = Iterables.size(elements);
+            Preconditions.checkArgument(size == 1, "Unexpected number of elements: %s, should be 1 for: %s",
+                    size, schema);
+            ((AttributesBuilder<?>) containerBuilder).withAttributes(attributes);
+        }
+
+        //parse keys first
+        if (schema instanceof ListSchemaNode) {
+            for (QName qname : ((ListSchemaNode) schema).getKeyDefinition()) {
+                if(mappedChildElements.get(qname.withoutRevision()).isEmpty()) {
+                    continue;
+                }
+
+                DataSchemaNode childSchema = getSchemaForChild(schema, qname);
+                List<E> childrenForQName = mappedChildElements.removeAll(qname.withoutRevision());
+
+
+                DataContainerChild<? extends YangInstanceIdentifier.PathArgument, ?> optionalChildNode = getDispatcher()
+                        .dispatchChildElement(childSchema, childrenForQName);
+                if (optionalChildNode != null) {
+                    containerBuilder.withChild(optionalChildNode);
+                }
+            }
+        }
+
+        //stage attribues for strategy before going deeper in the recursion
+        buildingStrategy.prepareAttributes(attributes, containerBuilder);
+
         // process Child nodes
         for (QName childPartialQName : mappedChildElements.keySet()) {
             DataSchemaNode childSchema = getSchemaForChild(schema, childPartialQName);
@@ -125,32 +174,39 @@ public abstract class BaseDispatcherParser<E, N extends DataContainerNode<?>, S>
                 choicesToElements.putAll(choiceSchema, childrenForQName);
                 // Regular child nodes
             } else {
-                DataContainerChild<? extends YangInstanceIdentifier.PathArgument, ?> builtChildNode = getDispatcher()
+                DataContainerChild<? extends YangInstanceIdentifier.PathArgument, ?> optionalChildNode = getDispatcher()
                         .dispatchChildElement(childSchema, childrenForQName);
-                containerBuilder.withChild(builtChildNode);
+                if (optionalChildNode != null) {
+                    containerBuilder.withChild(optionalChildNode);
+                }
             }
         }
 
         // TODO ordering is not preserved for choice and augment elements
         for (ChoiceSchemaNode choiceSchema : choicesToElements.keySet()) {
-            containerBuilder.withChild(getDispatcher().dispatchChildElement(choiceSchema,
-                    choicesToElements.get(choiceSchema)));
+            DataContainerChild<? extends YangInstanceIdentifier.PathArgument, ?> optionalChild = getDispatcher()
+                    .dispatchChildElement(choiceSchema, choicesToElements.get(choiceSchema));
+            if (optionalChild != null) {
+                containerBuilder.withChild(optionalChild);
+            }
         }
 
         for (AugmentationSchema augmentSchema : augmentsToElements.keySet()) {
             Set<DataSchemaNode> realChildSchemas = getRealSchemasForAugment(schema, augmentSchema);
             EffectiveAugmentationSchema augSchemaProxy = new EffectiveAugmentationSchema(augmentSchema, realChildSchemas);
-            containerBuilder.withChild(getDispatcher().dispatchChildElement(augSchemaProxy, augmentsToElements.get(augmentSchema)));
+            DataContainerChild<? extends YangInstanceIdentifier.PathArgument, ?> optionalChild = getDispatcher()
+                    .dispatchChildElement(augSchemaProxy, augmentsToElements.get(augmentSchema));
+            if (optionalChild != null) {
+                containerBuilder.withChild(optionalChild);
+            }
         }
 
-        if (containerBuilder instanceof AttributesBuilder) {
-            final int size = Iterables.size(elements);
-            Preconditions.checkArgument(size == 1, "Unexpected number of elements: %s, should be 1 for: %s",
-                    size, schema);
-            ((AttributesBuilder<?>) containerBuilder).withAttributes(getAttributes(elements.iterator().next()));
-        }
+        return buildingStrategy.build(containerBuilder);
+    }
 
-        return containerBuilder.build();
+    @Override
+    public BuildingStrategy<P, N> getBuildingStrategy() {
+        return buildingStrategy;
     }
 
     protected Map<QName, String> getAttributes(final E e) {
@@ -175,4 +231,16 @@ public abstract class BaseDispatcherParser<E, N extends DataContainerNode<?>, S>
         Preconditions.checkArgument(!Iterables.isEmpty(childNodes),
                 "Node detected 0 times, should be at least 1, identified by: %s, found: %s", schema, childNodes);
     }
+
+    public static class SimpleBuildingStrategy<P extends YangInstanceIdentifier.PathArgument, N extends DataContainerNode<P>> implements BuildingStrategy<P, N> {
+        @Override
+        public N build(final NormalizedNodeBuilder<P, ?, N> builder) {
+            return builder.build();
+        }
+
+        @Override
+        public void prepareAttributes(final Map<QName, String> attributes, final NormalizedNodeBuilder<P, ?, N> containerBuilder) {
+            // NOOP
+        }
+    }
 }
index a82f71685ad642e578b54fdc6d846a5409e9dbe0..371c59c3556c5df5ff3016d6d2f6f440ebd25cf9 100644 (file)
@@ -28,7 +28,13 @@ import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
  *
  * @param <E> type of elements to be parsed
  */
-public abstract class ChoiceNodeBaseParser<E> extends BaseDispatcherParser<E, ChoiceNode, ChoiceSchemaNode> {
+public abstract class ChoiceNodeBaseParser<E> extends BaseDispatcherParser<E, YangInstanceIdentifier.NodeIdentifier, ChoiceNode, ChoiceSchemaNode> {
+
+    protected ChoiceNodeBaseParser() {}
+
+    protected ChoiceNodeBaseParser(final BuildingStrategy<YangInstanceIdentifier.NodeIdentifier, ChoiceNode> buildingStrategy) {
+        super(buildingStrategy);
+    }
 
     @Override
     protected final DataContainerNodeBuilder<YangInstanceIdentifier.NodeIdentifier, ChoiceNode> getBuilder(
index f7cca88155f52cfe18a504ce8a5e4b0849ffef4b..99801cf3a1195f664a2ac84d75c1bf37493730c4 100644 (file)
@@ -27,7 +27,13 @@ import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
  * @param <E> type of elements to be parsed
  */
 public abstract class ContainerNodeBaseParser<E> extends
-        BaseDispatcherParser<E, ContainerNode, ContainerSchemaNode> {
+        BaseDispatcherParser<E, YangInstanceIdentifier.NodeIdentifier, ContainerNode, ContainerSchemaNode> {
+
+    public ContainerNodeBaseParser() {}
+
+    public ContainerNodeBaseParser(final BuildingStrategy<YangInstanceIdentifier.NodeIdentifier, ContainerNode> buildingStrategy) {
+        super(buildingStrategy);
+    }
 
     @Override
     protected final DataContainerNodeBuilder<YangInstanceIdentifier.NodeIdentifier, ContainerNode> getBuilder(
@@ -63,4 +69,5 @@ public abstract class ContainerNodeBaseParser<E> extends
 
     @Override
     protected abstract Map<QName, String> getAttributes(E e);
+
 }
diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/parser/ExtensibleParser.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/parser/ExtensibleParser.java
new file mode 100644 (file)
index 0000000..e2b5ec7
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2015 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 javax.annotation.Nullable;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNodeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.ToNormalizedNodeParser;
+
+/**
+ * Extensible parser allows its subclasses to customize the building process of normalized nodes
+ *
+ * @param <P>
+ * @param <E>
+ * @param <N>
+ * @param <S>
+ */
+public interface ExtensibleParser<P extends YangInstanceIdentifier.PathArgument, E, N extends NormalizedNode<P, ?>, S>
+        extends ToNormalizedNodeParser<E, N, S> {
+
+    /**
+     * Provide building strategy
+     */
+    BuildingStrategy<P, N> getBuildingStrategy();
+
+    /**
+     * Building strategy serves as a set of hooks into the parsing process.
+     *
+     * @param <P>
+     * @param <N>
+     */
+    interface BuildingStrategy<P extends YangInstanceIdentifier.PathArgument, N extends NormalizedNode<P, ?>> {
+
+        /**
+         * Build normalized node from its builder
+         *
+         * @param builder filled builder for node
+         * @return built normalized node or null if the node should not be built
+         */
+        @Nullable N build(NormalizedNodeBuilder<P, ?, N> builder);
+
+        /**
+         * Hook for subclasses to handle attributes associated with current node. This is called before the build method
+         * and allows subclasses to react to node's attributes e.g. modification operation
+         *
+         * @param attributes attributes for node
+         * @param containerBuilder builder created for node. Can be modified according to attributes e.g. remove attribute
+         */
+        void prepareAttributes(Map<QName, String> attributes, NormalizedNodeBuilder<P, ?, N> containerBuilder);
+    }
+}
index 4056d1da18512ddad3a32629ff1ea74d8856b262..f5dc67e1a322e8772d74456eca9f08ab3c162597 100644 (file)
@@ -7,27 +7,36 @@
  */
 package org.opendaylight.yangtools.yang.data.impl.schema.transform.base.parser;
 
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Iterables;
 import java.util.Map;
-
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
 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.builder.api.NormalizedNodeAttrBuilder;
-import org.opendaylight.yangtools.yang.data.impl.schema.transform.ToNormalizedNodeParser;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNodeBuilder;
 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> {
+public abstract class LeafNodeBaseParser<E> implements ExtensibleParser<NodeIdentifier, E, LeafNode<?>, LeafSchemaNode> {
+
+    private final BuildingStrategy<NodeIdentifier, LeafNode<?>> buildingStrategy;
+
+    public LeafNodeBaseParser() {
+        buildingStrategy = new SimpleLeafBuildingStrategy();
+    }
 
+    public LeafNodeBaseParser(final BuildingStrategy<NodeIdentifier, LeafNode<?>> buildingStrategy) {
+        this.buildingStrategy = buildingStrategy;
+    }
+
+    @SuppressWarnings("unchecked")
     @Override
     public final LeafNode<?> parse(Iterable<E> elements, LeafSchemaNode schema) {
         final int size = Iterables.size(elements);
@@ -36,11 +45,13 @@ public abstract class LeafNodeBaseParser<E> implements
         final E e = elements.iterator().next();
         Object value = parseLeaf(e, schema);
 
-        NormalizedNodeAttrBuilder<YangInstanceIdentifier.NodeIdentifier,Object,LeafNode<Object>> leafBuilder = Builders.leafBuilder(schema);
+        NormalizedNodeAttrBuilder<YangInstanceIdentifier.NodeIdentifier, Object, LeafNode<Object>> leafBuilder =
+                Builders.leafBuilder(schema);
 
         leafBuilder.withAttributes(getAttributes(e));
 
-        return leafBuilder.withValue(value).build();
+        final BuildingStrategy rawBuildingStrat = buildingStrategy;
+        return (LeafNode<?>) rawBuildingStrat.build(leafBuilder.withValue(value));
     }
 
     /**
@@ -59,4 +70,21 @@ public abstract class LeafNodeBaseParser<E> implements
      * @return attributes mapped to QNames
      */
     protected abstract Map<QName, String> getAttributes(E e);
+
+    @Override
+    public BuildingStrategy<NodeIdentifier, LeafNode<?>> getBuildingStrategy() {
+        return buildingStrategy;
+    }
+
+    public static class SimpleLeafBuildingStrategy implements BuildingStrategy<NodeIdentifier, LeafNode<?>> {
+        @Override
+        public LeafNode<?> build(final NormalizedNodeBuilder<NodeIdentifier, ?, LeafNode<?>> builder) {
+            return builder.build();
+        }
+
+        @Override
+        public void prepareAttributes(final Map<QName, String> attributes, final NormalizedNodeBuilder<NodeIdentifier, ?, LeafNode<?>> containerBuilder) {
+            // NOOP
+        }
+    }
 }
index 526cdf8615452893ccc3201a0cfdd1c26ea02eb0..7006c269ad0a4597a16f9b856659113202886662 100644 (file)
@@ -7,29 +7,38 @@
  */
 package org.opendaylight.yangtools.yang.data.impl.schema.transform.base.parser;
 
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Iterables;
 import java.util.Map;
-
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeWithValue;
 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.builder.api.NormalizedNodeAttrBuilder;
-import org.opendaylight.yangtools.yang.data.impl.schema.transform.ToNormalizedNodeParser;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNodeBuilder;
 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> {
+public abstract class LeafSetEntryNodeBaseParser<E> implements ExtensibleParser<YangInstanceIdentifier.NodeWithValue, E, LeafSetEntryNode<?>, LeafListSchemaNode> {
+
+    private final BuildingStrategy<YangInstanceIdentifier.NodeWithValue, LeafSetEntryNode<?>> buildingStrategy;
+
+    public LeafSetEntryNodeBaseParser() {
+        buildingStrategy = new SimpleLeafSetEntryBuildingStrategy();
+    }
 
+    public LeafSetEntryNodeBaseParser(final BuildingStrategy<YangInstanceIdentifier.NodeWithValue, LeafSetEntryNode<?>> buildingStrategy) {
+        this.buildingStrategy = buildingStrategy;
+    }
+
+    @SuppressWarnings("unchecked")
     @Override
-    public final LeafSetEntryNode<Object> parse(Iterable<E> elements, LeafListSchemaNode schema) {
+    public final LeafSetEntryNode<?> 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);
 
@@ -39,8 +48,15 @@ public abstract class LeafSetEntryNodeBaseParser<E> implements
         NormalizedNodeAttrBuilder<YangInstanceIdentifier.NodeWithValue, Object, LeafSetEntryNode<Object>> leafEntryBuilder = Builders
                 .leafSetEntryBuilder(schema);
         leafEntryBuilder.withAttributes(getAttributes(e));
+        leafEntryBuilder.withValue(value);
+
+        final BuildingStrategy rawBuildingStrat = buildingStrategy;
+        return (LeafSetEntryNode<?>) rawBuildingStrat.build(leafEntryBuilder);
+    }
 
-        return leafEntryBuilder.withValue(value).build();
+    @Override
+    public BuildingStrategy<NodeWithValue, LeafSetEntryNode<?>> getBuildingStrategy() {
+        return buildingStrategy;
     }
 
     /**
@@ -60,4 +76,15 @@ public abstract class LeafSetEntryNodeBaseParser<E> implements
      */
     protected abstract Map<QName, String> getAttributes(E e);
 
+    public static class SimpleLeafSetEntryBuildingStrategy implements BuildingStrategy<YangInstanceIdentifier.NodeWithValue, LeafSetEntryNode<?>> {
+
+        @Override
+        public LeafSetEntryNode<?> build(final NormalizedNodeBuilder<NodeWithValue, ?, LeafSetEntryNode<?>> builder) {
+            return builder.build();
+        }
+
+        @Override
+        public void prepareAttributes(final Map<QName, String> attributes, final NormalizedNodeBuilder<NodeWithValue, ?, LeafSetEntryNode<?>> containerBuilder) {
+        }
+    }
 }
index 4cdae37f3554f18f13d4f99872f3235f7839c310..3669cba16bad8c5e99aaabaa8feafe62df7d2d2b 100644 (file)
@@ -8,7 +8,6 @@
 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;
index dfa34abcc7d6881bb2ba696deb4c7e62202556c1..cd0b478ec0a4c6c53903c5d21a4f12014d3249c2 100644 (file)
@@ -10,6 +10,7 @@ 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.YangInstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.schema.DataContainerNode;
 import org.opendaylight.yangtools.yang.data.impl.schema.SchemaUtils;
 import org.opendaylight.yangtools.yang.model.api.AugmentationSchema;
@@ -24,8 +25,15 @@ import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
  * @param <E>
  *            type of elements to be parsed
  */
-public abstract class ListEntryNodeBaseParser<E, N extends DataContainerNode<?>> extends
-        BaseDispatcherParser<E, N, ListSchemaNode> {
+public abstract class ListEntryNodeBaseParser<P extends YangInstanceIdentifier.PathArgument, E, N extends DataContainerNode<P>> extends
+        BaseDispatcherParser<E, P, N, ListSchemaNode> {
+
+    public ListEntryNodeBaseParser(final BuildingStrategy<P, N> buildingStrategy) {
+        super(buildingStrategy);
+    }
+
+    public ListEntryNodeBaseParser() {
+    }
 
     @Override
     protected final Set<DataSchemaNode> getRealSchemasForAugment(final ListSchemaNode schema, final AugmentationSchema augmentSchema) {
index 67c97a767d042c56956fae92d2fa684b19293612..f8bc9c120b274b99948d9aa9de5ea73bfadaf7a1 100644 (file)
@@ -8,9 +8,12 @@
 package org.opendaylight.yangtools.yang.data.impl.schema.transform.base.parser;
 
 import java.util.Collections;
+import java.util.Map;
+import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
 import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.CollectionNodeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNodeBuilder;
 import org.opendaylight.yangtools.yang.data.impl.schema.transform.ToNormalizedNodeParser;
 import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
 
@@ -21,17 +24,32 @@ import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
  *            type of elements to be parsed
  */
 public abstract class ListNodeBaseParser<E, N extends NormalizedNode<?, ?>, O extends NormalizedNode<YangInstanceIdentifier.NodeIdentifier, ?>, S extends ListSchemaNode>
-        implements ToNormalizedNodeParser<E, O, S> {
+        implements ExtensibleParser<YangInstanceIdentifier.NodeIdentifier, E, O, S> {
+
+    private final BuildingStrategy<YangInstanceIdentifier.NodeIdentifier, O> buildingStrategy;
+
+    public ListNodeBaseParser() {
+        buildingStrategy = new SimpleListNodeBuildingStrategy<>();
+    }
+
+    public ListNodeBaseParser(final BuildingStrategy<YangInstanceIdentifier.NodeIdentifier, O> buildingStrategy) {
+        this.buildingStrategy = buildingStrategy;
+    }
 
     @Override
-    public final O parse(Iterable<E> childNodes, S schema) {
+    public O parse(Iterable<E> childNodes, S schema) {
         CollectionNodeBuilder<N, O> listBuilder = provideBuilder(schema);
+
+        buildingStrategy.prepareAttributes(Collections.<QName, String>emptyMap(), listBuilder);
+
         for (E childNode : childNodes) {
             N listChild = getListEntryNodeParser().parse(Collections.singletonList(childNode), schema);
-            listBuilder.withChild(listChild);
+            if (listChild != null) {
+                listBuilder.withChild(listChild);
+            }
         }
 
-        return listBuilder.build();
+        return buildingStrategy.build(listBuilder);
     }
 
     /**
@@ -46,4 +64,21 @@ public abstract class ListNodeBaseParser<E, N extends NormalizedNode<?, ?>, O ex
      * @return prepares builder which will contain entries of list according to concrete list type
      */
     protected abstract CollectionNodeBuilder<N, O> provideBuilder(S schema);
+
+    @Override
+    public BuildingStrategy<YangInstanceIdentifier.NodeIdentifier, O> getBuildingStrategy() {
+        return buildingStrategy;
+    }
+
+    public static class SimpleListNodeBuildingStrategy<O extends NormalizedNode<YangInstanceIdentifier.NodeIdentifier, ?>> implements BuildingStrategy<YangInstanceIdentifier.NodeIdentifier, O> {
+        @Override
+        public O build(final NormalizedNodeBuilder<YangInstanceIdentifier.NodeIdentifier, ?, O> builder) {
+            return builder.build();
+        }
+
+        @Override
+        public void prepareAttributes(final Map<QName, String> attributes, final NormalizedNodeBuilder<YangInstanceIdentifier.NodeIdentifier, ?, O> containerBuilder) {
+            // NOOP
+        }
+    }
 }
index a57a694e126668684bf9310804aa0f50aea7f062..805634046554609a8b3ca5e9b0f3d1c9019a6932 100644 (file)
@@ -7,6 +7,7 @@
  */
 package org.opendaylight.yangtools.yang.data.impl.schema.transform.base.parser;
 
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 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;
@@ -21,6 +22,13 @@ import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
  */
 public abstract class MapNodeBaseParser<E> extends ListNodeBaseParser<E, MapEntryNode, MapNode, ListSchemaNode> {
 
+    public MapNodeBaseParser() {
+    }
+
+    public MapNodeBaseParser(final BuildingStrategy<YangInstanceIdentifier.NodeIdentifier, MapNode> buildingStrategy) {
+        super(buildingStrategy);
+    }
+
     protected CollectionNodeBuilder<MapEntryNode, MapNode> provideBuilder(ListSchemaNode schema) {
         return Builders.mapBuilder(schema);
     }
index 6278accb61656b4ccad44924f31418d9e425e6d1..a2ca255ce8b0ac7aee2772b8da0f86e9d18cd0cd 100644 (file)
@@ -7,6 +7,7 @@
  */
 package org.opendaylight.yangtools.yang.data.impl.schema.transform.base.parser;
 
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
 import org.opendaylight.yangtools.yang.data.api.schema.OrderedMapNode;
 import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
@@ -21,8 +22,17 @@ import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
  */
 public abstract class OrderedListNodeBaseParser<E> extends
         ListNodeBaseParser<E, MapEntryNode, OrderedMapNode, ListSchemaNode> {
+
+    public OrderedListNodeBaseParser() {
+    }
+
+    public OrderedListNodeBaseParser(final BuildingStrategy<YangInstanceIdentifier.NodeIdentifier, OrderedMapNode> buildingStrategy) {
+        super(buildingStrategy);
+    }
+
     @Override
     protected CollectionNodeBuilder<MapEntryNode, OrderedMapNode> provideBuilder(ListSchemaNode schema) {
         return Builders.orderedMapBuilder(schema);
     }
+
 }
index 14d47890cf8ab66510e8915e927003ba0df539c8..73e7f3905292b4b54fa9a98707bdfc0aa218fd47 100644 (file)
@@ -22,6 +22,14 @@ import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
  */
 public abstract class UnkeyedListNodeBaseParser<E> extends
         ListNodeBaseParser<E, UnkeyedListEntryNode, UnkeyedListNode, ListSchemaNode> {
+
+    public UnkeyedListNodeBaseParser(final BuildingStrategy<NodeIdentifier, UnkeyedListNode> buildingStrategy) {
+        super(buildingStrategy);
+    }
+
+    public UnkeyedListNodeBaseParser() {
+    }
+
     @Override
     protected CollectionNodeBuilder<UnkeyedListEntryNode, UnkeyedListNode> provideBuilder(ListSchemaNode schema) {
         CollectionNodeBuilder<UnkeyedListEntryNode, UnkeyedListNode> listBuilder = Builders.unkeyedListBuilder();
index 73167f407a522232c3c105311ef26c2e5c1b9055..3fed808ad9814280b2c38f520fc5e70bdbfc457e 100644 (file)
@@ -7,15 +7,16 @@
  */
 package org.opendaylight.yangtools.yang.data.impl.schema.transform.dom.parser;
 
+import com.google.common.base.Preconditions;
+import com.google.common.collect.LinkedListMultimap;
 import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.AugmentationNode;
 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;
-
 final class AugmentationNodeDomParser extends AugmentationNodeBaseParser<Element> {
 
     private final NodeParserDispatcher<Element> dispatcher;
@@ -31,6 +32,13 @@ final class AugmentationNodeDomParser extends AugmentationNodeBaseParser<Element
         this.strictParsing = strictParsing;
     }
 
+    public AugmentationNodeDomParser(final BuildingStrategy<YangInstanceIdentifier.AugmentationIdentifier, AugmentationNode> buildingStrategy,
+                                     final NodeParserDispatcher<Element> dispatcher, final boolean strictParsing) {
+        super(buildingStrategy);
+        this.dispatcher = Preconditions.checkNotNull(dispatcher);
+        this.strictParsing = strictParsing;
+    }
+
     @Override
     protected LinkedListMultimap<QName, Element> mapChildElements(Iterable<Element> elements) {
         return DomUtils.mapChildElements(elements);
index 97e8a6171cdaaf0d82c1031247c181385fcbb0d6..2c2ccc6ad7aaf46a578412c78092e3ebcd62d28a 100644 (file)
@@ -7,25 +7,31 @@
  */
 package org.opendaylight.yangtools.yang.data.impl.schema.transform.dom.parser;
 
+import com.google.common.base.Preconditions;
+import com.google.common.collect.LinkedListMultimap;
 import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode;
 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;
-
 final class ChoiceNodeDomParser extends ChoiceNodeBaseParser<Element> {
 
     private final NodeParserDispatcher<Element> dispatcher;
 
-    ChoiceNodeDomParser(NodeParserDispatcher<Element> dispatcher) {
+    ChoiceNodeDomParser(final NodeParserDispatcher<Element> dispatcher) {
+        this.dispatcher = Preconditions.checkNotNull(dispatcher);
+    }
+
+    ChoiceNodeDomParser(final NodeParserDispatcher<Element> dispatcher, final BuildingStrategy<YangInstanceIdentifier.NodeIdentifier, ChoiceNode> buildingStrategy) {
+        super(buildingStrategy);
         this.dispatcher = Preconditions.checkNotNull(dispatcher);
     }
 
     @Override
-    protected LinkedListMultimap<QName, Element> mapChildElements(Iterable<Element> xml) {
+    protected LinkedListMultimap<QName, Element> mapChildElements(final Iterable<Element> xml) {
         return DomUtils.mapChildElements(xml);
     }
 
@@ -33,4 +39,5 @@ final class ChoiceNodeDomParser extends ChoiceNodeBaseParser<Element> {
     protected NodeParserDispatcher<Element> getDispatcher() {
         return dispatcher;
     }
+
 }
index ed4f2772ed453d83430deeac6525b871091583bc..397df436a5feefef5d5ac07378efab8450f162a9 100644 (file)
@@ -7,17 +7,17 @@
  */
 package org.opendaylight.yangtools.yang.data.impl.schema.transform.dom.parser;
 
+import com.google.common.base.Preconditions;
+import com.google.common.collect.LinkedListMultimap;
 import java.util.Map;
-
 import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
 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;
-
 final class ContainerNodeDomParser extends ContainerNodeBaseParser<Element> {
 
     private final NodeParserDispatcher<Element> dispatcher;
@@ -25,10 +25,16 @@ final class ContainerNodeDomParser extends ContainerNodeBaseParser<Element> {
 
     ContainerNodeDomParser(final NodeParserDispatcher<Element> dispatcher) {
         this.dispatcher = Preconditions.checkNotNull(dispatcher);
-        this.strictParsing = super.strictParsing();
+        strictParsing = super.strictParsing();
+    }
+
+    public ContainerNodeDomParser(final NodeParserDispatcher<Element> dispatcher, final boolean strictParsing) {
+        this.dispatcher = dispatcher;
+        this.strictParsing = strictParsing;
     }
 
-    ContainerNodeDomParser(final NodeParserDispatcher<Element> dispatcher, final boolean strictParsing) {
+    ContainerNodeDomParser(final NodeParserDispatcher<Element> dispatcher, final BuildingStrategy<YangInstanceIdentifier.NodeIdentifier, ContainerNode> parsingStrategy, final boolean strictParsing) {
+        super(parsingStrategy);
         this.dispatcher = Preconditions.checkNotNull(dispatcher);
         this.strictParsing = strictParsing;
     }
index 8e6381748ef856c7963739b0caf01a164795d64b..b86289a7be4ba4e30e39bf606dffd82f5cae3351 100644 (file)
@@ -7,6 +7,7 @@
  */
 package org.opendaylight.yangtools.yang.data.impl.schema.transform.dom.parser;
 
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.schema.AnyXmlNode;
 import org.opendaylight.yangtools.yang.data.api.schema.AugmentationNode;
 import org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode;
@@ -22,6 +23,11 @@ import org.opendaylight.yangtools.yang.data.api.schema.UnkeyedListNode;
 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.ToNormalizedNodeParserFactory;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.parser.BaseDispatcherParser;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.parser.ExtensibleParser;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.parser.LeafNodeBaseParser;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.parser.LeafSetEntryNodeBaseParser;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.parser.ListNodeBaseParser;
 import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.parser.NodeParserDispatcher;
 import org.opendaylight.yangtools.yang.model.api.AnyXmlSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.AugmentationSchema;
@@ -34,6 +40,7 @@ import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 import org.w3c.dom.Element;
 
 public final class DomToNormalizedNodeParserFactory implements ToNormalizedNodeParserFactory<Element> {
+
     private final AugmentationNodeDomParser augmentationNodeParser;
     private final ChoiceNodeDomParser choiceNodeParser;
     private final ContainerNodeDomParser containerNodeParser;
@@ -67,6 +74,31 @@ public final class DomToNormalizedNodeParserFactory implements ToNormalizedNodeP
         augmentationNodeParser = new AugmentationNodeDomParser(dispatcher, strictParsing);
     }
 
+    private DomToNormalizedNodeParserFactory(final XmlCodecProvider codecProvider, final SchemaContext schema,
+                                             final BuildingStrategyProvider buildingStratProvider, final boolean strictParsing) {
+        leafNodeParser = new LeafNodeDomParser(codecProvider, schema, buildingStratProvider.forLeaf());
+        leafSetEntryNodeParser = new LeafSetEntryNodeDomParser(codecProvider, schema, buildingStratProvider.forLeafSetEntry());
+
+        // no buildingStrategy for Augment (no use case for now)
+        leafSetNodeParser = new LeafSetNodeDomParser(leafSetEntryNodeParser);
+        // no buildingStrategy for anyXml (probably not necessary)
+        anyXmlNodeParser = new AnyXmlDomParser();
+
+        final NodeParserDispatcher<Element> dispatcher = new NodeParserDispatcher.BaseNodeParserDispatcher<Element>(this) {
+
+        };
+
+        containerNodeParser = new ContainerNodeDomParser(dispatcher, buildingStratProvider.forContainer(), strictParsing);
+        mapEntryNodeParser = new MapEntryNodeDomParser(dispatcher, buildingStratProvider.forMapEntry(), strictParsing);
+        mapNodeParser = new MapNodeDomParser(mapEntryNodeParser, buildingStratProvider.forMap());
+        orderedListNodeParser = new OrderedListNodeDomParser(mapEntryNodeParser, buildingStratProvider.forOrderedList());
+        unkeyedListEntryNodeParser = new UnkeyedListEntryNodeDomParser(buildingStratProvider.forUnkeyedListEntry(), dispatcher);
+        unkeyedListNodeParser = new UnkeyedListNodeDomParser(buildingStratProvider.forUnkeyedList(), unkeyedListEntryNodeParser);
+        choiceNodeParser = new ChoiceNodeDomParser(dispatcher, buildingStratProvider.forChoice());
+        // no buildingStrategy for Augment (no use case for now)
+        augmentationNodeParser = new AugmentationNodeDomParser(buildingStratProvider.forAugmentation(), dispatcher, strictParsing);
+    }
+
     @Deprecated
     private DomToNormalizedNodeParserFactory(final XmlCodecProvider codecProvider) {
         leafNodeParser = new LeafNodeDomParser(codecProvider);
@@ -96,6 +128,17 @@ public final class DomToNormalizedNodeParserFactory implements ToNormalizedNodeP
         return new DomToNormalizedNodeParserFactory(codecProvider, schema, true);
     }
 
+    public static DomToNormalizedNodeParserFactory getInstance(final XmlCodecProvider codecProvider, final SchemaContext schema,
+                                                               final BuildingStrategyProvider buildingStratProvider) {
+        return new DomToNormalizedNodeParserFactory(codecProvider, schema, buildingStratProvider, true);
+    }
+
+    public static DomToNormalizedNodeParserFactory getInstance(final XmlCodecProvider codecProvider, final SchemaContext schema,
+                                                               final BuildingStrategyProvider buildingStratProvider,
+                                                               final boolean strictParsing) {
+        return new DomToNormalizedNodeParserFactory(codecProvider, schema, buildingStratProvider, strictParsing);
+    }
+
     @Deprecated
     public static DomToNormalizedNodeParserFactory getInstance(final XmlCodecProvider codecProvider) {
         return new DomToNormalizedNodeParserFactory(codecProvider);
@@ -160,4 +203,50 @@ public final class DomToNormalizedNodeParserFactory implements ToNormalizedNodeP
     public ToNormalizedNodeParser<Element, AnyXmlNode, AnyXmlSchemaNode> getAnyXmlNodeParser() {
         return anyXmlNodeParser;
     }
+
+    /**
+     * Base provider of building strategies used for customizing parsing process
+     */
+    public static abstract class BuildingStrategyProvider {
+
+        protected ExtensibleParser.BuildingStrategy<YangInstanceIdentifier.NodeIdentifier,LeafNode<?>> forLeaf() {
+            return new LeafNodeBaseParser.SimpleLeafBuildingStrategy();
+        }
+
+        protected ExtensibleParser.BuildingStrategy<YangInstanceIdentifier.NodeWithValue,LeafSetEntryNode<?>> forLeafSetEntry() {
+            return new LeafSetEntryNodeBaseParser.SimpleLeafSetEntryBuildingStrategy();
+        }
+
+        protected ExtensibleParser.BuildingStrategy<YangInstanceIdentifier.NodeIdentifier,ContainerNode> forContainer() {
+            return new BaseDispatcherParser.SimpleBuildingStrategy<>();
+        }
+
+        protected ExtensibleParser.BuildingStrategy<YangInstanceIdentifier.NodeIdentifierWithPredicates,MapEntryNode> forMapEntry() {
+            return new BaseDispatcherParser.SimpleBuildingStrategy<>();
+        }
+
+        protected ExtensibleParser.BuildingStrategy<YangInstanceIdentifier.NodeIdentifier,MapNode> forMap() {
+            return new ListNodeBaseParser.SimpleListNodeBuildingStrategy<>();
+        }
+
+        protected ExtensibleParser.BuildingStrategy<YangInstanceIdentifier.NodeIdentifier,OrderedMapNode> forOrderedList() {
+            return new ListNodeBaseParser.SimpleListNodeBuildingStrategy<>();
+        }
+
+        protected ExtensibleParser.BuildingStrategy<YangInstanceIdentifier.NodeIdentifier,UnkeyedListEntryNode> forUnkeyedListEntry() {
+            return new BaseDispatcherParser.SimpleBuildingStrategy<>();
+        }
+
+        protected ExtensibleParser.BuildingStrategy<YangInstanceIdentifier.NodeIdentifier,UnkeyedListNode> forUnkeyedList() {
+            return new ListNodeBaseParser.SimpleListNodeBuildingStrategy<>();
+        }
+
+        protected ExtensibleParser.BuildingStrategy<YangInstanceIdentifier.NodeIdentifier,ChoiceNode> forChoice() {
+            return new BaseDispatcherParser.SimpleBuildingStrategy<>();
+        }
+
+        public ExtensibleParser.BuildingStrategy<YangInstanceIdentifier.AugmentationIdentifier, AugmentationNode> forAugmentation() {
+            return new BaseDispatcherParser.SimpleBuildingStrategy<>();
+        }
+    }
 }
index 2e8ab87bd749d0134ee6ad68f9cf058d2e263bb7..25b57ccf083f91c5531c97e437f89226768d187e 100644 (file)
@@ -7,9 +7,11 @@
  */
 package org.opendaylight.yangtools.yang.data.impl.schema.transform.dom.parser;
 
+import com.google.common.base.Preconditions;
 import java.util.Map;
-
 import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+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.schema.transform.base.parser.LeafNodeBaseParser;
 import org.opendaylight.yangtools.yang.data.impl.schema.transform.dom.DomUtils;
@@ -17,8 +19,6 @@ import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 import org.w3c.dom.Element;
 
-import com.google.common.base.Preconditions;
-
 final class LeafNodeDomParser extends LeafNodeBaseParser<Element> {
 
     private final XmlCodecProvider codecProvider;
@@ -29,6 +29,12 @@ final class LeafNodeDomParser extends LeafNodeBaseParser<Element> {
         this.codecProvider = Preconditions.checkNotNull(codecProvider);
     }
 
+    LeafNodeDomParser(XmlCodecProvider codecProvider, final SchemaContext schema, final BuildingStrategy<YangInstanceIdentifier.NodeIdentifier, LeafNode<?>> strategy) {
+        super(strategy);
+        this.ctx = schema;
+        this.codecProvider = Preconditions.checkNotNull(codecProvider);
+    }
+
     @Deprecated
     LeafNodeDomParser(XmlCodecProvider codecProvider) {
         this(codecProvider, null);
@@ -43,4 +49,5 @@ final class LeafNodeDomParser extends LeafNodeBaseParser<Element> {
     protected Map<QName, String> getAttributes(Element element) {
         return DomUtils.toAttributes(element.getAttributes());
     }
+
 }
index 0458cd5d106644cac40ed247956a640385fe9d8f..decf9013371a37003805a2381110761e6ca9e9f9 100644 (file)
@@ -7,9 +7,11 @@
  */
 package org.opendaylight.yangtools.yang.data.impl.schema.transform.dom.parser;
 
+import com.google.common.base.Preconditions;
 import java.util.Map;
-
 import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+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.schema.transform.base.parser.LeafSetEntryNodeBaseParser;
 import org.opendaylight.yangtools.yang.data.impl.schema.transform.dom.DomUtils;
@@ -17,15 +19,19 @@ import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 import org.w3c.dom.Element;
 
-import com.google.common.base.Preconditions;
-
 final class LeafSetEntryNodeDomParser extends LeafSetEntryNodeBaseParser<Element> {
 
     private final XmlCodecProvider codecProvider;
     private final SchemaContext ctx;
 
-    LeafSetEntryNodeDomParser(XmlCodecProvider codecProvider, final SchemaContext schema) {
-        ctx = schema;
+    LeafSetEntryNodeDomParser(final XmlCodecProvider codecProvider, final SchemaContext schema) {
+        this.ctx = schema;
+        this.codecProvider = Preconditions.checkNotNull(codecProvider);
+    }
+
+    LeafSetEntryNodeDomParser(final XmlCodecProvider codecProvider, final SchemaContext schema, final  BuildingStrategy<YangInstanceIdentifier.NodeWithValue, LeafSetEntryNode<?>> strategy) {
+        super(strategy);
+        this.ctx = schema;
         this.codecProvider = Preconditions.checkNotNull(codecProvider);
     }
 
@@ -43,4 +49,5 @@ final class LeafSetEntryNodeDomParser extends LeafSetEntryNodeBaseParser<Element
     protected Map<QName, String> getAttributes(Element element) {
         return DomUtils.toAttributes(element.getAttributes());
     }
+
 }
index 92496d79f7bcb5c8af6d3818c7ccb0a03b8c237d..90aca17fd84a1192a0d4e0af499e0649f35e0982 100644 (file)
@@ -11,13 +11,14 @@ import com.google.common.base.Preconditions;
 import com.google.common.collect.LinkedListMultimap;
 import java.util.Map;
 import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.schema.DataContainerNode;
 import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.parser.ListEntryNodeBaseParser;
 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;
 
-abstract class ListEntryNodeDomParser<N extends DataContainerNode<?>> extends ListEntryNodeBaseParser<Element, N> {
+abstract class ListEntryNodeDomParser<P extends YangInstanceIdentifier.PathArgument, N extends DataContainerNode<P>> extends ListEntryNodeBaseParser<P, Element, N> {
 
     private final NodeParserDispatcher<Element> dispatcher;
 
@@ -25,6 +26,11 @@ abstract class ListEntryNodeDomParser<N extends DataContainerNode<?>> extends Li
         this.dispatcher = Preconditions.checkNotNull(dispatcher);
     }
 
+    ListEntryNodeDomParser(final BuildingStrategy<P, N> buildingStrategy, final NodeParserDispatcher<Element> dispatcher) {
+        super(buildingStrategy);
+        this.dispatcher = dispatcher;
+    }
+
     @Override
     protected LinkedListMultimap<QName, Element> mapChildElements(Iterable<Element> elements) {
         return DomUtils.mapChildElementsForSingletonNode(elements.iterator().next());
index a6c467c22224159dcb4120bf84233752bb18f13a..05a086476cfa9216338fe7f0f4eabbe3426aded3 100644 (file)
@@ -15,12 +15,14 @@ import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.parser.No
 import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
 import org.w3c.dom.Element;
 
-final class MapEntryNodeDomParser extends ListEntryNodeDomParser<MapEntryNode> {
+final class MapEntryNodeDomParser extends ListEntryNodeDomParser<YangInstanceIdentifier.NodeIdentifierWithPredicates, MapEntryNode> {
 
     private final boolean strictParsing;
 
     MapEntryNodeDomParser(final NodeParserDispatcher<Element> dispatcher) {
         super(dispatcher);
+        // TODO strict parsing attribute should be injected into superclass via a constructor
+        // WIth current approach (getter) we have to call super.strictParsing in constructor and cannot reuse constructors
         this.strictParsing = super.strictParsing();
     }
 
@@ -29,6 +31,12 @@ final class MapEntryNodeDomParser extends ListEntryNodeDomParser<MapEntryNode> {
         this.strictParsing = strictParsing;
     }
 
+    MapEntryNodeDomParser(final NodeParserDispatcher<Element> dispatcher, final BuildingStrategy<YangInstanceIdentifier.NodeIdentifierWithPredicates, MapEntryNode> strategy,
+                          final boolean strictParsing) {
+        super(strategy, dispatcher);
+        this.strictParsing = strictParsing;
+    }
+
     @Override
     protected final DataContainerNodeBuilder<YangInstanceIdentifier.NodeIdentifierWithPredicates, MapEntryNode> getBuilder(
             ListSchemaNode schema) {
index 748564fdd1c6a3493112b3390259622caf6b3390..0f1c822ae101f29590906c58f31c208539c60189 100644 (file)
@@ -7,7 +7,9 @@
  */
 package org.opendaylight.yangtools.yang.data.impl.schema.transform.dom.parser;
 
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 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.ToNormalizedNodeParser;
 import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.parser.MapNodeBaseParser;
 import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
@@ -17,7 +19,12 @@ final class MapNodeDomParser extends MapNodeBaseParser<Element> {
 
     private final MapEntryNodeDomParser mapEntryParser;
 
-    MapNodeDomParser(MapEntryNodeDomParser mapEntryParser) {
+    MapNodeDomParser(final MapEntryNodeDomParser mapEntryParser) {
+        this.mapEntryParser = mapEntryParser;
+    }
+
+    MapNodeDomParser(MapEntryNodeDomParser mapEntryParser, final BuildingStrategy<YangInstanceIdentifier.NodeIdentifier, MapNode> strategy) {
+        super(strategy);
         this.mapEntryParser = mapEntryParser;
     }
 
@@ -25,4 +32,5 @@ final class MapNodeDomParser extends MapNodeBaseParser<Element> {
     protected ToNormalizedNodeParser<Element, MapEntryNode, ListSchemaNode> getListEntryNodeParser() {
         return mapEntryParser;
     }
+
 }
index 787bff8856b7c2ec2bcebd5301a7056ba72c19e4..920c30f3421be8de7eb4055b38eab951351034b8 100644 (file)
@@ -7,7 +7,9 @@
  */
 package org.opendaylight.yangtools.yang.data.impl.schema.transform.dom.parser;
 
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
+import org.opendaylight.yangtools.yang.data.api.schema.OrderedMapNode;
 import org.opendaylight.yangtools.yang.data.impl.schema.transform.ToNormalizedNodeParser;
 import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.parser.OrderedListNodeBaseParser;
 import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
@@ -17,7 +19,12 @@ final class OrderedListNodeDomParser extends OrderedListNodeBaseParser<Element>
 
     private final MapEntryNodeDomParser mapEntryNodeParser;
 
-    OrderedListNodeDomParser(MapEntryNodeDomParser mapEntryNodeParser) {
+    OrderedListNodeDomParser(final MapEntryNodeDomParser mapEntryNodeParser) {
+        this.mapEntryNodeParser = mapEntryNodeParser;
+    }
+
+    OrderedListNodeDomParser(MapEntryNodeDomParser mapEntryNodeParser, final BuildingStrategy<YangInstanceIdentifier.NodeIdentifier, OrderedMapNode> strategy) {
+        super(strategy);
         this.mapEntryNodeParser = mapEntryNodeParser;
     }
 
@@ -25,4 +32,5 @@ final class OrderedListNodeDomParser extends OrderedListNodeBaseParser<Element>
     protected ToNormalizedNodeParser<Element, MapEntryNode, ListSchemaNode> getListEntryNodeParser() {
         return mapEntryNodeParser;
     }
+
 }
index 781f06cb71ac917efb7061bb51952842edb8fc54..79d478fb47692b5746d13bbedfce1114a61f070c 100644 (file)
@@ -16,12 +16,16 @@ import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.parser.No
 import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
 import org.w3c.dom.Element;
 
-final class UnkeyedListEntryNodeDomParser extends ListEntryNodeDomParser<UnkeyedListEntryNode> {
+final class UnkeyedListEntryNodeDomParser extends ListEntryNodeDomParser<YangInstanceIdentifier.NodeIdentifier, UnkeyedListEntryNode> {
 
     UnkeyedListEntryNodeDomParser(final NodeParserDispatcher<Element> dispatcher) {
         super(dispatcher);
     }
 
+    UnkeyedListEntryNodeDomParser(final BuildingStrategy<NodeIdentifier, UnkeyedListEntryNode> buildingStrategy, final NodeParserDispatcher<Element> dispatcher) {
+        super(buildingStrategy, dispatcher);
+    }
+
     @Override
     protected final DataContainerNodeBuilder<YangInstanceIdentifier.NodeIdentifier, UnkeyedListEntryNode> getBuilder(
             ListSchemaNode schema) {
index 15eed32a2df5f6bfb4faab65279bd7e8cf9c103e..21ec64e5a527509257246c6f5c3f8762edd18840 100644 (file)
@@ -7,7 +7,9 @@
  */
 package org.opendaylight.yangtools.yang.data.impl.schema.transform.dom.parser;
 
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.schema.UnkeyedListEntryNode;
+import org.opendaylight.yangtools.yang.data.api.schema.UnkeyedListNode;
 import org.opendaylight.yangtools.yang.data.impl.schema.transform.ToNormalizedNodeParser;
 import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.parser.UnkeyedListNodeBaseParser;
 import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
@@ -21,8 +23,14 @@ final class UnkeyedListNodeDomParser extends UnkeyedListNodeBaseParser<Element>
         this.unkeyedListEntryNodeParser = unkeyedListEntryNodeParser;
     }
 
+    UnkeyedListNodeDomParser(final BuildingStrategy<YangInstanceIdentifier.NodeIdentifier, UnkeyedListNode> buildingStrategy, final UnkeyedListEntryNodeDomParser unkeyedListEntryNodeParser) {
+        super(buildingStrategy);
+        this.unkeyedListEntryNodeParser = unkeyedListEntryNodeParser;
+    }
+
     @Override
     protected ToNormalizedNodeParser<Element, UnkeyedListEntryNode, ListSchemaNode> getListEntryNodeParser() {
         return unkeyedListEntryNodeParser;
     }
+
 }
index f05db1e5da95e06c6c40afc4acf67d1020467368..2fd5694c011f1b96ce066ae767fcadf917bb2000 100644 (file)
@@ -178,7 +178,7 @@ public class YangDataOperationsTest {
         Document currentConfigElement = readXmlToDocument(resourceAsStream);
         Preconditions.checkNotNull(currentConfigElement);
 
-        return Optional.of(DomToNormalizedNodeParserFactory.getInstance(DomUtils.defaultValueCodecProvider(), schema).getContainerNodeParser().parse(
+        return Optional.fromNullable(DomToNormalizedNodeParserFactory.getInstance(DomUtils.defaultValueCodecProvider(), schema).getContainerNodeParser().parse(
                 Collections.singletonList(currentConfigElement.getDocumentElement()), containerNode));
     }