Bug 1443: Implemented Lazy deserialization using dynamic proxies
[mdsal.git] / code-generator / binding-data-codec / src / main / java / org / opendaylight / yangtools / binding / data / codec / impl / ListNodeCodecContext.java
index 4636c9f11a48cbb91a7e3dfd72b3896a7f7b03b9..ca2c94dadf06067c901647107b5671469e93b012 100644 (file)
@@ -7,37 +7,48 @@
  */
 package org.opendaylight.yangtools.binding.data.codec.impl;
 
+import com.google.common.collect.Iterables;
+
+import java.lang.reflect.Method;
+import java.util.ArrayList;
 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;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
+import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
+import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNodeContainer;
+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> {
+final class ListNodeCodecContext extends DataObjectCodecContext<ListSchemaNode> {
 
-    private final YangInstanceIdentifier.PathArgument yangIdentifier;
     private final Codec<NodeIdentifierWithPredicates, IdentifiableItem<?, ?>> codec;
+    private final Method keyGetter;
 
-    ListNodeCodecContext(final Class<?> cls, final ListSchemaNode nodeSchema, final CodecContextFactory loader) {
-        super(cls, nodeSchema.getQName().getModule(), nodeSchema, loader);
-        this.yangIdentifier = new YangInstanceIdentifier.NodeIdentifier(nodeSchema.getQName());
-        if (Identifiable.class.isAssignableFrom(cls)) {
-            this.codec = loader.getPathArgumentCodec(cls,nodeSchema);
+    ListNodeCodecContext(final DataContainerCodecPrototype<ListSchemaNode> prototype) {
+        super(prototype);
+        if (Identifiable.class.isAssignableFrom(bindingClass())) {
+            this.codec = factory().getPathArgumentCodec(bindingClass(),schema());
+            try {
+                this.keyGetter = bindingClass().getMethod("getKey");
+            } catch (NoSuchMethodException e) {
+                throw new IllegalStateException("Required method not available");
+            }
         } else {
             this.codec = null;
+            this.keyGetter = null;
         }
     }
 
-    @Override
-    public YangInstanceIdentifier.PathArgument getDomPathArgument() {
-        return yangIdentifier;
-    }
-
     @Override
     public void addYangPathArgument(final InstanceIdentifier.PathArgument arg, final List<YangInstanceIdentifier.PathArgument> builder) {
 
@@ -61,7 +72,7 @@ class ListNodeCodecContext extends DataObjectCodecContext<ListSchemaNode> {
     @Override
     public InstanceIdentifier.PathArgument getBindingPathArgument(
             final org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument domArg) {
-        if(domArg instanceof NodeIdentifierWithPredicates) {
+        if (domArg instanceof NodeIdentifierWithPredicates) {
             return codec.deserialize((NodeIdentifierWithPredicates) domArg);
         }
         return super.getBindingPathArgument(domArg);
@@ -69,6 +80,54 @@ class ListNodeCodecContext extends DataObjectCodecContext<ListSchemaNode> {
 
     @SuppressWarnings({ "rawtypes", "unchecked" })
     public NodeIdentifierWithPredicates serialize(final Identifier<?> key) {
-        return codec.serialize(new IdentifiableItem(bindingClass, key));
+        return codec.serialize(new IdentifiableItem(bindingClass(), key));
+    }
+
+    @Override
+    protected Object dataFromNormalizedNode(final NormalizedNode<?, ?> node) {
+        if (node instanceof MapNode) {
+            return fromMap((MapNode) node);
+        } else if(node instanceof MapEntryNode)  {
+            return fromMapEntry((MapEntryNode) node);
+        } else if (node instanceof UnkeyedListNode) {
+            return fromUnkeyedList((UnkeyedListNode) node);
+        }  else if(node instanceof UnkeyedListEntryNode) {
+            return fromUnkeyedListEntry((UnkeyedListEntryNode) node);
+        }
+        throw new IllegalStateException("Unsupported data type " + node.getClass());
+    }
+
+    private List<DataObject> fromMap(final MapNode nodes) {
+        List<DataObject> ret = new ArrayList<>(Iterables.size(nodes.getValue()));
+        for(MapEntryNode node : nodes.getValue()) {
+            ret.add(fromMapEntry(node));
+        }
+        return ret;
+    }
+
+    private DataObject fromMapEntry(final MapEntryNode node) {
+        return LazyDataObject.create(this, node);
+    }
+
+    private DataObject fromUnkeyedListEntry(final UnkeyedListEntryNode node) {
+        return LazyDataObject.create(this, node);
+    }
+
+    private List<DataObject> fromUnkeyedList(final UnkeyedListNode nodes) {
+        // FIXME: Could be this lazy transformed list?
+        List<DataObject> ret = new ArrayList<>(Iterables.size(nodes.getValue()));
+        for (UnkeyedListEntryNode node : nodes.getValue()) {
+            ret.add(fromUnkeyedListEntry(node));
+        }
+        return ret;
+    }
+
+    @Override
+    Object getBindingChildValue(final Method method, final NormalizedNodeContainer dom) {
+        if (method.equals(keyGetter) && dom instanceof MapEntryNode) {
+            NodeIdentifierWithPredicates identifier = ((MapEntryNode) dom).getIdentifier();
+            return codec.deserialize(identifier).getKey();
+        }
+        return super.getBindingChildValue(method, dom);
     }
 }
\ No newline at end of file