Convert mdsal-binding-dom-codec to a JPMS module
[mdsal.git] / binding / mdsal-binding-dom-codec / src / main / java / org / opendaylight / mdsal / binding / dom / codec / impl / DataObjectStreamerGenerator.java
index 5a3bc3d22908234d0adf63d896bb6b4e1dd7a079..b0da58398506299300e7e0c6db24b79a642e85f0 100644 (file)
@@ -21,7 +21,7 @@ import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
-import java.util.Map.Entry;
+import java.util.Set;
 import net.bytebuddy.ByteBuddy;
 import net.bytebuddy.description.field.FieldDescription;
 import net.bytebuddy.description.method.MethodDescription;
@@ -45,14 +45,15 @@ import net.bytebuddy.implementation.bytecode.member.MethodReturn;
 import net.bytebuddy.implementation.bytecode.member.MethodVariableAccess;
 import net.bytebuddy.jar.asm.MethodVisitor;
 import net.bytebuddy.jar.asm.Opcodes;
+import net.bytebuddy.matcher.ElementMatcher;
 import net.bytebuddy.matcher.ElementMatchers;
 import org.eclipse.jdt.annotation.Nullable;
 import org.opendaylight.mdsal.binding.dom.codec.api.BindingStreamEventWriter;
 import org.opendaylight.mdsal.binding.dom.codec.impl.NodeCodecContext.CodecContextFactory;
-import org.opendaylight.mdsal.binding.dom.codec.loader.CodecClassLoader;
-import org.opendaylight.mdsal.binding.dom.codec.loader.CodecClassLoader.ClassGenerator;
-import org.opendaylight.mdsal.binding.dom.codec.loader.CodecClassLoader.GeneratorResult;
-import org.opendaylight.mdsal.binding.dom.codec.util.BindingSchemaMapping;
+import org.opendaylight.mdsal.binding.dom.codec.impl.loader.CodecClassLoader;
+import org.opendaylight.mdsal.binding.dom.codec.impl.loader.CodecClassLoader.ClassGenerator;
+import org.opendaylight.mdsal.binding.dom.codec.impl.loader.CodecClassLoader.GeneratorResult;
+import org.opendaylight.mdsal.binding.dom.codec.spi.BindingSchemaMapping;
 import org.opendaylight.mdsal.binding.model.api.GeneratedType;
 import org.opendaylight.mdsal.binding.model.api.MethodSignature;
 import org.opendaylight.mdsal.binding.model.api.ParameterizedType;
@@ -67,10 +68,10 @@ import org.opendaylight.yangtools.yang.model.api.AnyxmlSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.AugmentationSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.CaseSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.ChoiceSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.ContainerLike;
 import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.DocumentedNode.WithStatus;
 import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
@@ -110,14 +111,14 @@ final class DataObjectStreamerGenerator<T extends DataObjectStreamer<?>> impleme
     private static final StackManipulation END_NODE = invokeMethod(BindingStreamEventWriter.class,
         "endNode");
 
-    // startMapEntryNode(obj.key(), UNKNOWN_SIZE);
+    // startMapEntryNode(obj.key(), UNKNOWN_SIZE)
     private static final StackManipulation START_MAP_ENTRY_NODE = new StackManipulation.Compound(
         OBJ,
         invokeMethod(Identifiable.class, "key"),
         UNKNOWN_SIZE,
         invokeMethod(BindingStreamEventWriter.class, "startMapEntryNode", Identifier.class, int.class));
 
-    // startUnkeyedListItem(UNKNOWN_SIZE);
+    // startUnkeyedListItem(UNKNOWN_SIZE)
     private static final StackManipulation START_UNKEYED_LIST_ITEM = new StackManipulation.Compound(
         UNKNOWN_SIZE,
         invokeMethod(BindingStreamEventWriter.class, "startUnkeyedListItem", int.class));
@@ -136,7 +137,7 @@ final class DataObjectStreamerGenerator<T extends DataObjectStreamer<?>> impleme
         "streamLeaf", BindingStreamEventWriter.class, String.class, Object.class);
     private static final StackManipulation STREAM_LEAF_LIST = invokeMethod(DataObjectStreamer.class,
         "streamLeafList",
-        BindingStreamEventWriter.class, String.class, List.class);
+        BindingStreamEventWriter.class, String.class, Set.class);
     private static final StackManipulation STREAM_ORDERED_LEAF_LIST = invokeMethod(DataObjectStreamer.class,
         "streamOrderedLeafList", BindingStreamEventWriter.class, String.class, List.class);
     private static final StackManipulation STREAM_LIST = invokeMethod(DataObjectStreamer.class,
@@ -149,7 +150,7 @@ final class DataObjectStreamerGenerator<T extends DataObjectStreamer<?>> impleme
         "streamOrderedMap", Class.class, DataObjectStreamer.class, DataObjectSerializerRegistry.class,
         BindingStreamEventWriter.class, List.class);
 
-    // streamAugmentations(reg, stream, obj);
+    // streamAugmentations(reg, stream, obj)
     private static final StackManipulation STREAM_AUGMENTATIONS = new StackManipulation.Compound(
         REG,
         STREAM,
@@ -175,17 +176,17 @@ final class DataObjectStreamerGenerator<T extends DataObjectStreamer<?>> impleme
     static Class<? extends DataObjectStreamer<?>> generateStreamer(final CodecClassLoader loader,
             final CodecContextFactory registry, final Class<?> type) {
 
-        final Entry<GeneratedType, WithStatus> typeAndSchema = registry.getRuntimeContext().getTypeWithSchema(type);
-        final WithStatus schema = typeAndSchema.getValue();
+        final var typeAndSchema = registry.getRuntimeContext().getTypeWithSchema(type);
+        final var schema = typeAndSchema.statement();
 
         final StackManipulation startEvent;
-        if (schema instanceof ContainerSchemaNode || schema instanceof NotificationDefinition) {
+        if (schema instanceof ContainerLike || schema instanceof NotificationDefinition) {
             startEvent = classUnknownSizeMethod(START_CONTAINER_NODE, type);
         } else if (schema instanceof ListSchemaNode) {
             startEvent = ((ListSchemaNode) schema).getKeyDefinition().isEmpty() ? START_UNKEYED_LIST_ITEM
                     : START_MAP_ENTRY_NODE;
         } else if (schema instanceof AugmentationSchemaNode) {
-            // startAugmentationNode(Foo.class);
+            // startAugmentationNode(Foo.class)
             startEvent = new StackManipulation.Compound(
                 ClassConstant.of(Sort.describe(type).asErasure()),
                 START_AUGMENTATION_NODE);
@@ -196,8 +197,9 @@ final class DataObjectStreamerGenerator<T extends DataObjectStreamer<?>> impleme
         }
 
         return loader.generateClass(type, "streamer",
-            new DataObjectStreamerGenerator<>(registry, typeAndSchema.getKey(), (DataNodeContainer) schema, type,
-                    startEvent));
+            // FIXME: cast to GeneratedType: we really should adjust getTypeWithSchema()
+            new DataObjectStreamerGenerator<>(registry, (GeneratedType) typeAndSchema.javaType(),
+                (DataNodeContainer) schema, type, startEvent));
     }
 
     @Override
@@ -288,7 +290,7 @@ final class DataObjectStreamerGenerator<T extends DataObjectStreamer<?>> impleme
     }
 
     private static ChildStream choiceChildStream(final Method getter) {
-        // streamChoice(Foo.class, reg, stream, obj.getFoo());
+        // streamChoice(Foo.class, reg, stream, obj.getFoo())
         return new ChildStream(
             ClassConstant.of(Sort.describe(getter.getReturnType()).asErasure()),
             REG,
@@ -302,7 +304,7 @@ final class DataObjectStreamerGenerator<T extends DataObjectStreamer<?>> impleme
         final Class<? extends DataObject> itemClass = getter.getReturnType().asSubclass(DataObject.class);
         final DataObjectStreamer<?> streamer = registry.getDataObjectSerializer(itemClass);
 
-        // streamContainer(FooStreamer.INSTANCE, reg, stream, obj.getFoo());
+        // streamContainer(FooStreamer.INSTANCE, reg, stream, obj.getFoo())
         return new ChildStream(streamer,
             streamerInstance(streamer),
             REG,
@@ -322,7 +324,7 @@ final class DataObjectStreamerGenerator<T extends DataObjectStreamer<?>> impleme
             method = childSchema.isUserOrdered() ? STREAM_ORDERED_MAP : STREAM_MAP;
         }
 
-        // <METHOD>(Foo.class, FooStreamer.INSTACE, reg, stream, obj.getFoo());
+        // <METHOD>(Foo.class, FooStreamer.INSTACE, reg, stream, obj.getFoo())
         return new ChildStream(streamer,
             ClassConstant.of(Sort.describe(itemClass).asErasure()),
             streamerInstance(streamer),
@@ -335,7 +337,7 @@ final class DataObjectStreamerGenerator<T extends DataObjectStreamer<?>> impleme
 
     private static ChildStream qnameChildStream(final StackManipulation method, final Method getter,
             final DataSchemaNode schema) {
-        // <METHOD>(stream, "foo", obj.getFoo());
+        // <METHOD>(stream, "foo", obj.getFoo())
         return new ChildStream(
             STREAM,
             new TextConstant(schema.getQName().getLocalName()),
@@ -353,7 +355,7 @@ final class DataObjectStreamerGenerator<T extends DataObjectStreamer<?>> impleme
     }
 
     private static StackManipulation classUnknownSizeMethod(final StackManipulation method, final Class<?> type) {
-        // <METHOD>(Foo.class, UNKNOWN_SIZE);
+        // <METHOD>(Foo.class, UNKNOWN_SIZE)
         return new StackManipulation.Compound(
                 ClassConstant.of(Sort.describe(type).asErasure()),
                 UNKNOWN_SIZE,
@@ -400,7 +402,7 @@ final class DataObjectStreamerGenerator<T extends DataObjectStreamer<?>> impleme
         @Override
         public InstrumentedType prepare(final InstrumentedType instrumentedType) {
             return instrumentedType
-                    // private static final This INSTANCE = new This();
+                    // private static final This INSTANCE = new This()
                     .withField(new FieldDescription.Token(INSTANCE_FIELD, PUB_CONST, instrumentedType.asGenericType()))
                     .withInitializer(InitializeInstanceField.INSTANCE);
         }
@@ -409,7 +411,7 @@ final class DataObjectStreamerGenerator<T extends DataObjectStreamer<?>> impleme
         public ByteCodeAppender appender(final Target implementationTarget) {
             final List<StackManipulation> manipulations = new ArrayList<>(children.size() + 6);
 
-            // stream.<START_EVENT>(...);
+            // stream.<START_EVENT>(...)
             manipulations.add(STREAM);
             manipulations.add(startEvent);
 
@@ -417,14 +419,14 @@ final class DataObjectStreamerGenerator<T extends DataObjectStreamer<?>> impleme
             manipulations.addAll(children);
 
             if (Augmentable.class.isAssignableFrom(bindingInterface)) {
-                // streamAugmentations(reg, stream, obj);
+                // streamAugmentations(reg, stream, obj)
                 manipulations.add(STREAM_AUGMENTATIONS);
             }
 
-            // stream.endNode();
+            // stream.endNode()
             manipulations.add(STREAM);
             manipulations.add(END_NODE);
-            // return;
+            // return
             manipulations.add(MethodReturn.VOID);
 
             return new ByteCodeAppender.Simple(manipulations);
@@ -452,6 +454,10 @@ final class DataObjectStreamerGenerator<T extends DataObjectStreamer<?>> impleme
     private enum InitializeInstanceField implements ByteCodeAppender {
         INSTANCE;
 
+        // TODO: eliminate this constant when ElementMatchers.isDefaultConstructor() returns a singleton
+        private static final ElementMatcher<MethodDescription> IS_DEFAULT_CONSTRUCTOR =
+            ElementMatchers.isDefaultConstructor();
+
         @Override
         public Size apply(final MethodVisitor methodVisitor, final Context implementationContext,
                 final MethodDescription instrumentedMethod) {
@@ -460,7 +466,7 @@ final class DataObjectStreamerGenerator<T extends DataObjectStreamer<?>> impleme
                 TypeCreation.of(instrumentedType),
                 Duplication.SINGLE,
                 MethodInvocation.invoke(instrumentedType.getDeclaredMethods()
-                    .filter(ElementMatchers.isDefaultConstructor()).getOnly().asDefined()),
+                    .filter(IS_DEFAULT_CONSTRUCTOR).getOnly().asDefined()),
                 putField(instrumentedType, INSTANCE_FIELD))
                     .apply(methodVisitor, implementationContext);
             return new Size(operandStackSize.getMaximalSize(), instrumentedMethod.getStackSize());