--- /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.api;
+
+import java.util.List;
+import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.jdt.annotation.Nullable;
+import org.opendaylight.yangtools.yang.binding.Augmentation;
+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;
+import org.opendaylight.yangtools.yang.common.Empty;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+
+/**
+ * A {@link BindingObjectCodecTreeNode} which corresponds to a {@link DataContainer} construct.
+ *
+ * @param <T> DataContainer type
+ */
+public interface BindingDataContainerCodecTreeNode<T extends BindingObject & DataContainer>
+ extends BindingObjectCodecTreeNode<T>, BindingDataObjectCodecTreeParent<Empty> {
+ /**
+ * Returns binding class of interface which represents API of current schema node. The result is same as invoking
+ * {@link DataContainer#implementedInterface()} on instance of data.
+ *
+ * @return interface which defines API of binding representation of data.
+ */
+ @Override
+ Class<T> getBindingClass();
+
+ /**
+ * Returns child context as if it was walked by {@link BindingStreamEventWriter}. This means that to enter case,
+ * one must issue getChild(ChoiceClass).getChild(CaseClass).
+ *
+ * <p>
+ * This method differs from {@link #getStreamChild(Class)}, that is less strict for interfaces representing
+ * augmentation and cases, that may return {@link BindingCodecTreeNode} even if augmentation interface containing
+ * same data was supplied and does not represent augmentation of this node.
+ *
+ * @param childClass Child class by Binding Stream navigation
+ * @return Context of child or {@code null} is supplied class is not applicable in context.
+ * @throws NullPointerException if {@code childClass} is {@code null}
+ */
+ <E extends DataObject> @Nullable CommonDataObjectCodecTreeNode<E> streamChild(@NonNull Class<E> childClass);
+
+ default <A extends Augmentation<?>> @Nullable BindingAugmentationCodecTreeNode<A> streamAugmentation(
+ final @NonNull Class<A> childClass) {
+ final var result = streamChild(childClass);
+ if (result instanceof BindingAugmentationCodecTreeNode) {
+ return (BindingAugmentationCodecTreeNode<A>) result;
+ } else if (result == null) {
+ return null;
+ } else {
+ throw new IllegalArgumentException(
+ "Child " + childClass.getName() + " results in non-Augmentation " + result);
+ }
+ }
+
+ default <E extends DataObject> @Nullable BindingDataObjectCodecTreeNode<E> streamDataObject(
+ final @NonNull Class<E> childClass) {
+ final var result = streamChild(childClass);
+ if (result instanceof BindingDataObjectCodecTreeNode) {
+ return (BindingDataObjectCodecTreeNode<E>) result;
+ } else if (result == null) {
+ return null;
+ } else {
+ throw new IllegalArgumentException(
+ "Child " + childClass.getName() + " results in non-DataObject " + result);
+ }
+ }
+
+ /**
+ * Returns nested node context using supplied YANG Instance Identifier.
+ *
+ * @param child
+ * Yang Instance Identifier Argument
+ * @return Context of child
+ * @throws IllegalArgumentException
+ * If supplied argument does not represent valid child.
+ */
+ @NonNull BindingCodecTreeNode yangPathArgumentChild(YangInstanceIdentifier.@NonNull PathArgument child);
+
+ /**
+ * Returns nested node context using supplied Binding Instance Identifier and adds YANG instance identifiers to
+ * the supplied list.
+ *
+ * @param arg
+ * Binding Instance Identifier Argument
+ * @param builder
+ * Mutable instance of list, which is appended by YangInstanceIdentifiers
+ * as tree is walked. Use null if such side-product is not needed.
+ * @return Context of child
+ * @throws IllegalArgumentException
+ * If supplied argument does not represent valid child.
+ */
+ @NonNull CommonDataObjectCodecTreeNode<?> bindingPathArgumentChild(InstanceIdentifier.@NonNull PathArgument arg,
+ @Nullable List<YangInstanceIdentifier.PathArgument> builder);
+
+ /**
+ * Return a summary of addressability of potential children. Binding specification does not allow all DOM tree
+ * elements to be directly addressed, which means some recursive tree operations, like data tree changes do not
+ * have a one-to-one mapping from DOM to binding in all cases. This method provides an optimization hint to guide
+ * translation of data structures, allowing for fast paths when all children are known to either be addressable
+ * or non-addressable.
+ *
+ * @return Summary children addressability.
+ */
+ @NonNull ChildAddressabilitySummary getChildAddressabilitySummary();
+
+ /**
+ * Enumeration of possible addressability attribute of all children.
+ */
+ enum ChildAddressabilitySummary {
+ /**
+ * All children are addressable.
+ */
+ ADDRESSABLE,
+ /**
+ * All children are non-addressable, including the case when this node does not have any children.
+ */
+ UNADDRESSABLE,
+ /**
+ * Mixed children, some are addressable and some are not.
+ */
+ MIXED
+ }
+}
package org.opendaylight.mdsal.binding.dom.codec.api;
import com.google.common.annotations.Beta;
-import java.util.List;
-import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;
-import org.opendaylight.yangtools.yang.binding.Augmentation;
import org.opendaylight.yangtools.yang.binding.DataObject;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import org.opendaylight.yangtools.yang.common.Empty;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
/**
*
* @param <T> DataObject type
*/
-public interface CommonDataObjectCodecTreeNode<T extends DataObject>
- extends BindingDataObjectCodecTreeParent<Empty>, BindingObjectCodecTreeNode<T> {
- /**
- * Returns binding class of interface which represents API of current schema node. The result is same as invoking
- * {@link DataObject#implementedInterface()} on instance of data.
- *
- * @return interface which defines API of binding representation of data.
- */
- @Override
- @NonNull Class<T> getBindingClass();
-
- /**
- * Returns child context as if it was walked by {@link BindingStreamEventWriter}. This means that to enter case,
- * one must issue getChild(ChoiceClass).getChild(CaseClass).
- *
- * <p>
- * This method differs from {@link #getStreamChild(Class)}, that is less strict for interfaces representing
- * augmentation and cases, that may return {@link BindingCodecTreeNode} even if augmentation interface containing
- * same data was supplied and does not represent augmentation of this node.
- *
- * @param childClass Child class by Binding Stream navigation
- * @return Context of child or {@code null} is supplied class is not applicable in context.
- * @throws NullPointerException if {@code childClass} is {@code null}
- */
- <E extends DataObject> @Nullable CommonDataObjectCodecTreeNode<E> streamChild(@NonNull Class<E> childClass);
-
- default <A extends Augmentation<?>> @Nullable BindingAugmentationCodecTreeNode<A> streamAugmentation(
- final @NonNull Class<A> childClass) {
- final var result = streamChild(childClass);
- if (result instanceof BindingAugmentationCodecTreeNode) {
- return (BindingAugmentationCodecTreeNode<A>) result;
- } else if (result == null) {
- return null;
- } else {
- throw new IllegalArgumentException(
- "Child " + childClass.getName() + " results in non-Augmentation " + result);
- }
- }
-
- default <E extends DataObject> @Nullable BindingDataObjectCodecTreeNode<E> streamDataObject(
- final @NonNull Class<E> childClass) {
- final var result = streamChild(childClass);
- if (result instanceof BindingDataObjectCodecTreeNode) {
- return (BindingDataObjectCodecTreeNode<E>) result;
- } else if (result == null) {
- return null;
- } else {
- throw new IllegalArgumentException(
- "Child " + childClass.getName() + " results in non-DataObject " + result);
- }
- }
-
- /**
- * Returns nested node context using supplied YANG Instance Identifier.
- *
- * @param child
- * Yang Instance Identifier Argument
- * @return Context of child
- * @throws IllegalArgumentException
- * If supplied argument does not represent valid child.
- */
- @NonNull BindingCodecTreeNode yangPathArgumentChild(YangInstanceIdentifier.@NonNull PathArgument child);
-
- /**
- * Returns nested node context using supplied Binding Instance Identifier and adds YANG instance identifiers to
- * the supplied list.
- *
- * @param arg
- * Binding Instance Identifier Argument
- * @param builder
- * Mutable instance of list, which is appended by YangInstanceIdentifiers
- * as tree is walked. Use null if such side-product is not needed.
- * @return Context of child
- * @throws IllegalArgumentException
- * If supplied argument does not represent valid child.
- */
- @NonNull CommonDataObjectCodecTreeNode<?> bindingPathArgumentChild(InstanceIdentifier.@NonNull PathArgument arg,
- @Nullable List<YangInstanceIdentifier.PathArgument> builder);
-
+public interface CommonDataObjectCodecTreeNode<T extends DataObject> extends BindingDataContainerCodecTreeNode<T> {
/**
* Serializes path argument for current node.
*
- * @param arg Binding Path Argument, may be null if Binding Instance Identifier does not have
- * representation for current node (e.g. choice or case).
- * @return Yang Path Argument, may be null if Yang Instance Identifier does not have
- * representation for current node (e.g. case).
+ * @param arg Binding Path Argument, may be null if Binding Instance Identifier does not have a representation for
+ * current node (e.g. choice or case).
+ * @return Yang Path Argument, may be null if Yang Instance Identifier does not have representation for current node
+ * (e.g. case).
* @throws IllegalArgumentException If supplied {@code arg} is not valid.
*/
@Beta
@Beta
InstanceIdentifier.@Nullable PathArgument deserializePathArgument(
YangInstanceIdentifier.@Nullable PathArgument arg);
-
- /**
- * Return a summary of addressability of potential children. Binding specification does not allow all DOM tree
- * elements to be directly addressed, which means some recursive tree operations, like data tree changes do not
- * have a one-to-one mapping from DOM to binding in all cases. This method provides an optimization hint to guide
- * translation of data structures, allowing for fast paths when all children are known to either be addressable
- * or non-addressable.
- *
- * @return Summary children addressability.
- */
- @NonNull ChildAddressabilitySummary getChildAddressabilitySummary();
-
- /**
- * Enumeration of possible addressability attribute of all children.
- */
- enum ChildAddressabilitySummary {
- /**
- * All children are addressable.
- */
- ADDRESSABLE,
- /**
- * All children are non-addressable, including the case when this node does not have any children.
- */
- UNADDRESSABLE,
- /**
- * Mixed children, some are addressable and some are not.
- */
- MIXED
- }
}
* 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 DataContainerCodecContext<D, T>
+ extends CommonDataObjectCodecContext<D, T>
permits AugmentationCodecContext, DataObjectCodecContext {
- private final ImmutableMap<Class<?>, DataContainerCodecPrototype<?>> byBindingArgClass;
- private final ImmutableMap<Class<?>, DataContainerCodecPrototype<?>> byStreamClass;
+ private final ImmutableMap<Class<?>, CommonDataObjectCodecPrototype<?>> byBindingArgClass;
+ private final ImmutableMap<Class<?>, CommonDataObjectCodecPrototype<?>> byStreamClass;
private final ImmutableMap<NodeIdentifier, CodecContextSupplier> byYang;
private final ImmutableMap<String, ValueNodeCodecContext> leafChild;
private final MethodHandle proxyConstructor;
- AbstractDataObjectCodecContext(final DataContainerCodecPrototype<T> prototype,
+ AbstractDataObjectCodecContext(final CommonDataObjectCodecPrototype<T> prototype,
final CodecDataObjectAnalysis<T> analysis) {
super(prototype);
byBindingArgClass = analysis.byBindingArgClass;
}
@Override
- public final <C extends DataObject> DataContainerCodecContext<C, ?> getStreamChild(final Class<C> childClass) {
+ public final <C extends DataObject> CommonDataObjectCodecContext<C, ?> getStreamChild(final Class<C> childClass) {
return childNonNull(streamChild(childClass), childClass,
"Child %s is not valid child of %s", getBindingClass(), childClass);
}
@SuppressWarnings("unchecked")
@Override
- public final <C extends DataObject> DataContainerCodecContext<C, ?> streamChild(final Class<C> childClass) {
+ public final <C extends DataObject> CommonDataObjectCodecContext<C, ?> streamChild(final Class<C> childClass) {
final var childProto = streamChildPrototype(childClass);
- return childProto == null ? null : (DataContainerCodecContext<C, ?>) childProto.get();
+ return childProto == null ? null : (CommonDataObjectCodecContext<C, ?>) childProto.get();
}
- @Nullable DataContainerCodecPrototype<?> streamChildPrototype(final @NonNull Class<?> childClass) {
+ @Nullable CommonDataObjectCodecPrototype<?> streamChildPrototype(final @NonNull Class<?> childClass) {
return byStreamClass.get(childClass);
}
@Override
- public final DataContainerCodecContext<?, ?> bindingPathArgumentChild(final InstanceIdentifier.PathArgument arg,
+ public final CommonDataObjectCodecContext<?, ?> bindingPathArgumentChild(final InstanceIdentifier.PathArgument arg,
final List<PathArgument> builder) {
final var argType = arg.getType();
final var context = childNonNull(pathChildPrototype(argType), argType,
return context;
}
- @Nullable DataContainerCodecPrototype<?> pathChildPrototype(final @NonNull Class<? extends DataObject> argType) {
+ @Nullable CommonDataObjectCodecPrototype<?> pathChildPrototype(final @NonNull Class<? extends DataObject> argType) {
return byBindingArgClass.get(argType);
}
import org.opendaylight.yangtools.yang.common.QNameModule;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
-final class AugmentationCodecPrototype extends DataContainerCodecPrototype<AugmentRuntimeType> {
+final class AugmentationCodecPrototype extends CommonDataObjectCodecPrototype<AugmentRuntimeType> {
private final @NonNull ImmutableSet<NodeIdentifier> childArgs;
@SuppressWarnings("unchecked")
BYTECODE_DIRECTORY = Strings.isNullOrEmpty(dir) ? null : new File(dir);
}
- private final LoadingCache<Class<?>, DataContainerStreamer<?>> streamers = CacheBuilder.newBuilder().build(
- new CacheLoader<>() {
+ private final LoadingCache<Class<?>, DataContainerStreamer<?>> streamers = CacheBuilder.newBuilder()
+ .build(new CacheLoader<>() {
@Override
public DataContainerStreamer<?> load(final Class<?> key) throws ReflectiveOperationException {
final var streamer = DataContainerStreamerGenerator.generateStreamer(loader, BindingCodecContext.this,
return (DataContainerStreamer<?>) instance.get(null);
}
});
- private final LoadingCache<Class<?>, DataContainerSerializer> serializers = CacheBuilder.newBuilder().build(
- new CacheLoader<>() {
+ private final LoadingCache<Class<?>, DataContainerSerializer> serializers = CacheBuilder.newBuilder()
+ .build(new CacheLoader<>() {
@Override
public DataContainerSerializer load(final Class<?> key) throws ExecutionException {
return new DataContainerSerializer(BindingCodecContext.this, streamers.get(key));
final List<YangInstanceIdentifier.PathArgument> builder) {
DataContainerCodecContext<?, ?> current = root;
for (var bindingArg : binding.getPathArguments()) {
- final var next = current.bindingPathArgumentChild(bindingArg, builder);
- if (next == null) {
- throw new IllegalArgumentException("%s is not valid: parent %s does not have a child %s".formatted(
- binding, current.bindingArg(), bindingArg));
- }
- current = next;
+ current = current.bindingPathArgumentChild(bindingArg, builder);
}
return current;
}
// We do not add path argument for choice, since
// it is not supported by binding instance identifier.
currentNode = nextNode;
- } else if (nextNode instanceof DataContainerCodecContext<?, ?> containerNode) {
+ } else if (nextNode instanceof CommonDataObjectCodecContext<?, ?> containerNode) {
if (bindingArguments != null) {
bindingArguments.add(containerNode.getBindingPathArgument(domArg));
}
* ambiguous reference and issue warn once when they are encountered -- tracking warning information in
* {@link #ambiguousByCaseChildWarnings}.
*/
-final class ChoiceCodecContext<D extends DataObject> extends DataContainerCodecContext<D, ChoiceRuntimeType>
+final class ChoiceCodecContext<D extends DataObject> extends CommonDataObjectCodecContext<D, ChoiceRuntimeType>
implements BindingDataObjectCodecTreeNode<D> {
private static final Logger LOG = LoggerFactory.getLogger(ChoiceCodecContext.class);
- private final ImmutableListMultimap<Class<?>, DataContainerCodecPrototype<?>> ambiguousByCaseChildClass;
- private final ImmutableMap<Class<?>, DataContainerCodecPrototype<?>> byCaseChildClass;
+ private final ImmutableListMultimap<Class<?>, CommonDataObjectCodecPrototype<?>> ambiguousByCaseChildClass;
+ private final ImmutableMap<Class<?>, CommonDataObjectCodecPrototype<?>> byCaseChildClass;
private final ImmutableMap<NodeIdentifier, CaseCodecPrototype> byYangCaseChild;
- private final ImmutableMap<Class<?>, DataContainerCodecPrototype<?>> byClass;
+ private final ImmutableMap<Class<?>, CommonDataObjectCodecPrototype<?>> byClass;
private final Set<Class<?>> ambiguousByCaseChildWarnings;
ChoiceCodecContext(final Class<D> cls, final ChoiceRuntimeType type, final CodecContextFactory factory) {
ChoiceCodecContext(final ChoiceCodecPrototype prototype) {
super(prototype);
final var byYangCaseChildBuilder = new HashMap<NodeIdentifier, CaseCodecPrototype>();
- final var byClassBuilder = new HashMap<Class<?>, DataContainerCodecPrototype<?>>();
+ final var byClassBuilder = new HashMap<Class<?>, CommonDataObjectCodecPrototype<?>>();
final var childToCase = SetMultimapBuilder.hashKeys().hashSetValues()
- .<Class<?>, DataContainerCodecPrototype<?>>build();
+ .<Class<?>, CommonDataObjectCodecPrototype<?>>build();
// Load case statements valid in this choice and keep track of their names
final var choiceType = prototype.getType();
byYangCaseChild = ImmutableMap.copyOf(byYangCaseChildBuilder);
// Move unambiguous child->case mappings to byCaseChildClass, removing them from childToCase
- final var ambiguousByCaseBuilder = ImmutableListMultimap.<Class<?>, DataContainerCodecPrototype<?>>builder();
- final var unambiguousByCaseBuilder = ImmutableMap.<Class<?>, DataContainerCodecPrototype<?>>builder();
+ final var ambiguousByCaseBuilder = ImmutableListMultimap.<Class<?>, CommonDataObjectCodecPrototype<?>>builder();
+ final var unambiguousByCaseBuilder = ImmutableMap.<Class<?>, CommonDataObjectCodecPrototype<?>>builder();
for (var entry : Multimaps.asMap(childToCase).entrySet()) {
final var cases = entry.getValue();
if (cases.size() != 1) {
* This is required due property of binding specification, that if choice is in grouping schema path location is
* lost, and users may use incorrect case class using copy builders.
*/
- final var bySubstitutionBuilder = new HashMap<Class<?>, DataContainerCodecPrototype<?>>();
+ final var bySubstitutionBuilder = new HashMap<Class<?>, CommonDataObjectCodecPrototype<?>>();
final var context = factory.getRuntimeContext();
for (var caseType : context.getTypes().allCaseChildren(choiceType)) {
final var caseName = caseType.getIdentifier();
}
@Override
- public <C extends DataObject> DataContainerCodecContext<C, ?> getStreamChild(final Class<C> childClass) {
+ public <C extends DataObject> CommonDataObjectCodecContext<C, ?> getStreamChild(final Class<C> childClass) {
return childNonNull(streamChild(childClass), childClass,
"Supplied class %s is not valid case in %s", childClass, bindingArg());
}
@SuppressWarnings("unchecked")
@Override
- public <C extends DataObject> DataContainerCodecContext<C, ?> streamChild(final Class<C> childClass) {
+ public <C extends DataObject> CommonDataObjectCodecContext<C, ?> streamChild(final Class<C> childClass) {
final var child = byClass.get(childClass);
- return child == null ? null : (DataContainerCodecContext<C, ?>) child.get();
+ return child == null ? null : (CommonDataObjectCodecContext<C, ?>) child.get();
}
Iterable<Class<?>> getCaseChildrenClasses() {
@Override
public CodecContext yangPathArgumentChild(final YangInstanceIdentifier.PathArgument arg) {
- final DataContainerCodecPrototype<?> cazeProto;
+ final CommonDataObjectCodecPrototype<?> cazeProto;
if (arg instanceof NodeIdentifierWithPredicates) {
cazeProto = byYangCaseChild.get(new NodeIdentifier(arg.getNodeType()));
} else {
not guaranteed to be stable and is subject to variations based on runtime circumstances. \
Please see the stack trace for hints about the source of ambiguity.""",
type, bindingArg(), result.getBindingClass(),
- Lists.transform(inexact, DataContainerCodecPrototype::getBindingClass), new Throwable());
+ Lists.transform(inexact, CommonDataObjectCodecPrototype::getBindingClass), new Throwable());
}
}
}
private static final MethodType DATAOBJECT_TYPE = MethodType.methodType(DataObject.class,
AbstractDataObjectCodecContext.class, DataContainerNode.class);
- final @NonNull ImmutableMap<Class<?>, DataContainerCodecPrototype<?>> byStreamClass;
- final @NonNull ImmutableMap<Class<?>, DataContainerCodecPrototype<?>> byBindingArgClass;
+ final @NonNull ImmutableMap<Class<?>, CommonDataObjectCodecPrototype<?>> byStreamClass;
+ final @NonNull ImmutableMap<Class<?>, CommonDataObjectCodecPrototype<?>> byBindingArgClass;
final @NonNull ImmutableMap<NodeIdentifier, CodecContextSupplier> byYang;
final @NonNull ImmutableMap<String, ValueNodeCodecContext> leafNodes;
final @NonNull Class<? extends CodecDataObject<?>> generatedClass;
final @NonNull List<AugmentRuntimeType> possibleAugmentations;
final @NonNull MethodHandle proxyConstructor;
- CodecDataObjectAnalysis(final DataContainerCodecPrototype<R> prototype, final CodecItemFactory itemFactory,
+ CodecDataObjectAnalysis(final CommonDataObjectCodecPrototype<R> prototype, final CodecItemFactory itemFactory,
final Method keyMethod) {
// Preliminaries from prototype
@SuppressWarnings("unchecked")
}
leafNodes = leafBuilder.build();
- final var byBindingArgClassBuilder = new HashMap<Class<?>, DataContainerCodecPrototype<?>>();
- final var byStreamClassBuilder = new HashMap<Class<?>, DataContainerCodecPrototype<?>>();
+ final var byBindingArgClassBuilder = new HashMap<Class<?>, CommonDataObjectCodecPrototype<?>>();
+ final var byStreamClassBuilder = new HashMap<Class<?>, CommonDataObjectCodecPrototype<?>>();
final var daoProperties = new HashMap<Class<?>, PropertyInfo>();
for (var childDataObj : clsToMethod.entrySet()) {
final var method = childDataObj.getValue();
proxyConstructor = ctor.asType(DATAOBJECT_TYPE);
}
- private static @NonNull DataContainerCodecPrototype<?> getChildPrototype(final CompositeRuntimeType type,
+ private static @NonNull CommonDataObjectCodecPrototype<?> getChildPrototype(final CompositeRuntimeType type,
final CodecContextFactory factory, final CodecItemFactory itemFactory,
final Class<? extends DataContainer> childClass) {
final var child = type.bindingChild(JavaTypeName.create(childClass));
--- /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.api.CommonDataObjectCodecTreeNode;
+import org.opendaylight.mdsal.binding.runtime.api.RuntimeTypeContainer;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument;
+import org.opendaylight.yangtools.yang.common.QNameModule;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
+
+/**
+ * Base implementation of {@link CommonDataObjectCodecTreeNode}.
+ */
+abstract sealed class CommonDataObjectCodecContext<D extends DataObject, T extends RuntimeTypeContainer>
+ extends DataContainerCodecContext<D, T> implements CommonDataObjectCodecTreeNode<D>
+ permits AbstractDataObjectCodecContext, ChoiceCodecContext {
+ final @NonNull CommonDataObjectCodecPrototype<T> prototype;
+
+ CommonDataObjectCodecContext(final CommonDataObjectCodecPrototype<T> prototype) {
+ super(prototype.getType());
+ this.prototype = requireNonNull(prototype);
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public final Class<D> getBindingClass() {
+ return Class.class.cast(prototype.getBindingClass());
+ }
+
+ @Override
+ protected final CodecContextFactory factory() {
+ return prototype.getFactory();
+ }
+
+ @Override
+ protected final T type() {
+ return prototype.getType();
+ }
+
+ @Override
+ protected NodeIdentifier getDomPathArgument() {
+ return prototype.getYangArg();
+ }
+
+ /**
+ * Returns deserialized Binding Path Argument from YANG instance identifier.
+ */
+ protected PathArgument getBindingPathArgument(final YangInstanceIdentifier.PathArgument domArg) {
+ return bindingArg();
+ }
+
+ protected final PathArgument bindingArg() {
+ return prototype.getBindingArg();
+ }
+
+ protected final QNameModule namespace() {
+ return prototype.getNamespace();
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. 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 java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
+import org.eclipse.jdt.annotation.NonNull;
+import org.opendaylight.mdsal.binding.runtime.api.RuntimeTypeContainer;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.Item;
+import org.opendaylight.yangtools.yang.common.QNameModule;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
+
+abstract sealed class CommonDataObjectCodecPrototype<T extends RuntimeTypeContainer> implements CodecContextSupplier
+ permits AugmentationCodecPrototype, DataObjectCodecPrototype {
+ private static final VarHandle INSTANCE;
+
+ static {
+ try {
+ INSTANCE = MethodHandles.lookup().findVarHandle(CommonDataObjectCodecPrototype.class,
+ "instance", CommonDataObjectCodecContext.class);
+ } catch (NoSuchFieldException | IllegalAccessException e) {
+ throw new ExceptionInInitializerError(e);
+ }
+ }
+
+ private final @NonNull T type;
+ private final @NonNull QNameModule namespace;
+ private final @NonNull CodecContextFactory factory;
+ private final @NonNull Item<?> bindingArg;
+
+ // multiple paths represent augmentation wrapper
+ // FIXME: this means it is either this or 'childArgs'
+
+ // Accessed via INSTANCE
+ @SuppressWarnings("unused")
+ private volatile CommonDataObjectCodecContext<?, T> instance;
+
+ CommonDataObjectCodecPrototype(final Item<?> bindingArg, final QNameModule namespace, final T type,
+ final CodecContextFactory factory) {
+ this.bindingArg = requireNonNull(bindingArg);
+ this.namespace = requireNonNull(namespace);
+ this.type = requireNonNull(type);
+ this.factory = requireNonNull(factory);
+ }
+
+ final @NonNull T getType() {
+ return type;
+ }
+
+ final @NonNull QNameModule getNamespace() {
+ return namespace;
+ }
+
+ final @NonNull CodecContextFactory getFactory() {
+ return factory;
+ }
+
+ final @NonNull Class<?> getBindingClass() {
+ return bindingArg.getType();
+ }
+
+ final @NonNull Item<?> getBindingArg() {
+ return bindingArg;
+ }
+
+ abstract @NonNull NodeIdentifier getYangArg();
+
+ @Override
+ public final CommonDataObjectCodecContext<?, T> get() {
+ final var existing = (CommonDataObjectCodecContext<?, T>) INSTANCE.getAcquire(this);
+ return existing != null ? existing : loadInstance();
+ }
+
+ private @NonNull CommonDataObjectCodecContext<?, T> loadInstance() {
+ final var tmp = createInstance();
+ final var witness = (CommonDataObjectCodecContext<?, T>) INSTANCE.compareAndExchangeRelease(this, null, tmp);
+ return witness == null ? tmp : witness;
+ }
+
+ // This method must allow concurrent loading, i.e. nothing in it may have effects outside of the loaded object
+ abstract @NonNull CommonDataObjectCodecContext<?, T> createInstance();
+}
import java.util.Set;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;
+import org.opendaylight.mdsal.binding.dom.codec.api.BindingDataContainerCodecTreeNode;
import org.opendaylight.mdsal.binding.dom.codec.api.BindingNormalizedNodeCachingCodec;
import org.opendaylight.mdsal.binding.dom.codec.api.BindingNormalizedNodeCodec;
import org.opendaylight.mdsal.binding.dom.codec.api.BindingStreamEventWriter;
-import org.opendaylight.mdsal.binding.dom.codec.api.CommonDataObjectCodecTreeNode;
import org.opendaylight.mdsal.binding.dom.codec.api.IncorrectNestingException;
import org.opendaylight.mdsal.binding.dom.codec.api.MissingClassInLoadingStrategyException;
import org.opendaylight.mdsal.binding.dom.codec.api.MissingSchemaException;
import org.opendaylight.mdsal.binding.model.api.Type;
import org.opendaylight.mdsal.binding.runtime.api.BindingRuntimeContext;
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.util.ClassLoaderUtils;
import org.opendaylight.yangtools.yang.binding.Augmentable;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.common.QNameModule;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNormalizedNodeStreamWriter;
import org.opendaylight.yangtools.yang.data.impl.schema.NormalizationResultHolder;
+import org.opendaylight.yangtools.yang.model.api.AnydataSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.AnyxmlSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.AugmentationSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.CaseSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.ChoiceSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.TypedDataSchemaNode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-abstract sealed class DataContainerCodecContext<D extends DataObject, T extends RuntimeTypeContainer>
- extends CodecContext implements CommonDataObjectCodecTreeNode<D>
- permits AbstractDataObjectCodecContext, ChoiceCodecContext, RootCodecContext {
+abstract sealed class DataContainerCodecContext<D extends BindingObject & DataContainer, T extends RuntimeTypeContainer>
+ extends CodecContext implements BindingDataContainerCodecTreeNode<D>
+ permits CommonDataObjectCodecContext, RootCodecContext {
private static final Logger LOG = LoggerFactory.getLogger(DataContainerCodecContext.class);
private static final VarHandle EVENT_STREAM_SERIALIZER;
}
}
- final @NonNull DataContainerCodecPrototype<T> prototype;
+ private final @NonNull ChildAddressabilitySummary childAddressabilitySummary;
// Accessed via a VarHandle
@SuppressWarnings("unused")
private volatile DataContainerSerializer eventStreamSerializer;
- DataContainerCodecContext(final DataContainerCodecPrototype<T> prototype) {
- this.prototype = requireNonNull(prototype);
+ DataContainerCodecContext(final T type) {
+ childAddressabilitySummary = type instanceof RuntimeType runtimeType
+ ? computeChildAddressabilitySummary(runtimeType.statement())
+ // BindingRuntimeTypes, does not matter
+ : ChildAddressabilitySummary.MIXED;
}
@Override
public final ChildAddressabilitySummary getChildAddressabilitySummary() {
- return prototype.getChildAddressabilitySummary();
+ return childAddressabilitySummary;
}
- protected final QNameModule namespace() {
- return prototype.getNamespace();
- }
-
- protected final CodecContextFactory factory() {
- return prototype.getFactory();
- }
-
- protected final @NonNull T type() {
- return prototype.getType();
- }
+ protected abstract @NonNull CodecContextFactory factory();
- @Override
- protected NodeIdentifier getDomPathArgument() {
- return prototype.getYangArg();
- }
+ protected abstract @NonNull T type();
/**
* Returns nested node context using supplied YANG Instance Identifier.
* @throws IllegalArgumentException If supplied argument does not represent valid child.
*/
@Override
- public DataContainerCodecContext<?, ?> bindingPathArgumentChild(final PathArgument arg,
+ public CommonDataObjectCodecContext<?, ?> bindingPathArgumentChild(final PathArgument arg,
final List<YangInstanceIdentifier.PathArgument> builder) {
final var child = getStreamChild(arg.getType());
child.addYangPathArgument(arg, builder);
}
}
- /**
- * Returns deserialized Binding Path Argument from YANG instance identifier.
- */
- protected PathArgument getBindingPathArgument(final YangInstanceIdentifier.PathArgument domArg) {
- return bindingArg();
- }
-
- protected final PathArgument bindingArg() {
- return prototype.getBindingArg();
- }
-
- @SuppressWarnings("unchecked")
- @Override
- public final Class<D> getBindingClass() {
- return Class.class.cast(prototype.getBindingClass());
- }
-
@Override
- public abstract <C extends DataObject> DataContainerCodecContext<C, ?> getStreamChild(Class<C> childClass);
+ public abstract <C extends DataObject> CommonDataObjectCodecContext<C, ?> getStreamChild(Class<C> childClass);
/**
* Returns child context as if it was walked by {@link BindingStreamEventWriter}. This means that to enter case, one
* @return Context of child or Optional.empty is supplied class is not applicable in context.
*/
@Override
- public abstract <C extends DataObject> DataContainerCodecContext<C, ?> streamChild(Class<C> childClass);
+ public abstract <C extends DataObject> CommonDataObjectCodecContext<C, ?> streamChild(Class<C> childClass);
@Override
public String toString() {
- return getClass().getSimpleName() + " [" + prototype.getBindingClass() + "]";
+ return getClass().getSimpleName() + " [" + getBindingClass() + "]";
}
static final <T extends DataObject, C extends DataContainerCodecContext<T, ?> & BindingNormalizedNodeCodec<T>>
Augmentation.class);
return opt.orElse(null);
}
+
+
+
+ private static @NonNull ChildAddressabilitySummary computeChildAddressabilitySummary(final Object nodeSchema) {
+ // FIXME: rework this to work on EffectiveStatements
+ if (nodeSchema instanceof DataNodeContainer contaner) {
+ boolean haveAddressable = false;
+ boolean haveUnaddressable = false;
+ for (DataSchemaNode child : contaner.getChildNodes()) {
+ if (child instanceof ContainerSchemaNode || child instanceof AugmentationSchemaNode) {
+ haveAddressable = true;
+ } else if (child instanceof ListSchemaNode list) {
+ if (list.getKeyDefinition().isEmpty()) {
+ haveUnaddressable = true;
+ } else {
+ haveAddressable = true;
+ }
+ } else if (child instanceof AnydataSchemaNode || child instanceof AnyxmlSchemaNode
+ || child instanceof TypedDataSchemaNode) {
+ haveUnaddressable = true;
+ } else if (child instanceof ChoiceSchemaNode choice) {
+ switch (computeChildAddressabilitySummary(choice)) {
+ case ADDRESSABLE -> haveAddressable = true;
+ case UNADDRESSABLE -> haveUnaddressable = true;
+ case MIXED -> {
+ haveAddressable = true;
+ haveUnaddressable = true;
+ }
+ default -> throw new IllegalStateException("Unhandled accessibility summary for " + child);
+ }
+ } else {
+ LOG.warn("Unhandled child node {}", child);
+ }
+ }
+
+ if (!haveAddressable) {
+ // Empty or all are unaddressable
+ return ChildAddressabilitySummary.UNADDRESSABLE;
+ }
+
+ return haveUnaddressable ? ChildAddressabilitySummary.MIXED : ChildAddressabilitySummary.ADDRESSABLE;
+ } else if (nodeSchema instanceof ChoiceSchemaNode choice) {
+ return computeChildAddressabilitySummary(choice);
+ }
+
+ // No child nodes possible: return unaddressable
+ return ChildAddressabilitySummary.UNADDRESSABLE;
+ }
+
+ private static @NonNull ChildAddressabilitySummary computeChildAddressabilitySummary(
+ final ChoiceSchemaNode choice) {
+ boolean haveAddressable = false;
+ boolean haveUnaddressable = false;
+ for (CaseSchemaNode child : choice.getCases()) {
+ switch (computeChildAddressabilitySummary(child)) {
+ case ADDRESSABLE:
+ haveAddressable = true;
+ break;
+ case UNADDRESSABLE:
+ haveUnaddressable = true;
+ break;
+ case MIXED:
+ // A child is mixed, which means we are mixed, too
+ return ChildAddressabilitySummary.MIXED;
+ default:
+ throw new IllegalStateException("Unhandled accessibility summary for " + child);
+ }
+ }
+
+ if (!haveAddressable) {
+ // Empty or all are unaddressable
+ return ChildAddressabilitySummary.UNADDRESSABLE;
+ }
+
+ return haveUnaddressable ? ChildAddressabilitySummary.MIXED : ChildAddressabilitySummary.ADDRESSABLE;
+ }
}
+++ /dev/null
-/*
- * Copyright (c) 2014 Cisco Systems, Inc. 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 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.RuntimeType;
-import org.opendaylight.mdsal.binding.runtime.api.RuntimeTypeContainer;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.Item;
-import org.opendaylight.yangtools.yang.common.QNameModule;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
-import org.opendaylight.yangtools.yang.model.api.AnydataSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.AnyxmlSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.AugmentationSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.CaseSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.ChoiceSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
-import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.TypedDataSchemaNode;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-abstract sealed class DataContainerCodecPrototype<T extends RuntimeTypeContainer> implements CodecContextSupplier
- permits AugmentationCodecPrototype, DataObjectCodecPrototype {
- private static final Logger LOG = LoggerFactory.getLogger(DataContainerCodecPrototype.class);
-
- private static final VarHandle INSTANCE;
-
- static {
- try {
- INSTANCE = MethodHandles.lookup().findVarHandle(DataContainerCodecPrototype.class,
- "instance", DataContainerCodecContext.class);
- } catch (NoSuchFieldException | IllegalAccessException e) {
- throw new ExceptionInInitializerError(e);
- }
- }
-
- private final @NonNull T type;
- private final @NonNull QNameModule namespace;
- private final @NonNull CodecContextFactory factory;
- private final @NonNull Item<?> bindingArg;
- private final @NonNull ChildAddressabilitySummary childAddressabilitySummary;
-
- // multiple paths represent augmentation wrapper
- // FIXME: this means it is either this or 'childArgs'
-
- // Accessed via INSTANCE
- @SuppressWarnings("unused")
- private volatile DataContainerCodecContext<?, T> instance;
-
- DataContainerCodecPrototype(final Item<?> bindingArg, final QNameModule namespace, final T type,
- final CodecContextFactory factory) {
- this.bindingArg = requireNonNull(bindingArg);
- this.namespace = requireNonNull(namespace);
- this.type = requireNonNull(type);
- this.factory = requireNonNull(factory);
-
- childAddressabilitySummary = type instanceof RuntimeType runtimeType
- ? computeChildAddressabilitySummary(runtimeType.statement())
- // BindingRuntimeTypes, does not matter
- : ChildAddressabilitySummary.MIXED;
- }
-
- private static @NonNull ChildAddressabilitySummary computeChildAddressabilitySummary(final Object nodeSchema) {
- // FIXME: rework this to work on EffectiveStatements
- if (nodeSchema instanceof DataNodeContainer contaner) {
- boolean haveAddressable = false;
- boolean haveUnaddressable = false;
- for (DataSchemaNode child : contaner.getChildNodes()) {
- if (child instanceof ContainerSchemaNode || child instanceof AugmentationSchemaNode) {
- haveAddressable = true;
- } else if (child instanceof ListSchemaNode list) {
- if (list.getKeyDefinition().isEmpty()) {
- haveUnaddressable = true;
- } else {
- haveAddressable = true;
- }
- } else if (child instanceof AnydataSchemaNode || child instanceof AnyxmlSchemaNode
- || child instanceof TypedDataSchemaNode) {
- haveUnaddressable = true;
- } else if (child instanceof ChoiceSchemaNode choice) {
- switch (computeChildAddressabilitySummary(choice)) {
- case ADDRESSABLE -> haveAddressable = true;
- case UNADDRESSABLE -> haveUnaddressable = true;
- case MIXED -> {
- haveAddressable = true;
- haveUnaddressable = true;
- }
- default -> throw new IllegalStateException("Unhandled accessibility summary for " + child);
- }
- } else {
- LOG.warn("Unhandled child node {}", child);
- }
- }
-
- if (!haveAddressable) {
- // Empty or all are unaddressable
- return ChildAddressabilitySummary.UNADDRESSABLE;
- }
-
- return haveUnaddressable ? ChildAddressabilitySummary.MIXED : ChildAddressabilitySummary.ADDRESSABLE;
- } else if (nodeSchema instanceof ChoiceSchemaNode choice) {
- return computeChildAddressabilitySummary(choice);
- }
-
- // No child nodes possible: return unaddressable
- return ChildAddressabilitySummary.UNADDRESSABLE;
- }
-
- private static @NonNull ChildAddressabilitySummary computeChildAddressabilitySummary(
- final ChoiceSchemaNode choice) {
- boolean haveAddressable = false;
- boolean haveUnaddressable = false;
- for (CaseSchemaNode child : choice.getCases()) {
- switch (computeChildAddressabilitySummary(child)) {
- case ADDRESSABLE:
- haveAddressable = true;
- break;
- case UNADDRESSABLE:
- haveUnaddressable = true;
- break;
- case MIXED:
- // A child is mixed, which means we are mixed, too
- return ChildAddressabilitySummary.MIXED;
- default:
- throw new IllegalStateException("Unhandled accessibility summary for " + child);
- }
- }
-
- if (!haveAddressable) {
- // Empty or all are unaddressable
- return ChildAddressabilitySummary.UNADDRESSABLE;
- }
-
- return haveUnaddressable ? ChildAddressabilitySummary.MIXED : ChildAddressabilitySummary.ADDRESSABLE;
- }
-
- final @NonNull T getType() {
- return type;
- }
-
- final @NonNull ChildAddressabilitySummary getChildAddressabilitySummary() {
- return childAddressabilitySummary;
- }
-
- final @NonNull QNameModule getNamespace() {
- return namespace;
- }
-
- final @NonNull CodecContextFactory getFactory() {
- return factory;
- }
-
- final @NonNull Class<?> getBindingClass() {
- return bindingArg.getType();
- }
-
- final @NonNull Item<?> getBindingArg() {
- return bindingArg;
- }
-
- abstract @NonNull NodeIdentifier getYangArg();
-
- @Override
- public final DataContainerCodecContext<?, T> get() {
- final var existing = (DataContainerCodecContext<?, T>) INSTANCE.getAcquire(this);
- return existing != null ? existing : loadInstance();
- }
-
- private @NonNull DataContainerCodecContext<?, T> loadInstance() {
- final var tmp = createInstance();
- final var witness = (DataContainerCodecContext<?, T>) INSTANCE.compareAndExchangeRelease(this, null, tmp);
- return witness == null ? tmp : witness;
- }
-
- // This method must allow concurrent loading, i.e. nothing in it may have effects outside of the loaded object
- abstract @NonNull DataContainerCodecContext<?, T> createInstance();
-}
// Note this the content of this field depends only of invariants expressed as this class's fields or
// BindingRuntimeContext. It is only accessed via MISMATCHED_AUGMENTED above.
@SuppressWarnings("unused")
- private volatile ImmutableMap<Class<?>, DataContainerCodecPrototype<?>> mismatchedAugmented = ImmutableMap.of();
+ private volatile ImmutableMap<Class<?>, CommonDataObjectCodecPrototype<?>> mismatchedAugmented = ImmutableMap.of();
- DataObjectCodecContext(final DataContainerCodecPrototype<T> prototype) {
+ DataObjectCodecContext(final CommonDataObjectCodecPrototype<T> prototype) {
this(prototype, CodecItemFactory.of());
}
- DataObjectCodecContext(final DataContainerCodecPrototype<T> prototype, final CodecItemFactory itemFactory) {
+ DataObjectCodecContext(final CommonDataObjectCodecPrototype<T> prototype, final CodecItemFactory itemFactory) {
this(prototype, new CodecDataObjectAnalysis<>(prototype, itemFactory, null));
}
- DataObjectCodecContext(final DataContainerCodecPrototype<T> prototype, final Method keyMethod) {
+ DataObjectCodecContext(final CommonDataObjectCodecPrototype<T> prototype, final Method keyMethod) {
this(prototype, new CodecDataObjectAnalysis<>(prototype, CodecItemFactory.of(), keyMethod));
}
- private DataObjectCodecContext(final DataContainerCodecPrototype<T> prototype,
+ private DataObjectCodecContext(final CommonDataObjectCodecPrototype<T> prototype,
final CodecDataObjectAnalysis<T> analysis) {
super(prototype, analysis);
}
@Override
- final DataContainerCodecPrototype<?> pathChildPrototype(final Class<? extends DataObject> argType) {
+ final CommonDataObjectCodecPrototype<?> pathChildPrototype(final Class<? extends DataObject> argType) {
final var child = super.pathChildPrototype(argType);
return child != null ? child : augmentToPrototype.get(argType);
}
@Override
- final DataContainerCodecPrototype<?> streamChildPrototype(final Class<?> childClass) {
+ final CommonDataObjectCodecPrototype<?> streamChildPrototype(final Class<?> childClass) {
final var child = super.streamChildPrototype(childClass);
if (child == null && Augmentation.class.isAssignableFrom(childClass)) {
return getAugmentationProtoByClass(childClass);
var expected = oldMismatched;
while (true) {
final var newMismatched =
- ImmutableMap.<Class<?>, DataContainerCodecPrototype<?>>builderWithExpectedSize(expected.size() + 1)
+ ImmutableMap.<Class<?>, CommonDataObjectCodecPrototype<?>>builderWithExpectedSize(expected.size() + 1)
.putAll(expected)
.put(childClass, prototype)
.build();
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.Item;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
-abstract sealed class DataObjectCodecPrototype<T extends RuntimeTypeContainer> extends DataContainerCodecPrototype<T>
+abstract sealed class DataObjectCodecPrototype<T extends RuntimeTypeContainer> extends CommonDataObjectCodecPrototype<T>
permits CaseCodecPrototype, ChoiceCodecPrototype, ContainerLikeCodecPrototype, ListCodecPrototype,
- NotificationCodecContext.Prototype, RootCodecContext.Prototype {
+ NotificationCodecContext.Prototype {
private final @NonNull NodeIdentifier yangArg;
// FIXME: this should not be needed
import org.opendaylight.yangtools.yang.binding.ChoiceIn;
import org.opendaylight.yangtools.yang.binding.DataContainer;
import org.opendaylight.yangtools.yang.binding.DataObject;
-import org.opendaylight.yangtools.yang.binding.DataRoot;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.opendaylight.yangtools.yang.binding.KeyedListAction;
import org.opendaylight.yangtools.yang.binding.Notification;
final class RootCodecContext<D extends DataObject> extends DataContainerCodecContext<D, BindingRuntimeTypes>
implements BindingDataObjectCodecTreeNode<D> {
- /**
- * Prototype for the root of YANG modeled world. This class only exists because DataContainerCodecContext requires
- * a prototype.
- */
- static final class Prototype extends DataObjectCodecPrototype<BindingRuntimeTypes> {
- private static final @NonNull NodeIdentifier ROOT_NODEID = NodeIdentifier.create(SchemaContext.NAME);
-
- private Prototype(final CodecContextFactory factory) {
- super(DataRoot.class, ROOT_NODEID, factory.getRuntimeContext().getTypes(), factory);
- }
-
- @Override
- RootCodecContext<?> createInstance() {
- throw new UnsupportedOperationException("Should never be invoked");
- }
- }
-
private final LoadingCache<Class<? extends DataObject>, DataContainerCodecContext<?, ?>> childrenByClass =
CacheBuilder.newBuilder().build(new CacheLoader<>() {
@Override
throw new IllegalArgumentException(key + " does not represent an RPC container");
}
- final CodecContextFactory factory = factory();
final BindingRuntimeContext context = factory.getRuntimeContext();
final QName qname = BindingReflections.findQName(key);
}
});
+ private static final @NonNull NodeIdentifier ROOT_NODEID = NodeIdentifier.create(SchemaContext.NAME);
+
+ private final @NonNull CodecContextFactory factory;
+
RootCodecContext(final CodecContextFactory factory) {
- super(new Prototype(factory));
+ super(factory.getRuntimeContext().getTypes());
+ this.factory = requireNonNull(factory);
}
@Override
public WithStatus getSchema() {
- return type().getEffectiveModelContext();
+ return factory.getRuntimeContext().getEffectiveModelContext();
+ }
+
+ @Override
+ public Class<D> getBindingClass() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ protected NodeIdentifier getDomPathArgument() {
+ // FIXME: this is not right
+ return ROOT_NODEID;
+ }
+
+ @Override
+ protected CodecContextFactory factory() {
+ return factory;
+ }
+
+ @Override
+ protected BindingRuntimeTypes type() {
+ return factory.getRuntimeContext().getTypes();
}
@Override
@SuppressWarnings("unchecked")
- public <C extends DataObject> DataContainerCodecContext<C, ?> getStreamChild(final Class<C> childClass) {
+ public <C extends DataObject> CommonDataObjectCodecContext<C, ?> getStreamChild(final Class<C> childClass) {
final var result = Notification.class.isAssignableFrom(childClass) ? getNotificationImpl(childClass)
: getOrRethrow(childrenByClass, childClass);
- return (DataContainerCodecContext<C, ?>) result;
+ return (CommonDataObjectCodecContext<C, ?>) result;
}
@Override
- public <C extends DataObject> DataContainerCodecContext<C, ?> streamChild(final Class<C> childClass) {
+ public <C extends DataObject> CommonDataObjectCodecContext<C, ?> streamChild(final Class<C> childClass) {
// FIXME: implement this
throw new UnsupportedOperationException("Not supported");
}
}
@Override
- public DataContainerCodecContext<?, ?> bindingPathArgumentChild(final InstanceIdentifier.PathArgument arg,
+ public CommonDataObjectCodecContext<?, ?> bindingPathArgumentChild(final InstanceIdentifier.PathArgument arg,
final List<PathArgument> builder) {
final var caseType = arg.getCaseType();
if (caseType.isPresent()) {