import com.google.common.collect.ImmutableCollection;
import com.google.common.collect.ImmutableSet;
import edu.umd.cs.findbugs.annotations.CheckReturnValue;
+import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import java.io.IOException;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.VarHandle;
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.PathArgument;
+import org.opendaylight.yangtools.yang.binding.DataObjectStep;
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.YangInstanceIdentifier.NodeIdentifierWithPredicates;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
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.slf4j.Logger;
import org.slf4j.LoggerFactory;
-abstract sealed class DataContainerCodecContext<D extends BindingObject & DataContainer, T extends CompositeRuntimeType>
+abstract sealed class DataContainerCodecContext<D extends DataContainer, R extends CompositeRuntimeType,
+ P extends DataContainerPrototype<?, R>>
extends CodecContext implements BindingDataContainerCodecTreeNode<D>
- permits CommonDataObjectCodecContext {
+ permits ChoiceCodecContext, CommonDataObjectCodecContext {
private static final Logger LOG = LoggerFactory.getLogger(DataContainerCodecContext.class);
private static final VarHandle EVENT_STREAM_SERIALIZER;
}
}
+ private final @NonNull P prototype;
private final @NonNull ChildAddressabilitySummary childAddressabilitySummary;
// Accessed via a VarHandle
@SuppressWarnings("unused")
+ @SuppressFBWarnings(value = "UUF_UNUSED_FIELD", justification = "https://github.com/spotbugs/spotbugs/issues/2749")
private volatile DataContainerSerializer eventStreamSerializer;
- DataContainerCodecContext(final T type) {
- childAddressabilitySummary = computeChildAddressabilitySummary(type.statement());
+ DataContainerCodecContext(final P prototype) {
+ this.prototype = requireNonNull(prototype);
+ childAddressabilitySummary = computeChildAddressabilitySummary(prototype.runtimeType().statement());
}
- @Override
- public final ChildAddressabilitySummary getChildAddressabilitySummary() {
- return childAddressabilitySummary;
+ final @NonNull P prototype() {
+ return prototype;
}
- protected abstract @NonNull CodecContextFactory factory();
+ @Override
+ @SuppressWarnings("unchecked")
+ public final Class<D> getBindingClass() {
+ return (Class<D>) prototype().javaClass();
+ }
- protected abstract @NonNull T type();
+ // overridden in AugmentationCodecContext
+ @Override
+ protected NodeIdentifier getDomPathArgument() {
+ return prototype.yangArg();
+ }
@Override
- public abstract CodecContext yangPathArgumentChild(YangInstanceIdentifier.PathArgument arg);
+ public final ChildAddressabilitySummary getChildAddressabilitySummary() {
+ return childAddressabilitySummary;
+ }
+ // Non-final for ChoiceCodecContext
@Override
- public CommonDataObjectCodecContext<?, ?> bindingPathArgumentChild(final PathArgument arg,
- final List<YangInstanceIdentifier.PathArgument> builder) {
- final var child = getStreamChild(arg.getType());
- child.addYangPathArgument(arg, builder);
- return child;
+ public CodecContext yangPathArgumentChild(final PathArgument arg) {
+ CodecContextSupplier supplier;
+ if (arg instanceof NodeIdentifier nodeId) {
+ supplier = yangChildSupplier(nodeId);
+ } else if (arg instanceof NodeIdentifierWithPredicates nip) {
+ supplier = yangChildSupplier(new NodeIdentifier(nip.getNodeType()));
+ } else {
+ supplier = null;
+ }
+ return childNonNull(supplier, arg, "Argument %s is not valid child of %s", arg, getSchema()).getCodecContext();
}
+ abstract @Nullable CodecContextSupplier yangChildSupplier(@NonNull NodeIdentifier arg);
+
+ @Override
+ public abstract CommonDataObjectCodecContext<?, ?> bindingPathArgumentChild(DataObjectStep<?> step,
+ List<PathArgument> builder);
+
/**
* Serializes supplied Binding Path Argument and adds all necessary YANG instance identifiers to supplied list.
*
- * @param arg Binding Path Argument
+ * @param step Binding Path Argument
* @param builder DOM Path argument.
*/
- final void addYangPathArgument(final PathArgument arg, final List<YangInstanceIdentifier.PathArgument> builder) {
+ final void addYangPathArgument(final DataObjectStep<?> step, final List<PathArgument> builder) {
if (builder != null) {
- addYangPathArgument(builder, arg);
+ addYangPathArgument(builder, step);
}
}
- void addYangPathArgument(final @NonNull List<YangInstanceIdentifier.PathArgument> builder, final PathArgument arg) {
+ void addYangPathArgument(final @NonNull List<PathArgument> builder, final DataObjectStep<?> step) {
final var yangArg = getDomPathArgument();
if (yangArg != null) {
builder.add(yangArg);
}
@Override
- public final <C extends DataObject> CommonDataObjectCodecContext<C, ?> getStreamChild(final Class<C> childClass) {
+ public final <C extends DataObject> DataContainerCodecContext<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> CommonDataObjectCodecContext<C, ?> streamChild(final Class<C> childClass) {
+ public final <C extends DataObject> DataContainerCodecContext<C, ?, ?> streamChild(final Class<C> childClass) {
final var childProto = streamChildPrototype(requireNonNull(childClass));
- return childProto == null ? null : (CommonDataObjectCodecContext<C, ?>) childProto.get();
+ return childProto == null ? null : (DataContainerCodecContext<C, ?, ?>) childProto.getCodecContext();
}
- abstract @Nullable CommonDataObjectCodecPrototype<?> streamChildPrototype(@NonNull Class<?> childClass);
+ abstract @Nullable DataContainerPrototype<?, ?> streamChildPrototype(@NonNull Class<?> childClass);
@Override
public String toString() {
return getClass().getSimpleName() + " [" + getBindingClass() + "]";
}
- static final <T extends DataObject, C extends DataContainerCodecContext<T, ?> & BindingNormalizedNodeCodec<T>>
+ static final <T extends DataObject, C extends DataContainerCodecContext<T, ?, ?> & BindingNormalizedNodeCodec<T>>
@NonNull BindingNormalizedNodeCachingCodec<T> createCachingCodec(final C context,
final ImmutableCollection<Class<? extends BindingObject>> cacheSpecifier) {
return cacheSpecifier.isEmpty() ? new NonCachingCodec<>(context)
: new CachingNormalizedNodeCodec<>(context, ImmutableSet.copyOf(cacheSpecifier));
}
- protected final <V> @NonNull V childNonNull(final @Nullable V nullable,
- final YangInstanceIdentifier.PathArgument child, final String message, final Object... args) {
+ protected final <V> @NonNull V childNonNull(final @Nullable V nullable, final PathArgument child,
+ final String message, final Object... args) {
if (nullable == null) {
throw childNullException(child.getNodeType(), message, args);
}
@CheckReturnValue
private IllegalArgumentException childNullException(final QName child, final String message, final Object... args) {
- final QNameModule module = child.getModule();
- if (!factory().getRuntimeContext().getEffectiveModelContext().findModule(module).isPresent()) {
+ final var module = child.getModule();
+ if (!prototype().contextFactory().getRuntimeContext().modelContext().findModule(module).isPresent()) {
return new MissingSchemaException("Module " + module + " is not present in current schema context.");
}
return new IncorrectNestingException(message, args);
@CheckReturnValue
private @NonNull IllegalArgumentException childNullException(final Class<?> childClass, final String message,
final Object... args) {
- return childNullException(factory().getRuntimeContext(), childClass, message, args);
+ return childNullException(prototype().contextFactory().getRuntimeContext(), childClass, message, args);
}
@CheckReturnValue
// Split out to aid inlining
private DataContainerSerializer loadEventStreamSerializer() {
- final DataContainerSerializer loaded = factory().getEventStreamSerializer(getBindingClass());
+ final DataContainerSerializer loaded = prototype().contextFactory().getEventStreamSerializer(getBindingClass());
final Object witness = EVENT_STREAM_SERIALIZER.compareAndExchangeRelease(this, null, loaded);
return witness == null ? loaded : (DataContainerSerializer) witness;
}