Merge "BUG-2882: introduce cursor-based modification API" into stable/lithium
authorRobert Varga <rovarga@cisco.com>
Mon, 4 May 2015 07:37:16 +0000 (07:37 +0000)
committerGerrit Code Review <gerrit@opendaylight.org>
Mon, 4 May 2015 07:37:16 +0000 (07:37 +0000)
38 files changed:
code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/ChoiceNodeCodecContext.java
code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/DataContainerCodecContext.java
code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/DataObjectCodecContext.java
code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/IncorrectNestingException.java [new file with mode: 0644]
code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/LeafNodeCodecContext.java
code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/MissingSchemaException.java [new file with mode: 0644]
code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/MissingSchemaForClassException.java [new file with mode: 0644]
code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/SchemaRootCodecContext.java
code-generator/binding-data-codec/src/test/java/org/opendaylight/yangtools/binding/data/codec/test/ExceptionReportingTest.java [new file with mode: 0644]
code-generator/binding-generator-impl/src/main/java/org/opendaylight/yangtools/sal/binding/generator/impl/BindingGeneratorImpl.java
code-generator/binding-generator-impl/src/main/java/org/opendaylight/yangtools/sal/binding/generator/util/BindingRuntimeContext.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 5240ecf6104ea600ad9cd092871b957362386657..7ab7e6b346e0dd972b9727ddbfb4f02f9e716afa 100644 (file)
@@ -23,6 +23,7 @@ import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument;
 import org.opendaylight.yangtools.yang.binding.util.BindingReflections;
 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.ChoiceNode;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNodeContainer;
 import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode;
@@ -39,27 +40,27 @@ final class ChoiceNodeCodecContext<D extends DataObject> extends DataContainerCo
 
     public ChoiceNodeCodecContext(final DataContainerCodecPrototype<ChoiceSchemaNode> prototype) {
         super(prototype);
-        Map<YangInstanceIdentifier.PathArgument, DataContainerCodecPrototype<?>> byYangCaseChildBuilder = new HashMap<>();
-        Map<Class<?>, DataContainerCodecPrototype<?>> byClassBuilder = new HashMap<>();
-        Map<Class<?>, DataContainerCodecPrototype<?>> byCaseChildClassBuilder = new HashMap<>();
-        Set<Class<?>> potentialSubstitutions = new HashSet<>();
+        final Map<YangInstanceIdentifier.PathArgument, DataContainerCodecPrototype<?>> byYangCaseChildBuilder = new HashMap<>();
+        final Map<Class<?>, DataContainerCodecPrototype<?>> byClassBuilder = new HashMap<>();
+        final Map<Class<?>, DataContainerCodecPrototype<?>> byCaseChildClassBuilder = new HashMap<>();
+        final Set<Class<?>> potentialSubstitutions = new HashSet<>();
         // Walks all cases for supplied choice in current runtime context
-        for (Class<?> caze : factory().getRuntimeContext().getCases(getBindingClass())) {
+        for (final Class<?> caze : factory().getRuntimeContext().getCases(getBindingClass())) {
             // We try to load case using exact match thus name
             // and original schema must equals
-            DataContainerCodecPrototype<ChoiceCaseNode> cazeDef = loadCase(caze);
+            final DataContainerCodecPrototype<ChoiceCaseNode> cazeDef = loadCase(caze);
             // If we have case definition, this case is instantiated
             // at current location and thus is valid in context of parent choice
             if (cazeDef != null) {
                 byClassBuilder.put(cazeDef.getBindingClass(), cazeDef);
                 // Updates collection of case children
                 @SuppressWarnings("unchecked")
-                Class<? extends DataObject> cazeCls = (Class<? extends DataObject>) caze;
-                for (Class<? extends DataObject> cazeChild : BindingReflections.getChildrenClasses(cazeCls)) {
+                final Class<? extends DataObject> cazeCls = (Class<? extends DataObject>) caze;
+                for (final Class<? extends DataObject> cazeChild : BindingReflections.getChildrenClasses(cazeCls)) {
                     byCaseChildClassBuilder.put(cazeChild, cazeDef);
                 }
                 // Updates collection of YANG instance identifier to case
-                for (DataSchemaNode cazeChild : cazeDef.getSchema().getChildNodes()) {
+                for (final DataSchemaNode cazeChild : cazeDef.getSchema().getChildNodes()) {
                     byYangCaseChildBuilder.put(new NodeIdentifier(cazeChild.getQName()), cazeDef);
                 }
             } else {
@@ -71,7 +72,7 @@ final class ChoiceNodeCodecContext<D extends DataObject> extends DataContainerCo
             }
         }
 
-        Map<Class<?>, DataContainerCodecPrototype<?>> bySubstitutionBuilder = new HashMap<>();
+        final Map<Class<?>, DataContainerCodecPrototype<?>> bySubstitutionBuilder = new HashMap<>();
         /*
          * Walks all cases which are not directly instantiated and
          * tries to match them to instantiated cases - represent same data as instantiated case,
@@ -79,8 +80,8 @@ final class ChoiceNodeCodecContext<D extends DataObject> extends DataContainerCo
          * binding specification, that if choice is in grouping schema path location is lost,
          * and users may use incorrect case class using copy builders.
          */
-        for(Class<?> substitution : potentialSubstitutions) {
-            search: for(Entry<Class<?>, DataContainerCodecPrototype<?>> real : byClassBuilder.entrySet()) {
+        for(final Class<?> substitution : potentialSubstitutions) {
+            search: for(final Entry<Class<?>, DataContainerCodecPrototype<?>> real : byClassBuilder.entrySet()) {
                 if(BindingReflections.isSubstitutionFor(substitution, real.getKey())) {
                     bySubstitutionBuilder.put(substitution, real.getValue());
                     break search;
@@ -96,18 +97,17 @@ final class ChoiceNodeCodecContext<D extends DataObject> extends DataContainerCo
 
     @SuppressWarnings("unchecked")
     @Override
-    public <DV extends DataObject> DataContainerCodecContext<DV, ?> streamChild(Class<DV> childClass) {
-        DataContainerCodecPrototype<?> child = byClass.get(childClass);
-        Preconditions.checkArgument(child != null,"Supplied class is not valid case",childClass);
-        return (DataContainerCodecContext<DV, ?>) child.get();
+    public <DV extends DataObject> DataContainerCodecContext<DV, ?> streamChild(final Class<DV> childClass) {
+        final DataContainerCodecPrototype<?> child = byClass.get(childClass);
+        return (DataContainerCodecContext<DV, ?>) childNonNull(child,childClass,"Supplied class %s is not valid case").get();
     }
 
 
     @SuppressWarnings("unchecked")
     @Override
     public <DV extends DataObject> Optional<DataContainerCodecContext<DV, ?>> possibleStreamChild(
-            Class<DV> childClass) {
-        DataContainerCodecPrototype<?> child = byClass.get(childClass);
+            final Class<DV> childClass) {
+        final DataContainerCodecPrototype<?> child = byClass.get(childClass);
         if(child != null) {
             return Optional.<DataContainerCodecContext<DV,?>>of((DataContainerCodecContext<DV, ?>) child.get());
         }
@@ -119,7 +119,7 @@ final class ChoiceNodeCodecContext<D extends DataObject> extends DataContainerCo
     }
 
     protected DataContainerCodecPrototype<ChoiceCaseNode> loadCase(final Class<?> childClass) {
-        Optional<ChoiceCaseNode> childSchema = factory().getRuntimeContext().getCaseSchemaDefinition(schema(), childClass);
+        final Optional<ChoiceCaseNode> childSchema = factory().getRuntimeContext().getCaseSchemaDefinition(schema(), childClass);
         if (childSchema.isPresent()) {
             return DataContainerCodecPrototype.from(childClass, childSchema.get(), factory());
         }
@@ -130,48 +130,47 @@ final class ChoiceNodeCodecContext<D extends DataObject> extends DataContainerCo
 
     @Override
     public NodeCodecContext<?> yangPathArgumentChild(final YangInstanceIdentifier.PathArgument arg) {
-        DataContainerCodecPrototype<?> cazeProto = byYangCaseChild.get(arg);
-        Preconditions.checkArgument(cazeProto != null, "Argument %s is not valid child of %s", arg, schema());
+        final DataContainerCodecPrototype<?> cazeProto = byYangCaseChild.get(arg);
+        childNonNull(cazeProto != null, arg,"Argument %s is not valid child of %s", arg, schema());
         return cazeProto.get().yangPathArgumentChild(arg);
     }
 
     @SuppressWarnings("unchecked")
     @Override
+    @Nullable
     public D deserialize(final NormalizedNode<?, ?> data) {
-        Preconditions
-                .checkArgument(data instanceof org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode);
-        NormalizedNodeContainer<?, ?, NormalizedNode<?,?>> casted = (NormalizedNodeContainer<?, ?, NormalizedNode<?,?>>) data;
-        NormalizedNode<?, ?> first = Iterables.getFirst(casted.getValue(), null);
+        Preconditions.checkArgument(data instanceof ChoiceNode);
+        final NormalizedNodeContainer<?, ?, NormalizedNode<?,?>> casted = (NormalizedNodeContainer<?, ?, NormalizedNode<?,?>>) data;
+        final NormalizedNode<?, ?> first = Iterables.getFirst(casted.getValue(), null);
 
         if (first == null) {
             return null;
         }
-        DataContainerCodecPrototype<?> caze = byYangCaseChild.get(first.getIdentifier());
+        final DataContainerCodecPrototype<?> caze = byYangCaseChild.get(first.getIdentifier());
         return (D) caze.get().deserialize(data);
     }
 
-    @Nullable DataContainerCodecContext<?,?> getCazeByChildClass(final @Nonnull Class<? extends DataObject> type) {
-        final DataContainerCodecPrototype<?> protoCtx = byCaseChildClass.get(type);
-        if(protoCtx != null) {
-            return protoCtx.get();
-        }
-        return null;
+    DataContainerCodecContext<?, ?> getCazeByChildClass(final @Nonnull Class<? extends DataObject> type) {
+        final DataContainerCodecPrototype<?> protoCtx =
+                childNonNull(byCaseChildClass.get(type), type, "Class %s is not child of any cases for %s", type,
+                        bindingArg());
+        return protoCtx.get();
     }
 
     @Override
-    protected Object deserializeObject(NormalizedNode<?, ?> normalizedNode) {
+    protected Object deserializeObject(final NormalizedNode<?, ?> normalizedNode) {
         return deserialize(normalizedNode);
     }
 
     @Override
-    public PathArgument deserializePathArgument(YangInstanceIdentifier.PathArgument arg) {
+    public PathArgument deserializePathArgument(final YangInstanceIdentifier.PathArgument arg) {
         Preconditions.checkArgument(getDomPathArgument().equals(arg));
         return null;
     }
 
     @Override
     public YangInstanceIdentifier.PathArgument serializePathArgument(
-            PathArgument arg) {
+            final PathArgument arg) {
         // FIXME: check for null, since binding container is null.
         return getDomPathArgument();
     }
index 371a181ce4111bc96f195d32fceb0f3a092b9a76..ef21235d59df191eefc00bb9511bc7be465ea4d6 100644 (file)
@@ -12,6 +12,7 @@ import com.google.common.collect.ImmutableCollection;
 import com.google.common.collect.ImmutableSet;
 import java.io.IOException;
 import java.util.List;
+import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
 import org.opendaylight.yangtools.binding.data.codec.api.BindingNormalizedNodeCachingCodec;
 import org.opendaylight.yangtools.yang.binding.BindingStreamEventWriter;
@@ -19,6 +20,7 @@ import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.DataObjectSerializer;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument;
+import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.common.QNameModule;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
@@ -146,6 +148,36 @@ abstract class DataContainerCodecContext<D extends DataObject,T> extends NodeCod
         return  new BindingToNormalizedStreamWriter(this, domWriter);
     }
 
+    @Nonnull
+    protected final <V> V childNonNull(@Nullable final V nullable, final YangInstanceIdentifier.PathArgument child,
+            final String message, final Object... args) {
+        if (nullable != null) {
+            return nullable;
+        }
+        MissingSchemaException.checkModulePresent(factory().getRuntimeContext().getSchemaContext(), child);
+        throw IncorrectNestingException.create(message, args);
+    }
+
+    @Nonnull
+    protected final <V> V childNonNull(@Nullable final V nullable, final QName child, final String message,
+            final Object... args) {
+        if (nullable != null) {
+            return nullable;
+        }
+        MissingSchemaException.checkModulePresent(factory().getRuntimeContext().getSchemaContext(), child);
+        throw IncorrectNestingException.create(message, args);
+    }
+
+    @Nonnull
+    protected final <V> V childNonNull(@Nullable final V nullable, final Class<?> childClass, final String message,
+            final Object... args) {
+        if (nullable != null) {
+            return nullable;
+        }
+        MissingSchemaForClassException.check(factory().getRuntimeContext(), childClass);
+        throw IncorrectNestingException.create(message, args);
+    }
+
     DataObjectSerializer eventStreamSerializer() {
         if(eventStreamSerializer == null) {
             eventStreamSerializer = factory().getEventStreamSerializer(getBindingClass());
index 8302aed0e6348d283b45d974bf8c2c105ba77edb..0ca1d2b8504d3183bb01783312eb1ea4717dcc23 100644 (file)
@@ -7,8 +7,6 @@
  */
 package org.opendaylight.yangtools.binding.data.codec.impl;
 
-import org.opendaylight.yangtools.yang.binding.AugmentationHolder;
-
 import com.google.common.base.Optional;
 import com.google.common.base.Preconditions;
 import com.google.common.base.Throwables;
@@ -33,6 +31,7 @@ import org.opendaylight.yangtools.sal.binding.generator.api.ClassLoadingStrategy
 import org.opendaylight.yangtools.sal.binding.model.api.Type;
 import org.opendaylight.yangtools.yang.binding.Augmentable;
 import org.opendaylight.yangtools.yang.binding.Augmentation;
+import org.opendaylight.yangtools.yang.binding.AugmentationHolder;
 import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.binding.util.BindingReflections;
@@ -155,8 +154,7 @@ abstract class DataObjectCodecContext<D extends DataObject,T extends DataNodeCon
                 }
             }
         }
-        Preconditions.checkArgument(childProto != null, " Child %s is not valid child.",childClass);
-        return (DataContainerCodecContext<DV, ?>) childProto.get();
+        return (DataContainerCodecContext<DV, ?>) childNonNull(childProto, childClass, " Child %s is not valid child.").get();
     }
 
 
@@ -177,23 +175,17 @@ abstract class DataObjectCodecContext<D extends DataObject,T extends DataNodeCon
 
         final Class<? extends DataObject> argType = arg.getType();
         final DataContainerCodecPrototype<?> ctxProto = byBindingArgClass.get(argType);
-        if(ctxProto != null) {
-            final DataContainerCodecContext<?,?> context = ctxProto.get();
-            if(context instanceof ChoiceNodeCodecContext) {
-                final ChoiceNodeCodecContext<?> choice = (ChoiceNodeCodecContext<?>) context;
-                final DataContainerCodecContext<?,?> caze = choice.getCazeByChildClass(arg.getType());
-                if(caze != null) {
-                    choice.addYangPathArgument(arg, builder);
-                    caze.addYangPathArgument(arg, builder);
-                    return caze.bindingPathArgumentChild(arg, builder);
-                }
-                return null;
-            }
-            context.addYangPathArgument(arg, builder);
-            return context;
+        final DataContainerCodecContext<?, ?> context =
+                childNonNull(ctxProto, argType, "Class %s is not valid child of %s", argType, getBindingClass()).get();
+        if (context instanceof ChoiceNodeCodecContext) {
+            final ChoiceNodeCodecContext<?> choice = (ChoiceNodeCodecContext<?>) context;
+            final DataContainerCodecContext<?, ?> caze = choice.getCazeByChildClass(arg.getType());
+            choice.addYangPathArgument(arg, builder);
+            caze.addYangPathArgument(arg, builder);
+            return caze.bindingPathArgumentChild(arg, builder);
         }
-        // Argument is not valid child.
-        return null;
+        context.addYangPathArgument(arg, builder);
+        return context;
     }
 
     @SuppressWarnings("unchecked")
@@ -203,14 +195,13 @@ abstract class DataObjectCodecContext<D extends DataObject,T extends DataNodeCon
             arg = new NodeIdentifier(arg.getNodeType());
         }
         final NodeContextSupplier childSupplier = byYang.get(arg);
-        Preconditions.checkArgument(childSupplier != null, "Argument %s is not valid child of %s", arg, schema());
+        childNonNull(childSupplier != null, arg, "Argument %s is not valid child of %s", arg, schema());
         return (NodeCodecContext<D>) childSupplier.get();
     }
 
     protected final LeafNodeCodecContext<?> getLeafChild(final String name) {
         final LeafNodeCodecContext<?> value = leafChild.get(name);
-        Preconditions.checkArgument(value != null, "Leaf %s is not valid for %s", name, getBindingClass());
-        return value;
+        return IncorrectNestingException.checkNonNull(value, "Leaf %s is not valid for %s", name, getBindingClass());
     }
 
     private DataContainerCodecPrototype<?> loadChildPrototype(final Class<?> childClass) {
@@ -248,8 +239,9 @@ abstract class DataObjectCodecContext<D extends DataObject,T extends DataNodeCon
                 childSchema = null;
             }
         }
-        Preconditions.checkArgument(childSchema != null, "Node %s does not have child named %s", schema(), childClass);
-        return DataContainerCodecPrototype.from(childClass, childSchema, factory());
+        final DataSchemaNode nonNullChild =
+                childNonNull(childSchema, childClass, "Node %s does not have child named %s", schema(), childClass);
+        return DataContainerCodecPrototype.from(childClass, nonNullChild, factory());
     }
 
     private DataContainerCodecPrototype<?> getAugmentationPrototype(final Type value) {
diff --git a/code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/IncorrectNestingException.java b/code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/IncorrectNestingException.java
new file mode 100644 (file)
index 0000000..5e7ec6a
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * 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.binding.data.codec.impl;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+/**
+ *
+ * Thrown where incorrect nesting of data structures was detected
+ * and was caused by user.
+ *
+ */
+public class IncorrectNestingException extends IllegalArgumentException {
+
+    private static final long serialVersionUID = 1L;
+
+    protected IncorrectNestingException(final String message) {
+        super(message);
+    }
+
+    public static IncorrectNestingException create(final String message, final Object... args) {
+        return new IncorrectNestingException(String.format(message, args));
+    }
+
+    public static void check(final boolean check, final String message, final Object... args) {
+        if(!check) {
+            throw IncorrectNestingException.create(message, args);
+        }
+    }
+
+    @Nonnull
+    public static <V> V checkNonNull(@Nullable final V nullable, final String message, final Object... args) {
+        if(nullable != null) {
+            return nullable;
+        }
+        throw IncorrectNestingException.create(message, args);
+    }
+}
index e8d115c16da8a71fa8fe51bde68d4fa16edbbcb8..81d9f3a609e75af35da4f76af9aabc51a4db1b0e 100644 (file)
@@ -64,58 +64,57 @@ final class LeafNodeCodecContext<D extends DataObject> extends NodeCodecContext<
     }
 
     @Override
-    public BindingCodecTreeNode<?> bindingPathArgumentChild(PathArgument arg,
-            List<YangInstanceIdentifier.PathArgument> builder) {
-        return null;
+    public BindingCodecTreeNode<?> bindingPathArgumentChild(final PathArgument arg,
+            final List<YangInstanceIdentifier.PathArgument> builder) {
+        throw new IllegalArgumentException("Leaf does not have children");
     }
 
     @Override
     public BindingNormalizedNodeCachingCodec<D> createCachingCodec(
-            ImmutableCollection<Class<? extends DataObject>> cacheSpecifier) {
-        return null;
+            final ImmutableCollection<Class<? extends DataObject>> cacheSpecifier) {
+        throw new UnsupportedOperationException("Leaves does not support caching codec.");
     }
 
     @Override
     public Class<D> getBindingClass() {
-        return null;
+        throw new UnsupportedOperationException("Leaf does not have DataObject representation");
     }
 
     @Override
-    public NormalizedNode<?, ?> serialize(D data) {
+    public NormalizedNode<?, ?> serialize(final D data) {
         throw new UnsupportedOperationException("Separete serialization of leaf node is not supported.");
     }
 
     @Override
-    public void writeAsNormalizedNode(D data, NormalizedNodeStreamWriter writer) {
+    public void writeAsNormalizedNode(final D data, final NormalizedNodeStreamWriter writer) {
         throw new UnsupportedOperationException("Separete serialization of leaf node is not supported.");
     }
 
     @Override
-    public <E extends DataObject> BindingCodecTreeNode<E> streamChild(Class<E> childClass) {
-        return null;
+    public <E extends DataObject> BindingCodecTreeNode<E> streamChild(final Class<E> childClass) {
+        throw new IllegalArgumentException("Leaf does not have children");
     }
 
     @Override
     public <E extends DataObject> Optional<? extends BindingCodecTreeNode<E>> possibleStreamChild(
-            Class<E> childClass) {
-        return null;
+            final Class<E> childClass) {
+        throw new IllegalArgumentException("Leaf does not have children");
     }
 
     @Override
-    public BindingCodecTreeNode<?> yangPathArgumentChild(
-            org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument child) {
-        return null;
+    public BindingCodecTreeNode<?> yangPathArgumentChild(final YangInstanceIdentifier.PathArgument child) {
+        throw new IllegalArgumentException("Leaf does not have children");
     }
 
     @Override
-    protected Object deserializeObject(NormalizedNode<?, ?> normalizedNode) {
+    protected Object deserializeObject(final NormalizedNode<?, ?> normalizedNode) {
         if (normalizedNode instanceof LeafNode<?>) {
             return valueCodec.deserialize(normalizedNode.getValue());
         } else if(normalizedNode instanceof LeafSetNode<?>) {
             @SuppressWarnings("unchecked")
-            Collection<LeafSetEntryNode<Object>> domValues = ((LeafSetNode<Object>) normalizedNode).getValue();
-            List<Object> result = new ArrayList<>(domValues.size());
-            for (LeafSetEntryNode<Object> valueNode : domValues) {
+            final Collection<LeafSetEntryNode<Object>> domValues = ((LeafSetNode<Object>) normalizedNode).getValue();
+            final List<Object> result = new ArrayList<>(domValues.size());
+            for (final LeafSetEntryNode<Object> valueNode : domValues) {
                 result.add(valueCodec.deserialize(valueNode.getValue()));
             }
             return result;
@@ -124,13 +123,13 @@ final class LeafNodeCodecContext<D extends DataObject> extends NodeCodecContext<
     }
 
     @Override
-    public InstanceIdentifier.PathArgument deserializePathArgument(YangInstanceIdentifier.PathArgument arg) {
+    public InstanceIdentifier.PathArgument deserializePathArgument(final YangInstanceIdentifier.PathArgument arg) {
         Preconditions.checkArgument(getDomPathArgument().equals(arg));
         return null;
     }
 
     @Override
-    public YangInstanceIdentifier.PathArgument serializePathArgument(InstanceIdentifier.PathArgument arg) {
+    public YangInstanceIdentifier.PathArgument serializePathArgument(final InstanceIdentifier.PathArgument arg) {
         return getDomPathArgument();
     }
 
diff --git a/code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/MissingSchemaException.java b/code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/MissingSchemaException.java
new file mode 100644 (file)
index 0000000..5c5bac6
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * 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.binding.data.codec.impl;
+
+import com.google.common.base.Preconditions;
+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.YangInstanceIdentifier.PathArgument;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+
+/**
+ * Thrown when codec was used with data which are not modeled
+ * and available in schema used by codec.
+ *
+ */
+public class MissingSchemaException extends IllegalArgumentException {
+
+    private static final long serialVersionUID = 1L;
+
+    protected MissingSchemaException(final String msg) {
+        super(msg);
+    }
+
+    private static MissingSchemaException create(final String format, final Object... args) {
+        return new MissingSchemaException(String.format(format, args));
+    }
+
+    static void checkModulePresent(final SchemaContext schemaContext, final QName name) {
+        if(schemaContext.findModuleByNamespaceAndRevision(name.getNamespace(), name.getRevision()) == null) {
+            throw MissingSchemaException.create("Module %s is not present in current schema context.",name.getModule());
+        }
+    }
+
+    static void checkModulePresent(final SchemaContext schemaContext, final YangInstanceIdentifier.PathArgument child) {
+        checkModulePresent(schemaContext, extractName(child));
+    }
+
+    private static QName extractName(final PathArgument child) {
+        if(child instanceof YangInstanceIdentifier.AugmentationIdentifier) {
+            final Set<QName> children = ((YangInstanceIdentifier.AugmentationIdentifier) child).getPossibleChildNames();
+            Preconditions.checkArgument(!children.isEmpty(),"Augmentation without childs must not be used in data");
+            return children.iterator().next();
+        }
+        return child.getNodeType();
+    }
+
+
+
+
+}
diff --git a/code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/MissingSchemaForClassException.java b/code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/MissingSchemaForClassException.java
new file mode 100644 (file)
index 0000000..6f9778f
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * 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.binding.data.codec.impl;
+
+import com.google.common.base.Preconditions;
+import org.opendaylight.yangtools.sal.binding.generator.util.BindingRuntimeContext;
+import org.opendaylight.yangtools.yang.binding.Augmentation;
+
+/**
+ *
+ * Thrown when Java Binding class was used in data for which codec does not
+ * have schema.
+ *
+ * By serialization /  deserialization of this exception {@link #getBindingClass()}
+ * will return null.
+ *
+ */
+public class MissingSchemaForClassException extends MissingSchemaException {
+
+    private static final long serialVersionUID = 1L;
+
+    private final transient Class<?> bindingClass;
+
+    private MissingSchemaForClassException(final Class<?> clz) {
+        super(String.format("Schema is not available for %s", clz));
+        this.bindingClass = Preconditions.checkNotNull(clz);
+    }
+
+    static MissingSchemaForClassException forClass(final Class<?> clz) {
+        return new MissingSchemaForClassException(clz);
+    }
+
+    public Class<?> getBindingClass() {
+        return bindingClass;
+    }
+
+    public static void check(final BindingRuntimeContext runtimeContext, final Class<?> bindingClass) {
+        final Object schema;
+        if (Augmentation.class.isAssignableFrom(bindingClass)) {
+            schema = runtimeContext.getAugmentationDefinition(bindingClass);
+        } else {
+            schema = runtimeContext.getSchemaDefinition(bindingClass);
+        }
+        if(schema == null) {
+            throw MissingSchemaForClassException.forClass(bindingClass);
+        }
+    }
+}
index b2fb7d0867a7cf5a470121819e4661546d66017c..16533f06a42647d471d4a999ec69302527771f77 100644 (file)
@@ -9,9 +9,11 @@ package org.opendaylight.yangtools.binding.data.codec.impl;
 
 import com.google.common.base.Optional;
 import com.google.common.base.Preconditions;
+import com.google.common.base.Throwables;
 import com.google.common.cache.CacheBuilder;
 import com.google.common.cache.CacheLoader;
 import com.google.common.cache.LoadingCache;
+import com.google.common.util.concurrent.UncheckedExecutionException;
 import org.opendaylight.yangtools.util.ClassLoaderUtils;
 import org.opendaylight.yangtools.yang.binding.BindingMapping;
 import org.opendaylight.yangtools.yang.binding.ChildOf;
@@ -70,9 +72,7 @@ final class SchemaRootCodecContext<D extends DataObject> extends DataContainerCo
                 @Override
                 public DataContainerCodecContext<?,?> load(final QName qname) {
                     final DataSchemaNode childSchema = schema().getDataChildByName(qname);
-                    Preconditions.checkArgument(childSchema != null, "Argument %s is not valid child of %s", qname,
-                            schema());
-
+                    childNonNull(childSchema, qname,"Argument %s is not valid child of %s", qname,schema());
                     if (childSchema instanceof DataNodeContainer || childSchema instanceof ChoiceSchemaNode) {
                         @SuppressWarnings("rawtypes")
                         final Class childCls = factory().getRuntimeContext().getClassForSchema(childSchema);
@@ -126,7 +126,7 @@ final class SchemaRootCodecContext<D extends DataObject> extends DataContainerCo
 
     @SuppressWarnings("unchecked")
     @Override
-    public <DV extends DataObject> DataContainerCodecContext<DV, ?> streamChild(Class<DV> childClass)
+    public <DV extends DataObject> DataContainerCodecContext<DV, ?> streamChild(final Class<DV> childClass)
             throws IllegalArgumentException {
         /* FIXME: This is still not solved for RPCs
          * TODO: Probably performance wise RPC, Data and Notification loading cache
@@ -136,7 +136,7 @@ final class SchemaRootCodecContext<D extends DataObject> extends DataContainerCo
         if (Notification.class.isAssignableFrom(childClass)) {
             return (DataContainerCodecContext<DV, ?>) getNotification((Class<? extends Notification>)childClass);
         }
-        return (DataContainerCodecContext<DV, ?>) childrenByClass.getUnchecked(childClass);
+        return (DataContainerCodecContext<DV, ?>) getOrRethrow(childrenByClass,childClass);
     }
 
     @Override
@@ -146,7 +146,7 @@ final class SchemaRootCodecContext<D extends DataObject> extends DataContainerCo
 
     @Override
     public DataContainerCodecContext<?,?> yangPathArgumentChild(final PathArgument arg) {
-        return childrenByQName.getUnchecked(arg.getNodeType());
+        return getOrRethrow(childrenByQName,arg.getNodeType());
     }
 
     @Override
@@ -157,26 +157,26 @@ final class SchemaRootCodecContext<D extends DataObject> extends DataContainerCo
 
 
     ContainerNodeCodecContext<?> getRpc(final Class<? extends DataContainer> rpcInputOrOutput) {
-        return rpcDataByClass.getUnchecked(rpcInputOrOutput);
+        return getOrRethrow(rpcDataByClass, rpcInputOrOutput);
     }
 
     NotificationCodecContext<?> getNotification(final Class<? extends Notification> notification) {
-        return notificationsByClass.getUnchecked(notification);
+        return getOrRethrow(notificationsByClass, notification);
     }
 
     NotificationCodecContext<?> getNotification(final SchemaPath notification) {
-        return notificationsByPath.getUnchecked(notification);
+        return getOrRethrow(notificationsByPath, notification);
     }
 
     ContainerNodeCodecContext<?> getRpc(final SchemaPath notification) {
-        return rpcDataByPath.getUnchecked(notification);
+        return getOrRethrow(rpcDataByPath, notification);
     }
 
     private DataContainerCodecContext<?,?> createDataTreeChildContext(final Class<?> key) {
         final Class<Object> parent = ClassLoaderUtils.findFirstGenericArgument(key, ChildOf.class);
-        Preconditions.checkArgument(DataRoot.class.isAssignableFrom(parent));
+        IncorrectNestingException.check(DataRoot.class.isAssignableFrom(parent), "Class %s is not top level item.", key);
         final QName qname = BindingReflections.findQName(key);
-        final DataSchemaNode childSchema = schema().getDataChildByName(qname);
+        final DataSchemaNode childSchema = childNonNull(schema().getDataChildByName(qname),key,"%s is not top-level item.",key);
         return DataContainerCodecPrototype.from(key, childSchema, factory()).get();
     }
 
@@ -226,20 +226,32 @@ final class SchemaRootCodecContext<D extends DataObject> extends DataContainerCo
     }
 
     @Override
-    protected Object deserializeObject(NormalizedNode<?, ?> normalizedNode) {
+    protected Object deserializeObject(final NormalizedNode<?, ?> normalizedNode) {
         throw new UnsupportedOperationException("Unable to deserialize root");
     }
 
     @Override
-    public InstanceIdentifier.PathArgument deserializePathArgument(YangInstanceIdentifier.PathArgument arg) {
+    public InstanceIdentifier.PathArgument deserializePathArgument(final YangInstanceIdentifier.PathArgument arg) {
         Preconditions.checkArgument(arg == null);
         return null;
     }
 
     @Override
-    public YangInstanceIdentifier.PathArgument serializePathArgument(InstanceIdentifier.PathArgument arg) {
+    public YangInstanceIdentifier.PathArgument serializePathArgument(final InstanceIdentifier.PathArgument arg) {
         Preconditions.checkArgument(arg == null);
         return null;
     }
 
+    private static <K,V> V getOrRethrow(final LoadingCache<K, V> cache, final K key) {
+        try {
+            return cache.getUnchecked(key);
+        } catch (final UncheckedExecutionException e) {
+            final Throwable cause = e.getCause();
+            if(cause != null) {
+                Throwables.propagateIfPossible(cause);
+            }
+            throw e;
+        }
+    }
+
 }
\ No newline at end of file
diff --git a/code-generator/binding-data-codec/src/test/java/org/opendaylight/yangtools/binding/data/codec/test/ExceptionReportingTest.java b/code-generator/binding-data-codec/src/test/java/org/opendaylight/yangtools/binding/data/codec/test/ExceptionReportingTest.java
new file mode 100644 (file)
index 0000000..4a565ed
--- /dev/null
@@ -0,0 +1,103 @@
+/*
+ * 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.binding.data.codec.test;
+
+import javassist.ClassPool;
+import org.junit.Test;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.augment.rev140709.TreeComplexUsesAugment;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.augment.rev140709.TreeLeafOnlyAugment;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701.Top;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701.two.level.list.TopLevelList;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701.two.level.list.TopLevelListKey;
+import org.opendaylight.yangtools.binding.data.codec.gen.impl.StreamWriterGenerator;
+import org.opendaylight.yangtools.binding.data.codec.impl.BindingNormalizedNodeCodecRegistry;
+import org.opendaylight.yangtools.binding.data.codec.impl.IncorrectNestingException;
+import org.opendaylight.yangtools.binding.data.codec.impl.MissingSchemaException;
+import org.opendaylight.yangtools.binding.data.codec.impl.MissingSchemaForClassException;
+import org.opendaylight.yangtools.sal.binding.generator.impl.ModuleInfoBackedContext;
+import org.opendaylight.yangtools.sal.binding.generator.util.BindingRuntimeContext;
+import org.opendaylight.yangtools.sal.binding.generator.util.JavassistUtils;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.YangModuleInfo;
+import org.opendaylight.yangtools.yang.binding.util.BindingReflections;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+
+
+public class ExceptionReportingTest {
+
+
+    private static final BindingNormalizedNodeCodecRegistry EMPTY_SCHEMA_CODEC = codec();
+    private static final BindingNormalizedNodeCodecRegistry ONLY_TOP_CODEC = codec(Top.class);
+    private static final BindingNormalizedNodeCodecRegistry FULL_CODEC = codec(TreeComplexUsesAugment.class);
+
+    private static final TopLevelListKey TOP_FOO_KEY = new TopLevelListKey("foo");
+    private static final InstanceIdentifier<TopLevelList> BA_TOP_LEVEL_LIST = InstanceIdentifier
+            .builder(Top.class).child(TopLevelList.class, TOP_FOO_KEY).build();
+    private static final InstanceIdentifier<TreeLeafOnlyAugment> BA_TREE_LEAF_ONLY =
+            BA_TOP_LEVEL_LIST.augmentation(TreeLeafOnlyAugment.class);
+
+    private static final QName TOP_QNAME =
+            QName.create("urn:opendaylight:params:xml:ns:yang:yangtools:test:binding", "2014-07-01", "top");
+    private static final YangInstanceIdentifier BI_TOP_PATH = YangInstanceIdentifier.builder().node(TOP_QNAME).build();
+    private static final YangInstanceIdentifier BI_TREE_LEAF_ONLY = FULL_CODEC.toYangInstanceIdentifier(BA_TREE_LEAF_ONLY);
+
+
+    @Test(expected=MissingSchemaException.class)
+    public void testDOMTop() {
+        EMPTY_SCHEMA_CODEC.fromYangInstanceIdentifier(BI_TOP_PATH);
+    }
+
+    @Test(expected=MissingSchemaException.class)
+    public void testDOMAugment() {
+        EMPTY_SCHEMA_CODEC.fromYangInstanceIdentifier(BI_TREE_LEAF_ONLY);
+    }
+
+    @Test(expected=MissingSchemaForClassException.class)
+    public void testBindingTop() {
+        EMPTY_SCHEMA_CODEC.toYangInstanceIdentifier(BA_TOP_LEVEL_LIST);
+    }
+
+    @Test(expected=MissingSchemaForClassException.class)
+    public void testBindingAugment() {
+        ONLY_TOP_CODEC.toYangInstanceIdentifier(BA_TREE_LEAF_ONLY);
+    }
+
+    @Test(expected=IncorrectNestingException.class)
+    public void testBindingSkippedRoot() {
+        FULL_CODEC.toYangInstanceIdentifier(InstanceIdentifier.create(TopLevelList.class));
+    }
+
+    @SuppressWarnings({"unchecked", "rawtypes"})
+    @Test(expected=IncorrectNestingException.class)
+    public void testBindingIncorrectAugment() {
+        FULL_CODEC.toYangInstanceIdentifier(InstanceIdentifier.create(Top.class).augmentation((Class) TreeComplexUsesAugment.class));
+    }
+
+
+    private static BindingNormalizedNodeCodecRegistry codec(final Class<?>... classes ) {
+        final ModuleInfoBackedContext ctx = ModuleInfoBackedContext.create();
+        for(final Class<?> clazz : classes) {
+            YangModuleInfo modInfo;
+            try {
+                modInfo = BindingReflections.getModuleInfo(clazz);
+                ctx.registerModuleInfo(modInfo);
+            } catch (final Exception e) {
+                throw new IllegalStateException(e);
+            }
+        }
+        final SchemaContext schema = ctx.tryToCreateSchemaContext().get();
+        final BindingRuntimeContext runtimeCtx = BindingRuntimeContext.create(ctx, schema);
+        final JavassistUtils utils = JavassistUtils.forClassPool(ClassPool.getDefault());
+        final BindingNormalizedNodeCodecRegistry registry = new BindingNormalizedNodeCodecRegistry(StreamWriterGenerator.create(utils));
+        registry.onBindingRuntimeContextUpdated(runtimeCtx);
+        return registry;
+    }
+
+}
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 0db4b7da8f89af4af8ffefdc3e4506c1775813dc..e92f1ca0d0562718b78effe222897276b3e2b12f 100644 (file)
@@ -26,6 +26,7 @@ import java.util.HashSet;
 import java.util.Map;
 import java.util.Map.Entry;
 import java.util.Set;
+import javax.annotation.Nullable;
 import org.opendaylight.yangtools.binding.generator.util.ReferencedTypeImpl;
 import org.opendaylight.yangtools.concepts.Immutable;
 import org.opendaylight.yangtools.sal.binding.generator.api.ClassLoadingStrategy;
@@ -40,7 +41,6 @@ import org.opendaylight.yangtools.sal.binding.model.api.type.builder.GeneratedTy
 import org.opendaylight.yangtools.yang.binding.Augmentation;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.AugmentationIdentifier;
-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.AugmentationTarget;
 import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode;
@@ -51,6 +51,7 @@ import org.opendaylight.yangtools.yang.model.api.Module;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 import org.opendaylight.yangtools.yang.model.api.SchemaNode;
 import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
+import org.opendaylight.yangtools.yang.model.util.EffectiveAugmentationSchema;
 import org.opendaylight.yangtools.yang.model.util.SchemaNodeUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -163,14 +164,12 @@ public class BindingRuntimeContext implements Immutable {
      * schema.
      *
      * @param augClass Augmentation class
-     * @return Schema of augmentation
-     * @throws IllegalArgumentException If supplied class is not an augmentation or current context does not contain schema for augmentation.
+     * @return Schema of augmentation or null if augmentaiton is not known in this context
+     * @throws IllegalArgumentException If supplied class is not an augmentation
      */
-    public AugmentationSchema getAugmentationDefinition(final Class<?> augClass) throws IllegalArgumentException {
+    public @Nullable AugmentationSchema getAugmentationDefinition(final Class<?> augClass) throws IllegalArgumentException {
         Preconditions.checkArgument(Augmentation.class.isAssignableFrom(augClass), "Class %s does not represent augmentation", augClass);
-        final AugmentationSchema ret = augmentationToSchema.get(referencedType(augClass));
-        Preconditions.checkArgument(ret != null, "Supplied augmentation %s is not valid in current context", augClass);
-        return ret;
+        return augmentationToSchema.get(referencedType(augClass));
     }
 
     /**
@@ -195,6 +194,7 @@ public class BindingRuntimeContext implements Immutable {
     public Entry<AugmentationIdentifier, AugmentationSchema> getResolvedAugmentationSchema(final DataNodeContainer target,
             final Class<? extends Augmentation<?>> aug) {
         final AugmentationSchema origSchema = getAugmentationDefinition(aug);
+        Preconditions.checkArgument(origSchema != null, "Augmentation %s is not known in current schema context",aug);
         /*
          * FIXME: Validate augmentation schema lookup
          *
@@ -215,7 +215,7 @@ public class BindingRuntimeContext implements Immutable {
         }
 
         final AugmentationIdentifier identifier = new AugmentationIdentifier(childNames);
-        final AugmentationSchema proxy = new AugmentationSchemaProxy(origSchema, realChilds);
+        final AugmentationSchema proxy = new EffectiveAugmentationSchema(origSchema, realChilds);
         return new AbstractMap.SimpleEntry<>(identifier, proxy);
     }
 
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));
     }