--- /dev/null
+/*
+ * 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
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));
}
@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);
}
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;
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;
@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);
}
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) {
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();
}
}
}
- 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;
// 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) {
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);
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 =
.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);
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()
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
--- /dev/null
+/*
+ * 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