Bug 2539: Properly report incorrect Instance Identifiers
authorTony Tkacik <ttkacik@cisco.com>
Mon, 19 Jan 2015 14:24:12 +0000 (15:24 +0100)
committerTony Tkacik <ttkacik@cisco.com>
Thu, 26 Feb 2015 14:34:34 +0000 (15:34 +0100)
Binding Data Codec throws IllegalArgumentException
with description for incorrect instance identifiers
instead of generic NullPointerExceptions.

Change-Id: Ia47c83925a18f029c70b2816e2fcb58632027e3c
Signed-off-by: Tony Tkacik <ttkacik@cisco.com>
code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/api/BindingNormalizedNodeSerializer.java
code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/api/BindingNormalizedNodeWriterFactory.java
code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/BindingCodecContext.java
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

index 5e3fd0be5f34a257904b0694b6b28114b7571885..d16fa50058b41bc5c01d371e439b836971871904 100644 (file)
@@ -32,6 +32,8 @@ public interface BindingNormalizedNodeSerializer {
      * @param binding
      *            Binding Instance Identifier
      * @return DOM Instance Identifier
+     * @throws IllegalArgumentException
+     *             If supplied Instance Identifier is not valid.
      */
     YangInstanceIdentifier toYangInstanceIdentifier(@Nonnull InstanceIdentifier<?> binding);
 
@@ -56,6 +58,8 @@ public interface BindingNormalizedNodeSerializer {
      * @param data
      *            Data object representing data
      * @return NormalizedNode representation
+     * @throws IllegalArgumentException
+     *             If supplied Instance Identifier is not valid.
      */
     <T extends DataObject> Entry<YangInstanceIdentifier, NormalizedNode<?, ?>> toNormalizedNode(
             InstanceIdentifier<T> path, T data);
index cd87da1f795e7a102c582efdcea3fa29b83d73e3..fe8bb26761dbf4f1c7d370dbb226cd0321f48a9c 100644 (file)
@@ -46,6 +46,7 @@ public interface BindingNormalizedNodeWriterFactory {
      *            Stream writer on which events will be invoked.
      * @return Instance Identifier and {@link BindingStreamEventWriter}
      *         which will write to supplied {@link NormalizedNodeStreamWriter}.
+     * @throws IllegalArgumentException If supplied Instance Identifier is not valid.
      */
     @Nonnull Entry<YangInstanceIdentifier, BindingStreamEventWriter> newWriterAndIdentifier(@Nonnull InstanceIdentifier<?> path,
             @Nonnull NormalizedNodeStreamWriter domWriter);
@@ -66,6 +67,7 @@ public interface BindingNormalizedNodeWriterFactory {
      * @param domWriter Stream writer on which events will be invoked.
      * @return {@link BindingStreamEventWriter}
      *         which will write to supplied {@link NormalizedNodeStreamWriter}.
+     * @throws IllegalArgumentException If supplied Instance Identifier is not valid.
      */
     @Nonnull
     BindingStreamEventWriter newWriter(@Nonnull InstanceIdentifier<?> path,
index 956b27bc31e586a53d9a7b2faf57af281b98e973..7a525078b0d62ad20652c62cd60a801892eb0e0f 100644 (file)
@@ -116,6 +116,7 @@ final class BindingCodecContext implements CodecContextFactory, Immutable {
         DataContainerCodecContext<?> currentNode = root;
         for (final InstanceIdentifier.PathArgument bindingArg : binding.getPathArguments()) {
             currentNode = currentNode.getIdentifierChild(bindingArg, builder);
+            Preconditions.checkArgument(currentNode != null, "Supplied Instance Identifier %s is not valid.",binding);
         }
         return currentNode;
     }
@@ -130,6 +131,7 @@ final class BindingCodecContext implements CodecContextFactory, Immutable {
      * @param bindingArguments Collection for traversed path arguments
      * @return Codec for target node, or @null if the node does not have a
      *         binding representation (choice, case, leaf).
+     *
      */
     @Nullable NodeCodecContext getCodecContextNode(final @Nonnull YangInstanceIdentifier dom,
             final @Nonnull Collection<InstanceIdentifier.PathArgument> bindingArguments) {
index 8bc5b0872117edd80e099d9977b92603546f6cb7..ee1d0083d3726d4192b6693e741813e3ee0a3c86 100644 (file)
@@ -11,13 +11,13 @@ import com.google.common.base.Optional;
 import com.google.common.base.Preconditions;
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.Iterables;
-
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Map;
 import java.util.Map.Entry;
 import java.util.Set;
-
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
 import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.util.BindingReflections;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
@@ -141,8 +141,12 @@ final class ChoiceNodeCodecContext extends DataContainerCodecContext<ChoiceNode>
         return caze.get().dataFromNormalizedNode(data);
     }
 
-    public DataContainerCodecContext<?> getCazeByChildClass(final Class<? extends DataObject> type) {
-        return byCaseChildClass.get(type).get();
+    public @Nullable DataContainerCodecContext<?> getCazeByChildClass(final @Nonnull Class<? extends DataObject> type) {
+        final DataContainerCodecPrototype<?> protoCtx = byCaseChildClass.get(type);
+        if(protoCtx != null) {
+            return protoCtx.get();
+        }
+        return null;
     }
 
 }
index 79c9eeed644afa2fa2f154394d4b5e1299c90c8d..1b8bdf040a308f0629adc57e63b1b90de29bc22f 100644 (file)
@@ -9,6 +9,7 @@ package org.opendaylight.yangtools.binding.data.codec.impl;
 
 import com.google.common.base.Optional;
 import java.util.List;
+import javax.annotation.Nullable;
 import org.opendaylight.yangtools.yang.binding.BindingStreamEventWriter;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument;
@@ -54,16 +55,19 @@ abstract class DataContainerCodecContext<T> extends NodeCodecContext {
      * and adds YANG instance identifiers to supplied list.
      *
      * @param arg Binding Instance Identifier Argument
-     * @return Context of child
+     * @return Context of child or null if supplied {@code arg} does not represent valid child.
      * @throws IllegalArgumentException If supplied argument does not represent valid child.
      */
-    protected  DataContainerCodecContext<?> getIdentifierChild(final InstanceIdentifier.PathArgument arg,
+    protected @Nullable DataContainerCodecContext<?> getIdentifierChild(final InstanceIdentifier.PathArgument arg,
             final List<YangInstanceIdentifier.PathArgument> builder) {
         final DataContainerCodecContext<?> child = getStreamChild(arg.getType());
-        if (builder != null) {
-            child.addYangPathArgument(arg,builder);
+        if(child != null) {
+            if (builder != null) {
+                child.addYangPathArgument(arg,builder);
+            }
+            return child;
         }
-        return child;
+        return null;
     }
 
     /**
@@ -91,10 +95,10 @@ abstract class DataContainerCodecContext<T> extends NodeCodecContext {
      * must issue getChild(ChoiceClass).getChild(CaseClass).
      *
      * @param childClass
-     * @return Context of child
+     * @return Context of child node or null, if supplied class is not subtree child
      * @throws IllegalArgumentException If supplied child class is not valid in specified context.
      */
-    protected abstract DataContainerCodecContext<?> getStreamChild(final Class<?> childClass) throws IllegalArgumentException;
+    protected abstract @Nullable DataContainerCodecContext<?> getStreamChild(final Class<?> childClass) throws IllegalArgumentException;
 
     /**
      *
index e5d58cc82f3cd15e60fcae946e588d9e20bcd47b..f63df0eba97a68becc65da989a929b0860f265b7 100644 (file)
@@ -177,20 +177,25 @@ abstract class DataObjectCodecContext<T extends DataNodeContainer> extends DataC
     protected DataContainerCodecContext<?> getIdentifierChild(final InstanceIdentifier.PathArgument arg,
             final List<YangInstanceIdentifier.PathArgument> builder) {
 
-        Class<? extends DataObject> argType = arg.getType();
-        DataContainerCodecPrototype<?> ctxProto = byBindingArgClass.get(argType);
-        Preconditions.checkArgument(ctxProto != null,"Invalid child");
-
-        DataContainerCodecContext<?> context = ctxProto.get();
-        if(context instanceof ChoiceNodeCodecContext) {
-            ChoiceNodeCodecContext casted = (ChoiceNodeCodecContext) context;
-            casted.addYangPathArgument(arg, builder);
-            DataContainerCodecContext<?> caze = casted.getCazeByChildClass(arg.getType());
-            caze.addYangPathArgument(arg, builder);
-            return caze.getIdentifierChild(arg, builder);
+        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.getIdentifierChild(arg, builder);
+                }
+                return null;
+            }
+            context.addYangPathArgument(arg, builder);
+            return context;
         }
-        context.addYangPathArgument(arg, builder);
-        return context;
+        // Argument is not valid child.
+        return null;
     }
 
     @Override