From ed1d404afce15a852d46c1b7f19cba1a57eb87a5 Mon Sep 17 00:00:00 2001 From: Robert Varga Date: Tue, 27 Jun 2023 21:20:37 +0200 Subject: [PATCH] Split up DataObjectCodecPrototype Having a type-based dispatch during createInstance() is not exactly nice. This patch splits up DataObjectCodecPrototype.createInstance() into individual prototypes, so that we have a prototype for pretty-much each CodecContext type. This also improves type safety, as CodecContexts now can be directly instantiated (and create a prototype internally). Change-Id: If740949bc15890f0ce4bfa5b59cda030b33e66a1 Signed-off-by: Robert Varga --- .../dom/codec/impl/BindingCodecContext.java | 4 +- .../impl/BindingToNormalizedStreamWriter.java | 2 +- .../dom/codec/impl/CaseCodecPrototype.java | 2 +- .../dom/codec/impl/ChoiceCodecContext.java | 13 ++++-- .../dom/codec/impl/ChoiceCodecPrototype.java | 26 +++++++++++ .../dom/codec/impl/CodecDataObject.java | 2 +- .../codec/impl/CodecDataObjectAnalysis.java | 22 ++++++++-- .../codec/impl/ContainerLikeCodecContext.java | 8 +++- .../impl/ContainerLikeCodecPrototype.java | 28 ++++++++++++ .../impl/DataContainerCodecPrototype.java | 26 ----------- .../codec/impl/DataObjectCodecContext.java | 2 +- .../codec/impl/DataObjectCodecPrototype.java | 35 +++------------ .../codec/impl/InstanceIdentifierCodec.java | 2 +- .../dom/codec/impl/LazyBindingList.java | 8 ++-- .../dom/codec/impl/LazyBindingMap.java | 2 +- ...odecContext.java => ListCodecContext.java} | 14 +++--- .../dom/codec/impl/ListCodecPrototype.java | 26 +++++++++++ ...CodecContext.java => MapCodecContext.java} | 44 +++++++++++-------- .../dom/codec/impl/MapCodecPrototype.java | 31 +++++++++++++ .../codec/impl/NotificationCodecContext.java | 8 ++-- .../dom/codec/impl/RootCodecContext.java | 40 ++++++++++------- .../impl/StructuralContainerCodecContext.java | 10 ++++- .../StructuralContainerCodecPrototype.java | 26 +++++++++++ 23 files changed, 259 insertions(+), 122 deletions(-) create mode 100644 binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/ChoiceCodecPrototype.java create mode 100644 binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/ContainerLikeCodecPrototype.java rename binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/{ListNodeCodecContext.java => ListCodecContext.java} (84%) create mode 100644 binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/ListCodecPrototype.java rename binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/{KeyedListNodeCodecContext.java => MapCodecContext.java} (68%) create mode 100644 binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/MapCodecPrototype.java create mode 100644 binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/StructuralContainerCodecPrototype.java diff --git a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/BindingCodecContext.java b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/BindingCodecContext.java index b1c52f7306..9e29114da4 100644 --- a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/BindingCodecContext.java +++ b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/BindingCodecContext.java @@ -253,7 +253,7 @@ public final class BindingCodecContext extends AbstractBindingNormalizedNodeSeri @Nullable BindingDataObjectCodecTreeNode getCodecContextNode(final @NonNull YangInstanceIdentifier dom, final @Nullable Collection bindingArguments) { CodecContext currentNode = root; - ListNodeCodecContext currentList = null; + ListCodecContext currentList = null; for (var domArg : dom.getPathArguments()) { checkArgument(currentNode instanceof DataContainerCodecContext, @@ -292,7 +292,7 @@ public final class BindingCodecContext extends AbstractBindingNormalizedNodeSeri } currentList = null; currentNode = nextNode; - } else if (nextNode instanceof ListNodeCodecContext listNode) { + } else if (nextNode instanceof ListCodecContext listNode) { // We enter list, we do not update current Node yet, // since we need to verify currentList = listNode; diff --git a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/BindingToNormalizedStreamWriter.java b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/BindingToNormalizedStreamWriter.java index 61885141bf..d2a88f7626 100644 --- a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/BindingToNormalizedStreamWriter.java +++ b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/BindingToNormalizedStreamWriter.java @@ -188,7 +188,7 @@ final class BindingToNormalizedStreamWriter implements AnydataBindingStreamWrite @Override public void startMapEntryNode(final Key key, final int childSizeHint) throws IOException { duplicateSchemaEnter(); - NodeIdentifierWithPredicates identifier = ((KeyedListNodeCodecContext) current()).serialize(key); + NodeIdentifierWithPredicates identifier = ((MapCodecContext) current()).serialize(key); delegate.startMapEntryNode(identifier, childSizeHint); } diff --git a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/CaseCodecPrototype.java b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/CaseCodecPrototype.java index da204eb6cb..351c0d2f85 100644 --- a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/CaseCodecPrototype.java +++ b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/CaseCodecPrototype.java @@ -16,7 +16,7 @@ final class CaseCodecPrototype extends DataObjectCodecPrototype } @Override - DataContainerCodecContext createInstance() { + CaseNodeCodecContext createInstance() { return new CaseNodeCodecContext<>(this); } } \ No newline at end of file diff --git a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/ChoiceCodecContext.java b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/ChoiceCodecContext.java index f111721f99..b2f443d8d3 100644 --- a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/ChoiceCodecContext.java +++ b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/ChoiceCodecContext.java @@ -35,6 +35,7 @@ import org.opendaylight.mdsal.binding.runtime.api.ChoiceRuntimeType; import org.opendaylight.yangtools.yang.binding.BindingObject; import org.opendaylight.yangtools.yang.binding.DataContainer; import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.Item; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument; import org.opendaylight.yangtools.yang.binding.contract.Naming; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier; @@ -98,15 +99,19 @@ final class ChoiceCodecContext extends DataContainerCodecC implements BindingDataObjectCodecTreeNode { private static final Logger LOG = LoggerFactory.getLogger(ChoiceCodecContext.class); - private final ImmutableMap> byYangCaseChild; private final ImmutableListMultimap, DataContainerCodecPrototype> ambiguousByCaseChildClass; private final ImmutableMap, DataContainerCodecPrototype> byCaseChildClass; + private final ImmutableMap byYangCaseChild; private final ImmutableMap, DataContainerCodecPrototype> byClass; private final Set> ambiguousByCaseChildWarnings; - ChoiceCodecContext(final DataContainerCodecPrototype prototype) { + ChoiceCodecContext(final Class cls, final ChoiceRuntimeType type, final CodecContextFactory factory) { + this(new ChoiceCodecPrototype(Item.of(cls), type, factory)); + } + + ChoiceCodecContext(final ChoiceCodecPrototype prototype) { super(prototype); - final var byYangCaseChildBuilder = new HashMap>(); + final var byYangCaseChildBuilder = new HashMap(); final var byClassBuilder = new HashMap, DataContainerCodecPrototype>(); final var childToCase = SetMultimapBuilder.hashKeys().hashSetValues() ., DataContainerCodecPrototype>build(); @@ -245,7 +250,7 @@ final class ChoiceCodecContext extends DataContainerCodecC return null; } final var caze = byYangCaseChild.get(first.name()); - return (D) caze.getDataObject().deserialize(data); + return ((CaseNodeCodecContext) caze.get()).deserialize(data); } @Override diff --git a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/ChoiceCodecPrototype.java b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/ChoiceCodecPrototype.java new file mode 100644 index 0000000000..7fc1f3cca9 --- /dev/null +++ b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/ChoiceCodecPrototype.java @@ -0,0 +1,26 @@ +/* + * 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 org.opendaylight.mdsal.binding.runtime.api.ChoiceRuntimeType; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.Item; +import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier; + +/** + * A prototype for {@link ChoiceCodecContext}. + */ +final class ChoiceCodecPrototype extends DataObjectCodecPrototype { + ChoiceCodecPrototype(final Item item, final ChoiceRuntimeType type, final CodecContextFactory factory) { + super(item, NodeIdentifier.create(type.statement().argument()), type, factory); + } + + @Override + ChoiceCodecContext createInstance() { + return new ChoiceCodecContext<>(this); + } +} diff --git a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/CodecDataObject.java b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/CodecDataObject.java index 2377d7f2e6..18b195540c 100644 --- a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/CodecDataObject.java +++ b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/CodecDataObject.java @@ -129,7 +129,7 @@ public abstract class CodecDataObject implements DataObjec if (!(data instanceof MapEntryNode mapEntry)) { throw new VerifyException("Unsupported value " + data); } - if (!(context instanceof KeyedListNodeCodecContext listContext)) { + if (!(context instanceof MapCodecContext listContext)) { throw new VerifyException("Unexpected context " + context); } diff --git a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/CodecDataObjectAnalysis.java b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/CodecDataObjectAnalysis.java index af08f5d4a4..fb20719dc8 100644 --- a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/CodecDataObjectAnalysis.java +++ b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/CodecDataObjectAnalysis.java @@ -26,6 +26,9 @@ import org.opendaylight.mdsal.binding.runtime.api.AugmentRuntimeType; import org.opendaylight.mdsal.binding.runtime.api.AugmentableRuntimeType; 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.yangtools.yang.binding.Augmentable; import org.opendaylight.yangtools.yang.binding.DataContainer; import org.opendaylight.yangtools.yang.binding.DataObject; @@ -33,6 +36,7 @@ import org.opendaylight.yangtools.yang.binding.OpaqueObject; import org.opendaylight.yangtools.yang.binding.contract.Naming; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier; import org.opendaylight.yangtools.yang.data.api.schema.DataContainerNode; +import org.opendaylight.yangtools.yang.model.api.stmt.PresenceEffectiveStatement; /** * Analysis of a {@link DataObject} specialization class. The primary point of this class is to separate out creation @@ -163,9 +167,21 @@ final class CodecDataObjectAnalysis { throw DataContainerCodecContext.childNullException(factory.getRuntimeContext(), childClass, "Node %s does not have child named %s", type, childClass); } - - return DataContainerCodecPrototype.from(itemFactory.createItem(childClass, child.statement()), - (CompositeRuntimeType) child, factory); + final var item = itemFactory.createItem(childClass, child.statement()); + if (child instanceof ContainerLikeRuntimeType containerLike) { + if (child instanceof ContainerRuntimeType container + && container.statement().findFirstEffectiveSubstatement(PresenceEffectiveStatement.class).isEmpty()) { + return new StructuralContainerCodecPrototype(item, container, factory); + } + return new ContainerLikeCodecPrototype(item, containerLike, factory); + } else if (child instanceof ListRuntimeType list) { + return list.keyType() != null ? new MapCodecPrototype(item, list, factory) + : new ListCodecPrototype(item, list, factory); + } else if (child instanceof ChoiceRuntimeType choice) { + return new ChoiceCodecPrototype(item, choice, factory); + } else { + throw new UnsupportedOperationException("Unhandled type " + child); + } } diff --git a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/ContainerLikeCodecContext.java b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/ContainerLikeCodecContext.java index cef279a5c5..b906ff3f25 100644 --- a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/ContainerLikeCodecContext.java +++ b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/ContainerLikeCodecContext.java @@ -9,13 +9,19 @@ package org.opendaylight.mdsal.binding.dom.codec.impl; import org.opendaylight.mdsal.binding.runtime.api.ContainerLikeRuntimeType; import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.Item; import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode; import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; sealed class ContainerLikeCodecContext extends DataObjectCodecContext> implements RpcInputCodec permits StructuralContainerCodecContext { - ContainerLikeCodecContext(final DataContainerCodecPrototype> prototype) { + ContainerLikeCodecContext(final Class cls, final ContainerLikeRuntimeType type, + final CodecContextFactory factory) { + this(new ContainerLikeCodecPrototype(Item.of(cls), type, factory)); + } + + ContainerLikeCodecContext(final ContainerLikeCodecPrototype prototype) { super(prototype); } diff --git a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/ContainerLikeCodecPrototype.java b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/ContainerLikeCodecPrototype.java new file mode 100644 index 0000000000..bfc9f009af --- /dev/null +++ b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/ContainerLikeCodecPrototype.java @@ -0,0 +1,28 @@ +/* + * 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 org.opendaylight.mdsal.binding.runtime.api.ContainerLikeRuntimeType; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.Item; +import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier; + +/** + * A prototype for a {@link ContainerLikeCodecContext}. + */ +sealed class ContainerLikeCodecPrototype extends DataObjectCodecPrototype> + permits StructuralContainerCodecPrototype { + ContainerLikeCodecPrototype(final Item item, final ContainerLikeRuntimeType type, + final CodecContextFactory factory) { + super(item, NodeIdentifier.create(type.statement().argument()), type, factory); + } + + @Override + ContainerLikeCodecContext createInstance() { + return new ContainerLikeCodecContext<>(this); + } +} 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 2a05e7df36..984d3ebee2 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 @@ -7,18 +7,15 @@ */ package org.opendaylight.mdsal.binding.dom.codec.impl; -import static com.google.common.base.Verify.verify; import static java.util.Objects.requireNonNull; 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.runtime.api.CompositeRuntimeType; import org.opendaylight.mdsal.binding.runtime.api.RuntimeType; import org.opendaylight.mdsal.binding.runtime.api.RuntimeTypeContainer; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.Item; -import org.opendaylight.yangtools.yang.common.QName; import org.opendaylight.yangtools.yang.common.QNameModule; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier; import org.opendaylight.yangtools.yang.model.api.AnydataSchemaNode; @@ -149,22 +146,6 @@ abstract sealed class DataContainerCodecPrototype DataContainerCodecPrototype from(final Class cls, final T type, - final CodecContextFactory factory) { - return new DataObjectCodecPrototype<>(cls, createIdentifier(type), type, factory); - } - - static DataContainerCodecPrototype from(final Item bindingArg, final T type, - final CodecContextFactory factory) { - return new DataObjectCodecPrototype<>(bindingArg, createIdentifier(type), type, factory); - } - - private static @NonNull NodeIdentifier createIdentifier(final CompositeRuntimeType type) { - final Object arg = type.statement().argument(); - verify(arg instanceof QName, "Unexpected type %s argument %s", type, arg); - return NodeIdentifier.create((QName) arg); - } - final @NonNull T getType() { return type; } @@ -197,13 +178,6 @@ abstract sealed class DataContainerCodecPrototype DataObjectCodecContext getDataObject() { - final var context = get(); - verify(context instanceof DataObjectCodecContext, "Unexpected instance %s", context); - return (DataObjectCodecContext) context; - } - private @NonNull DataContainerCodecContext loadInstance() { final var tmp = createInstance(); final var witness = (DataContainerCodecContext) INSTANCE.compareAndExchangeRelease(this, null, tmp); 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 4c9b0c5a8d..c2fa64c67c 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 @@ -48,7 +48,7 @@ import org.slf4j.LoggerFactory; @Beta public abstract sealed class DataObjectCodecContext extends AbstractDataObjectCodecContext implements BindingDataObjectCodecTreeNode - permits CaseNodeCodecContext, ContainerLikeCodecContext, ListNodeCodecContext, NotificationCodecContext { + permits CaseNodeCodecContext, ContainerLikeCodecContext, ListCodecContext, NotificationCodecContext { private static final Logger LOG = LoggerFactory.getLogger(DataObjectCodecContext.class); private static final VarHandle MISMATCHED_AUGMENTED; 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 index 21d8acde3e..be2fb03a18 100644 --- 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 @@ -10,21 +10,17 @@ 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.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.InstanceIdentifier.Item; -import org.opendaylight.yangtools.yang.binding.KeyAware; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier; -import org.opendaylight.yangtools.yang.model.api.stmt.PresenceEffectiveStatement; -// FIXME: abstract and sealed -non-sealed class DataObjectCodecPrototype extends DataContainerCodecPrototype { +abstract sealed class DataObjectCodecPrototype extends DataContainerCodecPrototype + permits CaseCodecPrototype, ChoiceCodecPrototype, ContainerLikeCodecPrototype, ListCodecPrototype, + NotificationCodecContext.Prototype, RootCodecContext.Prototype { private final @NonNull NodeIdentifier yangArg; + // FIXME: this should not be needed @SuppressWarnings("unchecked") DataObjectCodecPrototype(final Class cls, final NodeIdentifier yangArg, final T type, final CodecContextFactory factory) { @@ -41,25 +37,4 @@ non-sealed class DataObjectCodecPrototype extend final 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 StructuralContainerCodecContext(this); - } - return new ContainerLikeCodecContext(this); - } else if (type instanceof ListRuntimeType) { - return KeyAware.class.isAssignableFrom(getBindingClass()) - ? KeyedListNodeCodecContext.create((DataContainerCodecPrototype) this) - : new ListNodeCodecContext(this); - } else if (type instanceof ChoiceRuntimeType) { - return new ChoiceCodecContext(this); - } - throw new IllegalArgumentException("Unsupported type " + getBindingClass() + " " + type); - } -} \ No newline at end of file +} diff --git a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/InstanceIdentifierCodec.java b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/InstanceIdentifierCodec.java index 09590791b3..b7f60447f3 100644 --- a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/InstanceIdentifierCodec.java +++ b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/InstanceIdentifierCodec.java @@ -36,7 +36,7 @@ final class InstanceIdentifierCodec implements BindingInstanceIdentifierCodec, if (codec == null) { return null; } - if (codec instanceof ListNodeCodecContext && Iterables.getLast(builder) instanceof InstanceIdentifier.Item) { + if (codec instanceof ListCodecContext && Iterables.getLast(builder) instanceof InstanceIdentifier.Item) { // We ended up in list, but without key, which means it represent list as a whole, // which is not binding representable. return null; diff --git a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/LazyBindingList.java b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/LazyBindingList.java index adbc7ffeb6..66bc4574df 100644 --- a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/LazyBindingList.java +++ b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/LazyBindingList.java @@ -63,16 +63,16 @@ final class LazyBindingList extends AbstractList implem } } - private final ListNodeCodecContext codec; + private final ListCodecContext codec; private final Object[] objects; - private LazyBindingList(final ListNodeCodecContext codec, + private LazyBindingList(final ListCodecContext codec, final Collection> entries) { this.codec = requireNonNull(codec); objects = entries.toArray(); } - static @NonNull List create(final ListNodeCodecContext codec, final int size, + static @NonNull List create(final ListCodecContext codec, final int size, final Collection entries) { if (size == 1) { // Do not bother with lazy instantiation in case of a singleton @@ -81,7 +81,7 @@ final class LazyBindingList extends AbstractList implem return size > LAZY_CUTOFF ? new LazyBindingList<>(codec, entries) : eagerList(codec, size, entries); } - private static @NonNull List eagerList(final ListNodeCodecContext codec, + private static @NonNull List eagerList(final ListCodecContext codec, final int size, final Collection entries) { @SuppressWarnings("unchecked") final E[] objs = (E[]) new DataObject[size]; diff --git a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/LazyBindingMap.java b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/LazyBindingMap.java index bd84cc66e3..14b6946c0a 100644 --- a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/LazyBindingMap.java +++ b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/LazyBindingMap.java @@ -20,7 +20,7 @@ import java.util.Map; import java.util.Optional; import java.util.Set; import org.eclipse.jdt.annotation.NonNull; -import org.opendaylight.mdsal.binding.dom.codec.impl.KeyedListNodeCodecContext.Unordered; +import org.opendaylight.mdsal.binding.dom.codec.impl.MapCodecContext.Unordered; import org.opendaylight.yangtools.concepts.Immutable; import org.opendaylight.yangtools.yang.binding.DataObject; import org.opendaylight.yangtools.yang.binding.Key; diff --git a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/ListNodeCodecContext.java b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/ListCodecContext.java similarity index 84% rename from binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/ListNodeCodecContext.java rename to binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/ListCodecContext.java index 58c5d7178d..1cd594d605 100644 --- a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/ListNodeCodecContext.java +++ b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/ListCodecContext.java @@ -14,20 +14,24 @@ import java.util.List; import org.eclipse.jdt.annotation.NonNull; import org.opendaylight.mdsal.binding.runtime.api.ListRuntimeType; import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.Item; import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode; import org.opendaylight.yangtools.yang.data.api.schema.MapNode; import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; import org.opendaylight.yangtools.yang.data.api.schema.UnkeyedListEntryNode; import org.opendaylight.yangtools.yang.data.api.schema.UnkeyedListNode; -sealed class ListNodeCodecContext extends DataObjectCodecContext - permits KeyedListNodeCodecContext { - ListNodeCodecContext(final DataContainerCodecPrototype prototype) { +sealed class ListCodecContext extends DataObjectCodecContext + permits MapCodecContext { + ListCodecContext(final Class cls, final ListRuntimeType list, final CodecContextFactory factory) { + this(new ListCodecPrototype(Item.of(cls), list, factory)); + } + + ListCodecContext(final ListCodecPrototype prototype) { super(prototype); } - ListNodeCodecContext(final DataContainerCodecPrototype prototype, - final Method keyMethod) { + ListCodecContext(final ListCodecPrototype prototype, final Method keyMethod) { super(prototype, keyMethod); } diff --git a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/ListCodecPrototype.java b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/ListCodecPrototype.java new file mode 100644 index 0000000000..f63eaa27e9 --- /dev/null +++ b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/ListCodecPrototype.java @@ -0,0 +1,26 @@ +/* + * 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 org.opendaylight.mdsal.binding.runtime.api.ListRuntimeType; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.Item; +import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier; + +/** + * A prototype for {@link ListCodecContext}. + */ +sealed class ListCodecPrototype extends DataObjectCodecPrototype permits MapCodecPrototype { + ListCodecPrototype(final Item item, final ListRuntimeType type, final CodecContextFactory factory) { + super(item, NodeIdentifier.create(type.statement().argument()), type, factory); + } + + @Override + ListCodecContext createInstance() { + return new ListCodecContext<>(this); + } +} diff --git a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/KeyedListNodeCodecContext.java b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/MapCodecContext.java similarity index 68% rename from binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/KeyedListNodeCodecContext.java rename to binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/MapCodecContext.java index 61dcbe4b3c..98ccc705af 100644 --- a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/KeyedListNodeCodecContext.java +++ b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/MapCodecContext.java @@ -17,6 +17,7 @@ import org.opendaylight.mdsal.binding.runtime.api.ListRuntimeType; import org.opendaylight.yangtools.yang.binding.DataObject; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.IdentifiableItem; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.Item; import org.opendaylight.yangtools.yang.binding.Key; import org.opendaylight.yangtools.yang.binding.KeyAware; import org.opendaylight.yangtools.yang.binding.contract.Naming; @@ -25,19 +26,18 @@ import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates; import org.opendaylight.yangtools.yang.data.api.schema.MapNode; -abstract sealed class KeyedListNodeCodecContext, D extends DataObject & KeyAware> - extends ListNodeCodecContext { +abstract sealed class MapCodecContext, D extends DataObject & KeyAware> + extends ListCodecContext { private static final class Ordered, D extends DataObject & KeyAware> - extends KeyedListNodeCodecContext { - Ordered(final DataContainerCodecPrototype prototype, final Method keyMethod, - final IdentifiableItemCodec codec) { + extends MapCodecContext { + Ordered(final MapCodecPrototype prototype, final Method keyMethod, final IdentifiableItemCodec codec) { super(prototype, keyMethod, codec); } } static final class Unordered, D extends DataObject & KeyAware> - extends KeyedListNodeCodecContext { - Unordered(final DataContainerCodecPrototype prototype, final Method keyMethod, + extends MapCodecContext { + private Unordered(final MapCodecPrototype prototype, final Method keyMethod, final IdentifiableItemCodec codec) { super(prototype, keyMethod, codec); } @@ -50,15 +50,19 @@ abstract sealed class KeyedListNodeCodecContext, D extends Data private final IdentifiableItemCodec codec; - KeyedListNodeCodecContext(final DataContainerCodecPrototype prototype, - final Method keyMethod, final IdentifiableItemCodec codec) { + private MapCodecContext(final MapCodecPrototype prototype, final Method keyMethod, + final IdentifiableItemCodec codec) { super(prototype, keyMethod); this.codec = requireNonNull(codec); } - @SuppressWarnings("rawtypes") - static KeyedListNodeCodecContext create(final DataContainerCodecPrototype prototype) { - final Class bindingClass = prototype.getBindingClass(); + static @NonNull MapCodecContext of(final Class cls, + final ListRuntimeType list, final CodecContextFactory factory) { + return of(new MapCodecPrototype(Item.of(cls), list, factory)); + } + + static @NonNull MapCodecContext of(final MapCodecPrototype prototype) { + final var bindingClass = prototype.getBindingClass(); final Method keyMethod; try { keyMethod = bindingClass.getMethod(Naming.KEY_AWARE_KEY_NAME); @@ -66,8 +70,8 @@ abstract sealed class KeyedListNodeCodecContext, D extends Data throw new IllegalStateException("Required method not available", e); } - final ListRuntimeType type = prototype.getType(); - final IdentifiableItemCodec codec = prototype.getFactory().getPathArgumentCodec(bindingClass, type); + final var type = prototype.getType(); + final var codec = prototype.getFactory().getPathArgumentCodec(bindingClass, type); return type.statement().ordering() == Ordering.SYSTEM ? new Unordered<>(prototype, keyMethod, codec) : new Ordered<>(prototype, keyMethod, codec); @@ -92,28 +96,30 @@ abstract sealed class KeyedListNodeCodecContext, D extends Data } @Override - protected InstanceIdentifier.PathArgument getBindingPathArgument(final YangInstanceIdentifier.PathArgument domArg) { + protected final InstanceIdentifier.PathArgument getBindingPathArgument( + final YangInstanceIdentifier.PathArgument domArg) { return domArg instanceof NodeIdentifierWithPredicates nip ? codec.domToBinding(nip) : super.getBindingPathArgument(domArg); } @SuppressWarnings({ "rawtypes", "unchecked" }) - NodeIdentifierWithPredicates serialize(final Key key) { + final NodeIdentifierWithPredicates serialize(final Key key) { return codec.bindingToDom(IdentifiableItem.of((Class)getBindingClass(), (Key)key)); } - @NonNull Key deserialize(final @NonNull NodeIdentifierWithPredicates arg) { + final @NonNull Key deserialize(final @NonNull NodeIdentifierWithPredicates arg) { return codec.deserializeIdentifier(arg); } @Override - public YangInstanceIdentifier.PathArgument serializePathArgument(final InstanceIdentifier.PathArgument arg) { + public final YangInstanceIdentifier.PathArgument serializePathArgument(final InstanceIdentifier.PathArgument arg) { return arg instanceof IdentifiableItem identifiable ? codec.bindingToDom(identifiable) : super.serializePathArgument(arg); } @Override - public InstanceIdentifier.PathArgument deserializePathArgument(final YangInstanceIdentifier.PathArgument arg) { + public final InstanceIdentifier.PathArgument deserializePathArgument( + final YangInstanceIdentifier.PathArgument arg) { return arg instanceof NodeIdentifierWithPredicates nip ? codec.domToBinding(nip) : super.deserializePathArgument(arg); } diff --git a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/MapCodecPrototype.java b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/MapCodecPrototype.java new file mode 100644 index 0000000000..da5885f186 --- /dev/null +++ b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/MapCodecPrototype.java @@ -0,0 +1,31 @@ +/* + * 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 com.google.common.base.Preconditions.checkArgument; + +import org.opendaylight.mdsal.binding.runtime.api.ListRuntimeType; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.Item; +import org.opendaylight.yangtools.yang.binding.KeyAware; + +/** + * A prototype for a {@link MapCodecContext}. + */ +final class MapCodecPrototype extends ListCodecPrototype { + MapCodecPrototype(final Item item, final ListRuntimeType type, final CodecContextFactory factory) { + super(item, type, factory); + final var clazz = getBindingClass(); + checkArgument(KeyAware.class.isAssignableFrom(clazz), "%s is not KeyAware", clazz); + } + + @Override + @SuppressWarnings({ "rawtypes", "unchecked" }) + ListCodecContext createInstance() { + return MapCodecContext.of(this); + } +} diff --git a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/NotificationCodecContext.java b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/NotificationCodecContext.java index 9bae0af94c..8c9ea4ac3c 100644 --- a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/NotificationCodecContext.java +++ b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/NotificationCodecContext.java @@ -123,17 +123,17 @@ final class NotificationCodecContext } /** - * Prototype for a {@code notiofication}. This class only exists because DataContainerCodecContext requires a + * Prototype for a {@code notification}. This class only exists because DataContainerCodecContext requires a * prototype. */ - private static final class Prototype + static final class Prototype extends DataObjectCodecPrototype { - Prototype(final Class cls, final NotificationRuntimeType type, final CodecContextFactory factory) { + private Prototype(final Class cls, final NotificationRuntimeType type, final CodecContextFactory factory) { super(cls, NodeIdentifier.create(type.statement().argument()), type, factory); } @Override - DataContainerCodecContext createInstance() { + NotificationCodecContext createInstance() { throw new UnsupportedOperationException("Should never be invoked"); } } diff --git a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/RootCodecContext.java b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/RootCodecContext.java index fcf8a03ba0..d0ca5f876e 100644 --- a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/RootCodecContext.java +++ b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/RootCodecContext.java @@ -33,9 +33,10 @@ import org.opendaylight.mdsal.binding.runtime.api.ActionRuntimeType; import org.opendaylight.mdsal.binding.runtime.api.BindingRuntimeContext; import org.opendaylight.mdsal.binding.runtime.api.BindingRuntimeTypes; 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.DataRuntimeType; +import org.opendaylight.mdsal.binding.runtime.api.ListRuntimeType; import org.opendaylight.mdsal.binding.runtime.api.NotificationRuntimeType; import org.opendaylight.mdsal.binding.spec.reflect.BindingReflections; import org.opendaylight.yangtools.util.ClassLoaderUtils; @@ -64,6 +65,7 @@ import org.opendaylight.yangtools.yang.model.api.DocumentedNode.WithStatus; import org.opendaylight.yangtools.yang.model.api.Module; import org.opendaylight.yangtools.yang.model.api.RpcDefinition; import org.opendaylight.yangtools.yang.model.api.SchemaContext; +import org.opendaylight.yangtools.yang.model.api.stmt.PresenceEffectiveStatement; import org.opendaylight.yangtools.yang.model.api.stmt.SchemaNodeIdentifier.Absolute; final class RootCodecContext extends DataContainerCodecContext @@ -72,15 +74,15 @@ final class RootCodecContext extends DataContainerCodecCon * Prototype for the root of YANG modeled world. This class only exists because DataContainerCodecContext requires * a prototype. */ - private static final class Prototype extends DataObjectCodecPrototype { + static final class Prototype extends DataObjectCodecPrototype { private static final @NonNull NodeIdentifier ROOT_NODEID = NodeIdentifier.create(SchemaContext.NAME); - Prototype(final CodecContextFactory factory) { + private Prototype(final CodecContextFactory factory) { super(DataRoot.class, ROOT_NODEID, factory.getRuntimeContext().getTypes(), factory); } @Override - DataContainerCodecContext createInstance() { + RootCodecContext createInstance() { throw new UnsupportedOperationException("Should never be invoked"); } } @@ -160,11 +162,11 @@ final class RootCodecContext extends DataContainerCodecCon final ContainerLike schema = getRpcDataSchema(potential, qname); checkArgument(schema != null, "Schema for %s does not define input / output.", potentialQName); - final ContainerLikeRuntimeType type = lookup.apply(context.getTypes(), potentialQName) + final var type = lookup.apply(context.getTypes(), potentialQName) .orElseThrow(() -> new IllegalArgumentException("Cannot find runtime type for " + key)); - return (ContainerLikeCodecContext) DataContainerCodecPrototype.from(key, - (ContainerLikeRuntimeType) type, factory).get(); + // FIXME: accurate type + return new ContainerLikeCodecContext(key, type, factory); } } @@ -288,8 +290,17 @@ final class RootCodecContext extends DataContainerCodecCon DataContainerCodecContext createDataTreeChildContext(final Class key) { final var childSchema = childNonNull(type().bindingChild(JavaTypeName.create(key)), key, "%s is not top-level item.", key); - if (childSchema instanceof CompositeRuntimeType composite && childSchema instanceof DataRuntimeType) { - return DataContainerCodecPrototype.from(key, composite, factory()).get(); + if (childSchema instanceof ContainerLikeRuntimeType containerLike) { + if (childSchema instanceof ContainerRuntimeType container + && container.statement().findFirstEffectiveSubstatement(PresenceEffectiveStatement.class).isEmpty()) { + return new StructuralContainerCodecContext<>(key, container, factory()); + } + return new ContainerLikeCodecContext<>(key, containerLike, factory()); + } else if (childSchema instanceof ListRuntimeType list) { + return list.keyType() == null ? new ListCodecContext<>(key, list, factory()) + : MapCodecContext.of(key, list, factory()); + } else if (childSchema instanceof ChoiceRuntimeType choice) { + return new ChoiceCodecContext<>(key, choice, factory()); } throw new IncorrectNestingException("%s is not a valid data tree child of %s", key, this); } @@ -313,10 +324,8 @@ final class RootCodecContext extends DataContainerCodecCon checkArgument(args.length == expectedArgsLength, "Unexpected (%s) Action generatic arguments", args.length); final ActionRuntimeType schema = factory().getRuntimeContext().getActionDefinition(action); return new ActionCodecContext( - DataContainerCodecPrototype.from(asClass(args[inputOffset], RpcInput.class), schema.input(), - factory()).getDataObject(), - DataContainerCodecPrototype.from(asClass(args[outputOffset], RpcOutput.class), schema.output(), - factory()).getDataObject()); + new ContainerLikeCodecContext(asClass(args[inputOffset], RpcInput.class), schema.input(), factory()), + new ContainerLikeCodecContext(asClass(args[outputOffset], RpcOutput.class), schema.output(), factory())); } private static Class asClass(final Type type, final Class target) { @@ -353,9 +362,8 @@ final class RootCodecContext extends DataContainerCodecCon throw new IllegalArgumentException(caseType + " does not refer to a choice"); } - final var choice = DataContainerCodecPrototype.from(choiceClass, choiceType, factory()).get(); - verify(choice instanceof ChoiceCodecContext); - return (ChoiceCodecContext) choice; + // FIXME: accurate type! + return new ChoiceCodecContext(choiceClass, choiceType, factory()); } @Override diff --git a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/StructuralContainerCodecContext.java b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/StructuralContainerCodecContext.java index 3a79531807..def7a91d9b 100644 --- a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/StructuralContainerCodecContext.java +++ b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/StructuralContainerCodecContext.java @@ -10,8 +10,9 @@ package org.opendaylight.mdsal.binding.dom.codec.impl; import java.lang.invoke.MethodHandles; import java.lang.invoke.VarHandle; import org.eclipse.jdt.annotation.NonNull; -import org.opendaylight.mdsal.binding.runtime.api.ContainerLikeRuntimeType; +import org.opendaylight.mdsal.binding.runtime.api.ContainerRuntimeType; import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.Item; import org.opendaylight.yangtools.yang.data.impl.schema.Builders; /** @@ -32,7 +33,12 @@ final class StructuralContainerCodecContext extends Contai @SuppressWarnings("unused") private volatile D emptyObject; - StructuralContainerCodecContext(final DataContainerCodecPrototype> prototype) { + StructuralContainerCodecContext(final Class cls, final ContainerRuntimeType type, + final CodecContextFactory factory) { + this(new StructuralContainerCodecPrototype(Item.of(cls), type, factory)); + } + + StructuralContainerCodecContext(final StructuralContainerCodecPrototype prototype) { super(prototype); } diff --git a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/StructuralContainerCodecPrototype.java b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/StructuralContainerCodecPrototype.java new file mode 100644 index 0000000000..4fb130c5bf --- /dev/null +++ b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/StructuralContainerCodecPrototype.java @@ -0,0 +1,26 @@ +/* + * 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 org.opendaylight.mdsal.binding.runtime.api.ContainerRuntimeType; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.Item; + +/** + * A prototype for a {@link StructuralContainerCodecContext}. + */ +final class StructuralContainerCodecPrototype extends ContainerLikeCodecPrototype { + StructuralContainerCodecPrototype(final Item item, final ContainerRuntimeType container, + final CodecContextFactory factory) { + super(item, container, factory); + } + + @Override + StructuralContainerCodecContext createInstance() { + return new StructuralContainerCodecContext<>(this); + } +} -- 2.36.6