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