Make AugmentationCodecPrototype generic
[mdsal.git] / binding / mdsal-binding-dom-codec / src / main / java / org / opendaylight / mdsal / binding / dom / codec / impl / AugmentationCodecContext.java
index 5552daea8ddb36a60522403ce3bf6b8593ad41f1..c4250f65a36cf99a1f538057475054dc1742842b 100644 (file)
@@ -7,14 +7,18 @@
  */
 package org.opendaylight.mdsal.binding.dom.codec.impl;
 
+import com.google.common.base.Throwables;
 import com.google.common.collect.ImmutableSet;
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
 import java.util.List;
 import java.util.Map;
 import org.opendaylight.mdsal.binding.dom.codec.api.BindingAugmentationCodecTreeNode;
 import org.opendaylight.mdsal.binding.runtime.api.AugmentRuntimeType;
 import org.opendaylight.yangtools.yang.binding.Augmentation;
 import org.opendaylight.yangtools.yang.binding.DataObject;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.DataObjectStep;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
 import org.opendaylight.yangtools.yang.data.api.schema.DataContainerNode;
@@ -22,31 +26,61 @@ import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
 
 final class AugmentationCodecContext<D extends DataObject & Augmentation<?>>
         extends AbstractDataObjectCodecContext<D, AugmentRuntimeType> implements BindingAugmentationCodecTreeNode<D> {
-    AugmentationCodecContext(final AugmentationCodecPrototype prototype) {
-        super(prototype, new CodecDataObjectAnalysis<>(prototype, CodecItemFactory.of(), null));
+    private static final MethodType CONSTRUCTOR_TYPE = MethodType.methodType(void.class,
+        AbstractDataObjectCodecContext.class, DataContainerNode.class);
+    private static final MethodType DATAOBJECT_TYPE = MethodType.methodType(DataObject.class,
+        AugmentationCodecContext.class, DataContainerNode.class);
+
+    private final MethodHandle proxyConstructor;
+
+    private AugmentationCodecContext(final AugmentationCodecPrototype<D> prototype,
+            final DataContainerAnalysis<AugmentRuntimeType> analysis) {
+        super(prototype, analysis);
+
+        final var bindingClass = CodecDataObjectGenerator.generate(prototype.contextFactory().getLoader(),
+            prototype.javaClass(), analysis.leafContexts, analysis.daoProperties, null);
+
+        final MethodHandle ctor;
+        try {
+            ctor = MethodHandles.publicLookup().findConstructor(bindingClass, CONSTRUCTOR_TYPE);
+        } catch (NoSuchMethodException | IllegalAccessException e) {
+            throw new LinkageError("Failed to find contructor for class " + bindingClass, e);
+        }
+
+        proxyConstructor = ctor.asType(DATAOBJECT_TYPE);
+    }
+
+    AugmentationCodecContext(final AugmentationCodecPrototype<D> prototype) {
+        this(prototype, new DataContainerAnalysis<>(prototype, CodecItemFactory.of()));
     }
 
     @Override
-    public PathArgument serializePathArgument(final InstanceIdentifier.PathArgument arg) {
-        if (!bindingArg().equals(arg)) {
-            throw new IllegalArgumentException("Unexpected argument " + arg);
+    public PathArgument serializePathArgument(final DataObjectStep<?> step) {
+        if (!bindingArg().equals(step)) {
+            throw new IllegalArgumentException("Unexpected argument " + step);
         }
         return null;
     }
 
     @Override
-    public InstanceIdentifier.PathArgument deserializePathArgument(final PathArgument arg) {
+    public DataObjectStep<?> deserializePathArgument(final PathArgument arg) {
         if (arg != null) {
             throw new IllegalArgumentException("Unexpected argument " + arg);
         }
         return bindingArg();
     }
 
+    @SuppressWarnings("checkstyle:illegalCatch")
     @Override
     public D filterFrom(final DataContainerNode parentData) {
-        for (var childArg : ((AugmentationCodecPrototype) prototype).getChildArgs()) {
+        for (var childArg : ((AugmentationCodecPrototype<?>) prototype()).getChildArgs()) {
             if (parentData.childByArg(childArg) != null) {
-                return createBindingProxy(parentData);
+                try {
+                    return (D) proxyConstructor.invokeExact(this, parentData);
+                } catch (final Throwable e) {
+                    Throwables.throwIfUnchecked(e);
+                    throw new IllegalStateException(e);
+                }
             }
         }
         return null;
@@ -63,7 +97,7 @@ final class AugmentationCodecContext<D extends DataObject & Augmentation<?>>
     }
 
     @Override
-    void addYangPathArgument(final List<PathArgument> builder, final InstanceIdentifier.PathArgument arg) {
+    void addYangPathArgument(final List<PathArgument> builder, final DataObjectStep<?> step) {
         // No-op
     }