*/
package org.opendaylight.mdsal.binding.dom.codec.impl;
-import com.google.common.base.Throwables;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
-import java.lang.invoke.MethodHandle;
import java.util.List;
import java.util.Map;
import org.eclipse.jdt.annotation.NonNull;
import org.opendaylight.mdsal.binding.runtime.api.CompositeRuntimeType;
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.binding.DataObjectStep;
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.DataContainerNode;
import org.opendaylight.yangtools.yang.model.api.DocumentedNode.WithStatus;
public abstract sealed class AbstractDataObjectCodecContext<D extends DataObject, T extends CompositeRuntimeType>
extends CommonDataObjectCodecContext<D, T>
permits AugmentationCodecContext, DataObjectCodecContext {
- private final ImmutableMap<Class<?>, CommonDataObjectCodecPrototype<?>> byBindingArgClass;
- private final ImmutableMap<Class<?>, CommonDataObjectCodecPrototype<?>> byStreamClass;
+ private final ImmutableMap<Class<?>, DataContainerPrototype<?, ?>> byBindingArgClass;
+ private final ImmutableMap<Class<?>, DataContainerPrototype<?, ?>> byStreamClass;
private final ImmutableMap<NodeIdentifier, CodecContextSupplier> byYang;
private final ImmutableMap<String, ValueNodeCodecContext> leafChild;
- private final MethodHandle proxyConstructor;
AbstractDataObjectCodecContext(final CommonDataObjectCodecPrototype<T> prototype,
- final CodecDataObjectAnalysis<T> analysis) {
+ final DataContainerAnalysis<T> analysis) {
super(prototype);
byBindingArgClass = analysis.byBindingArgClass;
byStreamClass = analysis.byStreamClass;
byYang = analysis.byYang;
leafChild = analysis.leafNodes;
- proxyConstructor = analysis.proxyConstructor;
}
@Override
public final WithStatus getSchema() {
// FIXME: Bad cast, we should be returning an EffectiveStatement perhaps?
- return (WithStatus) type().statement();
+ return (WithStatus) prototype().runtimeType().statement();
}
@Override
- 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> CommonDataObjectCodecContext<C, ?> streamChild(final Class<C> childClass) {
- final var childProto = streamChildPrototype(childClass);
- return childProto == null ? null : (CommonDataObjectCodecContext<C, ?>) childProto.get();
- }
-
- @Nullable CommonDataObjectCodecPrototype<?> streamChildPrototype(final @NonNull Class<?> childClass) {
+ DataContainerPrototype<?, ?> streamChildPrototype(final Class<?> childClass) {
return byStreamClass.get(childClass);
}
@Override
- public final CommonDataObjectCodecContext<?, ?> bindingPathArgumentChild(final InstanceIdentifier.PathArgument arg,
+ public final CommonDataObjectCodecContext<?, ?> bindingPathArgumentChild(final DataObjectStep<?> step,
final List<PathArgument> builder) {
- final var argType = arg.getType();
- final var context = childNonNull(pathChildPrototype(argType), argType,
- "Class %s is not valid child of %s", argType, getBindingClass())
- .get();
- if (context instanceof ChoiceCodecContext<?> choice) {
- choice.addYangPathArgument(arg, builder);
-
- final var caseType = arg.getCaseType();
- final var type = arg.getType();
- final DataContainerCodecContext<?, ?> caze;
- if (caseType.isPresent()) {
- // Non-ambiguous addressing this should not pose any problems
- caze = choice.getStreamChild(caseType.orElseThrow());
- } else {
- caze = choice.getCaseByChildClass(type);
- }
-
- caze.addYangPathArgument(arg, builder);
- return caze.bindingPathArgumentChild(arg, 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);
}
- context.addYangPathArgument(arg, builder);
- return context;
}
- @Nullable CommonDataObjectCodecPrototype<?> pathChildPrototype(final @NonNull Class<? extends DataObject> argType) {
+ @Nullable DataContainerPrototype<?, ?> pathChildPrototype(final @NonNull Class<? extends DataObject> argType) {
return byBindingArgClass.get(argType);
}
@Override
- public final 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()).get();
- }
-
- @Nullable CodecContextSupplier yangChildSupplier(final @NonNull NodeIdentifier arg) {
+ CodecContextSupplier yangChildSupplier(final NodeIdentifier arg) {
return byYang.get(arg);
}
- @SuppressWarnings("checkstyle:illegalCatch")
- final @NonNull D createBindingProxy(final DataContainerNode node) {
- try {
- return (D) proxyConstructor.invokeExact(this, node);
- } catch (final Throwable e) {
- Throwables.throwIfUnchecked(e);
- throw new IllegalStateException(e);
- }
- }
-
final ValueNodeCodecContext getLeafChild(final String name) {
final ValueNodeCodecContext value = leafChild.get(name);
if (value == null) {