Bug 2857: Tied pre-existing implementation to BindingCodecTree. 01/16701/4
authorTony Tkacik <ttkacik@cisco.com>
Thu, 12 Mar 2015 11:06:00 +0000 (12:06 +0100)
committerTony Tkacik <ttkacik@cisco.com>
Wed, 18 Mar 2015 08:30:58 +0000 (09:30 +0100)
BindingCodecTree provides public view into backing structure
of binding-data-codec, which was designed and already implemented
as data tree.

By exposing these power-users could build their own
Binding to DOM adapters, where they could customize some aspects
of serialization or precache over-used codecs in order
to speed up performance.

Change-Id: I827eb6014b28d0b6d4256b677ee56d3081ff80b0
Signed-off-by: Tony Tkacik <ttkacik@cisco.com>
23 files changed:
code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/api/BindingCodecTreeFactory.java
code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/api/BindingCodecTreeNode.java
code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/AugmentationNodeContext.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/BindingNormalizedNodeCodecRegistry.java
code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/BindingToNormalizedStreamWriter.java
code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/CachingNormalizedNodeCodecImpl.java [new file with mode: 0644]
code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/CaseNodeCodecContext.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/ContainerNodeCodecContext.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/DataContainerCodecPrototype.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/InstanceIdentifierCodec.java
code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/KeyedListNodeCodecContext.java
code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/LazyDataObject.java
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/ListNodeCodecContext.java
code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/NodeCodecContext.java
code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/NodeContextSupplier.java
code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/NotificationCodecContext.java
code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/SchemaRootCodecContext.java
code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/ValueContext.java

index 4757038848ef5fce322f7a7e828078769731fcb7..25f45be30de8485aa91168888c200ce294a80c84 100644 (file)
@@ -25,15 +25,18 @@ public interface BindingCodecTreeFactory {
     BindingCodecTree create(BindingRuntimeContext context);
 
     /**
-    *
-    * Creates Binding Codec Tree for specified Binding runtime context.
-    *
-    * @param context
-    *            Binding Runtime Context for which Binding codecs should be
-    *            instantiated.
-    * @param bindingClasses
-    * @return Binding Codec Tree for specified Binding runtime context.
-    */
+     *
+     * Creates Binding Codec Tree for specified Binding runtime context.
+     *
+     * @param context
+     *            Binding Runtime Context for which Binding codecs should be
+     *            instantiated.
+     * @param bindingClasses
+     *            Binding Runtime Context will be constructed using bindings
+     *            which contains specified classes, in order to support
+     *            deserialization in multi-classloader environment.
+     * @return Binding Codec Tree for specified Binding runtime context.
+     */
     @Beta
    BindingCodecTree create(SchemaContext context, Class<?>... bindingClasses);
 
index 5e7b054b1dd8b6c29727ec0927cd1155a2e888ab..4317ef354ec993c61bdaf001fe424ee69e550ecd 100644 (file)
@@ -46,7 +46,7 @@ public interface BindingCodecTreeNode<T extends DataObject> extends BindingNorma
      * {@link BindingStreamEventWriter}. This means that to enter case, one must
      * issue getChild(ChoiceClass).getChild(CaseClass).
      *
-     * @param childClass
+     * @param childClass Child class by Biding Stream navigation
      * @return Context of child
      * @throws IllegalArgumentException
      *             If supplied child class is not valid in specified context.
index feb731f0b97f6ae7a5483d92513f363bb520109a..dd9e41d0da337920bdd9dff2e7f728990f86dc45 100644 (file)
@@ -8,19 +8,27 @@
 package org.opendaylight.yangtools.binding.data.codec.impl;
 
 import com.google.common.base.Preconditions;
+import org.opendaylight.yangtools.yang.binding.Augmentation;
+import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.data.api.schema.AugmentationNode;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
 import org.opendaylight.yangtools.yang.model.api.AugmentationSchema;
 
-final class AugmentationNodeContext extends DataObjectCodecContext<AugmentationSchema> {
+final class AugmentationNodeContext<D extends DataObject & Augmentation<?>> extends DataObjectCodecContext<D,AugmentationSchema> {
 
     public AugmentationNodeContext(final DataContainerCodecPrototype<AugmentationSchema> prototype) {
         super(prototype);
     }
 
     @Override
-    protected Object dataFromNormalizedNode(final NormalizedNode<?, ?> normalizedNode) {
+    public D deserialize(final NormalizedNode<?, ?> normalizedNode) {
         Preconditions.checkArgument(normalizedNode instanceof AugmentationNode);
         return createBindingProxy((AugmentationNode)normalizedNode);
     }
+
+    @Override
+    protected Object deserializeObject(NormalizedNode<?, ?> normalizedNode) {
+        return deserialize(normalizedNode);
+    }
+
 }
\ No newline at end of file
index 7a525078b0d62ad20652c62cd60a801892eb0e0f..e0e0c97777e2dfab31450eefb1480c7f954fabee 100644 (file)
@@ -22,6 +22,8 @@ import java.util.Map.Entry;
 import java.util.concurrent.Callable;
 import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
+import org.opendaylight.yangtools.binding.data.codec.api.BindingCodecTree;
+import org.opendaylight.yangtools.binding.data.codec.api.BindingCodecTreeNode;
 import org.opendaylight.yangtools.binding.data.codec.impl.NodeCodecContext.CodecContextFactory;
 import org.opendaylight.yangtools.concepts.Codec;
 import org.opendaylight.yangtools.concepts.Immutable;
@@ -31,6 +33,8 @@ import org.opendaylight.yangtools.util.ClassLoaderUtils;
 import org.opendaylight.yangtools.yang.binding.BindingMapping;
 import org.opendaylight.yangtools.yang.binding.BindingStreamEventWriter;
 import org.opendaylight.yangtools.yang.binding.DataContainer;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.DataObjectSerializer;
 import org.opendaylight.yangtools.yang.binding.Identifiable;
 import org.opendaylight.yangtools.yang.binding.Identifier;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
@@ -57,20 +61,22 @@ import org.opendaylight.yangtools.yang.model.api.type.UnionTypeDefinition;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-final class BindingCodecContext implements CodecContextFactory, Immutable {
+final class BindingCodecContext implements CodecContextFactory, BindingCodecTree, Immutable {
     private static final Logger LOG = LoggerFactory.getLogger(BindingCodecContext.class);
     static final String GETTER_PREFIX = "get";
 
     private final Codec<YangInstanceIdentifier, InstanceIdentifier<?>> instanceIdentifierCodec;
     private final Codec<QName, Class<?>> identityCodec;
+    private final BindingNormalizedNodeCodecRegistry registry;
     private final BindingRuntimeContext context;
-    private final SchemaRootCodecContext root;
+    private final SchemaRootCodecContext<?> root;
 
-    public BindingCodecContext(final BindingRuntimeContext context) {
+    BindingCodecContext(final BindingRuntimeContext context, BindingNormalizedNodeCodecRegistry registry) {
         this.context = Preconditions.checkNotNull(context, "Binding Runtime Context is required.");
         this.root = SchemaRootCodecContext.create(this);
         this.identityCodec = new IdentityCodec(context);
         this.instanceIdentifierCodec = new InstanceIdentifierCodec(this);
+        this.registry = Preconditions.checkNotNull(registry);
     }
 
     @Override
@@ -86,36 +92,39 @@ final class BindingCodecContext implements CodecContextFactory, Immutable {
         return identityCodec;
     }
 
+    @SuppressWarnings({"rawtypes", "unchecked"})
+    @Override
+    public DataObjectSerializer getEventStreamSerializer(Class<?> type) {
+        return registry.getSerializer((Class) type);
+    }
+
     public Entry<YangInstanceIdentifier, BindingStreamEventWriter> newWriter(final InstanceIdentifier<?> path,
             final NormalizedNodeStreamWriter domWriter) {
         final LinkedList<YangInstanceIdentifier.PathArgument> yangArgs = new LinkedList<>();
-        final DataContainerCodecContext<?> codecContext = getCodecContextNode(path, yangArgs);
-        final BindingStreamEventWriter writer = new BindingToNormalizedStreamWriter(codecContext, domWriter);
-        return new SimpleEntry<>(YangInstanceIdentifier.create(yangArgs), writer);
+        final DataContainerCodecContext<?,?> codecContext = getCodecContextNode(path, yangArgs);
+        return new SimpleEntry<>(YangInstanceIdentifier.create(yangArgs), codecContext.createWriter(domWriter));
     }
 
     public BindingStreamEventWriter newWriterWithoutIdentifier(final InstanceIdentifier<?> path,
             final NormalizedNodeStreamWriter domWriter) {
-        return new BindingToNormalizedStreamWriter(getCodecContextNode(path, null), domWriter);
+        return getCodecContextNode(path, null).createWriter(domWriter);
     }
 
     BindingStreamEventWriter newRpcWriter(final Class<? extends DataContainer> rpcInputOrOutput,
             final NormalizedNodeStreamWriter domWriter) {
-        final NodeCodecContext schema = root.getRpc(rpcInputOrOutput);
-        return new BindingToNormalizedStreamWriter(schema, domWriter);
+        return root.getRpc(rpcInputOrOutput).createWriter(domWriter);
     }
 
     BindingStreamEventWriter newNotificationWriter(final Class<? extends Notification> notification,
             final NormalizedNodeStreamWriter domWriter) {
-        final NodeCodecContext schema = root.getNotification(notification);
-        return new BindingToNormalizedStreamWriter(schema, domWriter);
+        return root.getNotification(notification).createWriter(domWriter);
     }
 
-    public DataContainerCodecContext<?> getCodecContextNode(final InstanceIdentifier<?> binding,
+    public DataContainerCodecContext<?,?> getCodecContextNode(final InstanceIdentifier<?> binding,
             final List<YangInstanceIdentifier.PathArgument> builder) {
-        DataContainerCodecContext<?> currentNode = root;
+        DataContainerCodecContext<?,?> currentNode = root;
         for (final InstanceIdentifier.PathArgument bindingArg : binding.getPathArguments()) {
-            currentNode = currentNode.getIdentifierChild(bindingArg, builder);
+            currentNode = currentNode.bindingPathArgumentChild(bindingArg, builder);
             Preconditions.checkArgument(currentNode != null, "Supplied Instance Identifier %s is not valid.",binding);
         }
         return currentNode;
@@ -133,15 +142,15 @@ final class BindingCodecContext implements CodecContextFactory, Immutable {
      *         binding representation (choice, case, leaf).
      *
      */
-    @Nullable NodeCodecContext getCodecContextNode(final @Nonnull YangInstanceIdentifier dom,
+    @Nullable NodeCodecContext<?> getCodecContextNode(final @Nonnull YangInstanceIdentifier dom,
             final @Nonnull Collection<InstanceIdentifier.PathArgument> bindingArguments) {
-        NodeCodecContext currentNode = root;
-        ListNodeCodecContext currentList = null;
+        NodeCodecContext<?> currentNode = root;
+        ListNodeCodecContext<?> currentList = null;
 
         for (final YangInstanceIdentifier.PathArgument domArg : dom.getPathArguments()) {
-            Preconditions.checkArgument(currentNode instanceof DataContainerCodecContext<?>, "Unexpected child of non-container node %s", currentNode);
-            final DataContainerCodecContext<?> previous = (DataContainerCodecContext<?>) currentNode;
-            final NodeCodecContext nextNode = previous.getYangIdentifierChild(domArg);
+            Preconditions.checkArgument(currentNode instanceof DataContainerCodecContext<?,?>, "Unexpected child of non-container node %s", currentNode);
+            final DataContainerCodecContext<?,?> previous = (DataContainerCodecContext<?,?>) currentNode;
+            final NodeCodecContext<?> nextNode = previous.yangPathArgumentChild(domArg);
 
             /*
              * List representation in YANG Instance Identifier consists of two
@@ -162,13 +171,13 @@ final class BindingCodecContext implements CodecContextFactory, Immutable {
             } else if (nextNode instanceof ListNodeCodecContext) {
                 // We enter list, we do not update current Node yet,
                 // since we need to verify
-                currentList = (ListNodeCodecContext) nextNode;
+                currentList = (ListNodeCodecContext<?>) nextNode;
             } else if (nextNode instanceof ChoiceNodeCodecContext) {
                 // We do not add path argument for choice, since
                 // it is not supported by binding instance identifier.
                 currentNode = nextNode;
-            } else if (nextNode instanceof DataContainerCodecContext<?>) {
-                bindingArguments.add(((DataContainerCodecContext<?>) nextNode).getBindingPathArgument(domArg));
+            } else if (nextNode instanceof DataContainerCodecContext<?,?>) {
+                bindingArguments.add(((DataContainerCodecContext<?,?>) nextNode).getBindingPathArgument(domArg));
                 currentNode = nextNode;
             } else if (nextNode instanceof LeafNodeCodecContext) {
                 LOG.debug("Instance identifier referencing a leaf is not representable (%s)", dom);
@@ -194,16 +203,16 @@ final class BindingCodecContext implements CodecContextFactory, Immutable {
         return currentNode;
     }
 
-    NotificationCodecContext getNotificationContext(final SchemaPath notification) {
+    NotificationCodecContext<?> getNotificationContext(final SchemaPath notification) {
         return root.getNotification(notification);
     }
 
-    ContainerNodeCodecContext getRpcDataContext(final SchemaPath path) {
+    ContainerNodeCodecContext<?> getRpcDataContext(final SchemaPath path) {
         return root.getRpc(path);
     }
 
     @Override
-    public ImmutableMap<String, LeafNodeCodecContext> getLeafNodes(final Class<?> parentClass,
+    public ImmutableMap<String, LeafNodeCodecContext<?>> getLeafNodes(final Class<?> parentClass,
             final DataNodeContainer childSchema) {
         final HashMap<String, DataSchemaNode> getterToLeafSchema = new HashMap<>();
         for (final DataSchemaNode leaf : childSchema.getChildNodes()) {
@@ -234,9 +243,9 @@ final class BindingCodecContext implements CodecContextFactory, Immutable {
         return GETTER_PREFIX + suffix;
     }
 
-    private ImmutableMap<String, LeafNodeCodecContext> getLeafNodesUsingReflection(final Class<?> parentClass,
+    private ImmutableMap<String, LeafNodeCodecContext<?>> getLeafNodesUsingReflection(final Class<?> parentClass,
             final Map<String, DataSchemaNode> getterToLeafSchema) {
-        final Map<String, LeafNodeCodecContext> leaves = new HashMap<>();
+        final Map<String, LeafNodeCodecContext<?>> leaves = new HashMap<>();
         for (final Method method : parentClass.getMethods()) {
             if (method.getParameterTypes().length == 0) {
                 final DataSchemaNode schema = getterToLeafSchema.get(method.getName());
@@ -257,7 +266,7 @@ final class BindingCodecContext implements CodecContextFactory, Immutable {
                     continue; // We do not have schema for leaf, so we will ignore it (eg. getClass, getImplementedInterface).
                 }
                 final Codec<Object, Object> codec = getCodec(valueType, schema);
-                final LeafNodeCodecContext leafNode = new LeafNodeCodecContext(schema, codec, method);
+                final LeafNodeCodecContext<?> leafNode = new LeafNodeCodecContext<>(schema, codec, method);
                 leaves.put(schema.getQName().getLocalName(), leafNode);
             }
         }
@@ -323,10 +332,27 @@ final class BindingCodecContext implements CodecContextFactory, Immutable {
         final Class<? extends Identifier<?>> identifier = ClassLoaderUtils.findFirstGenericArgument(listClz,
                 Identifiable.class);
         final Map<QName, ValueContext> valueCtx = new HashMap<>();
-        for (final LeafNodeCodecContext leaf : getLeafNodes(identifier, schema).values()) {
+        for (final LeafNodeCodecContext<?> leaf : getLeafNodes(identifier, schema).values()) {
             final QName name = leaf.getDomPathArgument().getNodeType();
             valueCtx.put(name, new ValueContext(identifier, leaf));
         }
         return new IdentifiableItemCodec(schema, identifier, listClz, valueCtx);
     }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public <T extends DataObject> BindingCodecTreeNode<T> getSubtreeCodec(InstanceIdentifier<T> path) {
+        // TODO Do we need defensive check here?
+        return (BindingCodecTreeNode<T>) getCodecContextNode(path, null);
+    }
+
+    @Override
+    public BindingCodecTreeNode<?> getSubtreeCodec(YangInstanceIdentifier path) {
+        return getCodecContextNode(path, null);
+    }
+
+    @Override
+    public BindingCodecTreeNode<?> getSubtreeCodec(SchemaPath path) {
+        throw new UnsupportedOperationException("Not implemented yet.");
+    }
 }
index 8d17af9a16510846b07c765451d2d993c87d7d43..0c59f342bc74e10371494e315432964da30740a3 100644 (file)
@@ -18,10 +18,12 @@ import java.util.AbstractMap.SimpleEntry;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Map.Entry;
+import org.opendaylight.yangtools.binding.data.codec.api.BindingCodecTreeFactory;
 import org.opendaylight.yangtools.binding.data.codec.api.BindingNormalizedNodeSerializer;
 import org.opendaylight.yangtools.binding.data.codec.api.BindingNormalizedNodeWriterFactory;
 import org.opendaylight.yangtools.binding.data.codec.gen.impl.DataObjectSerializerGenerator;
 import org.opendaylight.yangtools.concepts.Delegator;
+import org.opendaylight.yangtools.sal.binding.generator.impl.ModuleInfoBackedContext;
 import org.opendaylight.yangtools.sal.binding.generator.util.BindingRuntimeContext;
 import org.opendaylight.yangtools.yang.binding.BindingStreamEventWriter;
 import org.opendaylight.yangtools.yang.binding.DataContainer;
@@ -32,6 +34,7 @@ import org.opendaylight.yangtools.yang.binding.DataObjectSerializerRegistry;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument;
 import org.opendaylight.yangtools.yang.binding.Notification;
+import org.opendaylight.yangtools.yang.binding.util.BindingReflections;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode;
 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
@@ -44,11 +47,14 @@ import org.opendaylight.yangtools.yang.data.api.schema.UnkeyedListNode;
 import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeStreamWriter;
 import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNormalizedNodeStreamWriter;
 import org.opendaylight.yangtools.yang.data.impl.schema.NormalizedNodeResult;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 import org.opendaylight.yangtools.yang.model.api.SchemaPath;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-public class BindingNormalizedNodeCodecRegistry implements DataObjectSerializerRegistry, BindingNormalizedNodeWriterFactory, BindingNormalizedNodeSerializer {
+public class BindingNormalizedNodeCodecRegistry implements DataObjectSerializerRegistry,
+        BindingCodecTreeFactory, BindingNormalizedNodeWriterFactory,
+        BindingNormalizedNodeSerializer {
     private static final Logger LOG = LoggerFactory.getLogger(BindingNormalizedNodeCodecRegistry.class);
 
     private final DataObjectSerializerGenerator generator;
@@ -70,7 +76,7 @@ public class BindingNormalizedNodeCodecRegistry implements DataObjectSerializerR
     }
 
     public void onBindingRuntimeContextUpdated(final BindingRuntimeContext context) {
-        codecContext = new BindingCodecContext(context);
+        codecContext = create(context);
         generator.onBindingRuntimeContextUpdated(context);
     }
 
@@ -172,7 +178,7 @@ public class BindingNormalizedNodeCodecRegistry implements DataObjectSerializerR
         }
 
         final List<PathArgument> builder = new ArrayList<>();
-        final NodeCodecContext codec = codecContext.getCodecContextNode(path, builder);
+        final NodeCodecContext<?> codec = codecContext.getCodecContextNode(path, builder);
         if (codec == null) {
             if (data != null) {
                 LOG.warn("Path {} does not have a binding equivalent, should have been caught earlier ({})", path, data.getClass());
@@ -180,21 +186,21 @@ public class BindingNormalizedNodeCodecRegistry implements DataObjectSerializerR
             return null;
         }
 
-        final DataObject lazyObj = (DataObject) codec.dataFromNormalizedNode(data);
+        final DataObject lazyObj = codec.deserialize(data);
         final InstanceIdentifier<?> bindingPath = InstanceIdentifier.create(builder);
         return new SimpleEntry<InstanceIdentifier<?>, DataObject>(bindingPath, lazyObj);
     }
 
     @Override
     public Notification fromNormalizedNodeNotification(final SchemaPath path, final ContainerNode data) {
-        final NotificationCodecContext codec = codecContext.getNotificationContext(path);
-        return (Notification) codec.dataFromNormalizedNode(data);
+        final NotificationCodecContext<?> codec = codecContext.getNotificationContext(path);
+        return codec.deserialize(data);
     }
 
     @Override
     public DataObject fromNormalizedNodeRpcData(final SchemaPath path, final ContainerNode data) {
-        final ContainerNodeCodecContext codec = codecContext.getRpcDataContext(path);
-        return (DataObject) codec.dataFromNormalizedNode(data);
+        final ContainerNodeCodecContext<?> codec = codecContext.getRpcDataContext(path);
+        return codec.deserialize(data);
     }
 
    @Override
@@ -220,15 +226,36 @@ public class BindingNormalizedNodeCodecRegistry implements DataObjectSerializerR
     }
 
     public <T extends DataObject> Function<Optional<NormalizedNode<?, ?>>, Optional<T>>  deserializeFunction(final InstanceIdentifier<T> path) {
-        final DataObjectCodecContext<?> ctx = (DataObjectCodecContext<?>) codecContext.getCodecContextNode(path, null);
+        final DataObjectCodecContext<?,?> ctx = (DataObjectCodecContext<?,?>) codecContext.getCodecContextNode(path, null);
         return new DeserializeFunction<T>(ctx);
     }
 
+    @Override
+    public BindingCodecContext create(BindingRuntimeContext context) {
+        return new BindingCodecContext(context, this);
+    }
+
+    @Override
+    public BindingCodecContext create(SchemaContext context, Class<?>... bindingClasses) {
+        ModuleInfoBackedContext strategy = ModuleInfoBackedContext.create();
+        for (Class<?> bindingCls : bindingClasses) {
+            try {
+                strategy.registerModuleInfo(BindingReflections.getModuleInfo(bindingCls));
+            } catch (Exception e) {
+                throw new IllegalStateException(
+                        "Could not create BindingRuntimeContext from class " + bindingCls.getName(),
+                        e);
+            }
+        }
+        BindingRuntimeContext runtimeCtx = BindingRuntimeContext.create(strategy, context);
+        return create(runtimeCtx);
+    }
+
 
     private static final class DeserializeFunction<T> implements Function<Optional<NormalizedNode<?, ?>>, Optional<T>> {
-        private final DataObjectCodecContext<?> ctx;
+        private final DataObjectCodecContext<?,?> ctx;
 
-        DeserializeFunction(final DataObjectCodecContext<?> ctx) {
+        DeserializeFunction(final DataObjectCodecContext<?,?> ctx) {
             this.ctx = ctx;
         }
 
@@ -236,7 +263,7 @@ public class BindingNormalizedNodeCodecRegistry implements DataObjectSerializerR
         @Override
         public Optional<T> apply(final Optional<NormalizedNode<?, ?>> input) {
             if (input.isPresent()) {
-                return Optional.of((T) ctx.dataFromNormalizedNode(input.get()));
+                return Optional.of((T) ctx.deserialize(input.get()));
             }
             return Optional.absent();
         }
index a110ff8347bb2e5d7ba82fbb2c75b8e14a7c40fe..a608520a6315668cc71b613ef47ddf869301b66f 100644 (file)
@@ -30,21 +30,21 @@ import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeStre
 class BindingToNormalizedStreamWriter implements BindingStreamEventWriter, Delegator<NormalizedNodeStreamWriter> {
 
     private final NormalizedNodeStreamWriter delegate;
-    private final Deque<NodeCodecContext> schema = new ArrayDeque<>();
-    private final NodeCodecContext rootNodeSchema;
+    private final Deque<NodeCodecContext<?>> schema = new ArrayDeque<>();
+    private final NodeCodecContext<?> rootNodeSchema;
 
-    public BindingToNormalizedStreamWriter(final NodeCodecContext schema, final NormalizedNodeStreamWriter delegate) {
+    public BindingToNormalizedStreamWriter(final NodeCodecContext<?> schema, final NormalizedNodeStreamWriter delegate) {
         this.delegate = Preconditions.checkNotNull(delegate, "Delegate must not be null");
         this.rootNodeSchema = Preconditions.checkNotNull(schema);
 
     }
 
-    private NodeCodecContext current() {
+    private NodeCodecContext<?> current() {
         return schema.peek();
     }
 
     private NodeIdentifier duplicateSchemaEnter() {
-        final NodeCodecContext next;
+        final NodeCodecContext<?> next;
         if (current() == null) {
             // Entry of first node
             next = rootNodeSchema;
@@ -55,25 +55,25 @@ class BindingToNormalizedStreamWriter implements BindingStreamEventWriter, Deleg
         return (NodeIdentifier) current().getDomPathArgument();
     }
 
+    @SuppressWarnings({"unchecked", "rawtypes"})
     private <T extends YangInstanceIdentifier.PathArgument> T enter(final Class<?> name, final Class<T> identifier) {
-        final NodeCodecContext next;
+        final NodeCodecContext<?> next;
         if (current() == null) {
             // Entry of first node
             next = rootNodeSchema;
         } else {
             Preconditions.checkArgument((current() instanceof DataContainerCodecContext), "Could not start node %s",
                     name);
-            next = ((DataContainerCodecContext<?>) current()).getStreamChild(name);
+            next = ((DataContainerCodecContext<?,?>) current()).streamChild((Class) name);
         }
         this.schema.push(next);
-        @SuppressWarnings("unchecked")
         T arg = (T) next.getDomPathArgument();
         return arg;
     }
 
     private <T extends YangInstanceIdentifier.PathArgument> T enter(final String localName, final Class<T> identifier) {
-        NodeCodecContext current = current();
-        NodeCodecContext next = ((DataObjectCodecContext<?>) current).getLeafChild(localName);
+        NodeCodecContext<?> current = current();
+        NodeCodecContext<?> next = ((DataObjectCodecContext<?,?>) current).getLeafChild(localName);
         this.schema.push(next);
         @SuppressWarnings("unchecked")
         T arg = (T) next.getDomPathArgument();
@@ -82,7 +82,7 @@ class BindingToNormalizedStreamWriter implements BindingStreamEventWriter, Deleg
 
     @Override
     public void endNode() throws IOException {
-        NodeCodecContext left = schema.pop();
+        NodeCodecContext<?> left = schema.pop();
         // NormalizedNode writer does not have entry into case, but into choice
         // so for leaving case, we do not emit endNode.
         if (!(left instanceof CaseNodeCodecContext)) {
@@ -96,10 +96,10 @@ class BindingToNormalizedStreamWriter implements BindingStreamEventWriter, Deleg
     }
 
     private Map.Entry<NodeIdentifier, Object> serializeLeaf(final String localName, final Object value) {
-        Preconditions.checkArgument(current() instanceof DataObjectCodecContext<?>);
+        Preconditions.checkArgument(current() instanceof DataObjectCodecContext);
 
-        DataObjectCodecContext<?> currentCasted = (DataObjectCodecContext<?>) current();
-        LeafNodeCodecContext leafContext = currentCasted.getLeafChild(localName);
+        DataObjectCodecContext<?,?> currentCasted = (DataObjectCodecContext<?,?>) current();
+        LeafNodeCodecContext<?> leafContext = currentCasted.getLeafChild(localName);
 
         NodeIdentifier domArg = (NodeIdentifier) leafContext.getDomPathArgument();
         Object domValue = leafContext.getValueCodec().serialize(value);
@@ -120,7 +120,7 @@ class BindingToNormalizedStreamWriter implements BindingStreamEventWriter, Deleg
 
     @Override
     public void leafSetEntryNode(final Object value) throws IOException, IllegalArgumentException {
-        LeafNodeCodecContext ctx = (LeafNodeCodecContext) current();
+        LeafNodeCodecContext<?> ctx = (LeafNodeCodecContext<?>) current();
         getDelegate().leafSetEntryNode(ctx.getValueCodec().serialize(value));
     }
 
@@ -156,7 +156,7 @@ class BindingToNormalizedStreamWriter implements BindingStreamEventWriter, Deleg
     @Override
     public void startMapEntryNode(final Identifier<?> key, final int childSizeHint) throws IOException, IllegalArgumentException {
         duplicateSchemaEnter();
-        NodeIdentifierWithPredicates identifier = ((KeyedListNodeCodecContext) current()).serialize(key);
+        NodeIdentifierWithPredicates identifier = ((KeyedListNodeCodecContext<?>) current()).serialize(key);
         getDelegate().startMapEntryNode(identifier, childSizeHint);
     };
 
diff --git a/code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/CachingNormalizedNodeCodecImpl.java b/code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/CachingNormalizedNodeCodecImpl.java
new file mode 100644 (file)
index 0000000..0beb463
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * 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.binding.data.codec.api.BindingNormalizedNodeCachingCodec;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+
+class CachingNormalizedNodeCodecImpl<D extends DataObject> implements BindingNormalizedNodeCachingCodec<D>{
+
+    private final Set<Class<? extends DataObject>> cachedValues;
+    private final DataContainerCodecContext<D, ?> context;
+
+    CachingNormalizedNodeCodecImpl(DataContainerCodecContext<D, ?> subtreeRoot, Set<Class<? extends DataObject>> cacheSpec) {
+        this.context = Preconditions.checkNotNull(subtreeRoot);
+        this.cachedValues = Preconditions.checkNotNull(cacheSpec);
+    }
+
+    @Override
+    public D deserialize(NormalizedNode<?, ?> data) {
+        return context.deserialize(data);
+    }
+
+    @Override
+    public NormalizedNode<?, ?> serialize(D data) {
+        // FIXME: Add real-class based serialization.
+        return context.serialize(data);
+    }
+
+    @Override
+    public void close() {
+        // NOOP as of now.
+    }
+
+}
index 86d8098fc2b769cc7e3ecd583cf9625733b09c71..1b84553f1151df8ceb1d9ec108896ef56fd55cd2 100644 (file)
@@ -9,12 +9,13 @@ package org.opendaylight.yangtools.binding.data.codec.impl;
 
 import com.google.common.base.Preconditions;
 import java.util.List;
+import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument;
 import org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
 import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode;
 
-final class CaseNodeCodecContext extends DataObjectCodecContext<ChoiceCaseNode> {
+final class CaseNodeCodecContext<D extends DataObject> extends DataObjectCodecContext<D,ChoiceCaseNode> {
     public CaseNodeCodecContext(final DataContainerCodecPrototype<ChoiceCaseNode> prototype) {
         super(prototype);
     }
@@ -26,8 +27,13 @@ final class CaseNodeCodecContext extends DataObjectCodecContext<ChoiceCaseNode>
     }
 
     @Override
-    protected Object dataFromNormalizedNode(final NormalizedNode<?, ?> normalizedNode) {
+    public D deserialize(final NormalizedNode<?, ?> normalizedNode) {
         Preconditions.checkState(normalizedNode instanceof ChoiceNode);
         return createBindingProxy((ChoiceNode) normalizedNode);
     }
+
+    @Override
+    protected Object deserializeObject(NormalizedNode<?, ?> normalizedNode) {
+        return deserialize(normalizedNode);
+    }
 }
\ No newline at end of file
index 7f8877e29a23aa6fb6739b7647a851f0cbcc96f2..60da344ba109f300920fa1ee27c4e89ddaa2eb67 100644 (file)
@@ -30,7 +30,7 @@ import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-final class ChoiceNodeCodecContext extends DataContainerCodecContext<ChoiceSchemaNode> {
+final class ChoiceNodeCodecContext<D extends DataObject> extends DataContainerCodecContext<D,ChoiceSchemaNode> {
     private static final Logger LOG = LoggerFactory.getLogger(ChoiceNodeCodecContext.class);
     private final ImmutableMap<YangInstanceIdentifier.PathArgument, DataContainerCodecPrototype<?>> byYangCaseChild;
     private final ImmutableMap<Class<?>, DataContainerCodecPrototype<?>> byClass;
@@ -43,7 +43,7 @@ final class ChoiceNodeCodecContext extends DataContainerCodecContext<ChoiceSchem
         Map<Class<?>, DataContainerCodecPrototype<?>> byCaseChildClassBuilder = new HashMap<>();
         Set<Class<?>> potentialSubstitutions = new HashSet<>();
         // Walks all cases for supplied choice in current runtime context
-        for (Class<?> caze : factory().getRuntimeContext().getCases(bindingClass())) {
+        for (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);
@@ -52,7 +52,9 @@ final class ChoiceNodeCodecContext extends DataContainerCodecContext<ChoiceSchem
             if (cazeDef != null) {
                 byClassBuilder.put(cazeDef.getBindingClass(), cazeDef);
                 // Updates collection of case children
-                for (Class<? extends DataObject> cazeChild : BindingReflections.getChildrenClasses((Class<? extends DataObject>) caze)) {
+                @SuppressWarnings("unchecked")
+                Class<? extends DataObject> cazeCls = (Class<? extends DataObject>) caze;
+                for (Class<? extends DataObject> cazeChild : BindingReflections.getChildrenClasses(cazeCls)) {
                     byCaseChildClassBuilder.put(cazeChild, cazeDef);
                 }
                 // Updates collection of YANG instance identifier to case
@@ -90,18 +92,23 @@ final class ChoiceNodeCodecContext extends DataContainerCodecContext<ChoiceSchem
         byCaseChildClass = ImmutableMap.copyOf(byCaseChildClassBuilder);
     }
 
+
+    @SuppressWarnings("unchecked")
     @Override
-    protected DataContainerCodecContext<?> getStreamChild(final Class<?> childClass) {
+    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 child.get();
+        return (DataContainerCodecContext<DV, ?>) child.get();
     }
 
+
+    @SuppressWarnings("unchecked")
     @Override
-    protected Optional<DataContainerCodecContext<?>> getPossibleStreamChild(final Class<?> childClass) {
+    public <DV extends DataObject> Optional<DataContainerCodecContext<DV, ?>> possibleStreamChild(
+            Class<DV> childClass) {
         DataContainerCodecPrototype<?> child = byClass.get(childClass);
         if(child != null) {
-            return Optional.<DataContainerCodecContext<?>>of(child.get());
+            return Optional.<DataContainerCodecContext<DV,?>>of((DataContainerCodecContext<DV, ?>) child.get());
         }
         return Optional.absent();
     }
@@ -121,14 +128,15 @@ final class ChoiceNodeCodecContext extends DataContainerCodecContext<ChoiceSchem
     }
 
     @Override
-    protected NodeCodecContext getYangIdentifierChild(final YangInstanceIdentifier.PathArgument arg) {
+    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());
-        return cazeProto.get().getYangIdentifierChild(arg);
+        return cazeProto.get().yangPathArgumentChild(arg);
     }
 
+    @SuppressWarnings("unchecked")
     @Override
-    protected Object dataFromNormalizedNode(final NormalizedNode<?, ?> data) {
+    public D deserialize(final NormalizedNode<?, ?> data) {
         Preconditions
                 .checkArgument(data instanceof org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode);
         NormalizedNodeContainer<?, ?, NormalizedNode<?,?>> casted = (NormalizedNodeContainer<?, ?, NormalizedNode<?,?>>) data;
@@ -138,10 +146,10 @@ final class ChoiceNodeCodecContext extends DataContainerCodecContext<ChoiceSchem
             return null;
         }
         DataContainerCodecPrototype<?> caze = byYangCaseChild.get(first.getIdentifier());
-        return caze.get().dataFromNormalizedNode(data);
+        return (D) caze.get().deserialize(data);
     }
 
-    public @Nullable DataContainerCodecContext<?> getCazeByChildClass(final @Nonnull Class<? extends DataObject> type) {
+    @Nullable DataContainerCodecContext<?,?> getCazeByChildClass(final @Nonnull Class<? extends DataObject> type) {
         final DataContainerCodecPrototype<?> protoCtx = byCaseChildClass.get(type);
         if(protoCtx != null) {
             return protoCtx.get();
@@ -149,4 +157,9 @@ final class ChoiceNodeCodecContext extends DataContainerCodecContext<ChoiceSchem
         return null;
     }
 
+    @Override
+    protected Object deserializeObject(NormalizedNode<?, ?> normalizedNode) {
+        return deserialize(normalizedNode);
+    }
+
 }
index f70e7ce996818985b57ed74cfad405de87d7d95a..a179d9af59aed819d224fc13699160f9e13cfd0a 100644 (file)
@@ -8,20 +8,26 @@
 package org.opendaylight.yangtools.binding.data.codec.impl;
 
 import com.google.common.base.Preconditions;
+import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
 import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
 
-final class ContainerNodeCodecContext extends DataObjectCodecContext<ContainerSchemaNode> {
+final class ContainerNodeCodecContext<D extends DataObject> extends DataObjectCodecContext<D,ContainerSchemaNode> {
 
     ContainerNodeCodecContext(final DataContainerCodecPrototype<ContainerSchemaNode> prototype) {
         super(prototype);
     }
 
     @Override
-    protected Object dataFromNormalizedNode(final NormalizedNode<?, ?> data) {
+    public D deserialize(final NormalizedNode<?, ?> data) {
         Preconditions.checkState(data instanceof ContainerNode);
         return createBindingProxy((ContainerNode) data);
     }
 
+    @Override
+    protected Object deserializeObject(NormalizedNode<?, ?> normalizedNode) {
+        return deserialize(normalizedNode);
+    }
+
 }
\ No newline at end of file
index 1b8bdf040a308f0629adc57e63b1b90de29bc22f..455cf674bbf7494ab335bc1123ad2d99bafddb31 100644 (file)
@@ -8,17 +8,28 @@
 package org.opendaylight.yangtools.binding.data.codec.impl;
 
 import com.google.common.base.Optional;
+import com.google.common.collect.ImmutableCollection;
+import com.google.common.collect.ImmutableSet;
+import java.io.IOException;
 import java.util.List;
 import javax.annotation.Nullable;
+import org.opendaylight.yangtools.binding.data.codec.api.BindingNormalizedNodeCachingCodec;
 import org.opendaylight.yangtools.yang.binding.BindingStreamEventWriter;
+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.QNameModule;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeStreamWriter;
+import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNormalizedNodeStreamWriter;
+import org.opendaylight.yangtools.yang.data.impl.schema.NormalizedNodeResult;
 
-abstract class DataContainerCodecContext<T> extends NodeCodecContext {
+abstract class DataContainerCodecContext<D extends DataObject,T> extends NodeCodecContext<D>  {
 
     private final DataContainerCodecPrototype<T> prototype;
+    private volatile DataObjectSerializer eventStreamSerializer;
 
     protected DataContainerCodecContext(final DataContainerCodecPrototype<T> prototype) {
         this.prototype = prototype;
@@ -48,7 +59,8 @@ abstract class DataContainerCodecContext<T> extends NodeCodecContext {
      * @return Context of child
      * @throws IllegalArgumentException If supplied argument does not represent valid child.
      */
-    protected abstract NodeCodecContext getYangIdentifierChild(final YangInstanceIdentifier.PathArgument arg);
+    @Override
+    public abstract NodeCodecContext<?> yangPathArgumentChild(final YangInstanceIdentifier.PathArgument arg);
 
     /**
      * Returns nested node context using supplied Binding Instance Identifier
@@ -58,16 +70,17 @@ abstract class DataContainerCodecContext<T> extends NodeCodecContext {
      * @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 @Nullable DataContainerCodecContext<?> getIdentifierChild(final InstanceIdentifier.PathArgument arg,
+    @Override
+    public @Nullable DataContainerCodecContext<?,?> bindingPathArgumentChild(final InstanceIdentifier.PathArgument arg,
             final List<YangInstanceIdentifier.PathArgument> builder) {
-        final DataContainerCodecContext<?> child = getStreamChild(arg.getType());
+        final DataContainerCodecContext<?,?> child = streamChild(arg.getType());
         if(child != null) {
             if (builder != null) {
                 child.addYangPathArgument(arg,builder);
             }
             return child;
         }
-        return null;
+        throw new IllegalArgumentException("SUpplied argument is not valid child");
     }
 
     /**
@@ -84,8 +97,10 @@ abstract class DataContainerCodecContext<T> extends NodeCodecContext {
         return prototype.getBindingArg();
     }
 
-    protected final Class<?> bindingClass() {
-        return prototype.getBindingClass();
+    @SuppressWarnings("unchecked")
+    @Override
+    public final Class<D> getBindingClass() {
+        return Class.class.cast(prototype.getBindingClass());
     }
 
     /**
@@ -98,7 +113,8 @@ abstract class DataContainerCodecContext<T> extends NodeCodecContext {
      * @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 @Nullable DataContainerCodecContext<?> getStreamChild(final Class<?> childClass) throws IllegalArgumentException;
+    @Override
+    public abstract @Nullable <DV extends DataObject> DataContainerCodecContext<DV,?> streamChild(final Class<DV> childClass) throws IllegalArgumentException;
 
     /**
      *
@@ -109,11 +125,47 @@ abstract class DataContainerCodecContext<T> extends NodeCodecContext {
      * @param childClass
      * @return Context of child or Optional absent is supplied class is not applicable in context.
      */
-    protected abstract Optional<DataContainerCodecContext<?>> getPossibleStreamChild(final Class<?> childClass);
+    @Override
+    public abstract <DV extends DataObject> Optional<DataContainerCodecContext<DV,?>> possibleStreamChild(final Class<DV> childClass);
 
     @Override
     public String toString() {
         return getClass().getSimpleName() + " [" + prototype.getBindingClass() + "]";
     }
 
+    @Override
+    public BindingNormalizedNodeCachingCodec<D> createCachingCodec(
+            ImmutableCollection<Class<? extends DataObject>> cacheSpecifier) {
+        return new CachingNormalizedNodeCodecImpl<D>(this,ImmutableSet.copyOf(cacheSpecifier));
+    }
+
+    BindingStreamEventWriter createWriter(NormalizedNodeStreamWriter domWriter) {
+        return  new BindingToNormalizedStreamWriter(this, domWriter);
+    }
+
+    DataObjectSerializer eventStreamSerializer() {
+        if(eventStreamSerializer == null) {
+            eventStreamSerializer = factory().getEventStreamSerializer(getBindingClass());
+        }
+        return eventStreamSerializer;
+    }
+
+    @Override
+    public NormalizedNode<?, ?> serialize(D data) {
+        final NormalizedNodeResult result = new NormalizedNodeResult();
+        // We create DOM stream writer which produces normalized nodes
+        final NormalizedNodeStreamWriter domWriter = ImmutableNormalizedNodeStreamWriter.from(result);
+        writeAsNormalizedNode(data, domWriter);
+        return result.getResult();
+    }
+
+    @Override
+    public void writeAsNormalizedNode(D data, NormalizedNodeStreamWriter writer) {
+        try {
+            eventStreamSerializer().serialize(data, createWriter(writer));
+        } catch (IOException e) {
+            throw new IllegalStateException("Failed to serialize Binding DTO",e);
+        }
+    }
+
 }
\ No newline at end of file
index 5d2ad801dcef7734b78e2229cbf9e80750dc218c..2b2c54985857b7b80a3f4c7aeae0ecefec343c6a 100644 (file)
@@ -35,8 +35,9 @@ final class DataContainerCodecPrototype<T> implements NodeContextSupplier {
     private final Class<?> bindingClass;
     private final InstanceIdentifier.Item<?> bindingArg;
     private final YangInstanceIdentifier.PathArgument yangArg;
-    private volatile DataContainerCodecContext<T> instance = null;
+    private volatile DataContainerCodecContext<?,T> instance = null;
 
+    @SuppressWarnings({"rawtypes", "unchecked"})
     private DataContainerCodecPrototype(final Class<?> cls, final YangInstanceIdentifier.PathArgument arg, final T nodeSchema,
             final CodecContextFactory factory) {
         super();
@@ -53,8 +54,9 @@ final class DataContainerCodecPrototype<T> implements NodeContextSupplier {
         }
     }
 
+    @SuppressWarnings({"rawtypes", "unchecked"})
     private DataContainerCodecPrototype(final Class<?> cls, final YangInstanceIdentifier.PathArgument arg, final T nodeSchema,
-            final CodecContextFactory factory,final DataContainerCodecContext<T> instance) {
+            final CodecContextFactory factory,final DataContainerCodecContext<?,T> instance) {
         super();
         this.yangArg = arg;
         this.schema = nodeSchema;
@@ -115,8 +117,8 @@ final class DataContainerCodecPrototype<T> implements NodeContextSupplier {
     }
 
     @Override
-    public DataContainerCodecContext<T> get() {
-        DataContainerCodecContext<T> tmp = instance;
+    public DataContainerCodecContext<?,T> get() {
+        DataContainerCodecContext<?,T> tmp = instance;
         if (tmp == null) {
             synchronized (this) {
                 tmp = instance;
@@ -132,22 +134,22 @@ final class DataContainerCodecPrototype<T> implements NodeContextSupplier {
 
     @GuardedBy("this")
     @SuppressWarnings({ "rawtypes", "unchecked" })
-    private DataContainerCodecContext createInstance() {
+    private DataContainerCodecContext<?,T> createInstance() {
         // FIXME: make protected abstract
         if (schema instanceof ContainerSchemaNode) {
-            return new ContainerNodeCodecContext((DataContainerCodecPrototype) this);
+            return new ContainerNodeCodecContext(this);
         } else if (schema instanceof ListSchemaNode) {
             if (Identifiable.class.isAssignableFrom(getBindingClass())) {
-                return new KeyedListNodeCodecContext((DataContainerCodecPrototype) this);
+                return new KeyedListNodeCodecContext(this);
             } else {
-                return new ListNodeCodecContext((DataContainerCodecPrototype) this);
+                return new ListNodeCodecContext(this);
             }
         } else if (schema instanceof ChoiceSchemaNode) {
-            return new ChoiceNodeCodecContext((DataContainerCodecPrototype) this);
+            return new ChoiceNodeCodecContext(this);
         } else if (schema instanceof AugmentationSchema) {
-            return new AugmentationNodeContext((DataContainerCodecPrototype) this);
+            return new AugmentationNodeContext(this);
         } else if (schema instanceof ChoiceCaseNode) {
-            return new CaseNodeCodecContext((DataContainerCodecPrototype) this);
+            return new CaseNodeCodecContext(this);
         }
         throw new IllegalArgumentException("Unsupported type " + bindingClass + " " + schema);
     }
index f63df0eba97a68becc65da989a929b0860f265b7..6066064c8076daf4b482c8633f10b8abecb52cd2 100644 (file)
@@ -49,7 +49,7 @@ import org.opendaylight.yangtools.yang.model.util.SchemaNodeUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-abstract class DataObjectCodecContext<T extends DataNodeContainer> extends DataContainerCodecContext<T> {
+abstract class DataObjectCodecContext<D extends DataObject,T extends DataNodeContainer> extends DataContainerCodecContext<D,T> {
     private static final Logger LOG = LoggerFactory.getLogger(DataObjectCodecContext.class);
     private static final Lookup LOOKUP = MethodHandles.publicLookup();
     private static final MethodType CONSTRUCTOR_TYPE = MethodType.methodType(void.class, InvocationHandler.class);
@@ -61,64 +61,54 @@ abstract class DataObjectCodecContext<T extends DataNodeContainer> extends DataC
         }
     };
 
-    private final ImmutableMap<String, LeafNodeCodecContext> leafChild;
+    private final ImmutableMap<String, LeafNodeCodecContext<?>> leafChild;
     private final ImmutableMap<YangInstanceIdentifier.PathArgument, NodeContextSupplier> byYang;
     private final ImmutableSortedMap<Method, NodeContextSupplier> byMethod;
     private final ImmutableMap<Class<?>, DataContainerCodecPrototype<?>> byStreamClass;
     private final ImmutableMap<Class<?>, DataContainerCodecPrototype<?>> byBindingArgClass;
     private final MethodHandle proxyConstructor;
 
-    // FIXME: this field seems to be unused
-    private final Method augmentationGetter;
-
     protected DataObjectCodecContext(final DataContainerCodecPrototype<T> prototype) {
         super(prototype);
 
-        this.leafChild = factory().getLeafNodes(bindingClass(), schema());
+        this.leafChild = factory().getLeafNodes(getBindingClass(), schema());
 
-        Map<Class<?>, Method> clsToMethod = BindingReflections.getChildrenClassToMethod(bindingClass());
+        final Map<Class<?>, Method> clsToMethod = BindingReflections.getChildrenClassToMethod(getBindingClass());
 
-        Map<YangInstanceIdentifier.PathArgument, NodeContextSupplier> byYangBuilder = new HashMap<>();
-        SortedMap<Method, NodeContextSupplier> byMethodBuilder = new TreeMap<>(METHOD_BY_ALPHABET);
-        Map<Class<?>, DataContainerCodecPrototype<?>> byStreamClassBuilder = new HashMap<>();
-        Map<Class<?>, DataContainerCodecPrototype<?>> byBindingArgClassBuilder = new HashMap<>();
+        final Map<YangInstanceIdentifier.PathArgument, NodeContextSupplier> byYangBuilder = new HashMap<>();
+        final SortedMap<Method, NodeContextSupplier> byMethodBuilder = new TreeMap<>(METHOD_BY_ALPHABET);
+        final Map<Class<?>, DataContainerCodecPrototype<?>> byStreamClassBuilder = new HashMap<>();
+        final Map<Class<?>, DataContainerCodecPrototype<?>> byBindingArgClassBuilder = new HashMap<>();
 
         // Adds leaves to mapping
-        for (LeafNodeCodecContext leaf : leafChild.values()) {
+        for (final LeafNodeCodecContext<?> leaf : leafChild.values()) {
             byMethodBuilder.put(leaf.getGetter(), leaf);
             byYangBuilder.put(leaf.getDomPathArgument(), leaf);
         }
 
-        for (Entry<Class<?>, Method> childDataObj : clsToMethod.entrySet()) {
-            DataContainerCodecPrototype<?> childProto = loadChildPrototype(childDataObj.getKey());
+        for (final Entry<Class<?>, Method> childDataObj : clsToMethod.entrySet()) {
+            final DataContainerCodecPrototype<?> childProto = loadChildPrototype(childDataObj.getKey());
             byMethodBuilder.put(childDataObj.getValue(), childProto);
             byStreamClassBuilder.put(childProto.getBindingClass(), childProto);
             byYangBuilder.put(childProto.getYangArg(), childProto);
             if (childProto.isChoice()) {
-                ChoiceNodeCodecContext choice = (ChoiceNodeCodecContext) childProto.get();
-                for(Class<?> cazeChild : choice.getCaseChildrenClasses()) {
+                final ChoiceNodeCodecContext<?> choice = (ChoiceNodeCodecContext<?>) childProto.get();
+                for(final Class<?> cazeChild : choice.getCaseChildrenClasses()) {
                     byBindingArgClassBuilder.put(cazeChild, childProto);
                 }
             }
         }
         this.byMethod = ImmutableSortedMap.copyOfSorted(byMethodBuilder);
-        if (Augmentable.class.isAssignableFrom(bindingClass())) {
-            try {
-                augmentationGetter = bindingClass().getMethod("getAugmentation", Class.class);
-            } catch (NoSuchMethodException | SecurityException e) {
-               throw new IllegalStateException("Could not get required method.",e);
-            }
-            ImmutableMap<AugmentationIdentifier, Type> augmentations = factory().getRuntimeContext()
+        if (Augmentable.class.isAssignableFrom(getBindingClass())) {
+            final ImmutableMap<AugmentationIdentifier, Type> augmentations = factory().getRuntimeContext()
                     .getAvailableAugmentationTypes(schema());
-            for (Entry<AugmentationIdentifier, Type> augment : augmentations.entrySet()) {
-                DataContainerCodecPrototype<?> augProto = getAugmentationPrototype(augment.getValue());
+            for (final Entry<AugmentationIdentifier, Type> augment : augmentations.entrySet()) {
+                final DataContainerCodecPrototype<?> augProto = getAugmentationPrototype(augment.getValue());
                 if (augProto != null) {
                     byYangBuilder.put(augProto.getYangArg(), augProto);
                     byStreamClassBuilder.put(augProto.getBindingClass(), augProto);
                 }
             }
-        } else {
-            augmentationGetter = null;
         }
 
         this.byYang = ImmutableMap.copyOf(byYangBuilder);
@@ -126,7 +116,7 @@ abstract class DataObjectCodecContext<T extends DataNodeContainer> extends DataC
         byBindingArgClassBuilder.putAll(byStreamClass);
         this.byBindingArgClass = ImmutableMap.copyOf(byBindingArgClassBuilder);
 
-        final Class<?> proxyClass = Proxy.getProxyClass(bindingClass().getClassLoader(),  new Class[] { bindingClass() });
+        final Class<?> proxyClass = Proxy.getProxyClass(getBindingClass().getClassLoader(),  new Class[] { getBindingClass() });
         try {
             proxyConstructor = LOOKUP.findConstructor(proxyClass, CONSTRUCTOR_TYPE).asType(DATAOBJECT_TYPE);
         } catch (NoSuchMethodException | IllegalAccessException e) {
@@ -134,11 +124,13 @@ abstract class DataObjectCodecContext<T extends DataNodeContainer> extends DataC
         }
     }
 
+
+    @SuppressWarnings("unchecked")
     @Override
-    protected DataContainerCodecContext<?> getStreamChild(final Class<?> childClass) {
+    public <DV extends DataObject> DataContainerCodecContext<DV, ?> streamChild(final Class<DV> childClass) {
         DataContainerCodecPrototype<?> childProto = byStreamClass.get(childClass);
         if (childProto != null) {
-            return childProto.get();
+            return (DataContainerCodecContext<DV,?>) childProto.get();
         }
 
         if (Augmentation.class.isAssignableFrom(childClass))  {
@@ -149,9 +141,10 @@ abstract class DataObjectCodecContext<T extends DataNodeContainer> extends DataC
              *
              * FIXME: Cache mapping of mismatched augmentation to real one, to speed up lookup.
              */
-            Class<?> augTarget = BindingReflections.findAugmentationTarget((Class) childClass);
-            if ((bindingClass().equals(augTarget))) {
-                for (DataContainerCodecPrototype<?> realChild : byStreamClass.values()) {
+            @SuppressWarnings("rawtypes")
+            final Class<?> augTarget = BindingReflections.findAugmentationTarget((Class) childClass);
+            if ((getBindingClass().equals(augTarget))) {
+                for (final DataContainerCodecPrototype<?> realChild : byStreamClass.values()) {
                     if (Augmentation.class.isAssignableFrom(realChild.getBindingClass())
                             && BindingReflections.isSubstitutionFor(childClass,realChild.getBindingClass())) {
                         childProto = realChild;
@@ -161,33 +154,36 @@ abstract class DataObjectCodecContext<T extends DataNodeContainer> extends DataC
             }
         }
         Preconditions.checkArgument(childProto != null, " Child %s is not valid child.",childClass);
-        return childProto.get();
+        return (DataContainerCodecContext<DV, ?>) childProto.get();
     }
 
+
+    @SuppressWarnings("unchecked")
     @Override
-    protected Optional<DataContainerCodecContext<?>> getPossibleStreamChild(final Class<?> childClass) {
-        DataContainerCodecPrototype<?> childProto = byStreamClass.get(childClass);
+    public <DV extends DataObject> Optional<DataContainerCodecContext<DV, ?>> possibleStreamChild(
+            Class<DV> childClass) {
+        final DataContainerCodecPrototype<?> childProto = byStreamClass.get(childClass);
         if(childProto != null) {
-            return Optional.<DataContainerCodecContext<?>>of(childProto.get());
+            return Optional.<DataContainerCodecContext<DV,?>>of((DataContainerCodecContext<DV,?>) childProto.get());
         }
         return Optional.absent();
     }
 
     @Override
-    protected DataContainerCodecContext<?> getIdentifierChild(final InstanceIdentifier.PathArgument arg,
+    public DataContainerCodecContext<?,?> bindingPathArgumentChild(final InstanceIdentifier.PathArgument arg,
             final List<YangInstanceIdentifier.PathArgument> builder) {
 
         final Class<? extends DataObject> argType = arg.getType();
         final DataContainerCodecPrototype<?> ctxProto = byBindingArgClass.get(argType);
         if(ctxProto != null) {
-            final DataContainerCodecContext<?> context = ctxProto.get();
+            final DataContainerCodecContext<?,?> context = ctxProto.get();
             if(context instanceof ChoiceNodeCodecContext) {
-                final ChoiceNodeCodecContext choice = (ChoiceNodeCodecContext) context;
-                final DataContainerCodecContext<?> caze = choice.getCazeByChildClass(arg.getType());
+                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 caze.bindingPathArgumentChild(arg, builder);
                 }
                 return null;
             }
@@ -198,30 +194,31 @@ abstract class DataObjectCodecContext<T extends DataNodeContainer> extends DataC
         return null;
     }
 
+    @SuppressWarnings("unchecked")
     @Override
-    protected NodeCodecContext getYangIdentifierChild(YangInstanceIdentifier.PathArgument arg) {
+    public NodeCodecContext<D> yangPathArgumentChild(YangInstanceIdentifier.PathArgument arg) {
         if(arg instanceof NodeIdentifierWithPredicates) {
             arg = new NodeIdentifier(arg.getNodeType());
         }
-        NodeContextSupplier childSupplier = byYang.get(arg);
+        final NodeContextSupplier childSupplier = byYang.get(arg);
         Preconditions.checkArgument(childSupplier != null, "Argument %s is not valid child of %s", arg, schema());
-        return childSupplier.get();
+        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, bindingClass());
+    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;
     }
 
     private DataContainerCodecPrototype<?> loadChildPrototype(final Class<?> childClass) {
-        DataSchemaNode origDef = factory().getRuntimeContext().getSchemaDefinition(childClass);
+        final DataSchemaNode origDef = factory().getRuntimeContext().getSchemaDefinition(childClass);
         // Direct instantiation or use in same module in which grouping
         // was defined.
         DataSchemaNode sameName;
         try {
             sameName = schema().getDataChildByName(origDef.getQName());
-        } catch (IllegalArgumentException e) {
+        } catch (final IllegalArgumentException e) {
             sameName = null;
         }
         final DataSchemaNode childSchema;
@@ -239,8 +236,8 @@ abstract class DataObjectCodecContext<T extends DataNodeContainer> extends DataC
             }
         } else {
             // We are looking for instantiation via uses in other module
-            QName instantiedName = QName.create(namespace(), origDef.getQName().getLocalName());
-            DataSchemaNode potential = schema().getDataChildByName(instantiedName);
+            final QName instantiedName = QName.create(namespace(), origDef.getQName().getLocalName());
+            final DataSchemaNode potential = schema().getDataChildByName(instantiedName);
             // We check if it is really instantiated from same
             // definition as class was derived
             if (potential != null && origDef.equals(SchemaNodeUtils.getRootOriginalIfPossible(potential))) {
@@ -254,50 +251,53 @@ abstract class DataObjectCodecContext<T extends DataNodeContainer> extends DataC
     }
 
     private DataContainerCodecPrototype<?> getAugmentationPrototype(final Type value) {
-        ClassLoadingStrategy loader = factory().getRuntimeContext().getStrategy();
+        final ClassLoadingStrategy loader = factory().getRuntimeContext().getStrategy();
         @SuppressWarnings("rawtypes")
         final Class augClass;
         try {
             augClass = loader.loadClass(value);
-        } catch (ClassNotFoundException e) {
+        } catch (final ClassNotFoundException e) {
             LOG.warn("Failed to load augmentation prototype for {}", value, e);
             return null;
         }
 
-        Entry<AugmentationIdentifier, AugmentationSchema> augSchema = factory().getRuntimeContext()
+        @SuppressWarnings("unchecked")
+        final Entry<AugmentationIdentifier, AugmentationSchema> augSchema = factory().getRuntimeContext()
                 .getResolvedAugmentationSchema(schema(), augClass);
         return DataContainerCodecPrototype.from(augClass, augSchema.getKey(), augSchema.getValue(), factory());
     }
 
     @SuppressWarnings("rawtypes")
     Object getBindingChildValue(final Method method, final NormalizedNodeContainer domData) {
-        NodeCodecContext childContext = byMethod.get(method).get();
-        Optional<NormalizedNode<?, ?>> domChild = domData.getChild(childContext.getDomPathArgument());
+        final NodeCodecContext<?> childContext = byMethod.get(method).get();
+        @SuppressWarnings("unchecked")
+        final Optional<NormalizedNode<?, ?>> domChild = domData.getChild(childContext.getDomPathArgument());
         if (domChild.isPresent()) {
-            return childContext.dataFromNormalizedNode(domChild.get());
+            return childContext.deserializeObject(domChild.get());
         }
         return null;
     }
 
-    protected final DataObject createBindingProxy(final NormalizedNodeContainer<?, ?, ?> node) {
+    protected final D createBindingProxy(final NormalizedNodeContainer<?, ?, ?> node) {
         try {
-            return (DataObject) proxyConstructor.invokeExact((InvocationHandler)new LazyDataObject(this, node));
-        } catch (Throwable e) {
+            return (D) proxyConstructor.invokeExact((InvocationHandler)new LazyDataObject<>(this, node));
+        } catch (final Throwable e) {
             throw Throwables.propagate(e);
         }
     }
 
+    @SuppressWarnings("unchecked")
     public Map<Class<? extends Augmentation<?>>, Augmentation<?>> getAllAugmentationsFrom(
             final NormalizedNodeContainer<?, PathArgument, NormalizedNode<?, ?>> data) {
 
         @SuppressWarnings("rawtypes")
-        Map map = new HashMap<>();
+        final Map map = new HashMap<>();
 
-        for(DataContainerCodecPrototype<?> value : byStreamClass.values()) {
+        for(final DataContainerCodecPrototype<?> value : byStreamClass.values()) {
             if(Augmentation.class.isAssignableFrom(value.getBindingClass())) {
-                Optional<NormalizedNode<?, ?>> augData = data.getChild(value.getYangArg());
+                final Optional<NormalizedNode<?, ?>> augData = data.getChild(value.getYangArg());
                 if(augData.isPresent()) {
-                    map.put(value.getBindingClass(), value.get().dataFromNormalizedNode(augData.get()));
+                    map.put(value.getBindingClass(), value.get().deserializeObject(augData.get()));
                 }
             }
         }
index d15331f1adcb8af54ac71efe63275d3ba744b8e5..377f3744e0c9f10a54d5d5cfbe6c3787cfaa639a 100644 (file)
@@ -33,7 +33,7 @@ final class InstanceIdentifierCodec implements Codec<YangInstanceIdentifier, Ins
     @Override
     public InstanceIdentifier<?> deserialize(final YangInstanceIdentifier input) {
         final List<InstanceIdentifier.PathArgument> builder = new ArrayList<>();
-        final NodeCodecContext codec = context.getCodecContextNode(input, builder);
+        final NodeCodecContext<?> codec = context.getCodecContextNode(input, builder);
         if (codec == null) {
             return null;
         }
index e577c93fa6142bba8f2607201953b80c058dc9d0..a5b2a97f980ee7617284da394d5c87beacd85ee0 100644 (file)
@@ -10,6 +10,8 @@ package org.opendaylight.yangtools.binding.data.codec.impl;
 import java.lang.reflect.Method;
 import java.util.List;
 import org.opendaylight.yangtools.concepts.Codec;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.Identifiable;
 import org.opendaylight.yangtools.yang.binding.Identifier;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.IdentifiableItem;
@@ -19,16 +21,16 @@ import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNodeContainer;
 import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
 
-final class KeyedListNodeCodecContext extends ListNodeCodecContext {
+final class KeyedListNodeCodecContext<D extends DataObject & Identifiable<?>> extends ListNodeCodecContext<D> {
     private final Codec<NodeIdentifierWithPredicates, IdentifiableItem<?, ?>> codec;
     private final Method keyGetter;
 
     KeyedListNodeCodecContext(final DataContainerCodecPrototype<ListSchemaNode> prototype) {
         super(prototype);
 
-        this.codec = factory().getPathArgumentCodec(bindingClass(), schema());
+        this.codec = factory().getPathArgumentCodec(getBindingClass(), schema());
         try {
-            this.keyGetter = bindingClass().getMethod("getKey");
+            this.keyGetter = getBindingClass().getMethod("getKey");
         } catch (NoSuchMethodException e) {
             throw new IllegalStateException("Required method not available", e);
         }
@@ -75,6 +77,6 @@ final class KeyedListNodeCodecContext extends ListNodeCodecContext {
 
     @SuppressWarnings({ "rawtypes", "unchecked" })
     NodeIdentifierWithPredicates serialize(final Identifier<?> key) {
-        return codec.serialize(new IdentifiableItem(bindingClass(), key));
+        return codec.serialize(new IdentifiableItem(getBindingClass(), key));
     }
 }
index 5cfc6f056c63a08d4a9f05c5c4f3fba196c4d6e4..b92acca00784e382c8db2aba813c8701e800b54d 100644 (file)
@@ -22,13 +22,14 @@ import java.util.concurrent.ConcurrentHashMap;
 import org.opendaylight.yangtools.binding.data.codec.util.AugmentationReader;
 import org.opendaylight.yangtools.yang.binding.Augmentable;
 import org.opendaylight.yangtools.yang.binding.Augmentation;
+import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNodeContainer;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-class LazyDataObject implements InvocationHandler, AugmentationReader {
+class LazyDataObject<D extends DataObject> implements InvocationHandler, AugmentationReader {
 
     private static final Logger LOG = LoggerFactory.getLogger(LazyDataObject.class);
     private static final String GET_IMPLEMENTED_INTERFACE = "getImplementedInterface";
@@ -40,13 +41,13 @@ class LazyDataObject implements InvocationHandler, AugmentationReader {
 
     private final ConcurrentHashMap<Method, Object> cachedData = new ConcurrentHashMap<>();
     private final NormalizedNodeContainer<?, PathArgument, NormalizedNode<?, ?>> data;
-    private final DataObjectCodecContext<?> context;
+    private final DataObjectCodecContext<D,?> context;
 
     private volatile ImmutableMap<Class<? extends Augmentation<?>>, Augmentation<?>> cachedAugmentations = null;
     private volatile Integer cachedHashcode = null;
 
     @SuppressWarnings({ "rawtypes", "unchecked" })
-    LazyDataObject(final DataObjectCodecContext<?> ctx, final NormalizedNodeContainer data) {
+    LazyDataObject(final DataObjectCodecContext<D,?> ctx, final NormalizedNodeContainer data) {
         this.context = Preconditions.checkNotNull(ctx, "Context must not be null");
         this.data = Preconditions.checkNotNull(data, "Data must not be null");
     }
@@ -56,7 +57,7 @@ class LazyDataObject implements InvocationHandler, AugmentationReader {
         if (method.getParameterTypes().length == 0) {
             final String name = method.getName();
             if (GET_IMPLEMENTED_INTERFACE.equals(name)) {
-                return context.bindingClass();
+                return context.getBindingClass();
             } else if (TO_STRING.equals(name)) {
                 return bindingToString();
             } else if (HASHCODE.equals(name)) {
@@ -75,7 +76,7 @@ class LazyDataObject implements InvocationHandler, AugmentationReader {
         if (other == null) {
             return false;
         }
-        if (!context.bindingClass().isAssignableFrom(other.getClass())) {
+        if (!context.getBindingClass().isAssignableFrom(other.getClass())) {
             return false;
         }
         try {
@@ -105,7 +106,7 @@ class LazyDataObject implements InvocationHandler, AugmentationReader {
             final Object value = getBindingData(m);
             result += prime * result + ((value == null) ? 0 : value.hashCode());
         }
-        if (Augmentation.class.isAssignableFrom(context.bindingClass())) {
+        if (Augmentation.class.isAssignableFrom(context.getBindingClass())) {
             result += prime * result + (getAugmentations(this).hashCode());
         }
         cachedHashcode = result;
@@ -156,23 +157,25 @@ class LazyDataObject implements InvocationHandler, AugmentationReader {
             return aug.get(cls);
         }
         Preconditions.checkNotNull(cls,"Supplied augmentation must not be null.");
-        final Optional<DataContainerCodecContext<?>> augCtx= context.getPossibleStreamChild(cls);
+
+        @SuppressWarnings({"unchecked","rawtypes"})
+        final Optional<DataContainerCodecContext<?,?>> augCtx= context.possibleStreamChild((Class) cls);
         if(augCtx.isPresent()) {
             final Optional<NormalizedNode<?, ?>> augData = data.getChild(augCtx.get().getDomPathArgument());
             if (augData.isPresent()) {
-                return augCtx.get().dataFromNormalizedNode(augData.get());
+                return augCtx.get().deserialize(augData.get());
             }
         }
         return null;
     }
 
     public String bindingToString() {
-        final ToStringHelper helper = MoreObjects.toStringHelper(context.bindingClass()).omitNullValues();
+        final ToStringHelper helper = MoreObjects.toStringHelper(context.getBindingClass()).omitNullValues();
 
         for (final Method m :context.getHashCodeAndEqualsMethods()) {
             helper.add(m.getName(), getBindingData(m));
         }
-        if (Augmentable.class.isAssignableFrom(context.bindingClass())) {
+        if (Augmentable.class.isAssignableFrom(context.getBindingClass())) {
             helper.add("augmentations", getAugmentationsImpl());
         }
         return helper.toString();
@@ -198,7 +201,7 @@ class LazyDataObject implements InvocationHandler, AugmentationReader {
         if (getClass() != obj.getClass()) {
             return false;
         }
-        final LazyDataObject other = (LazyDataObject) obj;
+        final LazyDataObject<?> other = (LazyDataObject<?>) obj;
         if (context == null) {
             if (other.context != null) {
                 return false;
index 45bbd9e9454efff8785f1bd8f8d4c24ed2b64a95..f74b109cd8731de731e991bfbf0ea5c05e3a09b1 100644 (file)
@@ -7,19 +7,26 @@
  */
 package org.opendaylight.yangtools.binding.data.codec.impl;
 
+import com.google.common.base.Optional;
+import com.google.common.collect.ImmutableCollection;
 import java.lang.reflect.Method;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.List;
+import org.opendaylight.yangtools.binding.data.codec.api.BindingCodecTreeNode;
+import org.opendaylight.yangtools.binding.data.codec.api.BindingNormalizedNodeCachingCodec;
 import org.opendaylight.yangtools.concepts.Codec;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.schema.LeafNode;
 import org.opendaylight.yangtools.yang.data.api.schema.LeafSetEntryNode;
 import org.opendaylight.yangtools.yang.data.api.schema.LeafSetNode;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeStreamWriter;
 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
 
-final class LeafNodeCodecContext extends NodeCodecContext implements NodeContextSupplier {
+final class LeafNodeCodecContext<D extends DataObject> extends NodeCodecContext<D> implements NodeContextSupplier {
 
     private final YangInstanceIdentifier.PathArgument yangIdentifier;
     private final Codec<Object, Object> valueCodec;
@@ -41,10 +48,69 @@ final class LeafNodeCodecContext extends NodeCodecContext implements NodeContext
     }
 
     @Override
-    protected Object dataFromNormalizedNode(final NormalizedNode<?, ?> normalizedNode) {
+    public D deserialize(final NormalizedNode<?, ?> normalizedNode) {
+        throw new UnsupportedOperationException("Leaf can not be deserialized to DataObject");
+    }
+
+    @Override
+    public NodeCodecContext<?> get() {
+        return this;
+    }
+
+    final Method getGetter() {
+        return getter;
+    }
+
+    @Override
+    public BindingCodecTreeNode<?> bindingPathArgumentChild(PathArgument arg,
+            List<YangInstanceIdentifier.PathArgument> builder) {
+        return null;
+    }
+
+    @Override
+    public BindingNormalizedNodeCachingCodec<D> createCachingCodec(
+            ImmutableCollection<Class<? extends DataObject>> cacheSpecifier) {
+        return null;
+    }
+
+    @Override
+    public Class<D> getBindingClass() {
+        return null;
+    }
+
+    @Override
+    public NormalizedNode<?, ?> serialize(D data) {
+        throw new UnsupportedOperationException("Separete serialization of leaf node is not supported.");
+    }
+
+    @Override
+    public void writeAsNormalizedNode(D data, 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;
+    }
+
+    @Override
+    public <E extends DataObject> Optional<? extends BindingCodecTreeNode<E>> possibleStreamChild(
+            Class<E> childClass) {
+        return null;
+    }
+
+    @Override
+    public BindingCodecTreeNode<?> yangPathArgumentChild(
+            org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument child) {
+        return null;
+    }
+
+    @Override
+    protected Object deserializeObject(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) {
@@ -55,13 +121,4 @@ final class LeafNodeCodecContext extends NodeCodecContext implements NodeContext
         return null;
     }
 
-    @Override
-    public NodeCodecContext get() {
-        return this;
-    }
-
-    final Method getGetter() {
-        return getter;
-    }
-
 }
\ No newline at end of file
index c613cf61d65dfbda16f1942e93136e97c9ac4789..919df103cf583f199fe553f0d85ce69cbcb8a068 100644 (file)
@@ -17,13 +17,24 @@ import org.opendaylight.yangtools.yang.data.api.schema.UnkeyedListEntryNode;
 import org.opendaylight.yangtools.yang.data.api.schema.UnkeyedListNode;
 import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
 
-class ListNodeCodecContext extends DataObjectCodecContext<ListSchemaNode> {
+class ListNodeCodecContext<D extends DataObject> extends DataObjectCodecContext<D,ListSchemaNode> {
     protected ListNodeCodecContext(final DataContainerCodecPrototype<ListSchemaNode> prototype) {
         super(prototype);
     }
 
     @Override
-    protected Object dataFromNormalizedNode(final NormalizedNode<?, ?> node) {
+    public D deserialize(final NormalizedNode<?, ?> node) {
+        if (node instanceof MapEntryNode) {
+            return fromMapEntry((MapEntryNode) node);
+        } else if (node instanceof UnkeyedListEntryNode) {
+            return fromUnkeyedListEntry((UnkeyedListEntryNode) node);
+        } else {
+            throw new IllegalStateException("Unsupported data type " + node.getClass());
+        }
+    }
+
+    @Override
+    protected Object deserializeObject(NormalizedNode<?, ?> node) {
         if (node instanceof MapNode) {
             return fromMap((MapNode) node);
         } else if (node instanceof MapEntryNode) {
@@ -37,28 +48,29 @@ class ListNodeCodecContext extends DataObjectCodecContext<ListSchemaNode> {
         }
     }
 
-    private List<DataObject> fromMap(final MapNode nodes) {
-        List<DataObject> ret = new ArrayList<>(nodes.getValue().size());
+    private List<D> fromMap(final MapNode nodes) {
+        List<D> ret = new ArrayList<>(nodes.getValue().size());
         for (MapEntryNode node : nodes.getValue()) {
             ret.add(fromMapEntry(node));
         }
         return ret;
     }
 
-    private DataObject fromMapEntry(final MapEntryNode node) {
+    private D fromMapEntry(final MapEntryNode node) {
         return createBindingProxy(node);
     }
 
-    private DataObject fromUnkeyedListEntry(final UnkeyedListEntryNode node) {
+    private D fromUnkeyedListEntry(final UnkeyedListEntryNode node) {
         return createBindingProxy(node);
     }
 
-    private List<DataObject> fromUnkeyedList(final UnkeyedListNode nodes) {
+    private List<D> fromUnkeyedList(final UnkeyedListNode nodes) {
         // FIXME: Could be this lazy transformed list?
-        List<DataObject> ret = new ArrayList<>(nodes.getValue().size());
+        List<D> ret = new ArrayList<>(nodes.getValue().size());
         for (UnkeyedListEntryNode node : nodes.getValue()) {
             ret.add(fromUnkeyedListEntry(node));
         }
         return ret;
     }
+
 }
\ No newline at end of file
index 66e0dae1e35b8242d00a38402af27d04d70a47e1..028801bede157d4e7dad37324912d6e8015cc988 100644 (file)
@@ -8,11 +8,12 @@
 package org.opendaylight.yangtools.binding.data.codec.impl;
 
 import com.google.common.collect.ImmutableMap;
-
 import java.util.List;
-
+import org.opendaylight.yangtools.binding.data.codec.api.BindingCodecTreeNode;
 import org.opendaylight.yangtools.concepts.Codec;
 import org.opendaylight.yangtools.sal.binding.generator.util.BindingRuntimeContext;
+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.IdentifiableItem;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
@@ -37,7 +38,7 @@ import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
  * </ul>
  *
  */
-abstract class NodeCodecContext {
+abstract class NodeCodecContext<D extends DataObject> implements BindingCodecTreeNode<D> {
 
     /**
      * Returns Yang Instance Identifier Path Argument of current node
@@ -69,7 +70,7 @@ abstract class NodeCodecContext {
          * @param schema  Instantiated schema of binding type.
          * @return Map of local name to leaf node context.
          */
-        ImmutableMap<String, LeafNodeCodecContext> getLeafNodes(Class<?> type, DataNodeContainer schema);
+        ImmutableMap<String, LeafNodeCodecContext<?>> getLeafNodes(Class<?> type, DataNodeContainer schema);
 
         /**
          * Returns Path argument codec for list item
@@ -80,6 +81,8 @@ abstract class NodeCodecContext {
          */
         Codec<NodeIdentifierWithPredicates, IdentifiableItem<?, ?>> getPathArgumentCodec(Class<?> type,
                 ListSchemaNode schema);
+
+        DataObjectSerializer getEventStreamSerializer(Class<?> type);
     }
 
     /**
@@ -97,11 +100,5 @@ abstract class NodeCodecContext {
         }
     }
 
-    /**
-     * Return the data object for a normalized node
-     *
-     * @param normalizedNode Backing normalized node
-     * @return Data object
-     */
-    protected abstract Object dataFromNormalizedNode(NormalizedNode<?, ?> normalizedNode);
+    protected abstract Object deserializeObject(NormalizedNode<?, ?> normalizedNode);
 }
index a0529e504aa8ce3e04e58dc35fcc98ca51955649..c659990ddd4a0e8f9e81099a6065fb0bf708ea38 100644 (file)
@@ -13,7 +13,7 @@ import javax.annotation.Nonnull;
 /**
  * Type capture of an entity producing NodeCodecContexts.
  */
-interface NodeContextSupplier extends Supplier<NodeCodecContext> {
+interface NodeContextSupplier extends Supplier<NodeCodecContext<?>> {
     @Override
-    @Nonnull NodeCodecContext get();
+    @Nonnull NodeCodecContext<?> get();
 }
index 6d292bdeeba313dc376d98a26498090dcc7c05e0..25433b8dfea0f48d1c8aa23c4f4998f8d1b22a32 100644 (file)
@@ -8,21 +8,28 @@
 package org.opendaylight.yangtools.binding.data.codec.impl;
 
 import com.google.common.base.Preconditions;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.Notification;
 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
 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.NotificationDefinition;
 
-final class NotificationCodecContext extends DataObjectCodecContext<NotificationDefinition> {
+final class NotificationCodecContext<D extends DataObject & Notification> extends DataObjectCodecContext<D,NotificationDefinition> {
 
     public NotificationCodecContext(final Class<?> key, final NotificationDefinition schema, final CodecContextFactory factory) {
         super(DataContainerCodecPrototype.from(key, schema, factory));
     }
 
     @Override
-    protected Object dataFromNormalizedNode(final NormalizedNode<?, ?> data) {
+    public D deserialize(final NormalizedNode<?, ?> data) {
         Preconditions.checkState(data instanceof ContainerNode);
         return createBindingProxy((NormalizedNodeContainer<?, ?, ?>) data);
     }
 
+    @Override
+    protected Object deserializeObject(NormalizedNode<?, ?> normalizedNode) {
+        return deserialize(normalizedNode);
+    }
+
 }
\ No newline at end of file
index 9460bf2a173c8e0af046125b0e8608a83a9d0687..681b7906ed06a359b5d232013e833e1ed95ac5c3 100644 (file)
@@ -16,6 +16,7 @@ import org.opendaylight.yangtools.util.ClassLoaderUtils;
 import org.opendaylight.yangtools.yang.binding.BindingMapping;
 import org.opendaylight.yangtools.yang.binding.ChildOf;
 import org.opendaylight.yangtools.yang.binding.DataContainer;
+import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.DataRoot;
 import org.opendaylight.yangtools.yang.binding.Notification;
 import org.opendaylight.yangtools.yang.binding.util.BindingReflections;
@@ -34,52 +35,54 @@ import org.opendaylight.yangtools.yang.model.api.SchemaPath;
 import org.opendaylight.yangtools.yang.model.util.SchemaContextUtil;
 import org.opendaylight.yangtools.yang.model.util.SchemaNodeUtils;
 
-final class SchemaRootCodecContext extends DataContainerCodecContext<SchemaContext> {
+final class SchemaRootCodecContext<D extends DataObject> extends DataContainerCodecContext<D,SchemaContext> {
 
-    private final LoadingCache<Class<?>, DataContainerCodecContext<?>> childrenByClass = CacheBuilder.newBuilder()
-            .build(new CacheLoader<Class<?>, DataContainerCodecContext<?>>() {
+    private final LoadingCache<Class<?>, DataContainerCodecContext<?,?>> childrenByClass = CacheBuilder.newBuilder()
+            .build(new CacheLoader<Class<?>, DataContainerCodecContext<?,?>>() {
                 @Override
-                public DataContainerCodecContext<?> load(final Class<?> key) {
+                public DataContainerCodecContext<?,?> load(final Class<?> key) {
                     return createDataTreeChildContext(key);
                 }
 
             });
 
-    private final LoadingCache<Class<?>, ContainerNodeCodecContext> rpcDataByClass = CacheBuilder.newBuilder().build(
-            new CacheLoader<Class<?>, ContainerNodeCodecContext>() {
+    private final LoadingCache<Class<?>, ContainerNodeCodecContext<?>> rpcDataByClass = CacheBuilder.newBuilder().build(
+            new CacheLoader<Class<?>, ContainerNodeCodecContext<?>>() {
                 @Override
-                public ContainerNodeCodecContext load(final Class<?> key) {
+                public ContainerNodeCodecContext<?> load(final Class<?> key) {
                     return createRpcDataContext(key);
                 }
             });
 
-    private final LoadingCache<Class<?>, NotificationCodecContext> notificationsByClass = CacheBuilder.newBuilder()
-            .build(new CacheLoader<Class<?>, NotificationCodecContext>() {
+    private final LoadingCache<Class<?>, NotificationCodecContext<?>> notificationsByClass = CacheBuilder.newBuilder()
+            .build(new CacheLoader<Class<?>, NotificationCodecContext<?>>() {
                 @Override
-                public NotificationCodecContext load(final Class<?> key) {
+                public NotificationCodecContext<?> load(final Class<?> key) {
                     return createNotificationDataContext(key);
                 }
             });
 
-    private final LoadingCache<QName, DataContainerCodecContext<?>> childrenByQName = CacheBuilder.newBuilder().build(
-            new CacheLoader<QName, DataContainerCodecContext<?>>() {
+    private final LoadingCache<QName, DataContainerCodecContext<?,?>> childrenByQName = CacheBuilder.newBuilder().build(
+            new CacheLoader<QName, DataContainerCodecContext<?,?>>() {
+                @SuppressWarnings("unchecked")
                 @Override
-                public DataContainerCodecContext<?> load(final QName qname) {
+                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());
 
                     if (childSchema instanceof DataNodeContainer || childSchema instanceof ChoiceSchemaNode) {
-                        final Class<?> childCls = factory().getRuntimeContext().getClassForSchema(childSchema);
-                        return getStreamChild(childCls);
+                        @SuppressWarnings("rawtypes")
+                        final Class childCls = factory().getRuntimeContext().getClassForSchema(childSchema);
+                        return streamChild(childCls);
                     } else {
                         throw new UnsupportedOperationException("Unsupported child type " + childSchema.getClass());
                     }
                 }
             });
 
-    private final LoadingCache<SchemaPath, ContainerNodeCodecContext> rpcDataByPath = CacheBuilder.newBuilder().build(
-            new CacheLoader<SchemaPath, ContainerNodeCodecContext>() {
+    private final LoadingCache<SchemaPath, ContainerNodeCodecContext<?>> rpcDataByPath = CacheBuilder.newBuilder().build(
+            new CacheLoader<SchemaPath, ContainerNodeCodecContext<?>>() {
 
                 @SuppressWarnings({ "rawtypes", "unchecked" })
                 @Override
@@ -90,8 +93,8 @@ final class SchemaRootCodecContext extends DataContainerCodecContext<SchemaConte
                 }
             });
 
-    private final LoadingCache<SchemaPath, NotificationCodecContext> notificationsByPath = CacheBuilder.newBuilder()
-            .build(new CacheLoader<SchemaPath, NotificationCodecContext>() {
+    private final LoadingCache<SchemaPath, NotificationCodecContext<?>> notificationsByPath = CacheBuilder.newBuilder()
+            .build(new CacheLoader<SchemaPath, NotificationCodecContext<?>>() {
 
                 @SuppressWarnings({ "rawtypes", "unchecked" })
                 @Override
@@ -113,48 +116,53 @@ final class SchemaRootCodecContext extends DataContainerCodecContext<SchemaConte
      *            CodecContextFactory
      * @return
      */
-    static SchemaRootCodecContext create(final CodecContextFactory factory) {
+    static SchemaRootCodecContext<?> create(final CodecContextFactory factory) {
         final DataContainerCodecPrototype<SchemaContext> prototype = DataContainerCodecPrototype.rootPrototype(factory);
-        return new SchemaRootCodecContext(prototype);
+        return new SchemaRootCodecContext<>(prototype);
     }
 
+
+    @SuppressWarnings("unchecked")
     @Override
-    protected DataContainerCodecContext<?> getStreamChild(final Class<?> childClass) {
-        return childrenByClass.getUnchecked(childClass);
+    public <DV extends DataObject> DataContainerCodecContext<DV, ?> streamChild(Class<DV> childClass)
+            throws IllegalArgumentException {
+        return (DataContainerCodecContext<DV, ?>) childrenByClass.getUnchecked(childClass);
     }
 
     @Override
-    protected Optional<DataContainerCodecContext<?>> getPossibleStreamChild(final Class<?> childClass) {
+    public <E extends DataObject> Optional<DataContainerCodecContext<E,?>> possibleStreamChild(final Class<E> childClass) {
         throw new UnsupportedOperationException("Not supported");
     }
 
     @Override
-    protected NodeCodecContext getYangIdentifierChild(final PathArgument arg) {
+    public DataContainerCodecContext<?,?> yangPathArgumentChild(final PathArgument arg) {
         return childrenByQName.getUnchecked(arg.getNodeType());
     }
 
     @Override
-    protected Object dataFromNormalizedNode(final NormalizedNode<?, ?> normalizedNode) {
-        throw new UnsupportedOperationException("Could not create Binding data representation for root");
+    public D deserialize(final NormalizedNode<?, ?> normalizedNode) {
+        throw new UnsupportedOperationException(
+                "Could not create Binding data representation for root");
     }
 
-    ContainerNodeCodecContext getRpc(final Class<? extends DataContainer> rpcInputOrOutput) {
+
+    ContainerNodeCodecContext<?> getRpc(final Class<? extends DataContainer> rpcInputOrOutput) {
         return rpcDataByClass.getUnchecked(rpcInputOrOutput);
     }
 
-    NotificationCodecContext getNotification(final Class<? extends Notification> notification) {
+    NotificationCodecContext<?> getNotification(final Class<? extends Notification> notification) {
         return notificationsByClass.getUnchecked(notification);
     }
 
-    NotificationCodecContext getNotification(final SchemaPath notification) {
+    NotificationCodecContext<?> getNotification(final SchemaPath notification) {
         return notificationsByPath.getUnchecked(notification);
     }
 
-    ContainerNodeCodecContext getRpc(final SchemaPath notification) {
+    ContainerNodeCodecContext<?> getRpc(final SchemaPath notification) {
         return rpcDataByPath.getUnchecked(notification);
     }
 
-    private DataContainerCodecContext<?> createDataTreeChildContext(final Class<?> key) {
+    private DataContainerCodecContext<?,?> createDataTreeChildContext(final Class<?> key) {
         final Class<Object> parent = ClassLoaderUtils.findFirstGenericArgument(key, ChildOf.class);
         Preconditions.checkArgument(DataRoot.class.isAssignableFrom(parent));
         final QName qname = BindingReflections.findQName(key);
@@ -162,7 +170,7 @@ final class SchemaRootCodecContext extends DataContainerCodecContext<SchemaConte
         return DataContainerCodecPrototype.from(key, childSchema, factory()).get();
     }
 
-    private ContainerNodeCodecContext createRpcDataContext(final Class<?> key) {
+    private ContainerNodeCodecContext<?> createRpcDataContext(final Class<?> key) {
         Preconditions.checkArgument(DataContainer.class.isAssignableFrom(key));
         final QName qname = BindingReflections.findQName(key);
         final QNameModule module = qname.getModule();
@@ -189,10 +197,10 @@ final class SchemaRootCodecContext extends DataContainerCodecContext<SchemaConte
         Preconditions.checkArgument(rpc != null, "Supplied class %s is not valid RPC class.", key);
         final ContainerSchemaNode schema = SchemaNodeUtils.getRpcDataSchema(rpc, qname);
         Preconditions.checkArgument(schema != null, "Schema for %s does not define input / output.", rpc.getQName());
-        return (ContainerNodeCodecContext) DataContainerCodecPrototype.from(key, schema, factory()).get();
+        return (ContainerNodeCodecContext<?>) DataContainerCodecPrototype.from(key, schema, factory()).get();
     }
 
-    private NotificationCodecContext createNotificationDataContext(final Class<?> notificationType) {
+    private NotificationCodecContext<?> createNotificationDataContext(final Class<?> notificationType) {
         Preconditions.checkArgument(Notification.class.isAssignableFrom(notificationType));
         Preconditions.checkArgument(notificationType.isInterface(), "Supplied class must be interface.");
         final QName qname = BindingReflections.findQName(notificationType);
@@ -204,7 +212,12 @@ final class SchemaRootCodecContext extends DataContainerCodecContext<SchemaConte
                 SchemaPath.create(true, qname));
         Preconditions.checkArgument(schema != null, "Supplied %s is not valid notification", notificationType);
 
-        return new NotificationCodecContext(notificationType, schema, factory());
+        return new NotificationCodecContext<>(notificationType, schema, factory());
+    }
+
+    @Override
+    protected Object deserializeObject(NormalizedNode<?, ?> normalizedNode) {
+        throw new UnsupportedOperationException("Unable to deserialize root");
     }
 
 }
\ No newline at end of file
index 1308846cc8ebb79351382e93cf51e14850c704f9..e44ae3128f48b7839b4d66aefdd131255f630d1c 100644 (file)
@@ -24,7 +24,7 @@ final class ValueContext {
     private final Class<?> identifier;
     private final String getterName;
 
-    ValueContext(final Class<?> identifier, final LeafNodeCodecContext leaf) {
+    ValueContext(final Class<?> identifier, final LeafNodeCodecContext <?>leaf) {
         getterName = BindingCodecContext.GETTER_PREFIX + BindingMapping.getClassName(leaf.getDomPathArgument().getNodeType());
         try {
             getter = LOOKUP.unreflect(identifier.getMethod(getterName)).asType(OBJECT_METHOD);