Split out DataContainerCodecPrototype subclasses 76/106376/2
authorRobert Varga <robert.varga@pantheon.tech>
Sun, 4 Jun 2023 20:57:06 +0000 (22:57 +0200)
committerRobert Varga <robert.varga@pantheon.tech>
Sun, 4 Jun 2023 21:15:31 +0000 (23:15 +0200)
We are going to ditch the Regular specialization in favor of providing
proper specializations. Take the first step and promote the two
specializations to top-level classes.

Change-Id: I0d350c0f1b0c1e364cd4330a39a51ec01e9c9dbd
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/AugmentationCodecPrototype.java [new file with mode: 0644]
binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/AugmentationNodeContext.java
binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/DataContainerCodecPrototype.java
binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/DataObjectCodecContext.java
binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/DataObjectCodecPrototype.java [new file with mode: 0644]

diff --git a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/AugmentationCodecPrototype.java b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/AugmentationCodecPrototype.java
new file mode 100644 (file)
index 0000000..c91de7f
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2023 PANTHEON.tech, s.r.o. 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.mdsal.binding.dom.codec.impl;
+
+import static java.util.Objects.requireNonNull;
+
+import com.google.common.collect.ImmutableSet;
+import org.eclipse.jdt.annotation.NonNull;
+import org.opendaylight.mdsal.binding.dom.codec.impl.NodeCodecContext.CodecContextFactory;
+import org.opendaylight.mdsal.binding.runtime.api.AugmentRuntimeType;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.Item;
+import org.opendaylight.yangtools.yang.common.QNameModule;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
+
+final class AugmentationCodecPrototype extends DataContainerCodecPrototype<AugmentRuntimeType> {
+    private final @NonNull ImmutableSet<NodeIdentifier> childArgs;
+
+    @SuppressWarnings("unchecked")
+    AugmentationCodecPrototype(final Class<?> cls, final QNameModule namespace, final AugmentRuntimeType type,
+            final CodecContextFactory factory, final ImmutableSet<NodeIdentifier> childArgs) {
+        super(Item.of((Class<? extends DataObject>) cls), namespace, type, factory);
+        this.childArgs = requireNonNull(childArgs);
+    }
+
+    @Override
+    NodeIdentifier getYangArg() {
+        throw new UnsupportedOperationException("Augmentation does not have PathArgument address");
+    }
+
+    @Override
+    AugmentationNodeContext<?> createInstance() {
+        return new AugmentationNodeContext<>(this);
+    }
+
+    // Guaranteed to be non-empty
+    @NonNull ImmutableSet<NodeIdentifier> getChildArgs() {
+        return childArgs;
+    }
+}
\ No newline at end of file
index 1abdb5f58f169f7a026c96f108c72f1cafd17898..871badeada5b9043e310eda0f81e73209db02e9b 100644 (file)
@@ -22,7 +22,7 @@ import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
 
 final class AugmentationNodeContext<D extends DataObject & Augmentation<?>>
         extends AbstractDataObjectCodecContext<D, AugmentRuntimeType> implements BindingAugmentationCodecTreeNode<D> {
-    AugmentationNodeContext(final DataContainerCodecPrototype.Augmentation prototype) {
+    AugmentationNodeContext(final AugmentationCodecPrototype prototype) {
         super(prototype, new CodecDataObjectAnalysis<>(prototype, CodecItemFactory.of(), null));
     }
 
@@ -44,7 +44,7 @@ final class AugmentationNodeContext<D extends DataObject & Augmentation<?>>
 
     @Override
     public D filterFrom(final DataContainerNode parentData) {
-        for (var childArg : ((DataContainerCodecPrototype.Augmentation) prototype).getChildArgs()) {
+        for (var childArg : ((AugmentationCodecPrototype) prototype).getChildArgs()) {
             if (parentData.childByArg(childArg) != null) {
                 return createProxy(parentData);
             }
index 4a70dcad5487625d9a8238d1a3e344e9fe23ea68..c894b28cf44064fabe90cd63c99d3bb84dc7e8f0 100644 (file)
@@ -10,26 +10,17 @@ package org.opendaylight.mdsal.binding.dom.codec.impl;
 import static com.google.common.base.Verify.verify;
 import static java.util.Objects.requireNonNull;
 
-import com.google.common.collect.ImmutableSet;
 import java.lang.invoke.MethodHandles;
 import java.lang.invoke.VarHandle;
 import org.eclipse.jdt.annotation.NonNull;
 import org.opendaylight.mdsal.binding.dom.codec.api.CommonDataObjectCodecTreeNode.ChildAddressabilitySummary;
 import org.opendaylight.mdsal.binding.dom.codec.impl.NodeCodecContext.CodecContextFactory;
-import org.opendaylight.mdsal.binding.runtime.api.AugmentRuntimeType;
 import org.opendaylight.mdsal.binding.runtime.api.BindingRuntimeTypes;
-import org.opendaylight.mdsal.binding.runtime.api.CaseRuntimeType;
-import org.opendaylight.mdsal.binding.runtime.api.ChoiceRuntimeType;
 import org.opendaylight.mdsal.binding.runtime.api.CompositeRuntimeType;
-import org.opendaylight.mdsal.binding.runtime.api.ContainerLikeRuntimeType;
-import org.opendaylight.mdsal.binding.runtime.api.ContainerRuntimeType;
-import org.opendaylight.mdsal.binding.runtime.api.ListRuntimeType;
 import org.opendaylight.mdsal.binding.runtime.api.NotificationRuntimeType;
 import org.opendaylight.mdsal.binding.runtime.api.RuntimeType;
 import org.opendaylight.mdsal.binding.runtime.api.RuntimeTypeContainer;
-import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.DataRoot;
-import org.opendaylight.yangtools.yang.binding.Identifiable;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.Item;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.common.QNameModule;
@@ -45,81 +36,11 @@ import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 import org.opendaylight.yangtools.yang.model.api.TypedDataSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.stmt.PresenceEffectiveStatement;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-abstract sealed class DataContainerCodecPrototype<T extends RuntimeTypeContainer> implements NodeContextSupplier {
-    static final class Augmentation extends DataContainerCodecPrototype<AugmentRuntimeType> {
-        private final @NonNull ImmutableSet<NodeIdentifier> childArgs;
-
-        @SuppressWarnings("unchecked")
-        Augmentation(final Class<?> cls, final QNameModule namespace, final AugmentRuntimeType type,
-                final CodecContextFactory factory, final ImmutableSet<NodeIdentifier> childArgs) {
-            super(Item.of((Class<? extends DataObject>) cls), namespace, type, factory);
-            this.childArgs = requireNonNull(childArgs);
-        }
-
-        @Override
-        NodeIdentifier getYangArg() {
-            throw new UnsupportedOperationException("Augmentation does not have PathArgument address");
-        }
-
-        @Override
-        AugmentationNodeContext<?> createInstance() {
-            return new AugmentationNodeContext<>(this);
-        }
-
-        // Guaranteed to be non-empty
-        @NonNull ImmutableSet<NodeIdentifier> getChildArgs() {
-            return childArgs;
-        }
-    }
-
-    static final class Regular<T extends RuntimeTypeContainer> extends DataContainerCodecPrototype<T> {
-        private final @NonNull NodeIdentifier yangArg;
-
-        @SuppressWarnings("unchecked")
-        private Regular(final Class<?> cls, final NodeIdentifier yangArg, final T type,
-                final CodecContextFactory factory) {
-            this(Item.of((Class<? extends DataObject>) cls), yangArg, type, factory);
-        }
-
-        private Regular(final Item<?> bindingArg, final NodeIdentifier yangArg, final T type,
-                final CodecContextFactory factory) {
-            super(bindingArg, yangArg.getNodeType().getModule(), type, factory);
-            this.yangArg = requireNonNull(yangArg);
-        }
-
-        @Override
-        NodeIdentifier getYangArg() {
-            return yangArg;
-        }
-
-        @Override
-        @SuppressWarnings({ "rawtypes", "unchecked" })
-        DataContainerCodecContext<?, T> createInstance() {
-            final var type = getType();
-            if (type instanceof ContainerLikeRuntimeType containerLike) {
-                if (containerLike instanceof ContainerRuntimeType container
-                    && container.statement().findFirstEffectiveSubstatement(PresenceEffectiveStatement.class)
-                        .isEmpty()) {
-                    return new NonPresenceContainerNodeCodecContext(this);
-                }
-                return new ContainerNodeCodecContext(this);
-            } else if (type instanceof ListRuntimeType) {
-                return Identifiable.class.isAssignableFrom(getBindingClass())
-                        ? KeyedListNodeCodecContext.create((DataContainerCodecPrototype<ListRuntimeType>) this)
-                                : new ListNodeCodecContext(this);
-            } else if (type instanceof ChoiceRuntimeType) {
-                return new ChoiceNodeCodecContext(this);
-            } else if (type instanceof CaseRuntimeType) {
-                return new CaseNodeCodecContext(this);
-            }
-            throw new IllegalArgumentException("Unsupported type " + getBindingClass() + " " + type);
-        }
-    }
-
+abstract sealed class DataContainerCodecPrototype<T extends RuntimeTypeContainer> implements NodeContextSupplier
+        permits AugmentationCodecPrototype, DataObjectCodecPrototype {
     private static final Logger LOG = LoggerFactory.getLogger(DataContainerCodecPrototype.class);
 
     private static final VarHandle INSTANCE;
@@ -146,7 +67,7 @@ abstract sealed class DataContainerCodecPrototype<T extends RuntimeTypeContainer
     @SuppressWarnings("unused")
     private volatile DataContainerCodecContext<?, T> instance;
 
-    private DataContainerCodecPrototype(final Item<?> bindingArg, final QNameModule namespace, final T type,
+    DataContainerCodecPrototype(final Item<?> bindingArg, final QNameModule namespace, final T type,
             final CodecContextFactory factory) {
         this.bindingArg = requireNonNull(bindingArg);
         this.namespace = requireNonNull(namespace);
@@ -234,23 +155,24 @@ abstract sealed class DataContainerCodecPrototype<T extends RuntimeTypeContainer
     }
 
     static DataContainerCodecPrototype<BindingRuntimeTypes> rootPrototype(final CodecContextFactory factory) {
-        return new Regular<>(DataRoot.class, NodeIdentifier.create(SchemaContext.NAME),
+        return new DataObjectCodecPrototype<>(DataRoot.class, NodeIdentifier.create(SchemaContext.NAME),
             factory.getRuntimeContext().getTypes(), factory);
     }
 
     static <T extends CompositeRuntimeType> DataContainerCodecPrototype<T> from(final Class<?> cls, final T type,
             final CodecContextFactory factory) {
-        return new Regular<>(cls, createIdentifier(type), type, factory);
+        return new DataObjectCodecPrototype<>(cls, createIdentifier(type), type, factory);
     }
 
     static <T extends CompositeRuntimeType> DataContainerCodecPrototype<T> from(final Item<?> bindingArg, final T type,
             final CodecContextFactory factory) {
-        return new Regular<>(bindingArg, createIdentifier(type), type, factory);
+        return new DataObjectCodecPrototype<>(bindingArg, createIdentifier(type), type, factory);
     }
 
     static DataContainerCodecPrototype<NotificationRuntimeType> from(final Class<?> augClass,
             final NotificationRuntimeType schema, final CodecContextFactory factory) {
-        return new Regular<>(augClass, NodeIdentifier.create(schema.statement().argument()), schema, factory);
+        return new DataObjectCodecPrototype<>(augClass, NodeIdentifier.create(schema.statement().argument()), schema,
+            factory);
     }
 
     private static @NonNull NodeIdentifier createIdentifier(final CompositeRuntimeType type) {
@@ -304,7 +226,6 @@ abstract sealed class DataContainerCodecPrototype<T extends RuntimeTypeContainer
         return witness == null ? tmp : witness;
     }
 
-    @SuppressWarnings({ "rawtypes", "unchecked" })
     // This method must allow concurrent loading, i.e. nothing in it may have effects outside of the loaded object
     abstract @NonNull DataContainerCodecContext<?, T> createInstance();
 }
index 99735f9e1ae1342426a6d5029f150f65f7c16296..cbc3c15eb9b2bd759b42473798bd992ac596992b 100644 (file)
@@ -62,7 +62,7 @@ public abstract class DataObjectCodecContext<D extends DataObject, T extends Com
         }
     }
 
-    private final ImmutableMap<Class<?>, DataContainerCodecPrototype.Augmentation> augmentToPrototype;
+    private final ImmutableMap<Class<?>, AugmentationCodecPrototype> augmentToPrototype;
     private final ImmutableMap<NodeIdentifier, Class<?>> yangToAugmentClass;
     private final @NonNull Class<? extends CodecDataObject<?>> generatedClass;
 
@@ -92,7 +92,7 @@ public abstract class DataObjectCodecContext<D extends DataObject, T extends Com
 
         // Deal with augmentations, which are not something we analysis provides
         final var augPathToBinding = new HashMap<NodeIdentifier, Class<?>>();
-        final var augClassToProto = new HashMap<Class<?>, DataContainerCodecPrototype.Augmentation>();
+        final var augClassToProto = new HashMap<Class<?>, AugmentationCodecPrototype>();
         for (var augment : analysis.possibleAugmentations) {
             final var augProto = loadAugmentPrototype(augment);
             if (augProto != null) {
@@ -134,27 +134,24 @@ public abstract class DataObjectCodecContext<D extends DataObject, T extends Com
         return child;
     }
 
-    private DataContainerCodecPrototype.@Nullable Augmentation getAugmentationProtoByClass(
-            final @NonNull Class<?> augmClass) {
+    private @Nullable AugmentationCodecPrototype getAugmentationProtoByClass(final @NonNull Class<?> augmClass) {
         final var childProto = augmentToPrototype.get(augmClass);
         return childProto != null ? childProto : mismatchedAugmentationByClass(augmClass);
     }
 
-    private DataContainerCodecPrototype.@Nullable Augmentation mismatchedAugmentationByClass(
-            final @NonNull Class<?> childClass) {
+    private @Nullable AugmentationCodecPrototype mismatchedAugmentationByClass(final @NonNull Class<?> childClass) {
         /*
          * It is potentially mismatched valid augmentation - we look up equivalent augmentation using reflection
          * and walk all stream child and compare augmentations classes if they are equivalent. When we find a match
          * we'll cache it so we do not need to perform reflection operations again.
          */
-        final var local =
-            (ImmutableMap<Class<?>, DataContainerCodecPrototype.Augmentation>) MISMATCHED_AUGMENTED.getAcquire(this);
+        final var local = (ImmutableMap<Class<?>, AugmentationCodecPrototype>) MISMATCHED_AUGMENTED.getAcquire(this);
         final var mismatched = local.get(childClass);
         return mismatched != null ? mismatched : loadMismatchedAugmentation(local, childClass);
     }
 
-    private DataContainerCodecPrototype.@Nullable Augmentation loadMismatchedAugmentation(
-            final ImmutableMap<Class<?>, DataContainerCodecPrototype.Augmentation> oldMismatched,
+    private @Nullable AugmentationCodecPrototype loadMismatchedAugmentation(
+            final ImmutableMap<Class<?>, AugmentationCodecPrototype> oldMismatched,
             final @NonNull Class<?> childClass) {
         @SuppressWarnings("rawtypes")
         final Class<?> augTarget = BindingReflections.findAugmentationTarget((Class) childClass);
@@ -172,10 +169,9 @@ public abstract class DataObjectCodecContext<D extends DataObject, T extends Com
         return null;
     }
 
-    private DataContainerCodecPrototype.@NonNull Augmentation cacheMismatched(
-            final @NonNull ImmutableMap<Class<?>, DataContainerCodecPrototype.Augmentation> oldMismatched,
-            final @NonNull Class<?> childClass, final DataContainerCodecPrototype.@NonNull Augmentation prototype) {
-
+    private @NonNull AugmentationCodecPrototype cacheMismatched(
+            final @NonNull ImmutableMap<Class<?>, AugmentationCodecPrototype> oldMismatched,
+            final @NonNull Class<?> childClass, final @NonNull AugmentationCodecPrototype prototype) {
         var expected = oldMismatched;
         while (true) {
             final var newMismatched =
@@ -184,7 +180,7 @@ public abstract class DataObjectCodecContext<D extends DataObject, T extends Com
                     .put(childClass, prototype)
                     .build();
 
-            final var witness = (ImmutableMap<Class<?>, DataContainerCodecPrototype.Augmentation>)
+            final var witness = (ImmutableMap<Class<?>, AugmentationCodecPrototype>)
                 MISMATCHED_AUGMENTED.compareAndExchangeRelease(this, expected, newMismatched);
             if (witness == expected) {
                 LOG.trace("Cached mismatched augmentation {} -> {} in {}", childClass, prototype, this);
@@ -212,7 +208,7 @@ public abstract class DataObjectCodecContext<D extends DataObject, T extends Com
         return cls.equals(loaded);
     }
 
-    private DataContainerCodecPrototype.@Nullable Augmentation loadAugmentPrototype(final AugmentRuntimeType augment) {
+    private @Nullable AugmentationCodecPrototype loadAugmentPrototype(final AugmentRuntimeType augment) {
         // FIXME: in face of deviations this code should be looking at declared view, i.e. all possibilities at augment
         //        declaration site
         final var childPaths = augment.statement()
@@ -235,7 +231,7 @@ public abstract class DataObjectCodecContext<D extends DataObject, T extends Com
             throw new IllegalStateException(
                 "RuntimeContext references type " + javaType + " but failed to load its class", e);
         }
-        return new DataContainerCodecPrototype.Augmentation(augClass, namespace, augment, factory, childPaths);
+        return new AugmentationCodecPrototype(augClass, namespace, augment, factory, childPaths);
     }
 
     @Override
diff --git a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/DataObjectCodecPrototype.java b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/DataObjectCodecPrototype.java
new file mode 100644 (file)
index 0000000..defacb2
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2023 PANTHEON.tech, s.r.o. 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.mdsal.binding.dom.codec.impl;
+
+import static java.util.Objects.requireNonNull;
+
+import org.eclipse.jdt.annotation.NonNull;
+import org.opendaylight.mdsal.binding.dom.codec.impl.NodeCodecContext.CodecContextFactory;
+import org.opendaylight.mdsal.binding.runtime.api.CaseRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.ChoiceRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.ContainerLikeRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.ContainerRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.ListRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.RuntimeTypeContainer;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.Identifiable;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.Item;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
+import org.opendaylight.yangtools.yang.model.api.stmt.PresenceEffectiveStatement;
+
+final class DataObjectCodecPrototype<T extends RuntimeTypeContainer> extends DataContainerCodecPrototype<T> {
+    private final @NonNull NodeIdentifier yangArg;
+
+    @SuppressWarnings("unchecked")
+    DataObjectCodecPrototype(final Class<?> cls, final NodeIdentifier yangArg, final T type,
+            final CodecContextFactory factory) {
+        this(Item.of((Class<? extends DataObject>) cls), yangArg, type, factory);
+    }
+
+    DataObjectCodecPrototype(final Item<?> bindingArg, final NodeIdentifier yangArg, final T type,
+            final CodecContextFactory factory) {
+        super(bindingArg, yangArg.getNodeType().getModule(), type, factory);
+        this.yangArg = requireNonNull(yangArg);
+    }
+
+    @Override
+    NodeIdentifier getYangArg() {
+        return yangArg;
+    }
+
+    @Override
+    @SuppressWarnings({ "rawtypes", "unchecked" })
+    DataContainerCodecContext<?, T> createInstance() {
+        final var type = getType();
+        if (type instanceof ContainerLikeRuntimeType containerLike) {
+            if (containerLike instanceof ContainerRuntimeType container
+                && container.statement().findFirstEffectiveSubstatement(PresenceEffectiveStatement.class)
+                    .isEmpty()) {
+                return new NonPresenceContainerNodeCodecContext(this);
+            }
+            return new ContainerNodeCodecContext(this);
+        } else if (type instanceof ListRuntimeType) {
+            return Identifiable.class.isAssignableFrom(getBindingClass())
+                    ? KeyedListNodeCodecContext.create((DataContainerCodecPrototype<ListRuntimeType>) this)
+                            : new ListNodeCodecContext(this);
+        } else if (type instanceof ChoiceRuntimeType) {
+            return new ChoiceNodeCodecContext(this);
+        } else if (type instanceof CaseRuntimeType) {
+            return new CaseNodeCodecContext(this);
+        }
+        throw new IllegalArgumentException("Unsupported type " + getBindingClass() + " " + type);
+    }
+}
\ No newline at end of file