From 6dabf86d9ac01729eebcc7c6ee914e31ace5e3b0 Mon Sep 17 00:00:00 2001 From: Robert Varga Date: Sun, 4 Jun 2023 22:57:06 +0200 Subject: [PATCH] Split out DataContainerCodecPrototype subclasses 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 --- .../impl/AugmentationCodecPrototype.java | 45 +++++++++ .../codec/impl/AugmentationNodeContext.java | 4 +- .../impl/DataContainerCodecPrototype.java | 95 ++----------------- .../codec/impl/DataObjectCodecContext.java | 30 +++--- .../codec/impl/DataObjectCodecPrototype.java | 68 +++++++++++++ 5 files changed, 136 insertions(+), 106 deletions(-) create mode 100644 binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/AugmentationCodecPrototype.java create mode 100644 binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/DataObjectCodecPrototype.java 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 index 0000000000..c91de7f70f --- /dev/null +++ b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/AugmentationCodecPrototype.java @@ -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 { + private final @NonNull ImmutableSet childArgs; + + @SuppressWarnings("unchecked") + AugmentationCodecPrototype(final Class cls, final QNameModule namespace, final AugmentRuntimeType type, + final CodecContextFactory factory, final ImmutableSet childArgs) { + super(Item.of((Class) 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 getChildArgs() { + return childArgs; + } +} \ No newline at end of file diff --git a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/AugmentationNodeContext.java b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/AugmentationNodeContext.java index 1abdb5f58f..871badeada 100644 --- a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/AugmentationNodeContext.java +++ b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/AugmentationNodeContext.java @@ -22,7 +22,7 @@ import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; final class AugmentationNodeContext> extends AbstractDataObjectCodecContext implements BindingAugmentationCodecTreeNode { - AugmentationNodeContext(final DataContainerCodecPrototype.Augmentation prototype) { + AugmentationNodeContext(final AugmentationCodecPrototype prototype) { super(prototype, new CodecDataObjectAnalysis<>(prototype, CodecItemFactory.of(), null)); } @@ -44,7 +44,7 @@ final class AugmentationNodeContext> @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); } diff --git a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/DataContainerCodecPrototype.java b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/DataContainerCodecPrototype.java index 4a70dcad54..c894b28cf4 100644 --- a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/DataContainerCodecPrototype.java +++ b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/DataContainerCodecPrototype.java @@ -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 implements NodeContextSupplier { - static final class Augmentation extends DataContainerCodecPrototype { - private final @NonNull ImmutableSet childArgs; - - @SuppressWarnings("unchecked") - Augmentation(final Class cls, final QNameModule namespace, final AugmentRuntimeType type, - final CodecContextFactory factory, final ImmutableSet childArgs) { - super(Item.of((Class) 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 getChildArgs() { - return childArgs; - } - } - - static final class Regular extends DataContainerCodecPrototype { - 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) 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 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) 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 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 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 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 DataContainerCodecPrototype 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 DataContainerCodecPrototype 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 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 createInstance(); } diff --git a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/DataObjectCodecContext.java b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/DataObjectCodecContext.java index 99735f9e1a..cbc3c15eb9 100644 --- a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/DataObjectCodecContext.java +++ b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/DataObjectCodecContext.java @@ -62,7 +62,7 @@ public abstract class DataObjectCodecContext, DataContainerCodecPrototype.Augmentation> augmentToPrototype; + private final ImmutableMap, AugmentationCodecPrototype> augmentToPrototype; private final ImmutableMap> yangToAugmentClass; private final @NonNull Class> generatedClass; @@ -92,7 +92,7 @@ public abstract class DataObjectCodecContext>(); - final var augClassToProto = new HashMap, DataContainerCodecPrototype.Augmentation>(); + final var augClassToProto = new HashMap, AugmentationCodecPrototype>(); for (var augment : analysis.possibleAugmentations) { final var augProto = loadAugmentPrototype(augment); if (augProto != null) { @@ -134,27 +134,24 @@ public abstract class DataObjectCodecContext 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, DataContainerCodecPrototype.Augmentation>) MISMATCHED_AUGMENTED.getAcquire(this); + final var local = (ImmutableMap, 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, DataContainerCodecPrototype.Augmentation> oldMismatched, + private @Nullable AugmentationCodecPrototype loadMismatchedAugmentation( + final ImmutableMap, AugmentationCodecPrototype> oldMismatched, final @NonNull Class childClass) { @SuppressWarnings("rawtypes") final Class augTarget = BindingReflections.findAugmentationTarget((Class) childClass); @@ -172,10 +169,9 @@ public abstract class DataObjectCodecContext, DataContainerCodecPrototype.Augmentation> oldMismatched, - final @NonNull Class childClass, final DataContainerCodecPrototype.@NonNull Augmentation prototype) { - + private @NonNull AugmentationCodecPrototype cacheMismatched( + final @NonNull ImmutableMap, 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, DataContainerCodecPrototype.Augmentation>) + final var witness = (ImmutableMap, 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 extends DataContainerCodecPrototype { + private final @NonNull NodeIdentifier yangArg; + + @SuppressWarnings("unchecked") + DataObjectCodecPrototype(final Class cls, final NodeIdentifier yangArg, final T type, + final CodecContextFactory factory) { + this(Item.of((Class) 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 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) 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 -- 2.36.6