Bug 1260: Implemented Binding Caching Codec
[mdsal.git] / code-generator / binding-data-codec / src / main / java / org / opendaylight / yangtools / binding / data / codec / impl / DataContainerCodecContext.java
index 1b8bdf040a308f0629adc57e63b1b90de29bc22f..371a181ce4111bc96f195d32fceb0f3a092b9a76 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,50 @@ 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(
+            final ImmutableCollection<Class<? extends DataObject>> cacheSpecifier) {
+        if(cacheSpecifier.isEmpty()) {
+            return new NonCachingCodec<>(this);
+        }
+        return new CachingNormalizedNodeCodec<D>(this,ImmutableSet.copyOf(cacheSpecifier));
+    }
+
+    BindingStreamEventWriter createWriter(final NormalizedNodeStreamWriter domWriter) {
+        return  new BindingToNormalizedStreamWriter(this, domWriter);
+    }
+
+    DataObjectSerializer eventStreamSerializer() {
+        if(eventStreamSerializer == null) {
+            eventStreamSerializer = factory().getEventStreamSerializer(getBindingClass());
+        }
+        return eventStreamSerializer;
+    }
+
+    @Override
+    public NormalizedNode<?, ?> serialize(final 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(final D data, final NormalizedNodeStreamWriter writer) {
+        try {
+            eventStreamSerializer().serialize(data, createWriter(writer));
+        } catch (final IOException e) {
+            throw new IllegalStateException("Failed to serialize Binding DTO",e);
+        }
+    }
+
 }
\ No newline at end of file