Remove AbstractDataObjectCodecContext 68/112568/3
authorRobert Varga <robert.varga@pantheon.tech>
Mon, 15 Jul 2024 15:42:51 +0000 (17:42 +0200)
committerRobert Varga <robert.varga@pantheon.tech>
Mon, 15 Jul 2024 15:51:46 +0000 (17:51 +0200)
AbstractDataObjectCodecContext brings in bits of
CommonDataObjectCodecContext implementation into the picture, but it
really is its only specialization. Merge the two classes, adjusting
CodecDataObject accordingly.

JIRA: YANGTOOLS-1577
Change-Id: Iffe9b1981db6df974ab1a454f81aeaeca74c5656
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
binding/binding-data-codec-dynamic/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/AbstractDataObjectCodecContext.java [deleted file]
binding/binding-data-codec-dynamic/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/AugmentableCodecDataObject.java
binding/binding-data-codec-dynamic/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/AugmentationCodecContext.java
binding/binding-data-codec-dynamic/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/BindingToNormalizedStreamWriter.java
binding/binding-data-codec-dynamic/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/CachingNormalizedNodeSerializer.java
binding/binding-data-codec-dynamic/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/CodecDataObject.java
binding/binding-data-codec-dynamic/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/CommonDataObjectCodecContext.java
binding/binding-data-codec-dynamic/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/DataObjectCodecContext.java
binding/binding-data-codec-dynamic/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/NotificationCodecContext.java

diff --git a/binding/binding-data-codec-dynamic/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/AbstractDataObjectCodecContext.java b/binding/binding-data-codec-dynamic/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/AbstractDataObjectCodecContext.java
deleted file mode 100644 (file)
index bb29a14..0000000
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * 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.yangtools.binding.data.codec.impl;
-
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.ImmutableSet;
-import java.util.List;
-import java.util.Map;
-import org.eclipse.jdt.annotation.NonNull;
-import org.eclipse.jdt.annotation.Nullable;
-import org.opendaylight.yangtools.binding.Augmentation;
-import org.opendaylight.yangtools.binding.DataObject;
-import org.opendaylight.yangtools.binding.DataObjectStep;
-import org.opendaylight.yangtools.binding.data.codec.api.IncorrectNestingException;
-import org.opendaylight.yangtools.binding.runtime.api.CompositeRuntimeType;
-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;
-import org.opendaylight.yangtools.yang.model.api.DocumentedNode.WithStatus;
-
-/**
- * Abstract base for {@link DataObjectCodecContext} and {@link AugmentationCodecContext}. They share most of their
- * mechanics, but notably:
- * <ol>
- *   <li>DataObjectCodecContext has an exact DistinctNodeContainer and YangInstanceIdentifier mapping and can be the
- *       target of augmentations (i.e. can implement Augmentable contract)</li>
- *   <li>AugmentationNodeContext has neither of those traits and really is just a filter of its parent
- *       DistinctNodeContainer</li>
- * </ol>
- *
- * <p>
- * Unfortunately {@code Augmentation} is a also a {@link DataObject}, so things get a bit messy.
- *
- * <p>
- * While this class is public, it not part of API surface and is an implementation detail. The only reason for it being
- * public is that it needs to be accessible by code generated at runtime.
- */
-public abstract sealed class AbstractDataObjectCodecContext<D extends DataObject, T extends CompositeRuntimeType>
-        extends CommonDataObjectCodecContext<D, T>
-        permits AugmentationCodecContext, DataObjectCodecContext {
-    private final ImmutableMap<Class<?>, DataContainerPrototype<?, ?>> byBindingArgClass;
-    private final ImmutableMap<Class<?>, DataContainerPrototype<?, ?>> byStreamClass;
-    private final ImmutableMap<NodeIdentifier, CodecContextSupplier> byYang;
-    private final ImmutableMap<String, ValueNodeCodecContext> leafChild;
-
-    AbstractDataObjectCodecContext(final CommonDataObjectCodecPrototype<T> prototype,
-            final DataContainerAnalysis<T> analysis) {
-        super(prototype);
-        byBindingArgClass = analysis.byBindingArgClass;
-        byStreamClass = analysis.byStreamClass;
-        byYang = analysis.byYang;
-        leafChild = analysis.leafNodes;
-    }
-
-    @Override
-    @Deprecated(since = "13.0.0", forRemoval = true)
-    public final WithStatus getSchema() {
-        // FIXME: Bad cast, we should be returning an EffectiveStatement perhaps?
-        return (WithStatus) prototype().runtimeType().statement();
-    }
-
-    @Override
-    DataContainerPrototype<?, ?> streamChildPrototype(final Class<?> childClass) {
-        return byStreamClass.get(childClass);
-    }
-
-    @Override
-    public final CommonDataObjectCodecContext<?, ?> bindingPathArgumentChild(final DataObjectStep<?> step,
-            final List<PathArgument> builder) {
-        final var type = step.type();
-        final var context = childNonNull(pathChildPrototype(type), type,
-            "Class %s is not valid child of %s", type, getBindingClass())
-            .getCodecContext();
-        context.addYangPathArgument(step, builder);
-        if (context instanceof CommonDataObjectCodecContext<?, ?> dataObject) {
-            return dataObject;
-        } else if (context instanceof ChoiceCodecContext<?> choice) {
-            return choice.bindingPathArgumentChild(step, builder);
-        } else {
-            throw new IllegalStateException("Unhandled context " + context);
-        }
-    }
-
-    @Nullable DataContainerPrototype<?, ?> pathChildPrototype(final @NonNull Class<? extends DataObject> argType) {
-        return byBindingArgClass.get(argType);
-    }
-
-    @Override
-    CodecContextSupplier yangChildSupplier(final NodeIdentifier arg) {
-        return byYang.get(arg);
-    }
-
-    final ValueNodeCodecContext getLeafChild(final String name) {
-        final ValueNodeCodecContext value = leafChild.get(name);
-        if (value == null) {
-            throw new IncorrectNestingException("Leaf %s is not valid for %s", name, getBindingClass());
-        }
-        return value;
-    }
-
-    final @NonNull ImmutableSet<NodeIdentifier> byYangKeySet() {
-        return byYang.keySet();
-    }
-
-    abstract @NonNull Map<Class<? extends Augmentation<?>>, Augmentation<?>> getAllAugmentationsFrom(
-        DataContainerNode data);
-}
index 67b39c6abc2476284e7819e35242966db868dae4..82087f1e9edd83e4be8de1e66f24dc588ee7f860 100644 (file)
@@ -46,7 +46,7 @@ public abstract class AugmentableCodecDataObject<T extends DataObject & Augmenta
     @SuppressFBWarnings(value = "UUF_UNUSED_FIELD", justification = "https://github.com/spotbugs/spotbugs/issues/2749")
     private volatile ImmutableMap<Class<? extends Augmentation<T>>, Augmentation<T>> cachedAugmentations;
 
-    protected AugmentableCodecDataObject(final AbstractDataObjectCodecContext<T, ?> context,
+    protected AugmentableCodecDataObject(final CommonDataObjectCodecContext<T, ?> context,
             final DataContainerNode data) {
         super(context, data);
     }
index 2c2f4d8fc8646849871ad0f27a070c95a22f238a..f2fd7986ed23039aed9ef58420b6f659eb7e881f 100644 (file)
@@ -24,9 +24,9 @@ import org.opendaylight.yangtools.yang.data.api.schema.DataContainerNode;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
 
 final class AugmentationCodecContext<A extends Augmentation<?>>
-        extends AbstractDataObjectCodecContext<A, AugmentRuntimeType> implements BindingAugmentationCodecTreeNode<A> {
+        extends CommonDataObjectCodecContext<A, AugmentRuntimeType> implements BindingAugmentationCodecTreeNode<A> {
     private static final MethodType CONSTRUCTOR_TYPE = MethodType.methodType(void.class,
-        AbstractDataObjectCodecContext.class, DataContainerNode.class);
+        CommonDataObjectCodecContext.class, DataContainerNode.class);
     private static final MethodType AUGMENTATION_TYPE = MethodType.methodType(Augmentation.class,
         AugmentationCodecContext.class, DataContainerNode.class);
 
index 31f980395cefa1a57f382bd0aad34ed053396cc0..8b28a13cda77985cfc65c5b0813904e18582beed 100644 (file)
@@ -82,7 +82,7 @@ final class BindingToNormalizedStreamWriter implements AnydataBindingStreamWrite
 
     private <T extends PathArgument> T enter(final String localName, final Class<T> identifier) {
         final var current = current();
-        final var next = ((AbstractDataObjectCodecContext<?, ?>) current).getLeafChild(localName);
+        final var next = ((CommonDataObjectCodecContext<?, ?>) current).getLeafChild(localName);
         schema.push(next);
         return identifier.cast(next.getDomPathArgument());
     }
@@ -104,7 +104,7 @@ final class BindingToNormalizedStreamWriter implements AnydataBindingStreamWrite
 
     private Map.Entry<NodeIdentifier, Object> serializeLeaf(final String localName, final Object value) {
         final var current = current();
-        if (!(current instanceof AbstractDataObjectCodecContext<?, ?> currentCasted)) {
+        if (!(current instanceof CommonDataObjectCodecContext<?, ?> currentCasted)) {
             throw new IllegalArgumentException("Unexpected current context " + current);
         }
 
index 2aa02323862e6f84f12edf89f8db15dfbcde26df..3017b8ce7d00401dc69125e15e278fd01e605d7d 100644 (file)
@@ -75,7 +75,7 @@ final class CachingNormalizedNodeSerializer extends ForwardingBindingStreamEvent
             // They are immutable and hence we can safely wrap them in LeafNodes and reuse them, if directed to do so.
             final var type = typed.getClass();
             if (cacheHolder.isCached(type)) {
-                final var context = ((AbstractDataObjectCodecContext<?, ?>) delegate.current()).getLeafChild(localName);
+                final var context = ((CommonDataObjectCodecContext<?, ?>) delegate.current()).getLeafChild(localName);
                 if (context instanceof LeafNodeCodecContext.OfTypeObject<?> typeContext) {
                     final var cache = cacheHolder.getCachingSerializer(typeContext);
                     if (cache != null) {
index aea80ac9736ba536570a6fa3e8dada7450001dd0..06dba655e7f7c3b5a620d0f53844bdcf4bbb8196 100644 (file)
@@ -41,7 +41,7 @@ public abstract class CodecDataObject<T extends DataObject> implements DataObjec
         }
     }
 
-    private final @NonNull AbstractDataObjectCodecContext<T, ?> context;
+    private final @NonNull CommonDataObjectCodecContext<T, ?> context;
     private final @NonNull DataContainerNode data;
 
     // Accessed via a VarHandle
@@ -50,7 +50,7 @@ public abstract class CodecDataObject<T extends DataObject> implements DataObjec
     @SuppressFBWarnings(value = "UUF_UNUSED_FIELD", justification = "https://github.com/spotbugs/spotbugs/issues/2749")
     private volatile Integer cachedHashcode;
 
-    protected CodecDataObject(final AbstractDataObjectCodecContext<T, ?> context, final DataContainerNode data) {
+    protected CodecDataObject(final CommonDataObjectCodecContext<T, ?> context, final DataContainerNode data) {
         this.data = requireNonNull(data, "Data must not be null");
         this.context = requireNonNull(context, "Context must not be null");
     }
@@ -107,7 +107,7 @@ public abstract class CodecDataObject<T extends DataObject> implements DataObjec
 
     protected abstract boolean codecEquals(Object obj);
 
-    final @NonNull AbstractDataObjectCodecContext<T, ?> codecContext() {
+    final @NonNull CommonDataObjectCodecContext<T, ?> codecContext() {
         return context;
     }
 
index 12f02418db3961ed7b5ffa36b3acd801631c5d72..db73867eb24eedcfd2636c9bae6e297ed16e30cd 100644 (file)
@@ -7,21 +7,79 @@
  */
 package org.opendaylight.yangtools.binding.data.codec.impl;
 
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+import java.util.List;
+import java.util.Map;
+import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.jdt.annotation.Nullable;
+import org.opendaylight.yangtools.binding.Augmentation;
 import org.opendaylight.yangtools.binding.DataObject;
 import org.opendaylight.yangtools.binding.DataObjectStep;
 import org.opendaylight.yangtools.binding.data.codec.api.CommonDataObjectCodecTreeNode;
+import org.opendaylight.yangtools.binding.data.codec.api.IncorrectNestingException;
 import org.opendaylight.yangtools.binding.runtime.api.CompositeRuntimeType;
+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;
+import org.opendaylight.yangtools.yang.model.api.DocumentedNode.WithStatus;
+
 
 /**
- * Base implementation of {@link CommonDataObjectCodecTreeNode}.
+ * Base implementation of {@link CommonDataObjectCodecTreeNode}, shared between {@link DataObjectCodecContext} and
+ * {@link AugmentationCodecContext}. They share most of their mechanics, but notably:
+ * <ol>
+ *   <li>DataObjectCodecContext has an exact DistinctNodeContainer and YangInstanceIdentifier mapping and can be the
+ *       target of augmentations (i.e. can implement Augmentable contract)</li>
+ *   <li>AugmentationNodeContext has neither of those traits and really is just a filter of its parent
+ *       DistinctNodeContainer</li>
+ * </ol>
+ *
+ * <p>
+ * Unfortunately {@code Augmentation} is a also a {@link DataObject}, so things get a bit messy.
+ *
+ * <p>
+ * While this class is public, it not part of API surface and is an implementation detail. The only reason for it being
+ * public is that it needs to be accessible by code generated at runtime.
  */
-abstract sealed class CommonDataObjectCodecContext<D extends DataObject, T extends CompositeRuntimeType>
+public abstract sealed class CommonDataObjectCodecContext<D extends DataObject, T extends CompositeRuntimeType>
         extends DataContainerCodecContext<D, T, CommonDataObjectCodecPrototype<T>>
         implements CommonDataObjectCodecTreeNode<D>
-        permits AbstractDataObjectCodecContext {
-    CommonDataObjectCodecContext(final CommonDataObjectCodecPrototype<T> prototype) {
+        permits AugmentationCodecContext, DataObjectCodecContext {
+    private final ImmutableMap<Class<?>, DataContainerPrototype<?, ?>> byBindingArgClass;
+    private final ImmutableMap<Class<?>, DataContainerPrototype<?, ?>> byStreamClass;
+    private final ImmutableMap<NodeIdentifier, CodecContextSupplier> byYang;
+    private final ImmutableMap<String, ValueNodeCodecContext> leafChild;
+
+    CommonDataObjectCodecContext(final CommonDataObjectCodecPrototype<T> prototype,
+            final DataContainerAnalysis<T> analysis) {
         super(prototype);
+        byBindingArgClass = analysis.byBindingArgClass;
+        byStreamClass = analysis.byStreamClass;
+        byYang = analysis.byYang;
+        leafChild = analysis.leafNodes;
+    }
+
+    @Override
+    @Deprecated(since = "13.0.0", forRemoval = true)
+    public final WithStatus getSchema() {
+        // FIXME: Bad cast, we should be returning an EffectiveStatement perhaps?
+        return (WithStatus) prototype().runtimeType().statement();
+    }
+
+    @Override
+    public final CommonDataObjectCodecContext<?, ?> bindingPathArgumentChild(final DataObjectStep<?> step,
+            final List<PathArgument> builder) {
+        final var type = step.type();
+        final var context = childNonNull(pathChildPrototype(type), type,
+            "Class %s is not valid child of %s", type, getBindingClass())
+            .getCodecContext();
+        context.addYangPathArgument(step, builder);
+        return switch (context) {
+            case ChoiceCodecContext<?> choice -> choice.bindingPathArgumentChild(step, builder);
+            case CommonDataObjectCodecContext<?, ?> dataObject -> dataObject;
+            default -> throw new IllegalStateException("Unhandled context " + context);
+        };
     }
 
     /**
@@ -34,4 +92,34 @@ abstract sealed class CommonDataObjectCodecContext<D extends DataObject, T exten
     protected final DataObjectStep<?> bindingArg() {
         return prototype().getBindingArg();
     }
+
+
+    @Override
+    DataContainerPrototype<?, ?> streamChildPrototype(final Class<?> childClass) {
+        return byStreamClass.get(childClass);
+    }
+
+    @Nullable DataContainerPrototype<?, ?> pathChildPrototype(final @NonNull Class<? extends DataObject> argType) {
+        return byBindingArgClass.get(argType);
+    }
+
+    @Override
+    CodecContextSupplier yangChildSupplier(final NodeIdentifier arg) {
+        return byYang.get(arg);
+    }
+
+    final ValueNodeCodecContext getLeafChild(final String name) {
+        final ValueNodeCodecContext value = leafChild.get(name);
+        if (value == null) {
+            throw new IncorrectNestingException("Leaf %s is not valid for %s", name, getBindingClass());
+        }
+        return value;
+    }
+
+    final @NonNull ImmutableSet<NodeIdentifier> byYangKeySet() {
+        return byYang.keySet();
+    }
+
+    abstract @NonNull Map<Class<? extends Augmentation<?>>, Augmentation<?>> getAllAugmentationsFrom(
+        DataContainerNode data);
 }
index 872ff5a56f24a0efbb7a2fe8ea9eed25516bbc9d..294b354433114e33578f029665ab18eb92ad1d54 100644 (file)
@@ -54,12 +54,12 @@ import org.slf4j.LoggerFactory;
  */
 @Beta
 public abstract sealed class DataObjectCodecContext<D extends DataObject, T extends CompositeRuntimeType>
-        extends AbstractDataObjectCodecContext<D, T> implements BindingDataObjectCodecTreeNode<D>
+        extends CommonDataObjectCodecContext<D, T> implements BindingDataObjectCodecTreeNode<D>
         permits CaseCodecContext, ContainerLikeCodecContext, ListCodecContext, NotificationCodecContext {
     private static final Logger LOG = LoggerFactory.getLogger(DataObjectCodecContext.class);
 
     private static final MethodType CONSTRUCTOR_TYPE = MethodType.methodType(void.class,
-        AbstractDataObjectCodecContext.class, DataContainerNode.class);
+        CommonDataObjectCodecContext.class, DataContainerNode.class);
     private static final MethodType DATAOBJECT_TYPE = MethodType.methodType(DataObject.class,
         DataObjectCodecContext.class, DataContainerNode.class);
     private static final VarHandle MISMATCHED_AUGMENTED;
index be2f9c8ecbf6f7a74d04c9ab0d55bb0a50d47ac1..a1707c5bd03184ed8b4f74f68eadf55b754ad7e9 100644 (file)
@@ -142,7 +142,7 @@ final class NotificationCodecContext<D extends DataObject & BaseNotification>
         static {
             try {
                 LOAD_CTOR_ARGS = MethodVariableAccess.allArgumentsOf(new MethodDescription.ForLoadedConstructor(
-                    AugmentableCodecDataObject.class.getDeclaredConstructor(AbstractDataObjectCodecContext.class,
+                    AugmentableCodecDataObject.class.getDeclaredConstructor(CommonDataObjectCodecContext.class,
                         DataContainerNode.class)));
             } catch (NoSuchMethodException e) {
                 throw new ExceptionInInitializerError(e);