private Method findRpcMethod(final Class<? extends RpcService> key, final RpcDefinition rpcDef)
throws NoSuchMethodException {
- final String methodName = BindingMapping.getRpcMethodName(rpcDef.getQName());
- final Class<?> inputClz = getRuntimeContext().getClassForSchema(rpcDef.getInput());
- return key.getMethod(methodName, inputClz);
+ final var rpcName = rpcDef.getQName();
+ final var inputClz = getRuntimeContext().getRpcInput(rpcName);
+ return key.getMethod(BindingMapping.getRpcMethodName(rpcName), inputClz);
}
}
module org.opendaylight.mdsal.binding.dom.codec.api {
exports org.opendaylight.mdsal.binding.dom.codec.api;
+ requires transitive org.opendaylight.yangtools.yang.data.api;
requires transitive org.opendaylight.mdsal.binding.runtime.api;
requires org.opendaylight.mdsal.binding.spec.util;
import static java.util.Objects.requireNonNull;
-import org.opendaylight.yangtools.yang.model.api.InputSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.OutputSchemaNode;
+import org.opendaylight.mdsal.binding.runtime.api.InputRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.OutputRuntimeType;
/**
* This is not really a codec context, but rather a holder of input and output codec contexts.
*/
final class ActionCodecContext {
- private final DataContainerCodecContext<?, InputSchemaNode> input;
- private final DataContainerCodecContext<?, OutputSchemaNode> output;
+ private final DataContainerCodecContext<?, InputRuntimeType> input;
+ private final DataContainerCodecContext<?, OutputRuntimeType> output;
- ActionCodecContext(final DataContainerCodecContext<?, InputSchemaNode> input,
- final DataContainerCodecContext<?, OutputSchemaNode> output) {
+ ActionCodecContext(final DataContainerCodecContext<?, InputRuntimeType> input,
+ final DataContainerCodecContext<?, OutputRuntimeType> output) {
this.input = requireNonNull(input);
this.output = requireNonNull(output);
}
- DataContainerCodecContext<?, InputSchemaNode> input() {
+ DataContainerCodecContext<?, InputRuntimeType> input() {
return input;
}
- DataContainerCodecContext<?, OutputSchemaNode> output() {
+ DataContainerCodecContext<?, OutputRuntimeType> output() {
return output;
}
}
package org.opendaylight.mdsal.binding.dom.codec.impl;
import com.google.common.base.Preconditions;
+import org.opendaylight.mdsal.binding.runtime.api.AugmentRuntimeType;
import org.opendaylight.yangtools.yang.binding.Augmentation;
import org.opendaylight.yangtools.yang.binding.DataObject;
import org.opendaylight.yangtools.yang.data.api.schema.AugmentationNode;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
-import org.opendaylight.yangtools.yang.model.api.AugmentationSchemaNode;
final class AugmentationNodeContext<D extends DataObject & Augmentation<?>>
- extends DataObjectCodecContext<D, AugmentationSchemaNode> {
+ extends DataObjectCodecContext<D, AugmentRuntimeType> {
- AugmentationNodeContext(final DataContainerCodecPrototype<AugmentationSchemaNode> prototype) {
+ AugmentationNodeContext(final DataContainerCodecPrototype<AugmentRuntimeType> prototype) {
super(prototype);
}
import org.opendaylight.mdsal.binding.dom.codec.spi.AbstractBindingNormalizedNodeSerializer;
import org.opendaylight.mdsal.binding.dom.codec.spi.BindingDOMCodecServices;
import org.opendaylight.mdsal.binding.dom.codec.spi.BindingSchemaMapping;
-import org.opendaylight.mdsal.binding.model.api.GeneratedType;
import org.opendaylight.mdsal.binding.runtime.api.BindingRuntimeContext;
+import org.opendaylight.mdsal.binding.runtime.api.ListRuntimeType;
import org.opendaylight.mdsal.binding.spec.reflect.BindingReflections;
import org.opendaylight.yangtools.concepts.Delegator;
import org.opendaylight.yangtools.concepts.IllegalArgumentCodec;
import org.opendaylight.yangtools.yang.data.impl.schema.NormalizedNodeResult;
import org.opendaylight.yangtools.yang.model.api.AnydataSchemaNode;
import org.opendaylight.yangtools.yang.model.api.AnyxmlSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.DocumentedNode.WithStatus;
import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.TypeAware;
import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
import org.opendaylight.yangtools.yang.model.api.TypedDataSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
import org.opendaylight.yangtools.yang.model.api.stmt.SchemaNodeIdentifier.Absolute;
+import org.opendaylight.yangtools.yang.model.api.stmt.TypeDefinitionAware;
import org.opendaylight.yangtools.yang.model.api.type.IdentityrefTypeDefinition;
import org.opendaylight.yangtools.yang.model.api.type.InstanceIdentifierTypeDefinition;
import org.opendaylight.yangtools.yang.model.api.type.LeafrefTypeDefinition;
@Override
public ImmutableMap<Method, ValueNodeCodecContext> getLeafNodes(final Class<?> type,
- final DataNodeContainer schema) {
+ final EffectiveStatement<?, ?> schema) {
final Map<String, DataSchemaNode> getterToLeafSchema = new HashMap<>();
- for (final DataSchemaNode leaf : schema.getChildNodes()) {
- if (leaf instanceof TypedDataSchemaNode || leaf instanceof AnyxmlSchemaNode
- || leaf instanceof AnydataSchemaNode) {
- getterToLeafSchema.put(BindingSchemaMapping.getGetterMethodName(leaf), leaf);
+ for (var stmt : schema.effectiveSubstatements()) {
+ if (stmt instanceof TypedDataSchemaNode) {
+ putLeaf(getterToLeafSchema, (TypedDataSchemaNode) stmt);
+ } else if (stmt instanceof AnydataSchemaNode) {
+ putLeaf(getterToLeafSchema, (AnydataSchemaNode) stmt);
+ } else if (stmt instanceof AnyxmlSchemaNode) {
+ putLeaf(getterToLeafSchema, (AnyxmlSchemaNode) stmt);
}
}
return getLeafNodesUsingReflection(type, getterToLeafSchema);
}
+ private static void putLeaf(final Map<String, DataSchemaNode> map, final DataSchemaNode leaf) {
+ map.put(BindingSchemaMapping.getGetterMethodName(leaf), leaf);
+ }
+
private ImmutableMap<Method, ValueNodeCodecContext> getLeafNodesUsingReflection(
final Class<?> parentClass, final Map<String, DataSchemaNode> getterToLeafSchema) {
final Map<Method, ValueNodeCodecContext> leaves = new HashMap<>();
throw new IllegalStateException("Unable to load codec for " + valueType, e);
}
} else if (typeDef instanceof LeafrefTypeDefinition) {
- final Entry<GeneratedType, WithStatus> typeWithSchema = context.getTypeWithSchema(valueType);
- final WithStatus schema = typeWithSchema.getValue();
- checkState(schema instanceof TypeDefinition, "Unexpected schema %s", schema);
- return getCodec(valueType, (TypeDefinition<?>) schema);
+ final var typeWithSchema = context.getTypeWithSchema(valueType);
+ final var schema = typeWithSchema.statement();
+ final TypeDefinition<?> def;
+ if (schema instanceof TypeDefinitionAware) {
+ def = ((TypeDefinitionAware) schema).getTypeDefinition();
+ } else if (schema instanceof TypeAware) {
+ def = ((TypeAware) schema).getType();
+ } else {
+ throw new IllegalStateException("Unexpected schema " + schema);
+ }
+ return getCodec(valueType, def);
}
return ValueTypeCodec.getCodecFor(valueType, typeDef);
}
@Override
- public IdentifiableItemCodec getPathArgumentCodec(final Class<?> listClz, final ListSchemaNode schema) {
+ public IdentifiableItemCodec getPathArgumentCodec(final Class<?> listClz, final ListRuntimeType type) {
final Optional<Class<Identifier<?>>> optIdentifier = ClassLoaderUtils.findFirstGenericArgument(listClz,
Identifiable.class);
checkState(optIdentifier.isPresent(), "Failed to find identifier for %s", listClz);
final Class<Identifier<?>> identifier = optIdentifier.get();
final Map<QName, ValueContext> valueCtx = new HashMap<>();
- for (final ValueNodeCodecContext leaf : getLeafNodes(identifier, schema).values()) {
+ for (final ValueNodeCodecContext leaf : getLeafNodes(identifier, type.statement()).values()) {
final QName name = leaf.getDomPathArgument().getNodeType();
valueCtx.put(name, new ValueContext(identifier, leaf));
}
- return IdentifiableItemCodec.of(schema, identifier, listClz, valueCtx);
+ return IdentifiableItemCodec.of(type.statement(), identifier, listClz, valueCtx);
}
@SuppressWarnings("unchecked")
import static com.google.common.base.Preconditions.checkState;
import java.util.List;
+import org.opendaylight.mdsal.binding.runtime.api.CaseRuntimeType;
import org.opendaylight.yangtools.yang.binding.DataObject;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.Item;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
import org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
-import org.opendaylight.yangtools.yang.model.api.CaseSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.AddedByUsesAware;
+import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
-final class CaseNodeCodecContext<D extends DataObject> extends DataObjectCodecContext<D, CaseSchemaNode> {
- CaseNodeCodecContext(final DataContainerCodecPrototype<CaseSchemaNode> prototype) {
+final class CaseNodeCodecContext<D extends DataObject> extends DataObjectCodecContext<D, CaseRuntimeType> {
+ CaseNodeCodecContext(final DataContainerCodecPrototype<CaseRuntimeType> prototype) {
super(prototype);
}
@Override
@SuppressWarnings({ "unchecked", "rawtypes" })
- Item<?> createBindingArg(final Class<?> childClass, final DataSchemaNode childSchema) {
+ Item<?> createBindingArg(final Class<?> childClass, final EffectiveStatement<?, ?> childSchema) {
// FIXME: MDSAL-697: see overridden method for further guidance
- return childSchema.isAddedByUses() ? Item.of((Class)getBindingClass(), (Class)childClass)
- : super.createBindingArg(childClass, childSchema);
+ return childSchema instanceof AddedByUsesAware && ((AddedByUsesAware) childSchema).isAddedByUses()
+ ? Item.of((Class)getBindingClass(), (Class)childClass)
+ : super.createBindingArg(childClass, childSchema);
}
@Override
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
import org.eclipse.jdt.annotation.NonNull;
+import org.opendaylight.mdsal.binding.model.api.JavaTypeName;
+import org.opendaylight.mdsal.binding.runtime.api.CaseRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.ChoiceRuntimeType;
import org.opendaylight.mdsal.binding.spec.reflect.BindingReflections;
import org.opendaylight.yangtools.yang.binding.DataObject;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument;
import org.opendaylight.yangtools.yang.data.util.DataSchemaContextNode;
import org.opendaylight.yangtools.yang.data.util.NormalizedNodeSchemaUtils;
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.DataSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.DocumentedNode.WithStatus;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
* ambiguous reference and issue warn once when they are encountered -- tracking warning information in
* {@link #ambiguousByCaseChildWarnings}.
*/
-final class ChoiceNodeCodecContext<D extends DataObject> extends DataContainerCodecContext<D, ChoiceSchemaNode> {
+final class ChoiceNodeCodecContext<D extends DataObject> extends DataContainerCodecContext<D, ChoiceRuntimeType> {
private static final Logger LOG = LoggerFactory.getLogger(ChoiceNodeCodecContext.class);
private final ImmutableMap<YangInstanceIdentifier.PathArgument, DataContainerCodecPrototype<?>> byYangCaseChild;
private final ImmutableMap<Class<?>, DataContainerCodecPrototype<?>> byClass;
private final Set<Class<?>> ambiguousByCaseChildWarnings;
- ChoiceNodeCodecContext(final DataContainerCodecPrototype<ChoiceSchemaNode> prototype) {
+ ChoiceNodeCodecContext(final DataContainerCodecPrototype<ChoiceRuntimeType> prototype) {
super(prototype);
final Map<YangInstanceIdentifier.PathArgument, DataContainerCodecPrototype<?>> byYangCaseChildBuilder =
new HashMap<>();
SetMultimapBuilder.hashKeys().hashSetValues().build();
final Set<Class<?>> potentialSubstitutions = new HashSet<>();
// Walks all cases for supplied choice in current runtime context
- for (final Class<?> caze : factory().getRuntimeContext().getCases(getBindingClass())) {
+ // FIXME: 9.0.0: factory short-circuits to prototype, just as getBindingClass() does
+ for (final Class<?> caze : loadCaseClasses()) {
// We try to load case using exact match thus name
// and original schema must equals
- final DataContainerCodecPrototype<CaseSchemaNode> cazeDef = loadCase(caze);
+ final DataContainerCodecPrototype<CaseRuntimeType> cazeDef = loadCase(caze);
// If we have case definition, this case is instantiated
// at current location and thus is valid in context of parent choice
if (cazeDef != null) {
childToCase.put(cazeChild, cazeDef);
}
// Updates collection of YANG instance identifier to case
- for (final DataSchemaNode cazeChild : cazeDef.getSchema().getChildNodes()) {
- if (cazeChild.isAugmenting()) {
- final AugmentationSchemaNode augment =
- NormalizedNodeSchemaUtils.findCorrespondingAugment(cazeDef.getSchema(), cazeChild);
- if (augment != null) {
- byYangCaseChildBuilder.put(DataSchemaContextNode.augmentationIdentifierFrom(augment),
- cazeDef);
- continue;
+ for (var stmt : cazeDef.getType().statement().effectiveSubstatements()) {
+ if (stmt instanceof DataSchemaNode) {
+ final DataSchemaNode cazeChild = (DataSchemaNode) stmt;
+ if (cazeChild.isAugmenting()) {
+ final AugmentationSchemaNode augment = NormalizedNodeSchemaUtils.findCorrespondingAugment(
+ // FIXME: bad cast
+ (DataSchemaNode) cazeDef.getType().statement(), cazeChild);
+ if (augment != null) {
+ byYangCaseChildBuilder.put(DataSchemaContextNode.augmentationIdentifierFrom(augment),
+ cazeDef);
+ continue;
+ }
}
+ byYangCaseChildBuilder.put(NodeIdentifier.create(cazeChild.getQName()), cazeDef);
}
- byYangCaseChildBuilder.put(NodeIdentifier.create(cazeChild.getQName()), cazeDef);
}
} else {
/*
byClass = ImmutableMap.copyOf(byClassBuilder);
}
+ private List<Class<?>> loadCaseClasses() {
+ final var context = factory().getRuntimeContext();
+ final var type = getType();
+
+ return Stream.concat(type.validCaseChildren().stream(), type.additionalCaseChildren().stream())
+ .map(caseChild -> {
+ final var caseName = caseChild.getIdentifier();
+ try {
+ return context.loadClass(caseName);
+ } catch (ClassNotFoundException e) {
+ throw new IllegalStateException("Failed to load class for " + caseName, e);
+ }
+ })
+ .collect(Collectors.toUnmodifiableList());
+ }
+
+ @Override
+ public WithStatus getSchema() {
+ // FIXME: Bad cast, we should be returning an EffectiveStatement perhaps?
+ return (WithStatus) getType().statement();
+ }
+
@SuppressWarnings("unchecked")
@Override
public <C extends DataObject> DataContainerCodecContext<C, ?> streamChild(final Class<C> childClass) {
return Iterables.concat(byCaseChildClass.keySet(), ambiguousByCaseChildClass.keySet());
}
- protected DataContainerCodecPrototype<CaseSchemaNode> loadCase(final Class<?> childClass) {
- final Optional<CaseSchemaNode> childSchema = factory().getRuntimeContext().getCaseSchemaDefinition(getSchema(),
- childClass);
- if (childSchema.isPresent()) {
- return DataContainerCodecPrototype.from(childClass, childSchema.get(), factory());
+ protected DataContainerCodecPrototype<CaseRuntimeType> loadCase(final Class<?> childClass) {
+ final var child = getType().bindingCaseChild(JavaTypeName.create(childClass));
+ if (child == null) {
+ LOG.debug("Supplied class {} is not valid case in schema {}", childClass, getSchema());
+ return null;
}
- LOG.debug("Supplied class {} is not valid case in schema {}", childClass, getSchema());
- return null;
+ return DataContainerCodecPrototype.from(childClass, child, factory());
}
@Override
import static com.google.common.base.Preconditions.checkState;
+import org.opendaylight.mdsal.binding.runtime.api.ContainerLikeRuntimeType;
import org.opendaylight.yangtools.yang.binding.DataObject;
import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
-import org.opendaylight.yangtools.yang.model.api.ContainerLike;
-final class ContainerNodeCodecContext<D extends DataObject> extends DataObjectCodecContext<D, ContainerLike>
+final class ContainerNodeCodecContext<D extends DataObject>
+ extends DataObjectCodecContext<D, ContainerLikeRuntimeType<?, ?>>
implements RpcInputCodec<D> {
- ContainerNodeCodecContext(final DataContainerCodecPrototype<ContainerLike> prototype) {
+ ContainerNodeCodecContext(final DataContainerCodecPrototype<ContainerLikeRuntimeType<?, ?>> prototype) {
super(prototype);
}
import org.opendaylight.mdsal.binding.dom.codec.api.MissingSchemaForClassException;
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.RuntimeTypeContainer;
import org.opendaylight.yangtools.yang.binding.Augmentation;
import org.opendaylight.yangtools.yang.binding.BindingObject;
import org.opendaylight.yangtools.yang.binding.DataObject;
import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeStreamWriter;
import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNormalizedNodeStreamWriter;
import org.opendaylight.yangtools.yang.data.impl.schema.NormalizedNodeResult;
-import org.opendaylight.yangtools.yang.model.api.DocumentedNode.WithStatus;
-abstract class DataContainerCodecContext<D extends DataObject, T extends WithStatus> extends NodeCodecContext
+abstract class DataContainerCodecContext<D extends DataObject, T extends RuntimeTypeContainer> extends NodeCodecContext
implements BindingDataObjectCodecTreeNode<D> {
private static final VarHandle EVENT_STREAM_SERIALIZER;
this.prototype = requireNonNull(prototype);
}
- @Override
- public final T getSchema() {
- return prototype.getSchema();
+ public final @NonNull T getType() {
+ return prototype.getType();
}
@Override
private IllegalArgumentException childNullException(final Class<?> childClass, final String message,
final Object... args) {
final BindingRuntimeContext runtimeContext = factory().getRuntimeContext();
- final WithStatus schema;
+ final CompositeRuntimeType schema;
if (Augmentation.class.isAssignableFrom(childClass)) {
schema = runtimeContext.getAugmentationDefinition(childClass.asSubclass(Augmentation.class));
} else {
*/
package org.opendaylight.mdsal.binding.dom.codec.impl;
+import static com.google.common.base.Verify.verify;
+
import com.google.common.collect.Iterables;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.VarHandle;
import org.eclipse.jdt.annotation.NonNull;
import org.opendaylight.mdsal.binding.dom.codec.api.BindingDataObjectCodecTreeNode.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.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.data.api.YangInstanceIdentifier.AugmentationIdentifier;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
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.ContainerLike;
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.DocumentedNode.WithStatus;
-import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.NotificationDefinition;
import org.opendaylight.yangtools.yang.model.api.SchemaContext;
import org.opendaylight.yangtools.yang.model.api.TypedDataSchemaNode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-final class DataContainerCodecPrototype<T extends WithStatus> implements NodeContextSupplier {
+final class DataContainerCodecPrototype<T extends RuntimeTypeContainer> implements NodeContextSupplier {
private static final Logger LOG = LoggerFactory.getLogger(DataContainerCodecPrototype.class);
private static final VarHandle INSTANCE;
}
}
- private final T schema;
+ private final T type;
private final QNameModule namespace;
private final CodecContextFactory factory;
private final Item<?> bindingArg;
private volatile DataContainerCodecContext<?, T> instance;
@SuppressWarnings("unchecked")
- private DataContainerCodecPrototype(final Class<?> cls, final PathArgument arg, final T nodeSchema,
+ private DataContainerCodecPrototype(final Class<?> cls, final PathArgument arg, final T type,
final CodecContextFactory factory) {
- this(Item.of((Class<? extends DataObject>) cls), arg, nodeSchema, factory);
+ this(Item.of((Class<? extends DataObject>) cls), arg, type, factory);
}
- private DataContainerCodecPrototype(final Item<?> bindingArg, final PathArgument arg, final T nodeSchema,
+ private DataContainerCodecPrototype(final Item<?> bindingArg, final PathArgument arg, final T type,
final CodecContextFactory factory) {
this.bindingArg = bindingArg;
this.yangArg = arg;
- this.schema = nodeSchema;
+ this.type = type;
this.factory = factory;
if (arg instanceof AugmentationIdentifier) {
this.namespace = arg.getNodeType().getModule();
}
- this.childAddressabilitySummary = computeChildAddressabilitySummary(nodeSchema);
+ this.childAddressabilitySummary = type instanceof RuntimeType
+ ? computeChildAddressabilitySummary(((RuntimeType) type).statement())
+ // BindingRuntimeTypes, does not matter
+ : ChildAddressabilitySummary.MIXED;
}
- private static ChildAddressabilitySummary computeChildAddressabilitySummary(final WithStatus nodeSchema) {
+ private static ChildAddressabilitySummary computeChildAddressabilitySummary(final Object nodeSchema) {
+ // FIXME: rework this to work on EffectiveStatements
if (nodeSchema instanceof DataNodeContainer) {
boolean haveAddressable = false;
boolean haveUnaddressable = false;
return ChildAddressabilitySummary.UNADDRESSABLE;
}
- static DataContainerCodecPrototype<EffectiveModelContext> rootPrototype(final CodecContextFactory factory) {
- final EffectiveModelContext schema = factory.getRuntimeContext().getEffectiveModelContext();
- final NodeIdentifier arg = NodeIdentifier.create(SchemaContext.NAME);
- return new DataContainerCodecPrototype<>(DataRoot.class, arg, schema, factory);
+ static DataContainerCodecPrototype<BindingRuntimeTypes> rootPrototype(final CodecContextFactory factory) {
+ return new DataContainerCodecPrototype<>(DataRoot.class, NodeIdentifier.create(SchemaContext.NAME),
+ factory.getRuntimeContext().getTypes(), factory);
}
- static <T extends DataSchemaNode> DataContainerCodecPrototype<T> from(final Class<?> cls, final T schema,
+ static <T extends CompositeRuntimeType> DataContainerCodecPrototype<T> from(final Class<?> cls, final T type,
final CodecContextFactory factory) {
- return new DataContainerCodecPrototype<>(cls, NodeIdentifier.create(schema.getQName()), schema, factory);
+ return new DataContainerCodecPrototype<>(cls, createIdentifier(type), type, factory);
}
- static <T extends DataSchemaNode> DataContainerCodecPrototype<T> from(final Item<?> bindingArg, final T schema,
+ static <T extends CompositeRuntimeType> DataContainerCodecPrototype<T> from(final Item<?> bindingArg, final T type,
final CodecContextFactory factory) {
- return new DataContainerCodecPrototype<>(bindingArg, NodeIdentifier.create(schema.getQName()), schema, factory);
+ return new DataContainerCodecPrototype<>(bindingArg, createIdentifier(type), type, factory);
+ }
+
+ static DataContainerCodecPrototype<AugmentRuntimeType> from(final Class<?> augClass,
+ final AugmentationIdentifier arg, final AugmentRuntimeType schema, final CodecContextFactory factory) {
+ return new DataContainerCodecPrototype<>(augClass, arg, schema, factory);
}
- static DataContainerCodecPrototype<AugmentationSchemaNode> from(final Class<?> augClass,
- final AugmentationIdentifier arg, final AugmentationSchemaNode schema, final CodecContextFactory factory) {
+ static DataContainerCodecPrototype<NotificationRuntimeType> from(final Class<?> augClass,
+ final NotificationRuntimeType schema, final CodecContextFactory factory) {
+ final PathArgument arg = NodeIdentifier.create(schema.statement().argument());
return new DataContainerCodecPrototype<>(augClass, arg, schema, factory);
}
- static DataContainerCodecPrototype<NotificationDefinition> from(final Class<?> augClass,
- final NotificationDefinition schema, final CodecContextFactory factory) {
- final PathArgument arg = NodeIdentifier.create(schema.getQName());
- return new DataContainerCodecPrototype<>(augClass,arg, schema, factory);
+ private static @NonNull NodeIdentifier createIdentifier(final CompositeRuntimeType type) {
+ final Object arg = type.statement().argument();
+ verify(arg instanceof QName, "Unexpected type %s argument %s", type, arg);
+ return NodeIdentifier.create((QName) arg);
}
- T getSchema() {
- return schema;
+ @NonNull T getType() {
+ return type;
}
ChildAddressabilitySummary getChildAddressabilitySummary() {
// This method must allow concurrent loading, i.e. nothing in it may have effects outside of the loaded object
private @NonNull DataContainerCodecContext<?, T> createInstance() {
// FIXME: make protected abstract
- if (schema instanceof ContainerLike) {
+ if (type instanceof ContainerLikeRuntimeType) {
return new ContainerNodeCodecContext(this);
- } else if (schema instanceof ListSchemaNode) {
+ } else if (type instanceof ListRuntimeType) {
return Identifiable.class.isAssignableFrom(getBindingClass())
- ? KeyedListNodeCodecContext.create((DataContainerCodecPrototype<ListSchemaNode>) this)
+ ? KeyedListNodeCodecContext.create((DataContainerCodecPrototype<ListRuntimeType>) this)
: new ListNodeCodecContext(this);
- } else if (schema instanceof ChoiceSchemaNode) {
+ } else if (type instanceof ChoiceRuntimeType) {
return new ChoiceNodeCodecContext(this);
- } else if (schema instanceof AugmentationSchemaNode) {
+ } else if (type instanceof AugmentRuntimeType) {
return new AugmentationNodeContext(this);
- } else if (schema instanceof CaseSchemaNode) {
+ } else if (type instanceof CaseRuntimeType) {
return new CaseNodeCodecContext(this);
}
- throw new IllegalArgumentException("Unsupported type " + getBindingClass() + " " + schema);
- }
-
- // FIXME: eliminate with above createInstance() item
- boolean isChoice() {
- return schema instanceof ChoiceSchemaNode;
+ throw new IllegalArgumentException("Unsupported type " + getBindingClass() + " " + type);
}
}
import com.google.common.base.Throwables;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableMap.Builder;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Iterables;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;
import org.opendaylight.mdsal.binding.dom.codec.api.IncorrectNestingException;
+import org.opendaylight.mdsal.binding.model.api.GeneratedType;
+import org.opendaylight.mdsal.binding.model.api.JavaTypeName;
import org.opendaylight.mdsal.binding.model.api.Type;
+import org.opendaylight.mdsal.binding.runtime.api.AugmentRuntimeType;
import org.opendaylight.mdsal.binding.runtime.api.BindingRuntimeContext;
+import org.opendaylight.mdsal.binding.runtime.api.ChoiceRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.CompositeRuntimeType;
import org.opendaylight.mdsal.binding.spec.reflect.BindingReflections;
import org.opendaylight.yangtools.yang.binding.Augmentable;
import org.opendaylight.yangtools.yang.binding.Augmentation;
import org.opendaylight.yangtools.yang.data.api.schema.AugmentationNode;
import org.opendaylight.yangtools.yang.data.api.schema.DistinctNodeContainer;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
-import org.opendaylight.yangtools.yang.model.api.AugmentationSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
-import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
import org.opendaylight.yangtools.yang.model.api.DocumentedNode.WithStatus;
+import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.SchemaTreeEffectiveStatement;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
* This class is an implementation detail. It is public only due to technical reasons and may change at any time.
*/
@Beta
-public abstract class DataObjectCodecContext<D extends DataObject, T extends DataNodeContainer & WithStatus>
+public abstract class DataObjectCodecContext<D extends DataObject, T extends CompositeRuntimeType>
extends DataContainerCodecContext<D, T> {
private static final Logger LOG = LoggerFactory.getLogger(DataObjectCodecContext.class);
private static final MethodType CONSTRUCTOR_TYPE = MethodType.methodType(void.class,
final Class<D> bindingClass = getBindingClass();
- final ImmutableMap<Method, ValueNodeCodecContext> tmpLeaves = factory().getLeafNodes(bindingClass, getSchema());
+ final ImmutableMap<Method, ValueNodeCodecContext> tmpLeaves = factory().getLeafNodes(bindingClass,
+ getType().statement());
final Map<Class<? extends DataContainer>, Method> clsToMethod =
BindingReflections.getChildrenClassToMethod(bindingClass);
// FIXME: It really feels like we should be specializing DataContainerCodecPrototype so as to ditch
// createInstance() and then we could do an instanceof check instead.
- if (childProto.isChoice()) {
+ if (childProto.getType() instanceof ChoiceRuntimeType) {
final ChoiceNodeCodecContext<?> choice = (ChoiceNodeCodecContext<?>) childProto.get();
for (final Class<?> cazeChild : choice.getCaseChildrenClasses()) {
byBindingArgClassBuilder.put(cazeChild, childProto);
this.byBindingArgClass = byStreamClassBuilder.equals(byBindingArgClassBuilder) ? this.byStreamClass
: ImmutableMap.copyOf(byBindingArgClassBuilder);
- final ImmutableMap<AugmentationIdentifier, Type> possibleAugmentations;
+ final Iterable<AugmentRuntimeType> possibleAugmentations;
if (Augmentable.class.isAssignableFrom(bindingClass)) {
- possibleAugmentations = factory().getRuntimeContext().getAvailableAugmentationTypes(getSchema());
+ final var type = getType();
+ possibleAugmentations = Iterables.concat(type.augments(), type.mismatchedAugments());
generatedClass = CodecDataObjectGenerator.generateAugmentable(prototype.getFactory().getLoader(),
bindingClass, tmpLeaves, tmpDataObjects, keyMethod);
} else {
- possibleAugmentations = ImmutableMap.of();
+ possibleAugmentations = List.of();
generatedClass = CodecDataObjectGenerator.generate(prototype.getFactory().getLoader(), bindingClass,
tmpLeaves, tmpDataObjects, keyMethod);
}
// Iterate over all possible augmentations, indexing them as needed
final Map<PathArgument, DataContainerCodecPrototype<?>> augByYang = new HashMap<>();
final Map<Class<?>, DataContainerCodecPrototype<?>> augByStream = new HashMap<>();
- for (final Type augment : possibleAugmentations.values()) {
+ for (final AugmentRuntimeType augment : possibleAugmentations) {
final DataContainerCodecPrototype<?> augProto = getAugmentationPrototype(augment);
final PathArgument augYangArg = augProto.getYangArg();
if (augByYang.putIfAbsent(augYangArg, augProto) == null) {
proxyConstructor = ctor.asType(DATAOBJECT_TYPE);
}
- @SuppressWarnings("unchecked")
@Override
+ public final WithStatus getSchema() {
+ // FIXME: Bad cast, we should be returning an EffectiveStatement perhaps?
+ return (WithStatus) getType().statement();
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
public <C extends DataObject> DataContainerCodecContext<C, ?> streamChild(final Class<C> childClass) {
- final DataContainerCodecPrototype<?> childProto = streamChildPrototype(childClass);
- return (DataContainerCodecContext<C, ?>) childNonNull(childProto, childClass, " Child %s is not valid child.",
- childClass).get();
+ return (DataContainerCodecContext<C, ?>) childNonNull(streamChildPrototype(childClass), childClass,
+ "Child %s is not valid child of %s", getBindingClass(), childClass).get();
}
private DataContainerCodecPrototype<?> streamChildPrototype(final Class<?> childClass) {
}
private DataContainerCodecPrototype<?> loadChildPrototype(final Class<? extends DataContainer> childClass) {
- final DataSchemaNode childSchema = childNonNull(
- factory().getRuntimeContext().findChildSchemaDefinition(getSchema(), namespace(), childClass), childClass,
- "Node %s does not have child named %s", getSchema(), childClass);
- return DataContainerCodecPrototype.from(createBindingArg(childClass, childSchema), childSchema, factory());
+ final var type = getType();
+ final var child = childNonNull(type.bindingChild(JavaTypeName.create(childClass)), childClass,
+ "Node %s does not have child named %s", type, childClass);
+
+ return DataContainerCodecPrototype.from(createBindingArg(childClass, child.statement()),
+ (CompositeRuntimeType) child, factory());
}
// FIXME: MDSAL-697: move this method into BindingRuntimeContext
// the equivalent of Map.Entry<Item, DataSchemaNode>, along with the override we create here. One
// more input we may need to provide is our bindingClass().
@SuppressWarnings("unchecked")
- Item<?> createBindingArg(final Class<?> childClass, final DataSchemaNode childSchema) {
+ Item<?> createBindingArg(final Class<?> childClass, final EffectiveStatement<?, ?> childSchema) {
return Item.of((Class<? extends DataObject>) childClass);
}
.put(childClass, prototype)
.build();
- final Object witness = MISMATCHED_AUGMENTED.compareAndExchangeRelease(this, expected, newMismatched);
+ final var witness = (ImmutableMap<Class<?>, DataContainerCodecPrototype<?>>)
+ MISMATCHED_AUGMENTED.compareAndExchangeRelease(this, expected, newMismatched);
if (witness == expected) {
LOG.trace("Cached mismatched augmentation {} -> {} in {}", childClass, prototype, this);
return prototype;
}
- expected = (ImmutableMap<Class<?>, DataContainerCodecPrototype<?>>) witness;
+ expected = witness;
final DataContainerCodecPrototype<?> existing = expected.get(childClass);
if (existing != null) {
LOG.trace("Using raced mismatched augmentation {} -> {} in {}", childClass, existing, this);
return cls.equals(loaded);
}
- private @NonNull DataContainerCodecPrototype<?> getAugmentationPrototype(final Type value) {
+ private @NonNull DataContainerCodecPrototype<?> getAugmentationPrototype(final AugmentRuntimeType augment) {
final BindingRuntimeContext ctx = factory().getRuntimeContext();
+ final GeneratedType javaType = augment.javaType();
final Class<? extends Augmentation<?>> augClass;
try {
- augClass = ctx.loadClass(value);
+ augClass = ctx.loadClass(javaType);
} catch (final ClassNotFoundException e) {
- throw new IllegalStateException("RuntimeContext references type " + value + " but failed to its class", e);
+ throw new IllegalStateException(
+ "RuntimeContext references type " + javaType + " but failed to load its class", e);
}
- final Entry<AugmentationIdentifier, AugmentationSchemaNode> augSchema =
- ctx.getResolvedAugmentationSchema(getSchema(), augClass);
- return DataContainerCodecPrototype.from(augClass, augSchema.getKey(), augSchema.getValue(), factory());
+ // TODO: at some point we need the effective children
+ return DataContainerCodecPrototype.from(augClass, new AugmentationIdentifier(augment.statement()
+ .streamEffectiveSubstatements(SchemaTreeEffectiveStatement.class)
+ .map(SchemaTreeEffectiveStatement::getIdentifier)
+ .collect(ImmutableSet.toImmutableSet())), augment, factory());
}
@SuppressWarnings("checkstyle:illegalCatch")
}
}
for (final DataContainerCodecPrototype<?> value : augmentationByStream.values()) {
- final NormalizedNode augData = data.childByArg(value.getYangArg());
- if (augData != null) {
- map.put(value.getBindingClass(), value.get().deserializeObject(augData));
+ final var augClass = value.getBindingClass();
+ // Do not perform duplicate deserialization if we have already created the corresponding augmentation
+ // and validate whether the proposed augmentation is valid ion this instantiation context.
+ if (!map.containsKey(augClass) && getType().augments().contains(value.getType())) {
+ final NormalizedNode augData = data.childByArg(value.getYangArg());
+ if (augData != null) {
+ // ... make sure we do not replace an e
+ map.putIfAbsent(augClass, value.get().deserializeObject(augData));
+ }
}
}
return map;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
-import java.util.Map.Entry;
import java.util.Set;
import net.bytebuddy.ByteBuddy;
import net.bytebuddy.description.field.FieldDescription;
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.DocumentedNode.WithStatus;
import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
static Class<? extends DataObjectStreamer<?>> generateStreamer(final CodecClassLoader loader,
final CodecContextFactory registry, final Class<?> type) {
- final Entry<GeneratedType, WithStatus> typeAndSchema = registry.getRuntimeContext().getTypeWithSchema(type);
- final WithStatus schema = typeAndSchema.getValue();
+ final var typeAndSchema = registry.getRuntimeContext().getTypeWithSchema(type);
+ final var schema = typeAndSchema.statement();
final StackManipulation startEvent;
if (schema instanceof ContainerLike || schema instanceof NotificationDefinition) {
}
return loader.generateClass(type, "streamer",
- new DataObjectStreamerGenerator<>(registry, typeAndSchema.getKey(), (DataNodeContainer) schema, type,
- startEvent));
+ // FIXME: cast to GeneratedType: we really should adjust getTypeWithSchema()
+ new DataObjectStreamerGenerator<>(registry, (GeneratedType) typeAndSchema.javaType(),
+ (DataNodeContainer) schema, type, startEvent));
}
@Override
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
+import java.util.Set;
import org.eclipse.jdt.annotation.NonNull;
import org.opendaylight.mdsal.binding.spec.naming.BindingMapping;
import org.opendaylight.yangtools.concepts.AbstractIllegalArgumentCodec;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.IdentifiableItem;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
-import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.stmt.KeyEffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.ListEffectiveStatement;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
private final MethodHandle ctor;
private final QName keyName;
- SingleKey(final ListSchemaNode schema, final Class<? extends Identifier<?>> keyClass,
+ SingleKey(final ListEffectiveStatement schema, final Class<? extends Identifier<?>> keyClass,
final Class<?> identifiable, final QName keyName, final ValueContext keyContext) {
super(schema, keyClass, identifiable);
this.keyContext = requireNonNull(keyContext);
private final ImmutableList<QName> keysInBindingOrder;
private final MethodHandle ctor;
- MultiKey(final ListSchemaNode schema, final Class<? extends Identifier<?>> keyClass,
+ MultiKey(final ListEffectiveStatement schema, final Class<? extends Identifier<?>> keyClass,
final Class<?> identifiable, final Map<QName, ValueContext> keyValueContexts) {
super(schema, keyClass, identifiable);
final MethodHandle tmpCtor = getConstructor(keyClass, keyValueContexts.size());
final MethodHandle inv = MethodHandles.spreadInvoker(tmpCtor.type(), 0);
- this.ctor = inv.asType(inv.type().changeReturnType(Identifier.class)).bindTo(tmpCtor);
+ ctor = inv.asType(inv.type().changeReturnType(Identifier.class)).bindTo(tmpCtor);
/*
* We need to re-index to make sure we instantiate nodes in the order in which they are defined. We will
* also need to instantiate values in the same order.
*/
- final List<QName> keyDef = schema.getKeyDefinition();
+ final Set<QName> keyDef = schema.findFirstEffectiveSubstatementArgument(KeyEffectiveStatement.class)
+ .orElseThrow();
predicateTemplate = ImmutableOffsetMapTemplate.ordered(keyDef);
this.keyValueContexts = predicateTemplate.instantiateTransformed(keyValueContexts, (key, value) -> value);
final List<QName> tmp = new ArrayList<>(keyDef);
// This is not terribly efficient but gets the job done
tmp.sort(Comparator.comparing(qname -> BindingMapping.getPropertyName(qname.getLocalName())));
- this.keysInBindingOrder = ImmutableList.copyOf(tmp.equals(keyDef) ? keyDef : tmp);
+ keysInBindingOrder = ImmutableList.copyOf(tmp.equals(List.copyOf(keyDef)) ? keyDef : tmp);
}
@Override
private final Class<?> identifiable;
private final QName qname;
- IdentifiableItemCodec(final ListSchemaNode schema, final Class<? extends Identifier<?>> keyClass,
+ IdentifiableItemCodec(final ListEffectiveStatement schema, final Class<? extends Identifier<?>> keyClass,
final Class<?> identifiable) {
this.identifiable = requireNonNull(identifiable);
- this.qname = schema.getQName();
+ qname = schema.argument();
}
- static IdentifiableItemCodec of(final ListSchemaNode schema,
+ static IdentifiableItemCodec of(final ListEffectiveStatement schema,
final Class<? extends Identifier<?>> keyClass, final Class<?> identifiable,
final Map<QName, ValueContext> keyValueContexts) {
switch (keyValueContexts.size()) {
import java.util.List;
import java.util.Map;
import org.eclipse.jdt.annotation.NonNull;
+import org.opendaylight.mdsal.binding.runtime.api.ListRuntimeType;
import org.opendaylight.yangtools.yang.binding.DataObject;
import org.opendaylight.yangtools.yang.binding.Identifiable;
import org.opendaylight.yangtools.yang.binding.Identifier;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.IdentifiableItem;
+import org.opendaylight.yangtools.yang.common.Ordering;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
-import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.stmt.OrderedByEffectiveStatement;
abstract class KeyedListNodeCodecContext<I extends Identifier<D>, D extends DataObject & Identifiable<I>>
extends ListNodeCodecContext<D> {
private static final class Ordered<I extends Identifier<D>, D extends DataObject & Identifiable<I>>
extends KeyedListNodeCodecContext<I, D> {
- Ordered(final DataContainerCodecPrototype<ListSchemaNode> prototype, final Method keyMethod,
+ Ordered(final DataContainerCodecPrototype<ListRuntimeType> prototype, final Method keyMethod,
final IdentifiableItemCodec codec) {
super(prototype, keyMethod, codec);
}
static final class Unordered<I extends Identifier<D>, D extends DataObject & Identifiable<I>>
extends KeyedListNodeCodecContext<I, D> {
- Unordered(final DataContainerCodecPrototype<ListSchemaNode> prototype, final Method keyMethod,
+ Unordered(final DataContainerCodecPrototype<ListRuntimeType> prototype, final Method keyMethod,
final IdentifiableItemCodec codec) {
super(prototype, keyMethod, codec);
}
private final IdentifiableItemCodec codec;
- KeyedListNodeCodecContext(final DataContainerCodecPrototype<ListSchemaNode> prototype,
+ KeyedListNodeCodecContext(final DataContainerCodecPrototype<ListRuntimeType> prototype,
final Method keyMethod, final IdentifiableItemCodec codec) {
super(prototype, keyMethod);
this.codec = requireNonNull(codec);
}
@SuppressWarnings("rawtypes")
- static KeyedListNodeCodecContext create(final DataContainerCodecPrototype<ListSchemaNode> prototype) {
+ static KeyedListNodeCodecContext create(final DataContainerCodecPrototype<ListRuntimeType> prototype) {
final Class<?> bindingClass = prototype.getBindingClass();
final Method keyMethod;
try {
throw new IllegalStateException("Required method not available", e);
}
- final ListSchemaNode schema = prototype.getSchema();
- final IdentifiableItemCodec codec = prototype.getFactory().getPathArgumentCodec(bindingClass, schema);
- return schema.isUserOrdered() ? new Ordered<>(prototype, keyMethod, codec)
- : new Unordered<>(prototype, keyMethod, codec);
+ final ListRuntimeType type = prototype.getType();
+ final IdentifiableItemCodec codec = prototype.getFactory().getPathArgumentCodec(bindingClass, type);
+
+ return type.statement().findFirstEffectiveSubstatementArgument(OrderedByEffectiveStatement.class)
+ .orElse(Ordering.SYSTEM) == Ordering.SYSTEM ? new Unordered<>(prototype, keyMethod, codec)
+ : new Ordered<>(prototype, keyMethod, codec);
}
@Override
import java.lang.reflect.Method;
import java.util.List;
import org.eclipse.jdt.annotation.NonNull;
+import org.opendaylight.mdsal.binding.runtime.api.ListRuntimeType;
import org.opendaylight.yangtools.yang.binding.DataObject;
import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
import org.opendaylight.yangtools.yang.data.api.schema.UnkeyedListEntryNode;
import org.opendaylight.yangtools.yang.data.api.schema.UnkeyedListNode;
-import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
-class ListNodeCodecContext<D extends DataObject> extends DataObjectCodecContext<D, ListSchemaNode> {
- ListNodeCodecContext(final DataContainerCodecPrototype<ListSchemaNode> prototype) {
+class ListNodeCodecContext<D extends DataObject> extends DataObjectCodecContext<D, ListRuntimeType> {
+ ListNodeCodecContext(final DataContainerCodecPrototype<ListRuntimeType> prototype) {
super(prototype);
}
- ListNodeCodecContext(final DataContainerCodecPrototype<ListSchemaNode> prototype,
+ ListNodeCodecContext(final DataContainerCodecPrototype<ListRuntimeType> prototype,
final Method keyMethod) {
super(prototype, keyMethod);
}
import org.opendaylight.mdsal.binding.dom.codec.api.BindingCodecTreeNode;
import org.opendaylight.mdsal.binding.dom.codec.loader.CodecClassLoader;
import org.opendaylight.mdsal.binding.runtime.api.BindingRuntimeContext;
+import org.opendaylight.mdsal.binding.runtime.api.ListRuntimeType;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
-import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
-import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
/**
* Location specific context for schema nodes, which contains codec specific information to properly serialize
* @param schema Instantiated schema of binding type.
* @return Map of local name to leaf node context.
*/
- ImmutableMap<Method, ValueNodeCodecContext> getLeafNodes(Class<?> type, DataNodeContainer schema);
+ ImmutableMap<Method, ValueNodeCodecContext> getLeafNodes(Class<?> type, EffectiveStatement<?, ?> schema);
/**
* Returns Path argument codec for list item.
*
- * @param type Type of list item
- * @param schema Schema of list item
+ * @param listClz Type of list item
+ * @param type Schema of list item
* @return Path argument codec for supplied list item.
*/
- IdentifiableItemCodec getPathArgumentCodec(Class<?> type, ListSchemaNode schema);
+ IdentifiableItemCodec getPathArgumentCodec(Class<?> listClz, ListRuntimeType type);
/**
* Return the codec loader associated with this factory.
import net.bytebuddy.matcher.ElementMatchers;
import org.eclipse.jdt.annotation.NonNull;
import org.opendaylight.mdsal.binding.dom.codec.loader.CodecClassLoader.GeneratorResult;
+import org.opendaylight.mdsal.binding.runtime.api.NotificationRuntimeType;
import org.opendaylight.yangtools.yang.binding.DataObject;
import org.opendaylight.yangtools.yang.binding.EventInstantAware;
import org.opendaylight.yangtools.yang.binding.Notification;
import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
import org.opendaylight.yangtools.yang.data.api.schema.DistinctNodeContainer;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
-import org.opendaylight.yangtools.yang.model.api.NotificationDefinition;
-final class NotificationCodecContext<D extends DataObject & Notification>
- extends DataObjectCodecContext<D, NotificationDefinition> {
+final class NotificationCodecContext<D extends DataObject & Notification<D>>
+ extends DataObjectCodecContext<D, NotificationRuntimeType> {
private static final Generic EVENT_INSTANT_AWARE = TypeDefinition.Sort.describe(EventInstantAware.class);
private static final String EVENT_INSTANT_NAME;
private final MethodHandle eventProxy;
- NotificationCodecContext(final Class<?> key, final NotificationDefinition schema,
+ NotificationCodecContext(final Class<?> key, final NotificationRuntimeType schema,
final CodecContextFactory factory) {
super(DataContainerCodecPrototype.from(key, schema, factory));
final Class<D> bindingClass = getBindingClass();
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
-import java.util.Iterator;
import java.util.List;
import java.util.Optional;
+import java.util.function.BiFunction;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;
+import org.opendaylight.mdsal.binding.dom.codec.api.IncorrectNestingException;
+import org.opendaylight.mdsal.binding.model.api.JavaTypeName;
+import org.opendaylight.mdsal.binding.runtime.api.ActionRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.BindingRuntimeContext;
+import org.opendaylight.mdsal.binding.runtime.api.BindingRuntimeTypes;
+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.DataRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.NotificationRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.RuntimeType;
import org.opendaylight.mdsal.binding.spec.naming.BindingMapping;
import org.opendaylight.mdsal.binding.spec.reflect.BindingReflections;
import org.opendaylight.yangtools.util.ClassLoaderUtils;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
-import org.opendaylight.yangtools.yang.model.api.ActionDefinition;
import org.opendaylight.yangtools.yang.model.api.ChoiceSchemaNode;
import org.opendaylight.yangtools.yang.model.api.ContainerLike;
import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
-import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
+import org.opendaylight.yangtools.yang.model.api.DocumentedNode.WithStatus;
import org.opendaylight.yangtools.yang.model.api.Module;
-import org.opendaylight.yangtools.yang.model.api.NotificationDefinition;
import org.opendaylight.yangtools.yang.model.api.RpcDefinition;
import org.opendaylight.yangtools.yang.model.api.stmt.SchemaNodeIdentifier.Absolute;
-import org.opendaylight.yangtools.yang.model.api.stmt.SchemaTreeEffectiveStatement;
-final class SchemaRootCodecContext<D extends DataObject> extends DataContainerCodecContext<D, EffectiveModelContext> {
+final class SchemaRootCodecContext<D extends DataObject> extends DataContainerCodecContext<D, BindingRuntimeTypes> {
private final LoadingCache<Class<? extends DataObject>, DataContainerCodecContext<?, ?>> childrenByClass =
CacheBuilder.newBuilder().build(new CacheLoader<>() {
@Override
public NotificationCodecContext<?> load(final Class<?> key) {
checkArgument(key.isInterface(), "Supplied class must be interface.");
+
+ // TODO: we should be able to work with bindingChild() instead of schemaTreeChild() here
final QName qname = BindingReflections.findQName(key);
- final NotificationDefinition schema = getSchema().findNotification(qname).orElseThrow(
- () -> new IllegalArgumentException("Supplied " + key + " is not valid notification"));
- return new NotificationCodecContext<>(key, schema, factory());
+ final RuntimeType child = getType().schemaTreeChild(qname);
+ checkArgument(child instanceof NotificationRuntimeType, "Supplied %s is not valid notification",
+ key);
+ return new NotificationCodecContext<>(key, (NotificationRuntimeType) child, factory());
}
});
.build(new CacheLoader<Class<?>, ContainerNodeCodecContext<?>>() {
@Override
public ContainerNodeCodecContext<?> load(final Class<?> key) {
+ final BiFunction<BindingRuntimeTypes, QName, Optional<? extends ContainerLikeRuntimeType<?, ?>>> lookup;
+ if (RpcInput.class.isAssignableFrom(key)) {
+ lookup = BindingRuntimeTypes::findRpcInput;
+ } else if (RpcOutput.class.isAssignableFrom(key)) {
+ lookup = BindingRuntimeTypes::findRpcOutput;
+ } else {
+ 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);
final QNameModule qnameModule = qname.getModule();
- final Module module = getSchema().findModule(qnameModule).orElseThrow(
- () -> new IllegalArgumentException("Failed to find module for " + qnameModule));
+ final Module module = context.getEffectiveModelContext().findModule(qnameModule)
+ .orElseThrow(() -> new IllegalArgumentException("Failed to find module for " + qnameModule));
final String className = BindingMapping.getClassName(qname);
for (final RpcDefinition potential : module.getRpcs()) {
if (key.getSimpleName().equals(BindingMapping.getClassName(potentialQName) + className)) {
final ContainerLike schema = getRpcDataSchema(potential, qname);
checkArgument(schema != null, "Schema for %s does not define input / output.", potentialQName);
- return (ContainerNodeCodecContext<?>) DataContainerCodecPrototype.from(key, schema, factory())
- .get();
+
+ final ContainerLikeRuntimeType<?, ?> type = lookup.apply(context.getTypes(), potentialQName)
+ .orElseThrow(() -> new IllegalArgumentException("Cannot find runtime type for " + key));
+
+ return (ContainerNodeCodecContext) DataContainerCodecPrototype.from(key,
+ (ContainerLikeRuntimeType<?, ?>) type, factory).get();
}
}
private final LoadingCache<QName, DataContainerCodecContext<?,?>> childrenByQName =
CacheBuilder.newBuilder().build(new CacheLoader<>() {
@Override
- public DataContainerCodecContext<?, ?> load(final QName qname) {
- final DataSchemaNode childSchema = getSchema().dataChildByName(qname);
- childNonNull(childSchema, qname, "Argument %s is not valid child of %s", qname, getSchema());
+ public DataContainerCodecContext<?, ?> load(final QName qname) throws ClassNotFoundException {
+ final var type = getType();
+ final var child = childNonNull(type.schemaTreeChild(qname), qname,
+ "Argument %s is not valid child of %s", qname, type);
+ if (!(child instanceof DataRuntimeType)) {
+ throw IncorrectNestingException.create("Argument %s is not valid data tree child of %s", qname,
+ type);
+ }
+
+ // TODO: improve this check?
+ final var childSchema = child.statement();
if (childSchema instanceof DataNodeContainer || childSchema instanceof ChoiceSchemaNode) {
- @SuppressWarnings("unchecked")
- final Class<? extends DataObject> childCls = (Class<? extends DataObject>)
- factory().getRuntimeContext().getClassForSchema(childSchema);
- return streamChild(childCls);
+ return streamChild(factory().getRuntimeContext().loadClass(child.javaType()));
}
throw new UnsupportedOperationException("Unsupported child type " + childSchema.getClass());
CacheBuilder.newBuilder().build(new CacheLoader<>() {
@Override
public RpcInputCodec<?> load(final Absolute key) {
- final ContainerLike schema = getRpcDataSchema(getSchema(), key);
- @SuppressWarnings("unchecked")
- final Class<? extends DataContainer> cls = (Class<? extends DataContainer>)
- factory().getRuntimeContext().getClassForSchema(schema);
- return getRpc(cls);
+ final var rpcName = key.firstNodeIdentifier();
+ final var context = factory().getRuntimeContext();
+
+ final Class<? extends DataContainer> container;
+ switch (key.lastNodeIdentifier().getLocalName()) {
+ case "input":
+ container = context.getRpcInput(rpcName);
+ break;
+ case "output":
+ container = context.getRpcOutput(rpcName);
+ break;
+ default:
+ throw new IllegalArgumentException("Unhandled path " + key);
+ }
+
+ return getRpc(container);
}
});
CacheBuilder.newBuilder().build(new CacheLoader<>() {
@Override
public NotificationCodecContext<?> load(final Absolute key) {
- final SchemaTreeEffectiveStatement<?> stmt = getSchema().findSchemaTreeNode(key)
- .orElseThrow(() -> new IllegalArgumentException("Cannot find statement at " + key));
- checkArgument(stmt instanceof NotificationDefinition, "Statement %s is not a notification", stmt);
-
- @SuppressWarnings("unchecked")
- final Class<? extends Notification<?>> clz = (Class<? extends Notification<?>>)
- factory().getRuntimeContext().getClassForSchema((NotificationDefinition) stmt);
- return getNotification(clz);
+ final Class<?> cls = factory().getRuntimeContext().getClassForSchema(key);
+ checkArgument(Notification.class.isAssignableFrom(cls), "Path %s does not represent a notification",
+ key);
+ return getNotificationImpl(cls);
}
});
- private SchemaRootCodecContext(final DataContainerCodecPrototype<EffectiveModelContext> dataPrototype) {
+ private SchemaRootCodecContext(final DataContainerCodecPrototype<BindingRuntimeTypes> dataPrototype) {
super(dataPrototype);
}
return new SchemaRootCodecContext<>(DataContainerCodecPrototype.rootPrototype(factory));
}
+ @Override
+ public WithStatus getSchema() {
+ return getType().getEffectiveModelContext();
+ }
+
@SuppressWarnings("unchecked")
@Override
public <C extends DataObject> DataContainerCodecContext<C, ?> streamChild(final Class<C> childClass) {
return getOrRethrow(actionsByClass, action);
}
+ NotificationCodecContext<?> getNotification(final Absolute notification) {
+ return getOrRethrow(notificationsByPath, notification);
+ }
+
NotificationCodecContext<?> getNotification(final Class<? extends Notification<?>> notification) {
- return getOrRethrow(notificationsByClass, notification);
+ return getNotificationImpl(notification);
}
- NotificationCodecContext<?> getNotification(final Absolute notification) {
- return getOrRethrow(notificationsByPath, notification);
+ private NotificationCodecContext<?> getNotificationImpl(final Class<?> notification) {
+ return getOrRethrow(notificationsByClass, notification);
}
ContainerNodeCodecContext<?> getRpc(final Class<? extends DataContainer> rpcInputOrOutput) {
}
DataContainerCodecContext<?, ?> createDataTreeChildContext(final Class<? extends DataObject> key) {
- final QName qname = BindingReflections.findQName(key);
- final DataSchemaNode childSchema = childNonNull(getSchema().dataChildByName(qname), key,
+ final RuntimeType childSchema = childNonNull(getType().bindingChild(JavaTypeName.create(key)), key,
"%s is not top-level item.", key);
- return DataContainerCodecPrototype.from(key, childSchema, factory()).get();
+ if (childSchema instanceof CompositeRuntimeType && childSchema instanceof DataRuntimeType) {
+ return DataContainerCodecPrototype.from(key, (CompositeRuntimeType) childSchema, factory()).get();
+ }
+ throw IncorrectNestingException.create("%s is not a valid data tree child of %s", key, this);
}
ActionCodecContext createActionContext(final Class<? extends Action<?, ?, ?>> action) {
final ParameterizedType paramType = optParamType.get();
final Type[] args = paramType.getActualTypeArguments();
checkArgument(args.length == expectedArgsLength, "Unexpected (%s) Action generatic arguments", args.length);
- final ActionDefinition schema = factory().getRuntimeContext().getActionDefinition(action);
+ final ActionRuntimeType schema = factory().getRuntimeContext().getActionDefinition(action);
return new ActionCodecContext(
- DataContainerCodecPrototype.from(asClass(args[inputOffset], RpcInput.class), schema.getInput(),
- factory()).get(),
- DataContainerCodecPrototype.from(asClass(args[outputOffset], RpcOutput.class), schema.getOutput(),
- factory()).get());
+ DataContainerCodecPrototype.from(asClass(args[inputOffset], RpcInput.class), schema.input(),
+ factory()).get(),
+ DataContainerCodecPrototype.from(asClass(args[outputOffset], RpcOutput.class), schema.output(),
+ factory()).get());
}
private static <T extends DataObject> Class<? extends T> asClass(final Type type, final Class<T> target) {
* @param qname input or output QName with namespace same as RPC
* @return input or output schema. Returns null if RPC does not have input/output specified.
*/
+ @SuppressFBWarnings(value = "UPM_UNCALLED_PRIVATE_METHOD",
+ justification = "https://github.com/spotbugs/spotbugs/issues/811")
private static @Nullable ContainerLike getRpcDataSchema(final @NonNull RpcDefinition rpc,
final @NonNull QName qname) {
requireNonNull(rpc, "Rpc Schema must not be null");
}
}
- /**
- * Returns RPC Input or Output Data container from RPC definition.
- *
- * @param schema SchemaContext in which lookup should be performed.
- * @param path Schema path of RPC input/output data container
- * @return Notification schema or null, if notification is not present in schema context.
- */
- @SuppressFBWarnings(value = "UPM_UNCALLED_PRIVATE_METHOD",
- justification = "https://github.com/spotbugs/spotbugs/issues/811")
- private static @Nullable ContainerLike getRpcDataSchema(final @NonNull EffectiveModelContext schema,
- final @NonNull Absolute path) {
- requireNonNull(schema, "Schema context must not be null.");
- requireNonNull(path, "Schema path must not be null.");
- final Iterator<QName> it = path.getNodeIdentifiers().iterator();
- checkArgument(it.hasNext(), "Rpc must have QName.");
- final QName rpcName = it.next();
- checkArgument(it.hasNext(), "input or output must be part of path.");
- final QName inOrOut = it.next();
- for (final RpcDefinition potential : schema.getOperations()) {
- if (rpcName.equals(potential.getQName())) {
- return getRpcDataSchema(potential, inOrOut);
- }
- }
- return null;
- }
-
ChoiceNodeCodecContext<?> createChoiceDataContext(final Class<? extends DataObject> caseType) {
final Class<?> choiceClass = findCaseChoice(caseType);
checkArgument(choiceClass != null, "Class %s is not a valid case representation", caseType);
- final DataSchemaNode schema = factory().getRuntimeContext().getSchemaDefinition(choiceClass);
- checkArgument(schema instanceof ChoiceSchemaNode, "Class %s does not refer to a choice", caseType);
+ final CompositeRuntimeType schema = factory().getRuntimeContext().getSchemaDefinition(choiceClass);
+ checkArgument(schema instanceof ChoiceRuntimeType, "Class %s does not refer to a choice", caseType);
- final DataContainerCodecContext<?, ChoiceSchemaNode> choice = DataContainerCodecPrototype.from(choiceClass,
- (ChoiceSchemaNode)schema, factory()).get();
+ final DataContainerCodecContext<?, ChoiceRuntimeType> choice = DataContainerCodecPrototype.from(choiceClass,
+ (ChoiceRuntimeType)schema, factory()).get();
Verify.verify(choice instanceof ChoiceNodeCodecContext);
return (ChoiceNodeCodecContext<?>) choice;
}
import java.util.List;
import java.util.concurrent.Callable;
import org.opendaylight.mdsal.binding.model.api.GeneratedTransferObject;
-import org.opendaylight.mdsal.binding.model.api.GeneratedType;
+import org.opendaylight.mdsal.binding.model.api.Type;
import org.opendaylight.mdsal.binding.runtime.api.RuntimeGeneratedUnion;
import org.opendaylight.mdsal.binding.spec.naming.BindingMapping;
import org.opendaylight.yangtools.concepts.IllegalArgumentCodec;
final BindingCodecContext codecContext) {
return () -> {
final List<String> unionProperties = extractUnionProperties(codecContext.getRuntimeContext()
- .getTypeWithSchema(unionCls).getKey());
+ .getTypeWithSchema(unionCls).javaType());
final List<TypeDefinition<?>> unionTypes = unionType.getTypes();
verify(unionTypes.size() == unionProperties.size(), "Mismatched union types %s and properties %s",
unionTypes, unionProperties);
};
}
- private static List<String> extractUnionProperties(final GeneratedType type) {
+ private static List<String> extractUnionProperties(final Type type) {
verify(type instanceof GeneratedTransferObject, "Unexpected runtime type %s", type);
GeneratedTransferObject gto = (GeneratedTransferObject) type;
() -> codecContext.fromYangInstanceIdentifier(yiid));
assertThat(ex.getMessage(),
startsWith("Argument (urn:opendaylight:params:xml:ns:yang:controller:md:sal:test:bi:ba:notification"
- + "?revision=2015-02-05)out-of-pixie-dust-notification is not valid child of "));
+ + "?revision=2015-02-05)out-of-pixie-dust-notification is not valid data tree child of "));
}
@Test
*/
package org.opendaylight.mdsal.binding.dom.codec.impl;
-import static org.hamcrest.CoreMatchers.startsWith;
-import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThrows;
final var iid = InstanceIdentifier.create((Class) OutOfPixieDustNotification.class);
final var ex = assertThrows(IllegalArgumentException.class, () -> codecContext.toYangInstanceIdentifier(iid));
- assertThat(ex.getMessage(), startsWith("Supplied class must not be a notification ("));
+ assertEquals("interface org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test"
+ + ".bi.ba.notification.rev150205.OutOfPixieDustNotification is not a valid data tree child of "
+ + "SchemaRootCodecContext [interface org.opendaylight.yangtools.yang.binding.DataRoot]", ex.getMessage());
}
@Test
<groupId>org.opendaylight.yangtools</groupId>
<artifactId>yang-model-util</artifactId>
</dependency>
+ <dependency>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>yang-xpath-api</artifactId>
+ </dependency>
<dependency>
<groupId>org.opendaylight.mdsal</groupId>
<artifactId>yang-binding</artifactId>
import static com.google.common.base.Verify.verify;
import com.google.common.base.Stopwatch;
-import java.util.Collection;
import java.util.HashMap;
-import java.util.IdentityHashMap;
import java.util.Map;
import org.eclipse.jdt.annotation.NonNull;
import org.opendaylight.mdsal.binding.generator.impl.reactor.AbstractExplicitGenerator;
import org.opendaylight.mdsal.binding.generator.impl.reactor.Generator;
import org.opendaylight.mdsal.binding.generator.impl.reactor.GeneratorReactor;
+import org.opendaylight.mdsal.binding.generator.impl.reactor.IdentityGenerator;
import org.opendaylight.mdsal.binding.generator.impl.reactor.ModuleGenerator;
+import org.opendaylight.mdsal.binding.generator.impl.reactor.RpcGenerator;
+import org.opendaylight.mdsal.binding.generator.impl.reactor.RpcInputGenerator;
+import org.opendaylight.mdsal.binding.generator.impl.reactor.RpcOutputGenerator;
import org.opendaylight.mdsal.binding.generator.impl.reactor.TypeBuilderFactory;
+import org.opendaylight.mdsal.binding.generator.impl.rt.DefaultBindingRuntimeTypes;
import org.opendaylight.mdsal.binding.model.api.GeneratedType;
-import org.opendaylight.mdsal.binding.model.api.Type;
+import org.opendaylight.mdsal.binding.model.api.JavaTypeName;
import org.opendaylight.mdsal.binding.runtime.api.BindingRuntimeTypes;
+import org.opendaylight.mdsal.binding.runtime.api.IdentityRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.InputRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.ModuleRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.OutputRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.RuntimeType;
import org.opendaylight.yangtools.concepts.Mutable;
import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.model.api.AugmentationSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.DocumentedNode.WithStatus;
+import org.opendaylight.yangtools.yang.common.QNameModule;
import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
-import org.opendaylight.yangtools.yang.model.api.TypedDataSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
-import org.opendaylight.yangtools.yang.model.api.stmt.AugmentEffectiveStatement;
-import org.opendaylight.yangtools.yang.model.api.stmt.IdentityEffectiveStatement;
-import org.opendaylight.yangtools.yang.model.api.stmt.TypedefEffectiveStatement;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
final class BindingRuntimeTypesFactory implements Mutable {
private static final Logger LOG = LoggerFactory.getLogger(BindingRuntimeTypesFactory.class);
- private final Map<Type, AugmentationSchemaNode> augmentationToSchema = new HashMap<>();
- private final Map<Type, WithStatus> typeToSchema = new HashMap<>();
- private final Map<QName, Type> identities = new HashMap<>();
-
- // Note: we are keying through WithStatus, but these nodes compare on semantics, so equivalent schema nodes
- // can result in two distinct types. We certainly need to keep them separate.
- private final Map<WithStatus, Type> schemaToType = new IdentityHashMap<>();
+ // Modules, indexed by their QNameModule
+ private final Map<QNameModule, ModuleRuntimeType> modules = new HashMap<>();
+ // Identities, indexed by their QName
+ private final Map<QName, IdentityRuntimeType> identities = new HashMap<>();
+ // All known types, indexed by their JavaTypeName
+ private final Map<JavaTypeName, RuntimeType> allTypes = new HashMap<>();
+ // All RpcOutputs, indexed by their RPC's QName
+ private final Map<QName, OutputRuntimeType> rpcOutputs = new HashMap<>();
+ // All RpcInputs, indexed by their RPC's QName
+ private final Map<QName, InputRuntimeType> rpcInputs = new HashMap<>();
private BindingRuntimeTypesFactory() {
// Hidden on purpose
}
static @NonNull BindingRuntimeTypes createTypes(final @NonNull EffectiveModelContext context) {
- final Collection<ModuleGenerator> moduleGens = new GeneratorReactor(context)
- .execute(TypeBuilderFactory.runtime())
- .values();
+ final var moduleGens = new GeneratorReactor(context).execute(TypeBuilderFactory.runtime());
final Stopwatch sw = Stopwatch.createStarted();
final BindingRuntimeTypesFactory factory = new BindingRuntimeTypesFactory();
- factory.indexTypes(moduleGens);
+ factory.indexModules(moduleGens);
LOG.debug("Indexed {} generators in {}", moduleGens.size(), sw);
- return new DefaultBindingRuntimeTypes(context, factory.augmentationToSchema, factory.typeToSchema,
- factory.schemaToType, factory.identities);
+ return new DefaultBindingRuntimeTypes(context, factory.modules, factory.allTypes, factory.identities,
+ factory.rpcInputs, factory.rpcOutputs);
}
- private void indexTypes(final Iterable<? extends Generator> generators) {
- for (Generator gen : generators) {
- gen.generatedType().ifPresent(type -> indexType(gen, type));
- indexTypes(gen);
- }
- }
+ private void indexModules(final Map<QNameModule, ModuleGenerator> moduleGens) {
+ for (var entry : moduleGens.entrySet()) {
+ final var modGen = entry.getValue();
- private void indexType(final @NonNull Generator generator, final @NonNull GeneratedType type) {
- if (generator instanceof AbstractExplicitGenerator) {
- final EffectiveStatement<?, ?> stmt = ((AbstractExplicitGenerator<?>) generator).statement();
- if (stmt instanceof IdentityEffectiveStatement) {
- identities.put(((IdentityEffectiveStatement) stmt).argument(), type);
- } else if (stmt instanceof AugmentEffectiveStatement) {
- verify(stmt instanceof AugmentationSchemaNode, "Unexpected statement %s", stmt);
- augmentationToSchema.put(type, (AugmentationSchemaNode) stmt);
- }
+ // index the module's runtime type
+ modGen.runtimeType().ifPresent(type -> {
+ safePut(modules, "modules", entry.getKey(), type);
+ });
- final WithStatus schema;
- if (stmt instanceof TypedDataSchemaNode) {
- schema = ((TypedDataSchemaNode) stmt).getType();
- } else if (stmt instanceof TypedefEffectiveStatement) {
- schema = ((TypedefEffectiveStatement) stmt).getTypeDefinition();
- } else if (stmt instanceof WithStatus) {
- schema = (WithStatus) stmt;
- } else {
- return;
+ // index module's identities and RPC input/outputs
+ for (var gen : modGen) {
+ if (gen instanceof IdentityGenerator) {
+ ((IdentityGenerator) gen).runtimeType().ifPresent(identity -> {
+ safePut(identities, "identities", identity.statement().argument(), identity);
+ });
+ }
+ // FIXME: do not collect these once we they generate a proper RuntimeType
+ if (gen instanceof RpcGenerator) {
+ final QName rpcName = ((RpcGenerator) gen).statement().argument();
+ for (var subgen : gen) {
+ if (subgen instanceof RpcInputGenerator) {
+ ((RpcInputGenerator) subgen).runtimeType()
+ .ifPresent(input -> rpcInputs.put(rpcName, input));
+ } else if (subgen instanceof RpcOutputGenerator) {
+ ((RpcOutputGenerator) subgen).runtimeType()
+ .ifPresent(output -> rpcOutputs.put(rpcName, output));
+ }
+ }
+ }
}
+ }
- typeToSchema.put(type, schema);
- final var prevType = schemaToType.put(schema, type);
- verify(prevType == null, "Conflicting types %s and %s on %s", type, prevType, schema);
+ indexRuntimeTypes(moduleGens.values());
+ }
+
+ private void indexRuntimeTypes(final Iterable<? extends Generator> generators) {
+ for (Generator gen : generators) {
+ if (gen instanceof AbstractExplicitGenerator && gen.generatedType().isPresent()) {
+ final var type = ((AbstractExplicitGenerator<?, ?>) gen).runtimeType().orElseThrow();
+ final var javaType = type.javaType();
+ if (javaType instanceof GeneratedType) {
+ final var name = javaType.getIdentifier();
+ final var prev = allTypes.put(name, type);
+ verify(prev == null || prev == type, "Conflict on runtime type mapping of %s between %s and %s",
+ name, prev, type);
+ }
+ }
+ indexRuntimeTypes(gen);
}
}
+
+ private static <K, V> void safePut(final Map<K, V> map, final String name, final K key, final V value) {
+ final var prev = map.put(key, value);
+ verify(prev == null, "Conflict in %s, key %s conflicts on %s versus %s", name, key, prev, value);
+ }
}
+++ /dev/null
-/*
- * Copyright (c) 2018 Pantheon Technologies, s.r.o. 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.generator.impl;
-
-import static com.google.common.base.Verify.verify;
-import static com.google.common.base.Verify.verifyNotNull;
-import static java.util.Objects.requireNonNull;
-
-import com.google.common.base.MoreObjects;
-import com.google.common.collect.BiMap;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.ImmutableMultimap;
-import com.google.common.collect.Multimap;
-import com.google.common.collect.MultimapBuilder;
-import java.util.Collection;
-import java.util.IdentityHashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Optional;
-import java.util.Set;
-import java.util.stream.Collectors;
-import org.eclipse.jdt.annotation.NonNull;
-import org.opendaylight.mdsal.binding.model.api.GeneratedType;
-import org.opendaylight.mdsal.binding.model.api.Type;
-import org.opendaylight.mdsal.binding.runtime.api.BindingRuntimeTypes;
-import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.model.api.AugmentationSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.DocumentedNode.WithStatus;
-import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
-import org.opendaylight.yangtools.yang.model.api.stmt.CaseEffectiveStatement;
-import org.opendaylight.yangtools.yang.model.api.stmt.ChoiceEffectiveStatement;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-final class DefaultBindingRuntimeTypes implements BindingRuntimeTypes {
- private static final Logger LOG = LoggerFactory.getLogger(DefaultBindingRuntimeTypes.class);
-
- private final @NonNull EffectiveModelContext schemaContext;
- private final ImmutableMap<Type, AugmentationSchemaNode> typeToAugmentation;
- private final ImmutableMap<Type, WithStatus> typeToSchema;
- private final ImmutableMultimap<Type, Type> choiceToCases;
- private final ImmutableMap<QName, Type> identities;
- // Not Immutable as we use two different implementations
- private final Map<WithStatus, Type> schemaToType;
-
- DefaultBindingRuntimeTypes(final EffectiveModelContext schemaContext,
- final Map<Type, AugmentationSchemaNode> typeToAugmentation,
- final Map<Type, WithStatus> typeToSchema, final Map<WithStatus, Type> schemaToType,
- final Map<QName, Type> identities) {
- this.schemaContext = requireNonNull(schemaContext);
- this.typeToAugmentation = ImmutableMap.copyOf(typeToAugmentation);
- this.typeToSchema = ImmutableMap.copyOf(typeToSchema);
- this.identities = ImmutableMap.copyOf(identities);
-
- // Careful to use identity for SchemaNodes, but only if needed
- // FIXME: 8.0.0: YT should be switching to identity for equals(), so this should become unnecessary
- Map<WithStatus, Type> copy;
- try {
- copy = ImmutableMap.copyOf(schemaToType);
- } catch (IllegalArgumentException e) {
- LOG.debug("Equality-duplicates found in {}", schemaToType.keySet());
- copy = new IdentityHashMap<>(schemaToType);
- }
-
- this.schemaToType = copy;
-
- // Two-phase indexing of choice/case nodes. First we load all choices. Note we are using typeToSchema argument,
- // not field, so as not to instantiate its entrySet.
- final Set<GeneratedType> choiceTypes = typeToSchema.entrySet().stream()
- .filter(entry -> entry.getValue() instanceof ChoiceEffectiveStatement)
- .map(entry -> {
- final Type key = entry.getKey();
- verify(key instanceof GeneratedType, "Unexpected choice type %s", key);
- return (GeneratedType) key;
- })
- .collect(Collectors.toUnmodifiableSet());
-
- final Multimap<Type, Type> builder = MultimapBuilder.hashKeys(choiceTypes.size()).arrayListValues().build();
- for (Entry<Type, WithStatus> entry : typeToSchema.entrySet()) {
- if (entry.getValue() instanceof CaseEffectiveStatement) {
- final Type type = entry.getKey();
- verify(type instanceof GeneratedType, "Unexpected case type %s", type);
- builder.put(verifyNotNull(implementedChoiceType(((GeneratedType) type).getImplements(), choiceTypes),
- "Cannot determine choice type for %s", type), type);
- }
- }
-
- choiceToCases = ImmutableMultimap.copyOf(builder);
- }
-
- private static GeneratedType implementedChoiceType(final List<Type> impls, final Set<GeneratedType> choiceTypes) {
- for (Type impl : impls) {
- if (impl instanceof GeneratedType && choiceTypes.contains(impl)) {
- return (GeneratedType) impl;
- }
- }
- return null;
- }
-
- DefaultBindingRuntimeTypes(final EffectiveModelContext schemaContext,
- final Map<Type, AugmentationSchemaNode> typeToAugmentation,
- final BiMap<Type, WithStatus> typeToDefiningSchema, final Map<QName, Type> identities) {
- this(schemaContext, typeToAugmentation, typeToDefiningSchema, typeToDefiningSchema.inverse(), identities);
- }
-
- @Override
- public EffectiveModelContext getEffectiveModelContext() {
- return schemaContext;
- }
-
- @Override
- public Optional<AugmentationSchemaNode> findAugmentation(final Type type) {
- return Optional.ofNullable(typeToAugmentation.get(type));
- }
-
- @Override
- public Optional<Type> findIdentity(final QName qname) {
- return Optional.ofNullable(identities.get(qname));
- }
-
- @Override
- public Optional<WithStatus> findSchema(final Type type) {
- return Optional.ofNullable(typeToSchema.get(type));
- }
-
- @Override
- public Optional<Type> findType(final WithStatus schema) {
- return Optional.ofNullable(schemaToType.get(schema));
- }
-
- @Override
- public Optional<Type> findOriginalAugmentationType(final AugmentationSchemaNode augment) {
- // If the augment statement does not contain any child nodes, we did not generate an augmentation, as it would
- // be plain littering.
- // FIXME: MDSAL-695: this check is rather costly (involves filtering), can we just rely on the not being found
- // in the end? all we are saving is essentially two map lookups after all...
- if (augment.getChildNodes().isEmpty()) {
- return Optional.empty();
- }
-
- // FIXME: MDSAL-695: We should have enough information from mdsal-binding-generator to receive a (sparse) Map
- // for current -> original lookup. When combined with schemaToType, this amounts to the
- // inverse view of what 'typeToSchema' holds
- AugmentationSchemaNode current = augment;
- while (true) {
- // If this augmentation has been added through 'uses foo { augment bar { ... } }', we need to invert that
- // walk and arrive at the original declaration site, as that is where we generated 'grouping foo's
- // augmentation. That site may have a different module, hence the augment namespace may be different.
- final Optional<AugmentationSchemaNode> original = current.getOriginalDefinition();
- if (original.isEmpty()) {
- return findType(current);
- }
- current = original.orElseThrow();
- }
- }
-
- @Override
- public Multimap<Type, Type> getChoiceToCases() {
- return choiceToCases;
- }
-
- @Override
- public Collection<Type> findCases(final Type choiceType) {
- return choiceToCases.get(choiceType);
- }
-
- @Override
- public String toString() {
- return MoreObjects.toStringHelper(this)
- .add("typeToAugmentation", typeToAugmentation)
- .add("typeToSchema", typeToSchema)
- .add("choiceToCases", choiceToCases)
- .add("identities", identities)
- .toString();
- }
-}
import java.util.Comparator;
import java.util.Iterator;
+import java.util.List;
import org.eclipse.jdt.annotation.NonNull;
import org.opendaylight.mdsal.binding.generator.impl.reactor.CollisionDomain.Member;
+import org.opendaylight.mdsal.binding.generator.impl.rt.DefaultAugmentRuntimeType;
import org.opendaylight.mdsal.binding.model.api.GeneratedType;
import org.opendaylight.mdsal.binding.model.api.type.builder.GeneratedTypeBuilder;
import org.opendaylight.mdsal.binding.model.api.type.builder.GeneratedTypeBuilderBase;
import org.opendaylight.mdsal.binding.model.ri.BindingTypes;
+import org.opendaylight.mdsal.binding.runtime.api.AugmentRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.RuntimeType;
import org.opendaylight.yangtools.odlext.model.api.AugmentIdentifierEffectiveStatement;
import org.opendaylight.yangtools.yang.common.AbstractQName;
import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
import org.opendaylight.yangtools.yang.model.api.stmt.AugmentEffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.SchemaTreeAwareEffectiveStatement;
import org.opendaylight.yangtools.yang.model.util.SchemaInferenceStack;
/**
* A generator corresponding to a {@code augment} statement. This class is further specialized for the two distinct uses
* an augment is used.
*/
-abstract class AbstractAugmentGenerator extends AbstractCompositeGenerator<AugmentEffectiveStatement> {
+abstract class AbstractAugmentGenerator
+ extends AbstractCompositeGenerator<AugmentEffectiveStatement, AugmentRuntimeType> {
/**
* Comparator comparing target path length. This is useful for quickly determining order the order in which two
* (or more) {@link AbstractAugmentGenerator}s need to be evaluated. This is necessary when augments are layered on
return otherIt.hasNext() ? -1 : 0;
};
- private AbstractCompositeGenerator<?> targetGen;
+ private AugmentEffectiveStatement effectiveStatement;
+ private AbstractCompositeGenerator<?, ?> targetGen;
- AbstractAugmentGenerator(final AugmentEffectiveStatement statement, final AbstractCompositeGenerator<?> parent) {
+ AbstractAugmentGenerator(final AugmentEffectiveStatement statement, final AbstractCompositeGenerator<?, ?> parent) {
super(statement, parent);
}
ClassPlacement classPlacement() {
// if the target is a choice we are NOT creating an explicit augmentation, but we still need a phantom to
// reserve the appropriate package name
- final AbstractCompositeGenerator<?> target = targetGenerator();
+ final AbstractCompositeGenerator<?, ?> target = targetGenerator();
return target instanceof ChoiceGenerator ? ClassPlacement.PHANTOM : super.classPlacement();
}
return builder.build();
}
+ @Override
+ final AugmentEffectiveStatement effectiveStatement() {
+ return verifyNotNull(effectiveStatement, "Effective statement not set in %s", this);
+ }
+
+ @Override
+ final AugmentRuntimeType createRuntimeType(final GeneratedType type, final AugmentEffectiveStatement statement,
+ final List<RuntimeType> children, final List<AugmentRuntimeType> augments) {
+ verify(statement instanceof TargetAugmentEffectiveStatement, "Unexpected statement %s", statement);
+ return new DefaultAugmentRuntimeType(type, ((TargetAugmentEffectiveStatement) statement).delegate(), children,
+ augments);
+ }
+
@Override
final void addAsGetterMethod(final GeneratedTypeBuilderBase<?> builder, final TypeBuilderFactory builderFactory) {
// Augments are never added as getters, as they are handled via Augmentable mechanics
}
- final void setTargetGenerator(final AbstractCompositeGenerator<?> targetGenerator) {
+ final void setTargetGenerator(final AbstractCompositeGenerator<?, ?> targetGenerator) {
verify(targetGen == null, "Attempted to relink %s, already have target %s", this, targetGen);
targetGen = requireNonNull(targetGenerator);
}
- final @NonNull AbstractCompositeGenerator<?> targetGenerator() {
+ final @NonNull AbstractCompositeGenerator<?, ?> targetGenerator() {
return verifyNotNull(targetGen, "No target for %s", this);
}
+
+ final void setTargetStatement(final EffectiveStatement<?, ?> targetStatement) {
+ verify(targetStatement instanceof SchemaTreeAwareEffectiveStatement, "Unexpected target statement %s",
+ targetStatement);
+ effectiveStatement = new TargetAugmentEffectiveStatement(statement(),
+ (SchemaTreeAwareEffectiveStatement<?, ?>) targetStatement);
+ }
}
package org.opendaylight.mdsal.binding.generator.impl.reactor;
import static com.google.common.base.Verify.verify;
+import static com.google.common.base.Verify.verifyNotNull;
import static java.util.Objects.requireNonNull;
+import com.google.common.collect.ImmutableList;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
+import java.util.Optional;
import java.util.stream.Collectors;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;
-import org.opendaylight.mdsal.binding.generator.impl.tree.SchemaTreeChild;
-import org.opendaylight.mdsal.binding.generator.impl.tree.SchemaTreeParent;
import org.opendaylight.mdsal.binding.model.api.Enumeration;
import org.opendaylight.mdsal.binding.model.api.GeneratedTransferObject;
import org.opendaylight.mdsal.binding.model.api.GeneratedType;
import org.opendaylight.mdsal.binding.model.api.type.builder.GeneratedTypeBuilder;
import org.opendaylight.mdsal.binding.model.ri.BindingTypes;
+import org.opendaylight.mdsal.binding.runtime.api.AugmentRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.CompositeRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.RuntimeType;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.model.api.AddedByUsesAware;
import org.opendaylight.yangtools.yang.model.api.CopyableNode;
* with linking original instances in the tree iteration order. The part dealing with augment attachment lives mostly
* in {@link AugmentRequirement}.
*/
-public abstract class AbstractCompositeGenerator<T extends EffectiveStatement<?, ?>>
- extends AbstractExplicitGenerator<T> implements SchemaTreeParent<T> {
+public abstract class AbstractCompositeGenerator<S extends EffectiveStatement<?, ?>, R extends CompositeRuntimeType>
+ extends AbstractExplicitGenerator<S, R> {
private static final Logger LOG = LoggerFactory.getLogger(AbstractCompositeGenerator.class);
// FIXME: we want to allocate this lazily to lower memory footprint
private final @NonNull CollisionDomain domain = new CollisionDomain(this);
private final @NonNull List<Generator> childGenerators;
- /**
- * {@link SchemaTreeChild} children of this generator. Generator linkage is ensured on first access.
- */
- private final @NonNull List<SchemaTreeChild<?, ?>> schemaTreeChildren;
/**
* List of {@code augment} statements targeting this generator. This list is maintained only for the primary
* incarnation. This list is an evolving entity until after we have finished linkage of original statements. It is
* expected to be stable at the start of {@code step 2} in {@link GeneratorReactor#execute(TypeBuilderFactory)}.
*/
- private List<AbstractAugmentGenerator> augments = List.of();
+ private @NonNull List<AbstractAugmentGenerator> augments = List.of();
/**
* List of {@code grouping} statements this statement references. This field is set once by
* have some children which have not completed linking. Once we have completed linking of all children, including
* {@link #unlinkedChildren}, this will be set to {@code null}.
*/
- private List<AbstractCompositeGenerator<?>> unlinkedComposites = List.of();
+ private List<AbstractCompositeGenerator<?, ?>> unlinkedComposites = List.of();
/**
* List of children which have not had their original linked. This list starts of as null. When we first attempt
* linkage, it becomes non-null.
*/
private List<Generator> unlinkedChildren;
- AbstractCompositeGenerator(final T statement) {
+ AbstractCompositeGenerator(final S statement) {
super(statement);
-
- final var children = createChildren(statement);
- childGenerators = children.getKey();
- schemaTreeChildren = children.getValue();
+ childGenerators = createChildren(statement);
}
- AbstractCompositeGenerator(final T statement, final AbstractCompositeGenerator<?> parent) {
+ AbstractCompositeGenerator(final S statement, final AbstractCompositeGenerator<?, ?> parent) {
super(statement, parent);
-
- final var children = createChildren(statement);
- childGenerators = children.getKey();
- schemaTreeChildren = children.getValue();
+ childGenerators = createChildren(statement);
}
@Override
return childGenerators.iterator();
}
+ @NonNull S effectiveStatement() {
+ return statement();
+ }
+
+ @Override
+ public final R createRuntimeType() {
+ return generatedType()
+ .map(type -> {
+ final var stmt = effectiveStatement();
+ return createRuntimeType(type, stmt, indexChildren(stmt), augmentRuntimeTypes());
+ })
+ .orElse(null);
+ }
+
+ abstract @NonNull R createRuntimeType(@NonNull GeneratedType type, @NonNull S statement,
+ @NonNull List<RuntimeType> children, @NonNull List<AugmentRuntimeType> augments);
+
@Override
- public List<SchemaTreeChild<?, ?>> schemaTreeChildren() {
- for (var child : schemaTreeChildren) {
- if (child instanceof SchemaTreePlaceholder) {
- ((SchemaTreePlaceholder<?, ?>) child).setGenerator(this);
+ final R rebaseRuntimeType(final R type, final S statement) {
+ return createRuntimeType(type.javaType(), statement, indexChildren(statement), augmentRuntimeTypes());
+ }
+
+ private @NonNull List<RuntimeType> indexChildren(final @NonNull S statement) {
+ final var childMap = new ArrayList<RuntimeType>();
+
+ for (var stmt : statement.effectiveSubstatements()) {
+ if (stmt instanceof SchemaTreeEffectiveStatement) {
+ final var child = (SchemaTreeEffectiveStatement<?>) stmt;
+ final var qname = child.getIdentifier();
+
+ // Note: getOriginal() is needed for augments of cases
+ @SuppressWarnings("rawtypes")
+ final AbstractExplicitGenerator childGen = getOriginal().resolveRuntimeChild(statement.argument(),
+ qname);
+ @SuppressWarnings("unchecked")
+ final Optional<RuntimeType> rt = childGen.runtimeTypeOf(child);
+ rt.ifPresent(childMap::add);
}
}
- return schemaTreeChildren;
+
+ return childMap;
+ }
+
+ private @NonNull AbstractExplicitGenerator<?, ?> resolveRuntimeChild(final Object parentArg, final QName qname) {
+ final var exact = findSchemaTreeGenerator(qname);
+ if (exact != null) {
+ return exact;
+ }
+
+ // TODO: this is quite hacky: what we are trying to do is rebase the lookup QName to parent QName, as the only
+ // way we should be arriving here is through uses -> grouping squash
+ verify(parentArg instanceof QName, "Cannot deal with parent argument %s", parentArg);
+ final var namespace = ((QName) parentArg).getModule();
+
+ verify(namespace.equals(qname.getModule()), "Cannot deal with %s in namespace %s", qname, namespace);
+ final var local = qname.bindTo(getQName().getModule());
+ return verifyNotNull(findSchemaTreeGenerator(local), "Failed to find %s as %s in %s", qname, local, this);
+ }
+
+ final @NonNull List<AbstractAugmentGenerator> augments() {
+ return augments;
+ }
+
+ private @NonNull List<AugmentRuntimeType> augmentRuntimeTypes() {
+ // Augments are attached to original instance: at least CaseGenerator is instantiated in non-original place
+ // and thus we need to go back to original
+ return getOriginal().augments.stream()
+ .map(AbstractAugmentGenerator::runtimeType)
+ .filter(Optional::isPresent)
+ .map(Optional::orElseThrow)
+ .collect(ImmutableList.toImmutableList());
}
@Override
return childGenerators.isEmpty();
}
- final @Nullable AbstractExplicitGenerator<?> findGenerator(final List<EffectiveStatement<?, ?>> stmtPath) {
+ final @Nullable AbstractExplicitGenerator<?, ?> findGenerator(final List<EffectiveStatement<?, ?>> stmtPath) {
return findGenerator(MatchStrategy.identity(), stmtPath, 0);
}
- final @Nullable AbstractExplicitGenerator<?> findGenerator(final MatchStrategy childStrategy,
+ final @Nullable AbstractExplicitGenerator<?, ?> findGenerator(final MatchStrategy childStrategy,
// TODO: Wouldn't this method be nicer with Deque<EffectiveStatement<?, ?>> ?
final List<EffectiveStatement<?, ?>> stmtPath, final int offset) {
final EffectiveStatement<?, ?> stmt = stmtPath.get(offset);
// Try direct children first, which is simple
- AbstractExplicitGenerator<?> ret = childStrategy.findGenerator(stmt, childGenerators);
+ AbstractExplicitGenerator<?, ?> ret = childStrategy.findGenerator(stmt, childGenerators);
if (ret != null) {
final int next = offset + 1;
if (stmtPath.size() == next) {
}
if (ret instanceof AbstractCompositeGenerator) {
// We know how to descend down
- return ((AbstractCompositeGenerator<?>) ret).findGenerator(childStrategy, stmtPath, next);
+ return ((AbstractCompositeGenerator<?, ?>) ret).findGenerator(childStrategy, stmtPath, next);
}
// Yeah, don't know how to continue here
return null;
requirements.add(((UsesAugmentGenerator) child).startLinkage());
}
if (child instanceof AbstractCompositeGenerator) {
- ((AbstractCompositeGenerator<?>) child).startUsesAugmentLinkage(requirements);
+ ((AbstractCompositeGenerator<?, ?>) child).startUsesAugmentLinkage(requirements);
}
}
}
if (unlinkedChildren == null) {
unlinkedChildren = childGenerators.stream()
.filter(AbstractExplicitGenerator.class::isInstance)
- .map(child -> (AbstractExplicitGenerator<?>) child)
+ .map(child -> (AbstractExplicitGenerator<?, ?>) child)
.collect(Collectors.toList());
}
while (it.hasNext()) {
final var child = it.next();
if (child instanceof AbstractExplicitGenerator) {
- if (((AbstractExplicitGenerator<?>) child).linkOriginalGenerator()) {
+ if (((AbstractExplicitGenerator<?, ?>) child).linkOriginalGenerator()) {
progress = LinkageProgress.SOME;
it.remove();
if (unlinkedComposites.isEmpty()) {
unlinkedComposites = new ArrayList<>();
}
- unlinkedComposites.add((AbstractCompositeGenerator<?>) child);
+ unlinkedComposites.add((AbstractCompositeGenerator<?, ?>) child);
}
}
}
}
@Override
- final AbstractCompositeGenerator<T> getOriginal() {
- return (AbstractCompositeGenerator<T>) super.getOriginal();
+ final AbstractCompositeGenerator<S, R> getOriginal() {
+ return (AbstractCompositeGenerator<S, R>) super.getOriginal();
}
@Override
- final AbstractCompositeGenerator<T> tryOriginal() {
- return (AbstractCompositeGenerator<T>) super.tryOriginal();
+ final AbstractCompositeGenerator<S, R> tryOriginal() {
+ return (AbstractCompositeGenerator<S, R>) super.tryOriginal();
}
- final <S extends EffectiveStatement<?, ?>> @Nullable OriginalLink<S> originalChild(final QName childQName) {
+ final <X extends EffectiveStatement<?, ?>, Y extends RuntimeType> @Nullable OriginalLink<X, Y> originalChild(
+ final QName childQName) {
// First try groupings/augments ...
var found = findInferredGenerator(childQName);
if (found != null) {
- return (OriginalLink<S>) OriginalLink.partial(found);
+ return (OriginalLink<X, Y>) OriginalLink.partial(found);
}
// ... no luck, we really need to start looking at our origin
final QName prevQName = childQName.bindTo(prev.getQName().getModule());
found = prev.findSchemaTreeGenerator(prevQName);
if (found != null) {
- return (OriginalLink<S>) found.originalLink();
+ return (OriginalLink<X, Y>) found.originalLink();
}
}
}
@Override
- final AbstractExplicitGenerator<?> findSchemaTreeGenerator(final QName qname) {
- final AbstractExplicitGenerator<?> found = super.findSchemaTreeGenerator(qname);
+ final AbstractExplicitGenerator<?, ?> findSchemaTreeGenerator(final QName qname) {
+ final AbstractExplicitGenerator<?, ?> found = super.findSchemaTreeGenerator(qname);
return found != null ? found : findInferredGenerator(qname);
}
return null;
}
- private @Nullable AbstractExplicitGenerator<?> findInferredGenerator(final QName qname) {
+ private @Nullable AbstractExplicitGenerator<?, ?> findInferredGenerator(final QName qname) {
// First search our local groupings ...
for (var grouping : groupings) {
final var gen = grouping.findSchemaTreeGenerator(qname.bindTo(grouping.statement().argument().getModule()));
for (Generator child : this) {
// Only process explicit generators here
if (child instanceof AbstractExplicitGenerator) {
- ((AbstractExplicitGenerator<?>) child).addAsGetterMethod(builder, builderFactory);
+ ((AbstractExplicitGenerator<?, ?>) child).addAsGetterMethod(builder, builderFactory);
}
final GeneratedType enclosedType = child.enclosedType(builderFactory);
}
}
- private Entry<List<Generator>, List<SchemaTreeChild<?, ?>>> createChildren(
- final EffectiveStatement<?, ?> statement) {
+ private @NonNull List<Generator> createChildren(final EffectiveStatement<?, ?> statement) {
final var tmp = new ArrayList<Generator>();
final var tmpAug = new ArrayList<AbstractAugmentGenerator>();
- final var tmpSchema = new ArrayList<SchemaTreeChild<?, ?>>();
for (var stmt : statement.effectiveSubstatements()) {
if (stmt instanceof ActionEffectiveStatement) {
- final var cast = (ActionEffectiveStatement) stmt;
- if (isAugmenting(cast)) {
- tmpSchema.add(new SchemaTreePlaceholder<>(cast, ActionGenerator.class));
- } else {
- tmp.add(new ActionGenerator(cast, this));
+ if (!isAugmenting(stmt)) {
+ tmp.add(new ActionGenerator((ActionEffectiveStatement) stmt, this));
}
} else if (stmt instanceof AnydataEffectiveStatement) {
- final var cast = (AnydataEffectiveStatement) stmt;
- if (isAugmenting(stmt)) {
- tmpSchema.add(new SchemaTreePlaceholder<>(cast, OpaqueObjectGenerator.class));
- } else {
- tmp.add(new OpaqueObjectGenerator<>(cast, this));
+ if (!isAugmenting(stmt)) {
+ tmp.add(new OpaqueObjectGenerator.Anydata((AnydataEffectiveStatement) stmt, this));
}
} else if (stmt instanceof AnyxmlEffectiveStatement) {
- final var cast = (AnyxmlEffectiveStatement) stmt;
- if (isAugmenting(stmt)) {
- tmpSchema.add(new SchemaTreePlaceholder<>(cast, OpaqueObjectGenerator.class));
- } else {
- tmp.add(new OpaqueObjectGenerator<>(cast, this));
+ if (!isAugmenting(stmt)) {
+ tmp.add(new OpaqueObjectGenerator.Anyxml((AnyxmlEffectiveStatement) stmt, this));
}
} else if (stmt instanceof CaseEffectiveStatement) {
tmp.add(new CaseGenerator((CaseEffectiveStatement) stmt, this));
} else if (stmt instanceof ChoiceEffectiveStatement) {
- final var cast = (ChoiceEffectiveStatement) stmt;
// FIXME: use isOriginalDeclaration() ?
- if (isAddedByUses(stmt)) {
- tmpSchema.add(new SchemaTreePlaceholder<>(cast, ChoiceGenerator.class));
- } else {
- tmp.add(new ChoiceGenerator(cast, this));
+ if (!isAddedByUses(stmt)) {
+ tmp.add(new ChoiceGenerator((ChoiceEffectiveStatement) stmt, this));
}
} else if (stmt instanceof ContainerEffectiveStatement) {
- final var cast = (ContainerEffectiveStatement) stmt;
if (isOriginalDeclaration(stmt)) {
tmp.add(new ContainerGenerator((ContainerEffectiveStatement) stmt, this));
- } else {
- tmpSchema.add(new SchemaTreePlaceholder<>(cast, ContainerGenerator.class));
}
} else if (stmt instanceof GroupingEffectiveStatement) {
tmp.add(new GroupingGenerator((GroupingEffectiveStatement) stmt, this));
} else if (stmt instanceof IdentityEffectiveStatement) {
tmp.add(new IdentityGenerator((IdentityEffectiveStatement) stmt, this));
} else if (stmt instanceof InputEffectiveStatement) {
+ final var cast = (InputEffectiveStatement) stmt;
// FIXME: do not generate legacy RPC layout
- tmp.add(this instanceof RpcGenerator ? new RpcContainerGenerator((InputEffectiveStatement) stmt, this)
- : new OperationContainerGenerator((InputEffectiveStatement) stmt, this));
+ tmp.add(this instanceof RpcGenerator ? new RpcInputGenerator(cast, this)
+ : new InputGenerator(cast, this));
} else if (stmt instanceof LeafEffectiveStatement) {
- final var cast = (LeafEffectiveStatement) stmt;
- if (isAugmenting(stmt)) {
- tmpSchema.add(new SchemaTreePlaceholder<>(cast, LeafGenerator.class));
- } else {
- tmp.add(new LeafGenerator(cast, this));
+ if (!isAugmenting(stmt)) {
+ tmp.add(new LeafGenerator((LeafEffectiveStatement) stmt, this));
}
} else if (stmt instanceof LeafListEffectiveStatement) {
- final var cast = (LeafListEffectiveStatement) stmt;
- if (isAugmenting(stmt)) {
- tmpSchema.add(new SchemaTreePlaceholder<>(cast, LeafListGenerator.class));
- } else {
+ if (!isAugmenting(stmt)) {
tmp.add(new LeafListGenerator((LeafListEffectiveStatement) stmt, this));
}
} else if (stmt instanceof ListEffectiveStatement) {
- final var cast = (ListEffectiveStatement) stmt;
if (isOriginalDeclaration(stmt)) {
- final ListGenerator listGen = new ListGenerator(cast, this);
+ final ListGenerator listGen = new ListGenerator((ListEffectiveStatement) stmt, this);
tmp.add(listGen);
final KeyGenerator keyGen = listGen.keyGenerator();
if (keyGen != null) {
tmp.add(keyGen);
}
- } else {
- tmpSchema.add(new SchemaTreePlaceholder<>(cast, ListGenerator.class));
}
} else if (stmt instanceof NotificationEffectiveStatement) {
- final var cast = (NotificationEffectiveStatement) stmt;
- if (isAugmenting(stmt)) {
- tmpSchema.add(new SchemaTreePlaceholder<>(cast, NotificationGenerator.class));
- } else {
- tmp.add(new NotificationGenerator(cast, this));
+ if (!isAugmenting(stmt)) {
+ tmp.add(new NotificationGenerator((NotificationEffectiveStatement) stmt, this));
}
} else if (stmt instanceof OutputEffectiveStatement) {
+ final var cast = (OutputEffectiveStatement) stmt;
// FIXME: do not generate legacy RPC layout
- tmp.add(this instanceof RpcGenerator ? new RpcContainerGenerator((OutputEffectiveStatement) stmt, this)
- : new OperationContainerGenerator((OutputEffectiveStatement) stmt, this));
+ tmp.add(this instanceof RpcGenerator ? new RpcOutputGenerator(cast, this)
+ : new OutputGenerator(cast, this));
} else if (stmt instanceof RpcEffectiveStatement) {
tmp.add(new RpcGenerator((RpcEffectiveStatement) stmt, this));
} else if (stmt instanceof TypedefEffectiveStatement) {
}
}
- // Add any SchemaTreeChild generators to the list
- for (var child : tmp) {
- if (child instanceof SchemaTreeChild) {
- tmpSchema.add((SchemaTreeChild<?, ?>) child);
- }
- }
-
// Sort augments and add them last. This ensures child iteration order always reflects potential
// interdependencies, hence we do not need to worry about them. This is extremely important, as there are a
// number of places where we would have to either move the logic to parent statement and explicitly filter/sort
}
}
- return Map.entry(List.copyOf(tmp), List.copyOf(tmpSchema));
+ return List.copyOf(tmp);
}
// Utility equivalent of (!isAddedByUses(stmt) && !isAugmenting(stmt)). Takes advantage of relationship between
*/
package org.opendaylight.mdsal.binding.generator.impl.reactor;
+import org.opendaylight.mdsal.binding.runtime.api.RuntimeType;
import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
/**
* A simple {@link Generator} which (potentially) has dependencies on other generators.
*/
-abstract class AbstractDependentGenerator<T extends EffectiveStatement<?, ?>> extends AbstractExplicitGenerator<T> {
- AbstractDependentGenerator(final T statement, final AbstractCompositeGenerator<?> parent) {
+abstract class AbstractDependentGenerator<S extends EffectiveStatement<?, ?>, R extends RuntimeType>
+ extends AbstractExplicitGenerator<S, R> {
+ AbstractDependentGenerator(final S statement, final AbstractCompositeGenerator<?, ?> parent) {
super(statement, parent);
}
import static java.util.Objects.requireNonNull;
import com.google.common.base.MoreObjects.ToStringHelper;
+import java.util.Optional;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;
import org.opendaylight.mdsal.binding.generator.impl.reactor.CollisionDomain.Member;
+import org.opendaylight.mdsal.binding.generator.impl.tree.StatementRepresentation;
import org.opendaylight.mdsal.binding.model.api.MethodSignature.ValueMechanics;
import org.opendaylight.mdsal.binding.model.api.Type;
import org.opendaylight.mdsal.binding.model.api.TypeMemberComment;
import org.opendaylight.mdsal.binding.model.api.type.builder.AnnotableTypeBuilder;
import org.opendaylight.mdsal.binding.model.api.type.builder.GeneratedTypeBuilderBase;
import org.opendaylight.mdsal.binding.model.api.type.builder.MethodSignatureBuilder;
+import org.opendaylight.mdsal.binding.runtime.api.RuntimeType;
import org.opendaylight.mdsal.binding.spec.naming.BindingMapping;
import org.opendaylight.yangtools.yang.common.AbstractQName;
import org.opendaylight.yangtools.yang.common.QName;
/**
* An explicit {@link Generator}, associated with a particular {@link EffectiveStatement}.
*/
-public abstract class AbstractExplicitGenerator<T extends EffectiveStatement<?, ?>> extends Generator
- implements CopyableNode {
+public abstract class AbstractExplicitGenerator<S extends EffectiveStatement<?, ?>, R extends RuntimeType>
+ extends Generator implements CopyableNode, StatementRepresentation<S> {
private static final Logger LOG = LoggerFactory.getLogger(AbstractExplicitGenerator.class);
- private final @NonNull T statement;
+ private final @NonNull S statement;
/**
* Field tracking previous incarnation (along reverse of 'uses' and 'augment' axis) of this statement. This field
* <li>a generator which is one step closer to the original definition</li>
* </ul>
*/
- private AbstractExplicitGenerator<T> prev;
+ private AbstractExplicitGenerator<S, R> prev;
/**
* Field holding the original incarnation, i.e. the terminal node along {@link #prev} links.
*/
- private AbstractExplicitGenerator<T> orig;
+ private AbstractExplicitGenerator<S, R> orig;
+ /**
+ * Field containing and indicator holding the runtime type, if applicable.
+ */
+ private @Nullable R runtimeType;
+ private boolean runtimeTypeInitialized;
- AbstractExplicitGenerator(final T statement) {
+ AbstractExplicitGenerator(final S statement) {
this.statement = requireNonNull(statement);
}
- AbstractExplicitGenerator(final T statement, final AbstractCompositeGenerator<?> parent) {
+ AbstractExplicitGenerator(final S statement, final AbstractCompositeGenerator<?, ?> parent) {
super(parent);
this.statement = requireNonNull(statement);
}
+ @Override
+ public final @NonNull S statement() {
+ return statement;
+ }
+
/**
- * Return the {@link EffectiveStatement} associated with this generator.
+ * Return the {@link RuntimeType} associated with this object, of applicable.
*
- * @return An EffectiveStatement
+ * @return Associated run-time type, or empty
*/
- public final @NonNull T statement() {
- return statement;
+ public final Optional<R> runtimeType() {
+ if (!runtimeTypeInitialized) {
+ runtimeType = createRuntimeType();
+ runtimeTypeInitialized = true;
+ }
+ return Optional.ofNullable(runtimeType);
}
+ final Optional<R> runtimeTypeOf(final @NonNull S stmt) {
+ return recursiveRuntimeType().map(childType -> rebaseRuntimeType(childType, stmt));
+ }
+
+ public final Optional<R> recursiveRuntimeType() {
+ AbstractExplicitGenerator<S, R> gen = this;
+ do {
+ final var ret = gen.runtimeType();
+ if (ret.isPresent()) {
+ return ret;
+ }
+
+ gen = gen.previous();
+ } while (gen != null);
+
+ return Optional.empty();
+ }
+
+ abstract @Nullable R createRuntimeType();
+
+ abstract @NonNull R rebaseRuntimeType(@NonNull R type, @NonNull S statement);
+
@Override
public final boolean isAddedByUses() {
return statement instanceof AddedByUsesAware && ((AddedByUsesAware) statement).isAddedByUses();
return true;
}
- final var link = getParent().<T>originalChild(getQName());
+ final var link = getParent().<S, R>originalChild(getQName());
if (link == null) {
LOG.trace("Cannot link {} yet", this);
return false;
*
* @return Previous incarnation or {@code null}
*/
- final @Nullable AbstractExplicitGenerator<T> previous() {
+ final @Nullable AbstractExplicitGenerator<S, R> previous() {
final var local = verifyNotNull(prev, "Generator %s does not have linkage to previous instance resolved", this);
return local == this ? null : local;
}
*
* @return Original incarnation of this generator
*/
- @NonNull AbstractExplicitGenerator<T> getOriginal() {
+ @NonNull AbstractExplicitGenerator<S, R> getOriginal() {
return verifyNotNull(orig, "Generator %s does not have linkage to original instance resolved", this);
}
- @Nullable AbstractExplicitGenerator<T> tryOriginal() {
+ @Nullable AbstractExplicitGenerator<S, R> tryOriginal() {
return orig;
}
*
* @return Link towards the original generator.
*/
- final @NonNull OriginalLink<T> originalLink() {
+ final @NonNull OriginalLink<S, R> originalLink() {
final var local = prev;
if (local == null) {
return OriginalLink.partial(this);
}
}
- @Nullable AbstractExplicitGenerator<?> findSchemaTreeGenerator(final QName qname) {
+ @Nullable AbstractExplicitGenerator<?, ?> findSchemaTreeGenerator(final QName qname) {
return findLocalSchemaTreeGenerator(qname);
}
- final @Nullable AbstractExplicitGenerator<?> findLocalSchemaTreeGenerator(final QName qname) {
+ final @Nullable AbstractExplicitGenerator<?, ?> findLocalSchemaTreeGenerator(final QName qname) {
for (Generator child : this) {
if (child instanceof AbstractExplicitGenerator) {
- final AbstractExplicitGenerator<?> gen = (AbstractExplicitGenerator<?>) child;
+ final AbstractExplicitGenerator<?, ?> gen = (AbstractExplicitGenerator<?, ?>) child;
final EffectiveStatement<?, ?> stmt = gen.statement();
if (stmt instanceof SchemaTreeEffectiveStatement && qname.equals(stmt.argument())) {
return gen;
import static com.google.common.base.Verify.verify;
-import org.opendaylight.mdsal.binding.generator.impl.tree.SchemaTreeChild;
import org.opendaylight.mdsal.binding.model.api.GeneratedTransferObject;
import org.opendaylight.mdsal.binding.model.api.JavaTypeName;
import org.opendaylight.mdsal.binding.model.api.Type;
import org.opendaylight.mdsal.binding.model.api.type.builder.GeneratedTypeBuilderBase;
import org.opendaylight.mdsal.binding.model.api.type.builder.MethodSignatureBuilder;
import org.opendaylight.mdsal.binding.model.ri.BindingTypes;
+import org.opendaylight.mdsal.binding.runtime.api.RuntimeType;
import org.opendaylight.yangtools.odlext.model.api.ContextReferenceEffectiveStatement;
import org.opendaylight.yangtools.yang.model.api.TypeAware;
import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
/**
* Common base class for {@link LeafGenerator} and {@link LeafListGenerator}.
*/
-abstract class AbstractTypeAwareGenerator<T extends DataTreeEffectiveStatement<?>,
- G extends AbstractTypeAwareGenerator<T, G>>
- extends AbstractTypeObjectGenerator<T> implements SchemaTreeChild<T, G> {
+abstract class AbstractTypeAwareGenerator<T extends DataTreeEffectiveStatement<?>, R extends RuntimeType,
+ G extends AbstractTypeAwareGenerator<T, R, G>>
+ extends AbstractTypeObjectGenerator<T, R> {
private IdentityGenerator contextType;
- AbstractTypeAwareGenerator(final T statement, final AbstractCompositeGenerator<?> parent) {
+ AbstractTypeAwareGenerator(final T statement, final AbstractCompositeGenerator<?, ?> parent) {
super(statement, parent);
verify(statement instanceof TypeAware, "Unexpected statement %s", statement);
}
- @Override
- @SuppressWarnings("unchecked")
- public final G generator() {
- return (G) this;
- }
-
@Override
final void pushToInference(final SchemaInferenceStack dataTree) {
dataTree.enterDataTree(statement().getIdentifier());
@Override
final TypeDefinition<?> extractTypeDefinition() {
- return ((TypedDataSchemaNode) statement()).getType();
+ final var stmt = statement();
+ verify(stmt instanceof TypedDataSchemaNode, "Unexpected statement %s", stmt);
+ return ((TypedDataSchemaNode) stmt).getType();
}
@Override
import org.opendaylight.mdsal.binding.model.ri.Types;
import org.opendaylight.mdsal.binding.model.ri.generated.type.builder.AbstractEnumerationBuilder;
import org.opendaylight.mdsal.binding.model.ri.generated.type.builder.GeneratedPropertyBuilderImpl;
+import org.opendaylight.mdsal.binding.runtime.api.RuntimeType;
import org.opendaylight.mdsal.binding.spec.naming.BindingMapping;
import org.opendaylight.yangtools.concepts.Immutable;
import org.opendaylight.yangtools.yang.binding.RegexPatterns;
* type indirection in YANG constructs is therefore explicitly excluded from the generated Java code, but the Binding
* Specification still takes them into account when determining types as outlined above.
*/
-abstract class AbstractTypeObjectGenerator<T extends EffectiveStatement<?, ?>> extends AbstractDependentGenerator<T> {
+abstract class AbstractTypeObjectGenerator<S extends EffectiveStatement<?, ?>, R extends RuntimeType>
+ extends AbstractDependentGenerator<S, R> {
private static final class UnionDependencies implements Immutable {
private final Map<EffectiveStatement<?, ?>, TypeReference> identityTypes = new HashMap<>();
private final Map<EffectiveStatement<?, ?>, TypeReference> leafTypes = new HashMap<>();
private TypeReference refType;
private List<GeneratedType> auxiliaryGeneratedTypes = List.of();
private UnionDependencies unionDependencies;
- private List<AbstractTypeObjectGenerator<?>> inferred = List.of();
+ private List<AbstractTypeObjectGenerator<?, ?>> inferred = List.of();
- AbstractTypeObjectGenerator(final T statement, final AbstractCompositeGenerator<?> parent) {
+ /**
+ * The type of single-element return type of the getter method associated with this generator. This is retained for
+ * run-time type purposes. It may be uninitialized, in which case this object must have a generated type.
+ */
+ private Type methodReturnTypeElement;
+
+ AbstractTypeObjectGenerator(final S statement, final AbstractCompositeGenerator<?, ?> parent) {
super(statement, parent);
type = statement().findFirstEffectiveSubstatement(TypeEffectiveStatement.class).orElseThrow();
}
return;
}
- final AbstractExplicitGenerator<?> prev = previous();
+ final AbstractExplicitGenerator<S, R> prev = previous();
if (prev != null) {
verify(prev instanceof AbstractTypeObjectGenerator, "Unexpected previous %s", prev);
- ((AbstractTypeObjectGenerator<?>) prev).linkInferred(this);
+ ((AbstractTypeObjectGenerator<S, R>) prev).linkInferred(this);
} else {
linkBaseGen(context.resolveTypedef(typeName));
}
}
- private void linkInferred(final AbstractTypeObjectGenerator<?> downstream) {
+ private void linkInferred(final AbstractTypeObjectGenerator<?, ?> downstream) {
if (inferred == null) {
downstream.linkBaseGen(verifyNotNull(baseGen, "Mismatch on linking between %s and %s", this, downstream));
return;
private void linkBaseGen(final TypedefGenerator upstreamBaseGen) {
verify(baseGen == null, "Attempted to replace base %s with %s in %s", baseGen, upstreamBaseGen, this);
- final List<AbstractTypeObjectGenerator<?>> downstreams = verifyNotNull(inferred,
+ final List<AbstractTypeObjectGenerator<?, ?>> downstreams = verifyNotNull(inferred,
"Duplicated linking of %s", this);
baseGen = verifyNotNull(upstreamBaseGen);
baseGen.addDerivedGenerator(this);
inferred = null;
- for (AbstractTypeObjectGenerator<?> downstream : downstreams) {
+ for (AbstractTypeObjectGenerator<?, ?> downstream : downstreams) {
downstream.linkBaseGen(upstreamBaseGen);
}
}
.map(context::resolveIdentity)
.collect(Collectors.toUnmodifiableList()));
} else if (TypeDefinitions.LEAFREF.equals(arg)) {
- final AbstractTypeObjectGenerator<?> targetGenerator = context.resolveLeafref(
+ final AbstractTypeObjectGenerator<?, ?> targetGenerator = context.resolveLeafref(
type.findFirstEffectiveSubstatementArgument(PathEffectiveStatement.class).orElseThrow());
checkArgument(targetGenerator != this, "Effective model contains self-referencing leaf %s",
statement().argument());
return methodReturnElementType(builderFactory);
}
+ @Override
+ final R createRuntimeType() {
+ if (methodReturnTypeElement != null) {
+ return createRuntimeType(methodReturnTypeElement);
+ }
+ final var genType = generatedType();
+ if (genType.isPresent()) {
+ return createRuntimeType(genType.orElseThrow());
+ }
+ final var prev = verifyNotNull(previous(), "No previous generator for %s", this);
+ return prev.runtimeType().orElse(null);
+ }
+
+ abstract @NonNull R createRuntimeType(Type type);
+
final @NonNull Type methodReturnElementType(final @NonNull TypeBuilderFactory builderFactory) {
+ var local = methodReturnTypeElement;
+ if (local == null) {
+ methodReturnTypeElement = local = createMethodReturnElementType(builderFactory);
+ }
+ return local;
+ }
+
+ private @NonNull Type createMethodReturnElementType(final @NonNull TypeBuilderFactory builderFactory) {
final GeneratedType generatedType = tryGeneratedType(builderFactory);
if (generatedType != null) {
// We have generated a type here, so return it. This covers 'bits', 'enumeration' and 'union'.
return refType.methodReturnType(builderFactory);
}
- final AbstractExplicitGenerator<?> prev = previous();
+ final AbstractExplicitGenerator<?, ?> prev = previous();
if (prev != null) {
// We have been added through augment/uses, defer to the original definition
return prev.methodReturnType(builderFactory);
return;
}
- final AbstractTypeObjectGenerator<?> prev =
- (AbstractTypeObjectGenerator<?>) verifyNotNull(previous(), "Missing previous link in %s", this);
+ final AbstractTypeObjectGenerator<?, ?> prev =
+ (AbstractTypeObjectGenerator<?, ?>) verifyNotNull(previous(), "Missing previous link in %s", this);
if (prev.refType instanceof ResolvedLeafref) {
// We should be already inheriting the correct type
return;
Type baseType = SIMPLE_TYPES.get(subName);
if (baseType == null) {
// This has to be a reference to a typedef, let's lookup it up and pick up its type
- final AbstractTypeObjectGenerator<?> baseGen = verifyNotNull(
+ final AbstractTypeObjectGenerator<?, ?> baseGen = verifyNotNull(
dependencies.baseTypes.get(subName), "Cannot resolve base type %s in %s", subName,
definingStatement);
baseType = baseGen.methodReturnType(builderFactory);
*/
package org.opendaylight.mdsal.binding.generator.impl.reactor;
+import java.util.List;
import org.eclipse.jdt.annotation.NonNull;
+import org.opendaylight.mdsal.binding.generator.impl.rt.DefaultActionRuntimeType;
import org.opendaylight.mdsal.binding.model.api.GeneratedType;
import org.opendaylight.mdsal.binding.model.api.Type;
import org.opendaylight.mdsal.binding.model.api.type.builder.GeneratedTypeBuilder;
import org.opendaylight.mdsal.binding.model.api.type.builder.GeneratedTypeBuilderBase;
import org.opendaylight.mdsal.binding.model.ri.BindingTypes;
+import org.opendaylight.mdsal.binding.runtime.api.ActionRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.AugmentRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.RuntimeType;
import org.opendaylight.yangtools.yang.model.api.stmt.ActionEffectiveStatement;
import org.opendaylight.yangtools.yang.model.api.stmt.InputEffectiveStatement;
import org.opendaylight.yangtools.yang.model.api.stmt.OutputEffectiveStatement;
/**
* Generator corresponding to a {@code action} statement.
*/
-final class ActionGenerator extends CompositeSchemaTreeGenerator<ActionEffectiveStatement, ActionGenerator> {
- ActionGenerator(final ActionEffectiveStatement statement, final AbstractCompositeGenerator<?> parent) {
+final class ActionGenerator extends CompositeSchemaTreeGenerator<ActionEffectiveStatement, ActionRuntimeType> {
+ ActionGenerator(final ActionEffectiveStatement statement, final AbstractCompositeGenerator<?, ?> parent) {
super(statement, parent);
}
return builder.build();
}
+ @Override
+ ActionRuntimeType createRuntimeType(final GeneratedType type, final ActionEffectiveStatement statement,
+ final List<RuntimeType> children, final List<AugmentRuntimeType> augments) {
+ return new DefaultActionRuntimeType(type, statement, children, augments);
+ }
+
private @NonNull Type implementedType(final TypeBuilderFactory builderFactory) {
final GeneratedType input = getChild(this, InputEffectiveStatement.class).getOriginal()
.getGeneratedType(builderFactory);
final GeneratedType output = getChild(this, OutputEffectiveStatement.class).getOriginal()
.getGeneratedType(builderFactory);
- final AbstractCompositeGenerator<?> parent = getParent();
+ final AbstractCompositeGenerator<?, ?> parent = getParent();
if (parent instanceof ListGenerator) {
final KeyGenerator keyGen = ((ListGenerator) parent).keyGenerator();
if (keyGen != null) {
private final @NonNull AbstractAugmentGenerator augment;
private final @NonNull Iterator<QName> remaining;
- private @NonNull AbstractCompositeGenerator<?> target;
+ private @NonNull AbstractCompositeGenerator<?, ?> target;
private QNameModule localNamespace;
private QName qname;
- private AugmentRequirement(final AbstractAugmentGenerator augment, final AbstractCompositeGenerator<?> target) {
+ private AugmentRequirement(final AbstractAugmentGenerator augment, final AbstractCompositeGenerator<?, ?> target) {
this.augment = requireNonNull(augment);
this.target = requireNonNull(target);
remaining = augment.statement().argument().getNodeIdentifiers().iterator();
return LinkageProgress.NONE;
}
- private @NonNull LinkageProgress moveTo(final @NonNull AbstractCompositeGenerator<?> newTarget) {
+ private @NonNull LinkageProgress moveTo(final @NonNull AbstractCompositeGenerator<?, ?> newTarget) {
target = newTarget;
return tryProgress();
}
- private @NonNull LinkageProgress progressTo(final @NonNull AbstractExplicitGenerator<?> newTarget) {
+ private @NonNull LinkageProgress progressTo(final @NonNull AbstractExplicitGenerator<?, ?> newTarget) {
verify(newTarget instanceof AbstractCompositeGenerator, "Unexpected generator %s", newTarget);
- target = (AbstractCompositeGenerator<?>) newTarget;
+ target = (AbstractCompositeGenerator<?, ?>) newTarget;
qname = remaining.hasNext() ? remaining.next() : null;
return tryProgress();
}
import static com.google.common.base.Verify.verify;
+import java.util.List;
+import org.opendaylight.mdsal.binding.generator.impl.rt.DerivedCaseRuntimeType;
+import org.opendaylight.mdsal.binding.generator.impl.rt.OriginalCaseRuntimeType;
import org.opendaylight.mdsal.binding.model.api.GeneratedType;
import org.opendaylight.mdsal.binding.model.api.type.builder.GeneratedTypeBuilder;
import org.opendaylight.mdsal.binding.model.ri.BindingTypes;
+import org.opendaylight.mdsal.binding.runtime.api.AugmentRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.CaseRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.RuntimeType;
import org.opendaylight.yangtools.yang.model.api.stmt.CaseEffectiveStatement;
import org.opendaylight.yangtools.yang.model.util.SchemaInferenceStack;
/**
* Generator corresponding to a {@code case} statement.
*/
-final class CaseGenerator extends CompositeSchemaTreeGenerator<CaseEffectiveStatement, CaseGenerator> {
- CaseGenerator(final CaseEffectiveStatement statement, final AbstractCompositeGenerator<?> parent) {
+final class CaseGenerator extends CompositeSchemaTreeGenerator<CaseEffectiveStatement, CaseRuntimeType> {
+ CaseGenerator(final CaseEffectiveStatement statement, final AbstractCompositeGenerator<?, ?> parent) {
super(statement, parent);
}
// We also are implementing target choice's type. This is tricky, as we need to cover two distinct cases:
// - being a child of a choice (i.e. normal definition)
// - being a child of an augment (i.e. augmented into a choice)
- final AbstractCompositeGenerator<?> parent = getParent();
+ final AbstractCompositeGenerator<?, ?> parent = getParent();
final ChoiceGenerator choice;
if (parent instanceof AbstractAugmentGenerator) {
- final AbstractCompositeGenerator<?> target = ((AbstractAugmentGenerator) parent).targetGenerator();
+ final AbstractCompositeGenerator<?, ?> target = ((AbstractAugmentGenerator) parent).targetGenerator();
verify(target instanceof ChoiceGenerator, "Unexpected parent augment %s target %s", parent, target);
choice = (ChoiceGenerator) target;
} else {
return builder.build();
}
+
+ @Override
+ CaseRuntimeType createRuntimeType(final GeneratedType type, final CaseEffectiveStatement statement,
+ final List<RuntimeType> children, final List<AugmentRuntimeType> augments) {
+ final var original = getOriginal();
+ return statement.equals(original.statement())
+ ? new OriginalCaseRuntimeType(type, statement, children, augments)
+ : new DerivedCaseRuntimeType(type, statement, children, augments, original.runtimeType().orElseThrow());
+ }
}
*/
package org.opendaylight.mdsal.binding.generator.impl.reactor;
+import com.google.common.collect.Iterables;
+import java.util.ArrayList;
+import java.util.List;
+import org.opendaylight.mdsal.binding.generator.impl.rt.DerivedChoiceRuntimeType;
+import org.opendaylight.mdsal.binding.generator.impl.rt.OriginalChoiceRuntimeType;
import org.opendaylight.mdsal.binding.model.api.GeneratedType;
import org.opendaylight.mdsal.binding.model.api.Type;
import org.opendaylight.mdsal.binding.model.api.type.builder.GeneratedTypeBuilder;
import org.opendaylight.mdsal.binding.model.ri.BindingTypes;
+import org.opendaylight.mdsal.binding.runtime.api.AugmentRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.CaseRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.ChoiceRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.RuntimeType;
import org.opendaylight.yangtools.yang.model.api.stmt.ChoiceEffectiveStatement;
import org.opendaylight.yangtools.yang.model.util.SchemaInferenceStack;
/**
* Generator corresponding to a {@code choice} statement.
*/
-final class ChoiceGenerator extends CompositeSchemaTreeGenerator<ChoiceEffectiveStatement, ChoiceGenerator> {
- ChoiceGenerator(final ChoiceEffectiveStatement statement, final AbstractCompositeGenerator<?> parent) {
+final class ChoiceGenerator extends CompositeSchemaTreeGenerator<ChoiceEffectiveStatement, ChoiceRuntimeType> {
+ ChoiceGenerator(final ChoiceEffectiveStatement statement, final AbstractCompositeGenerator<?, ?> parent) {
super(statement, parent);
}
return builder.build();
}
+
+ @Override
+ ChoiceRuntimeType createRuntimeType(final GeneratedType type, final ChoiceEffectiveStatement statement,
+ final List<RuntimeType> children, final List<AugmentRuntimeType> augments) {
+ final var original = getOriginal();
+ if (!statement.equals(original.statement())) {
+ return new DerivedChoiceRuntimeType(type, statement, children, augments,
+ original.runtimeType().orElseThrow());
+ }
+
+ // Pick up any case statements added by augments which are not reflected in our children. This can happen when
+ // a choice is added via uses into two different places and then augmented. Since groupings are reused, validity
+ // of such use is not guarded by compile-time checks.
+ //
+ // Furthermore such case statements can be freely propagated via copy builders and thus can occur in unexpected
+ // places. If that happens, though, the two case statements can be equivalent, e.g. by having the exact same
+ // shape -- in which case Binding -> DOM translation needs to correct this mishap and play pretend the correct
+ // case was used.
+ final var augmentedCases = new ArrayList<CaseRuntimeType>();
+ for (var augment : original.augments()) {
+ for (var gen : augment) {
+ if (gen instanceof CaseGenerator) {
+ ((CaseGenerator) gen).runtimeType().ifPresent(augmented -> {
+ for (var child : Iterables.concat(children, augmentedCases)) {
+ if (child instanceof CaseRuntimeType && child.javaType().equals(augmented.javaType())) {
+ return;
+ }
+ }
+ augmentedCases.add(augmented);
+ });
+ }
+ }
+ }
+
+ return new OriginalChoiceRuntimeType(type, statement, children, augments, augmentedCases);
+ }
}
import java.util.List;
import java.util.Map.Entry;
import org.eclipse.jdt.annotation.NonNull;
+import org.opendaylight.mdsal.binding.spec.naming.BindingMapping;
import org.opendaylight.yangtools.yang.common.AbstractQName;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.model.api.stmt.SchemaNodeIdentifier;
Secondary(final Generator gen, final Member primary, final String classSuffix) {
super(gen);
- this.classPrimary = requireNonNull(primary);
+ classPrimary = requireNonNull(primary);
this.classSuffix = requireNonNull(classSuffix);
primary.addSecondary(this);
}
}
}
- private final AbstractCompositeGenerator<?> gen;
+ private final AbstractCompositeGenerator<?, ?> gen;
private List<Member> members = List.of();
private boolean solved;
- CollisionDomain(final AbstractCompositeGenerator<?> gen) {
+ CollisionDomain(final AbstractCompositeGenerator<?, ?> gen) {
this.gen = requireNonNull(gen);
}
return addMember(new LeafSecondary(memberGen, primary, classSuffix));
}
- @NonNull Member addSecondary(final RpcContainerGenerator memberGen, final Member primary, final String classSuffix,
- final AbstractQName packageSuffix) {
- return addMember(new SuffixSecondary(memberGen, primary, classSuffix, packageSuffix));
+ @NonNull Member addSecondary(final RpcInputGenerator memberGen, final Member primary) {
+ return addMember(new SuffixSecondary(memberGen, primary, BindingMapping.RPC_INPUT_SUFFIX,
+ memberGen.statement().argument()));
+ }
+
+ @NonNull Member addSecondary(final RpcOutputGenerator memberGen, final Member primary) {
+ return addMember(new SuffixSecondary(memberGen, primary, BindingMapping.RPC_OUTPUT_SUFFIX,
+ memberGen.statement().argument()));
}
@NonNull Member addSecondary(final AbstractAugmentGenerator memberGen, final Member classPrimary,
*/
package org.opendaylight.mdsal.binding.generator.impl.reactor;
-import org.opendaylight.mdsal.binding.generator.impl.tree.SchemaTreeChild;
+import org.opendaylight.mdsal.binding.runtime.api.CompositeRuntimeType;
import org.opendaylight.yangtools.yang.model.api.stmt.SchemaTreeEffectiveStatement;
/**
* Abstract base class for {@link AbstractCompositeGenerator}s which are also {@link SchemaTreeChild}ren.
*/
-abstract class CompositeSchemaTreeGenerator<S extends SchemaTreeEffectiveStatement<?>,
- G extends CompositeSchemaTreeGenerator<S, G>>
- extends AbstractCompositeGenerator<S> implements SchemaTreeChild<S, G> {
- CompositeSchemaTreeGenerator(final S statement, final AbstractCompositeGenerator<?> parent) {
+abstract class CompositeSchemaTreeGenerator<S extends SchemaTreeEffectiveStatement<?>, R extends CompositeRuntimeType>
+ extends AbstractCompositeGenerator<S, R> {
+ CompositeSchemaTreeGenerator(final S statement, final AbstractCompositeGenerator<?, ?> parent) {
super(statement, parent);
}
-
- @Override
- @SuppressWarnings("unchecked")
- public final G generator() {
- return (G) this;
- }
}
*/
package org.opendaylight.mdsal.binding.generator.impl.reactor;
+import java.util.List;
+import org.opendaylight.mdsal.binding.generator.impl.rt.DefaultContainerRuntimeType;
import org.opendaylight.mdsal.binding.model.api.GeneratedType;
import org.opendaylight.mdsal.binding.model.api.type.builder.GeneratedTypeBuilder;
+import org.opendaylight.mdsal.binding.runtime.api.AugmentRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.ContainerRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.RuntimeType;
import org.opendaylight.yangtools.yang.model.api.stmt.ContainerEffectiveStatement;
import org.opendaylight.yangtools.yang.model.util.SchemaInferenceStack;
/**
* Generator corresponding to a {@code container} statement.
*/
-final class ContainerGenerator extends CompositeSchemaTreeGenerator<ContainerEffectiveStatement, ContainerGenerator> {
- ContainerGenerator(final ContainerEffectiveStatement statement, final AbstractCompositeGenerator<?> parent) {
+final class ContainerGenerator extends CompositeSchemaTreeGenerator<ContainerEffectiveStatement, ContainerRuntimeType> {
+ ContainerGenerator(final ContainerEffectiveStatement statement, final AbstractCompositeGenerator<?, ?> parent) {
super(statement, parent);
}
return builder.build();
}
+
+ @Override
+ ContainerRuntimeType createRuntimeType(final GeneratedType type, final ContainerEffectiveStatement statement,
+ final List<RuntimeType> children, final List<AugmentRuntimeType> augments) {
+ return new DefaultContainerRuntimeType(type, statement, children, augments);
+ }
}
private static final JavaTypeName DEPRECATED_ANNOTATION = JavaTypeName.create(Deprecated.class);
static final JavaTypeName OVERRIDE_ANNOTATION = JavaTypeName.create(Override.class);
- private final AbstractCompositeGenerator<?> parent;
+ private final AbstractCompositeGenerator<?, ?> parent;
private Optional<Member> member;
private GeneratorResult result;
parent = null;
}
- Generator(final AbstractCompositeGenerator<?> parent) {
+ Generator(final AbstractCompositeGenerator<?, ?> parent) {
this.parent = requireNonNull(parent);
}
*
* @return Parent generator
*/
- final @NonNull AbstractCompositeGenerator<?> getParent() {
+ final @NonNull AbstractCompositeGenerator<?, ?> getParent() {
return verifyNotNull(parent, "No parent for %s", this);
}
return JavaTypeName.create(getPackageParent().javaPackage(), assignedName());
}
- @NonNull AbstractCompositeGenerator<?> getPackageParent() {
+ @NonNull AbstractCompositeGenerator<?, ?> getPackageParent() {
return getParent();
}
}
final void addImplementsChildOf(final GeneratedTypeBuilder builder) {
- AbstractCompositeGenerator<?> ancestor = getParent();
+ AbstractCompositeGenerator<?, ?> ancestor = getParent();
while (true) {
// choice/case hierarchy does not factor into 'ChildOf' hierarchy, hence we need to skip them
if (ancestor instanceof CaseGenerator || ancestor instanceof ChoiceGenerator) {
// if we into a choice we need to follow the hierararchy of that choice
if (ancestor instanceof AbstractAugmentGenerator) {
- final AbstractCompositeGenerator<?> target = ((AbstractAugmentGenerator) ancestor).targetGenerator();
+ final AbstractCompositeGenerator<?, ?> target = ((AbstractAugmentGenerator) ancestor).targetGenerator();
if (target instanceof ChoiceGenerator) {
ancestor = target;
continue;
defineImplementedInterfaceMethod(builder, Type.of(builder)).setDefault(true);
}
- static final <T extends EffectiveStatement<?, ?>> AbstractExplicitGenerator<T> getChild(final Generator parent,
+ static final <T extends EffectiveStatement<?, ?>> AbstractExplicitGenerator<T, ?> getChild(final Generator parent,
final Class<T> type) {
for (Generator child : parent) {
if (child instanceof AbstractExplicitGenerator) {
@SuppressWarnings("unchecked")
- final AbstractExplicitGenerator<T> explicit = (AbstractExplicitGenerator<T>)child;
+ final AbstractExplicitGenerator<T, ?> explicit = (AbstractExplicitGenerator<T, ?>)child;
if (type.isInstance(explicit.statement())) {
return explicit;
}
import org.eclipse.jdt.annotation.NonNull;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.common.QNameModule;
+import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
import org.opendaylight.yangtools.yang.model.api.PathExpression;
import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
+import org.opendaylight.yangtools.yang.model.spi.AbstractEffectiveModelContextProvider;
/**
* Abstract view on generation tree as viewed by a particular {@link Generator}.
*/
-abstract class GeneratorContext {
+abstract class GeneratorContext extends AbstractEffectiveModelContextProvider {
+ GeneratorContext(final EffectiveModelContext modelContext) {
+ super(modelContext);
+ }
+
/**
* Resolve generator for the type object pointed to by a {@code path} expression, or {@code null} it the if cannot
* the current generator is nested inside a {@code grouping} and the generator cannot be found.
* @throws NullPointerException if {@code path} is {@code null}
* @throws IllegalStateException if this generator is not inside a {@code grouping} and the path cannot be resolved
*/
- abstract @Nullable AbstractTypeObjectGenerator<?> resolveLeafref(@NonNull PathExpression path);
+ abstract @Nullable AbstractTypeObjectGenerator<?, ?> resolveLeafref(@NonNull PathExpression path);
/**
* Resolve a tree-scoped namespace reference. This covers {@code typedef} and {@code grouping} statements, as per
* @throws NullPointerException if any argument is null
* @throws IllegalStateException if the generator cannot be found
*/
- abstract <E extends EffectiveStatement<QName, ?>, G extends AbstractExplicitGenerator<E>>
+ abstract <E extends EffectiveStatement<QName, ?>, G extends AbstractExplicitGenerator<E, ?>>
@NonNull G resolveTreeScoped(@NonNull Class<G> type, @NonNull QName argument);
abstract @NonNull ModuleGenerator resolveModule(@NonNull QNameModule namespace);
private State state = State.INITIALIZED;
public GeneratorReactor(final EffectiveModelContext context) {
+ super(context);
inferenceStack = SchemaInferenceStack.of(context);
// Construct modules and their subtrees. Dependency sort is very much needed here, as it establishes order of
gen.ensureMember();
collectCollisionDomains(result, gen);
if (gen instanceof AbstractCompositeGenerator) {
- result.add(((AbstractCompositeGenerator<?>) gen).domain());
+ result.add(((AbstractCompositeGenerator<?, ?>) gen).domain());
}
}
}
@Override
- <E extends EffectiveStatement<QName, ?>, G extends AbstractExplicitGenerator<E>> G resolveTreeScoped(
+ <E extends EffectiveStatement<QName, ?>, G extends AbstractExplicitGenerator<E, ?>> G resolveTreeScoped(
final Class<G> type, final QName argument) {
LOG.trace("Searching for tree-scoped argument {} at {}", argument, stack);
}
@Override
- AbstractTypeObjectGenerator<?> resolveLeafref(final PathExpression path) {
+ AbstractTypeObjectGenerator<?, ?> resolveLeafref(final PathExpression path) {
LOG.trace("Resolving path {}", path);
verify(inferenceStack.isEmpty(), "Unexpected data tree state %s", inferenceStack);
try {
}
}
- private @NonNull AbstractTypeAwareGenerator<?, ?> strictResolvePath(final @NonNull PathExpression path) {
+ private @NonNull AbstractTypeAwareGenerator<?, ?, ?> strictResolvePath(final @NonNull PathExpression path) {
try {
inferenceStack.resolvePathExpression(path);
} catch (IllegalArgumentException e) {
return mapToGenerator();
}
- private @Nullable AbstractTypeAwareGenerator<?, ?> lenientResolveLeafref(final @NonNull PathExpression path) {
+ private @Nullable AbstractTypeAwareGenerator<?, ?, ?> lenientResolveLeafref(final @NonNull PathExpression path) {
try {
inferenceStack.resolvePathExpression(path);
} catch (IllegalArgumentException e) {
}
// Map a statement to the corresponding generator
- private @NonNull AbstractTypeAwareGenerator<?, ?> mapToGenerator() {
+ private @NonNull AbstractTypeAwareGenerator<?, ?, ?> mapToGenerator() {
// Some preliminaries first: we need to be in the correct module to walk the path
final ModuleEffectiveStatement module = inferenceStack.currentModule();
final ModuleGenerator gen = verifyNotNull(generators.get(module.localQNameModule()),
// Now kick of the search
final List<EffectiveStatement<?, ?>> stmtPath = inferenceStack.toInference().statementPath();
- final AbstractExplicitGenerator<?> found = gen.findGenerator(stmtPath);
+ final AbstractExplicitGenerator<?, ?> found = gen.findGenerator(stmtPath);
if (found instanceof AbstractTypeAwareGenerator) {
- return (AbstractTypeAwareGenerator<?, ?>) found;
+ return (AbstractTypeAwareGenerator<?, ?, ?>) found;
}
throw new VerifyException("Statements " + stmtPath + " resulted in unexpected " + found);
}
for (Generator child : parent) {
if (child instanceof AbstractCompositeGenerator) {
LOG.trace("Visiting composite {}", child);
- final AbstractCompositeGenerator<?> composite = (AbstractCompositeGenerator<?>) child;
+ final var composite = (AbstractCompositeGenerator<?, ?>) child;
stack.push(composite);
composite.linkUsesDependencies(this);
linkUsesDependencies(composite);
private void linkDependencies(final Iterable<? extends Generator> parent) {
for (Generator child : parent) {
if (child instanceof AbstractDependentGenerator) {
- ((AbstractDependentGenerator<?>) child).linkDependencies(this);
+ ((AbstractDependentGenerator<?, ?>) child).linkDependencies(this);
} else if (child instanceof AbstractCompositeGenerator) {
stack.push(child);
linkDependencies(child);
for (Generator child : parent) {
stack.push(child);
if (child instanceof AbstractTypeObjectGenerator) {
- ((AbstractTypeObjectGenerator<?>) child).bindTypeDefinition(this);
+ ((AbstractTypeObjectGenerator<?, ?>) child).bindTypeDefinition(this);
} else if (child instanceof AbstractCompositeGenerator) {
bindTypeDefinition(child);
}
*/
package org.opendaylight.mdsal.binding.generator.impl.reactor;
+import java.util.List;
+import org.opendaylight.mdsal.binding.generator.impl.rt.DefaultGroupingRuntimeType;
import org.opendaylight.mdsal.binding.model.api.GeneratedType;
import org.opendaylight.mdsal.binding.model.api.type.builder.GeneratedTypeBuilder;
import org.opendaylight.mdsal.binding.model.api.type.builder.GeneratedTypeBuilderBase;
import org.opendaylight.mdsal.binding.model.ri.BindingTypes;
+import org.opendaylight.mdsal.binding.runtime.api.AugmentRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.GroupingRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.RuntimeType;
import org.opendaylight.yangtools.yang.model.api.stmt.GroupingEffectiveStatement;
import org.opendaylight.yangtools.yang.model.util.SchemaInferenceStack;
/**
* Generator corresponding to a {@code grouping} statement.
*/
-final class GroupingGenerator extends AbstractCompositeGenerator<GroupingEffectiveStatement> {
- GroupingGenerator(final GroupingEffectiveStatement statement, final AbstractCompositeGenerator<?> parent) {
+final class GroupingGenerator extends AbstractCompositeGenerator<GroupingEffectiveStatement, GroupingRuntimeType> {
+ GroupingGenerator(final GroupingEffectiveStatement statement, final AbstractCompositeGenerator<?, ?> parent) {
super(statement, parent);
}
return builder.build();
}
+ @Override
+ GroupingRuntimeType createRuntimeType(final GeneratedType type, final GroupingEffectiveStatement statement,
+ final List<RuntimeType> children, final List<AugmentRuntimeType> augments) {
+ return new DefaultGroupingRuntimeType(type, statement, children, augments);
+ }
+
@Override
void addAsGetterMethod(final GeneratedTypeBuilderBase<?> builder, final TypeBuilderFactory builderFactory) {
// groupings are a separate concept
import java.util.List;
import java.util.stream.Collectors;
+import org.opendaylight.mdsal.binding.generator.impl.rt.DefaultIdentityRuntimeType;
import org.opendaylight.mdsal.binding.model.api.GeneratedType;
import org.opendaylight.mdsal.binding.model.api.type.builder.GeneratedTypeBuilder;
import org.opendaylight.mdsal.binding.model.api.type.builder.GeneratedTypeBuilderBase;
+import org.opendaylight.mdsal.binding.runtime.api.IdentityRuntimeType;
import org.opendaylight.yangtools.yang.model.api.stmt.BaseEffectiveStatement;
import org.opendaylight.yangtools.yang.model.api.stmt.IdentityEffectiveStatement;
import org.opendaylight.yangtools.yang.model.util.SchemaInferenceStack;
/**
* Generator corresponding to a {@code identity} statement.
*/
-final class IdentityGenerator extends AbstractDependentGenerator<IdentityEffectiveStatement> {
+public final class IdentityGenerator
+ extends AbstractDependentGenerator<IdentityEffectiveStatement, IdentityRuntimeType> {
private List<IdentityGenerator> baseIdentities = null;
- IdentityGenerator(final IdentityEffectiveStatement statement, final AbstractCompositeGenerator<?> parent) {
+ IdentityGenerator(final IdentityEffectiveStatement statement, final AbstractCompositeGenerator<?, ?> parent) {
super(statement, parent);
}
return builder.build();
}
+ @Override
+ IdentityRuntimeType createRuntimeType() {
+ return generatedType().map(type -> new DefaultIdentityRuntimeType(type, statement())).orElse(null);
+ }
+
+ @Override
+ IdentityRuntimeType rebaseRuntimeType(final IdentityRuntimeType type, final IdentityEffectiveStatement statement) {
+ return new DefaultIdentityRuntimeType(type.javaType(), statement);
+ }
+
@Override
void addAsGetterMethod(final GeneratedTypeBuilderBase<?> builder, final TypeBuilderFactory builderFactory) {
// identities are a separate concept
--- /dev/null
+/*
+ * Copyright (c) 2022 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.generator.impl.reactor;
+
+import java.util.List;
+import org.opendaylight.mdsal.binding.generator.impl.rt.DefaultInputRuntimeType;
+import org.opendaylight.mdsal.binding.model.api.GeneratedType;
+import org.opendaylight.mdsal.binding.model.ri.BindingTypes;
+import org.opendaylight.mdsal.binding.runtime.api.AugmentRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.InputRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.RuntimeType;
+import org.opendaylight.yangtools.yang.model.api.stmt.InputEffectiveStatement;
+
+/**
+ * Generator corresponding to an {@code input} statement.
+ */
+class InputGenerator extends OperationContainerGenerator<InputEffectiveStatement, InputRuntimeType> {
+ InputGenerator(final InputEffectiveStatement statement, final AbstractCompositeGenerator<?, ?> parent) {
+ super(statement, parent, BindingTypes.RPC_INPUT);
+ }
+
+ @Override
+ final InputRuntimeType createRuntimeType(final GeneratedType type, final InputEffectiveStatement statement,
+ final List<RuntimeType> children, final List<AugmentRuntimeType> augments) {
+ return new DefaultInputRuntimeType(type, statement, children, augments);
+ }
+}
*/
package org.opendaylight.mdsal.binding.generator.impl.reactor;
+import static com.google.common.base.Verify.verify;
import static java.util.Objects.requireNonNull;
import java.util.Set;
import org.opendaylight.mdsal.binding.generator.impl.reactor.CollisionDomain.Member;
-import org.opendaylight.mdsal.binding.model.api.GeneratedType;
+import org.opendaylight.mdsal.binding.generator.impl.rt.DefaultKeyRuntimeType;
+import org.opendaylight.mdsal.binding.model.api.GeneratedTransferObject;
import org.opendaylight.mdsal.binding.model.api.Type;
import org.opendaylight.mdsal.binding.model.api.type.builder.GeneratedPropertyBuilder;
import org.opendaylight.mdsal.binding.model.api.type.builder.GeneratedTOBuilder;
import org.opendaylight.mdsal.binding.model.api.type.builder.GeneratedTypeBuilderBase;
import org.opendaylight.mdsal.binding.model.ri.BindingTypes;
+import org.opendaylight.mdsal.binding.runtime.api.KeyRuntimeType;
import org.opendaylight.mdsal.binding.spec.naming.BindingMapping;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.model.api.stmt.KeyEffectiveStatement;
import org.opendaylight.yangtools.yang.model.util.SchemaInferenceStack;
-final class KeyGenerator extends AbstractExplicitGenerator<KeyEffectiveStatement> {
+final class KeyGenerator extends AbstractExplicitGenerator<KeyEffectiveStatement, KeyRuntimeType> {
private final ListGenerator listGen;
- KeyGenerator(final KeyEffectiveStatement statement, final AbstractCompositeGenerator<?> parent,
+ KeyGenerator(final KeyEffectiveStatement statement, final AbstractCompositeGenerator<?, ?> parent,
final ListGenerator listGen) {
super(statement, parent);
this.listGen = requireNonNull(listGen);
}
@Override
- GeneratedType createTypeImpl(final TypeBuilderFactory builderFactory) {
+ GeneratedTransferObject createTypeImpl(final TypeBuilderFactory builderFactory) {
final GeneratedTOBuilder builder = builderFactory.newGeneratedTOBuilder(typeName());
builder.addImplementsType(BindingTypes.identifier(Type.of(listGen.typeName())));
return builder.build();
}
+ @Override
+ KeyRuntimeType createRuntimeType() {
+ return generatedType().map(type -> {
+ verify(type instanceof GeneratedTransferObject, "Unexpected type %s", type);
+ return new DefaultKeyRuntimeType((GeneratedTransferObject) type, statement());
+ }).orElse(null);
+ }
+
+ @Override
+ KeyRuntimeType rebaseRuntimeType(final KeyRuntimeType type, final KeyEffectiveStatement statement) {
+ return new DefaultKeyRuntimeType(type.javaType(), statement);
+ }
+
@Override
void addAsGetterMethod(final GeneratedTypeBuilderBase<?> builder, final TypeBuilderFactory builderFactory) {
// Keys are explicitly handled by their corresponding list
*/
package org.opendaylight.mdsal.binding.generator.impl.reactor;
+import org.opendaylight.mdsal.binding.generator.impl.rt.DefaultLeafRuntimeType;
+import org.opendaylight.mdsal.binding.model.api.Type;
+import org.opendaylight.mdsal.binding.runtime.api.LeafRuntimeType;
import org.opendaylight.yangtools.yang.model.api.stmt.LeafEffectiveStatement;
/**
* Generator corresponding to a {@code leaf} statement.
*/
-final class LeafGenerator extends AbstractTypeAwareGenerator<LeafEffectiveStatement, LeafGenerator> {
- LeafGenerator(final LeafEffectiveStatement statement, final AbstractCompositeGenerator<?> parent) {
+final class LeafGenerator extends AbstractTypeAwareGenerator<LeafEffectiveStatement, LeafRuntimeType, LeafGenerator> {
+ LeafGenerator(final LeafEffectiveStatement statement, final AbstractCompositeGenerator<?, ?> parent) {
super(statement, parent);
}
+
+ @Override
+ LeafRuntimeType createRuntimeType(final Type type) {
+ return new DefaultLeafRuntimeType(type, statement());
+ }
+
+ @Override
+ LeafRuntimeType rebaseRuntimeType(final LeafRuntimeType type, final LeafEffectiveStatement statement) {
+ return new DefaultLeafRuntimeType(type.javaType(), statement);
+ }
}
*/
package org.opendaylight.mdsal.binding.generator.impl.reactor;
+import org.opendaylight.mdsal.binding.generator.impl.rt.DefaultLeafListRuntimeType;
import org.opendaylight.mdsal.binding.model.api.Type;
import org.opendaylight.mdsal.binding.model.ri.Types;
+import org.opendaylight.mdsal.binding.runtime.api.LeafListRuntimeType;
import org.opendaylight.yangtools.yang.common.Ordering;
import org.opendaylight.yangtools.yang.model.api.stmt.LeafListEffectiveStatement;
import org.opendaylight.yangtools.yang.model.api.stmt.OrderedByEffectiveStatement;
/**
* Generator corresponding to a {@code leaf-list} statement.
*/
-final class LeafListGenerator extends AbstractTypeAwareGenerator<LeafListEffectiveStatement, LeafListGenerator> {
- LeafListGenerator(final LeafListEffectiveStatement statement, final AbstractCompositeGenerator<?> parent) {
+final class LeafListGenerator
+ extends AbstractTypeAwareGenerator<LeafListEffectiveStatement, LeafListRuntimeType, LeafListGenerator> {
+ LeafListGenerator(final LeafListEffectiveStatement statement, final AbstractCompositeGenerator<?, ?> parent) {
super(statement, parent);
}
throw new IllegalStateException("Unexpected ordering " + ordering);
}
}
+
+ @Override
+ LeafListRuntimeType createRuntimeType(final Type type) {
+ return new DefaultLeafListRuntimeType(type, statement());
+ }
+
+ @Override
+ LeafListRuntimeType rebaseRuntimeType(final LeafListRuntimeType type, final LeafListEffectiveStatement statement) {
+ return new DefaultLeafListRuntimeType(type.javaType(), statement);
+ }
}
import static org.opendaylight.mdsal.binding.model.ri.BindingTypes.identifiable;
+import java.util.List;
import org.eclipse.jdt.annotation.Nullable;
+import org.opendaylight.mdsal.binding.generator.impl.rt.DefaultListRuntimeType;
import org.opendaylight.mdsal.binding.model.api.GeneratedType;
import org.opendaylight.mdsal.binding.model.api.MethodSignature.ValueMechanics;
import org.opendaylight.mdsal.binding.model.api.Type;
import org.opendaylight.mdsal.binding.model.api.type.builder.GeneratedTypeBuilderBase;
import org.opendaylight.mdsal.binding.model.api.type.builder.MethodSignatureBuilder;
import org.opendaylight.mdsal.binding.model.ri.Types;
+import org.opendaylight.mdsal.binding.runtime.api.AugmentRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.ListRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.RuntimeType;
import org.opendaylight.mdsal.binding.spec.naming.BindingMapping;
import org.opendaylight.yangtools.yang.common.Ordering;
import org.opendaylight.yangtools.yang.model.api.stmt.KeyEffectiveStatement;
/**
* Generator corresponding to a {@code list} statement.
*/
-final class ListGenerator extends CompositeSchemaTreeGenerator<ListEffectiveStatement, ListGenerator> {
+final class ListGenerator extends CompositeSchemaTreeGenerator<ListEffectiveStatement, ListRuntimeType> {
private final @Nullable KeyGenerator keyGen;
- ListGenerator(final ListEffectiveStatement statement, final AbstractCompositeGenerator<?> parent) {
+ ListGenerator(final ListEffectiveStatement statement, final AbstractCompositeGenerator<?, ?> parent) {
super(statement, parent);
keyGen = statement.findFirstEffectiveSubstatement(KeyEffectiveStatement.class)
.map(key -> new KeyGenerator(key, parent, this))
return builder.build();
}
+ @Override
+ ListRuntimeType createRuntimeType(final GeneratedType type, final ListEffectiveStatement statement,
+ final List<RuntimeType> children, final List<AugmentRuntimeType> augments) {
+ return new DefaultListRuntimeType(type, statement, children, augments,
+ keyGen != null ? keyGen.runtimeType().orElseThrow() : null);
+ }
+
@Override
Type methodReturnType(final TypeBuilderFactory builderFactory) {
final Type generatedType = super.methodReturnType(builderFactory);
static final @NonNull Identity INSTANCE = new Identity();
@Override
- AbstractExplicitGenerator<?> findGenerator(final EffectiveStatement<?, ?> needle,
+ AbstractExplicitGenerator<?, ?> findGenerator(final EffectiveStatement<?, ?> needle,
final Iterable<? extends Generator> haystack) {
for (Generator gen : haystack) {
if (gen instanceof AbstractExplicitGenerator) {
- final AbstractExplicitGenerator<?> ret = (AbstractExplicitGenerator<?>) gen;
+ final AbstractExplicitGenerator<?, ?> ret = (AbstractExplicitGenerator<?, ?>) gen;
if (needle == ret.statement()) {
return ret;
}
static final @NonNull OnQName INSTANCE = new OnQName();
@Override
- final AbstractExplicitGenerator<?> findGenerator(final EffectiveStatement<?, ?> needle,
+ final AbstractExplicitGenerator<?, ?> findGenerator(final EffectiveStatement<?, ?> needle,
final Iterable<? extends Generator> haystack) {
final Object arg = needle.argument();
verify(arg instanceof QName, "Unexpected argument %s in %s", arg, needle);
return findGenerator((QName) arg, haystack);
}
- AbstractExplicitGenerator<?> findGenerator(final QName needle, final Iterable<? extends Generator> haystack) {
+ AbstractExplicitGenerator<?, ?> findGenerator(final QName needle,
+ final Iterable<? extends Generator> haystack) {
for (Generator gen : haystack) {
if (gen instanceof AbstractExplicitGenerator) {
- final AbstractExplicitGenerator<?> ret = (AbstractExplicitGenerator<?>) gen;
+ final AbstractExplicitGenerator<?, ?> ret = (AbstractExplicitGenerator<?, ?>) gen;
if (needle.equals(ret.statement().argument())) {
return ret;
}
}
@Override
- AbstractExplicitGenerator<?> findGenerator(final QName needle, final Iterable<? extends Generator> haystack) {
+ AbstractExplicitGenerator<?, ?> findGenerator(final QName needle,
+ final Iterable<? extends Generator> haystack) {
return super.findGenerator(needle.bindTo(module), haystack);
}
return Identity.INSTANCE;
}
- abstract @Nullable AbstractExplicitGenerator<?> findGenerator(EffectiveStatement<?, ?> needle,
+ abstract @Nullable AbstractExplicitGenerator<?, ?> findGenerator(EffectiveStatement<?, ?> needle,
Iterable<? extends Generator> haystack);
@Override
import org.eclipse.jdt.annotation.NonNull;
import org.opendaylight.yangtools.yang.model.api.stmt.AugmentEffectiveStatement;
+import org.opendaylight.yangtools.yang.model.util.SchemaInferenceStack;
/**
* Generator corresponding to a {@code augment} statement used as a child of a {@code module} statement.
*/
final class ModuleAugmentGenerator extends AbstractAugmentGenerator {
- ModuleAugmentGenerator(final AugmentEffectiveStatement statement, final AbstractCompositeGenerator<?> parent) {
+ ModuleAugmentGenerator(final AugmentEffectiveStatement statement, final AbstractCompositeGenerator<?, ?> parent) {
super(statement, parent);
}
@NonNull AugmentRequirement startLinkage(final GeneratorContext context) {
+ setTargetStatement(SchemaInferenceStack.of(context.getEffectiveModelContext())
+ .enterSchemaTree(statement().argument()));
+
return new AugmentRequirement(this,
context.resolveModule(statement().argument().firstNodeIdentifier().getModule()));
}
import static com.google.common.base.Verify.verifyNotNull;
+import java.util.List;
import java.util.Map;
import org.eclipse.jdt.annotation.NonNull;
import org.opendaylight.mdsal.binding.generator.impl.reactor.CollisionDomain.Member;
+import org.opendaylight.mdsal.binding.generator.impl.rt.DefaultModuleRuntimeType;
import org.opendaylight.mdsal.binding.model.api.GeneratedType;
import org.opendaylight.mdsal.binding.model.api.JavaTypeName;
import org.opendaylight.mdsal.binding.model.api.type.builder.GeneratedTypeBuilder;
import org.opendaylight.mdsal.binding.model.api.type.builder.GeneratedTypeBuilderBase;
import org.opendaylight.mdsal.binding.model.ri.BindingTypes;
+import org.opendaylight.mdsal.binding.runtime.api.AugmentRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.ModuleRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.RuntimeType;
import org.opendaylight.mdsal.binding.spec.naming.BindingMapping;
import org.opendaylight.yangtools.yang.common.AbstractQName;
import org.opendaylight.yangtools.yang.common.QNameModule;
* Generator corresponding to a {@code module} statement. These generators are roots for generating types for a
* particular {@link QNameModule} as mapped into the root package.
*/
-public final class ModuleGenerator extends AbstractCompositeGenerator<ModuleEffectiveStatement> {
+public final class ModuleGenerator extends AbstractCompositeGenerator<ModuleEffectiveStatement, ModuleRuntimeType> {
private final @NonNull JavaTypeName yangModuleInfo;
private final @NonNull ClassPlacement placement;
}
@Override
- AbstractCompositeGenerator<?> getPackageParent() {
+ AbstractCompositeGenerator<?, ?> getPackageParent() {
return this;
}
return builder.build();
}
+ @Override
+ ModuleRuntimeType createRuntimeType(final GeneratedType type, final ModuleEffectiveStatement statement,
+ final List<RuntimeType> children, final List<AugmentRuntimeType> augments) {
+ return new DefaultModuleRuntimeType(type, statement, children, augments);
+ }
+
@NonNull Member getPrefixMember() {
return verifyNotNull(prefixMember);
}
*/
package org.opendaylight.mdsal.binding.generator.impl.reactor;
+import java.util.List;
+import org.opendaylight.mdsal.binding.generator.impl.rt.DefaultNotificationRuntimeType;
import org.opendaylight.mdsal.binding.model.api.GeneratedType;
import org.opendaylight.mdsal.binding.model.api.Type;
import org.opendaylight.mdsal.binding.model.api.type.builder.GeneratedTypeBuilder;
import org.opendaylight.mdsal.binding.model.api.type.builder.GeneratedTypeBuilderBase;
import org.opendaylight.mdsal.binding.model.ri.BindingTypes;
+import org.opendaylight.mdsal.binding.runtime.api.AugmentRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.NotificationRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.RuntimeType;
import org.opendaylight.yangtools.yang.model.api.stmt.NotificationEffectiveStatement;
import org.opendaylight.yangtools.yang.model.util.SchemaInferenceStack;
* Generator corresponding to a {@code notification} statement.
*/
final class NotificationGenerator
- extends CompositeSchemaTreeGenerator<NotificationEffectiveStatement, NotificationGenerator> {
- NotificationGenerator(final NotificationEffectiveStatement statement, final AbstractCompositeGenerator<?> parent) {
+ extends CompositeSchemaTreeGenerator<NotificationEffectiveStatement, NotificationRuntimeType> {
+ NotificationGenerator(final NotificationEffectiveStatement statement,
+ final AbstractCompositeGenerator<?, ?> parent) {
super(statement, parent);
}
return builder.build();
}
+ @Override
+ NotificationRuntimeType createRuntimeType(final GeneratedType type, final NotificationEffectiveStatement statement,
+ final List<RuntimeType> children, final List<AugmentRuntimeType> augments) {
+ return new DefaultNotificationRuntimeType(type, statement, children, augments);
+ }
+
@Override
void addAsGetterMethod(final GeneratedTypeBuilderBase<?> builder, final TypeBuilderFactory builderFactory) {
// Notifications are a distinct concept
}
private Type notificationType(final GeneratedTypeBuilder builder, final TypeBuilderFactory builderFactory) {
- final AbstractCompositeGenerator<?> parent = getParent();
+ final AbstractCompositeGenerator<?, ?> parent = getParent();
if (parent instanceof ModuleGenerator) {
return BindingTypes.notification(builder);
}
*/
package org.opendaylight.mdsal.binding.generator.impl.reactor;
-import org.opendaylight.mdsal.binding.generator.impl.tree.SchemaTreeChild;
+import org.opendaylight.mdsal.binding.generator.impl.rt.DefaultAnydataRuntimeType;
+import org.opendaylight.mdsal.binding.generator.impl.rt.DefaultAnyxmlRuntimeType;
import org.opendaylight.mdsal.binding.model.api.GeneratedType;
import org.opendaylight.mdsal.binding.model.api.Type;
import org.opendaylight.mdsal.binding.model.api.type.builder.GeneratedTypeBuilder;
import org.opendaylight.mdsal.binding.model.api.type.builder.GeneratedTypeBuilderBase;
import org.opendaylight.mdsal.binding.model.ri.BindingTypes;
+import org.opendaylight.mdsal.binding.runtime.api.AnydataRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.AnyxmlRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.OpaqueRuntimeType;
+import org.opendaylight.yangtools.yang.model.api.stmt.AnydataEffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.AnyxmlEffectiveStatement;
import org.opendaylight.yangtools.yang.model.api.stmt.DataTreeEffectiveStatement;
import org.opendaylight.yangtools.yang.model.util.SchemaInferenceStack;
/**
* Common generator for {@code anydata} and {@code anyxml}.
*/
-final class OpaqueObjectGenerator<T extends DataTreeEffectiveStatement<?>> extends AbstractExplicitGenerator<T>
- implements SchemaTreeChild<T, OpaqueObjectGenerator<T>> {
- OpaqueObjectGenerator(final T statement, final AbstractCompositeGenerator<?> parent) {
- super(statement, parent);
+abstract class OpaqueObjectGenerator<S extends DataTreeEffectiveStatement<?>, R extends OpaqueRuntimeType>
+ extends AbstractExplicitGenerator<S, R> {
+ static final class Anydata extends OpaqueObjectGenerator<AnydataEffectiveStatement, AnydataRuntimeType> {
+ Anydata(final AnydataEffectiveStatement statement, final AbstractCompositeGenerator<?, ?> parent) {
+ super(statement, parent);
+ }
+
+ @Override
+ AnydataRuntimeType createRuntimeType() {
+ return generatedType().map(type -> new DefaultAnydataRuntimeType(type, statement())).orElse(null);
+ }
+
+ @Override
+ AnydataRuntimeType rebaseRuntimeType(final AnydataRuntimeType type, final AnydataEffectiveStatement statement) {
+ return new DefaultAnydataRuntimeType(type.javaType(), statement);
+ }
}
- @Override
- public OpaqueObjectGenerator<T> generator() {
- return this;
+ static final class Anyxml extends OpaqueObjectGenerator<AnyxmlEffectiveStatement, AnyxmlRuntimeType> {
+ Anyxml(final AnyxmlEffectiveStatement statement, final AbstractCompositeGenerator<?, ?> parent) {
+ super(statement, parent);
+ }
+
+ @Override
+ AnyxmlRuntimeType createRuntimeType() {
+ return generatedType().map(type -> new DefaultAnyxmlRuntimeType(type, statement())).orElse(null);
+ }
+
+ @Override
+ AnyxmlRuntimeType rebaseRuntimeType(final AnyxmlRuntimeType type, final AnyxmlEffectiveStatement statement) {
+ return new DefaultAnyxmlRuntimeType(type.javaType(), statement);
+ }
+ }
+
+ OpaqueObjectGenerator(final S statement, final AbstractCompositeGenerator<?, ?> parent) {
+ super(statement, parent);
}
@Override
*/
package org.opendaylight.mdsal.binding.generator.impl.reactor;
+import static java.util.Objects.requireNonNull;
+
import org.opendaylight.mdsal.binding.model.api.ConcreteType;
import org.opendaylight.mdsal.binding.model.api.GeneratedType;
import org.opendaylight.mdsal.binding.model.api.type.builder.GeneratedTypeBuilder;
-import org.opendaylight.mdsal.binding.model.ri.BindingTypes;
-import org.opendaylight.yangtools.yang.model.api.stmt.InputEffectiveStatement;
-import org.opendaylight.yangtools.yang.model.api.stmt.OutputEffectiveStatement;
-import org.opendaylight.yangtools.yang.model.api.stmt.SchemaTreeEffectiveStatement;
+import org.opendaylight.mdsal.binding.runtime.api.CompositeRuntimeType;
+import org.opendaylight.yangtools.yang.model.api.stmt.DataTreeEffectiveStatement;
import org.opendaylight.yangtools.yang.model.util.SchemaInferenceStack;
/**
* Generator corresponding to an {@code input} or an {@code output} statement.
*/
-class OperationContainerGenerator
- extends CompositeSchemaTreeGenerator<SchemaTreeEffectiveStatement<?>, OperationContainerGenerator> {
+abstract class OperationContainerGenerator<S extends DataTreeEffectiveStatement<?>, R extends CompositeRuntimeType>
+ extends CompositeSchemaTreeGenerator<S, R> {
private final ConcreteType baseInterface;
- OperationContainerGenerator(final InputEffectiveStatement statement, final AbstractCompositeGenerator<?> parent) {
- super(statement, parent);
- baseInterface = BindingTypes.RPC_INPUT;
- }
-
- OperationContainerGenerator(final OutputEffectiveStatement statement, final AbstractCompositeGenerator<?> parent) {
+ OperationContainerGenerator(final S statement, final AbstractCompositeGenerator<?, ?> parent,
+ final ConcreteType baseInterface) {
super(statement, parent);
- baseInterface = BindingTypes.RPC_OUTPUT;
+ this.baseInterface = requireNonNull(baseInterface);
}
@Override
@Override
final GeneratedType createTypeImpl(final TypeBuilderFactory builderFactory) {
- final AbstractCompositeGenerator<?> parent = getParent();
+ final AbstractCompositeGenerator<?, ?> parent = getParent();
if (parent instanceof ActionGenerator && ((ActionGenerator) parent).isAddedByUses()) {
// final ActionDefinition orig = findOrigAction(parentSchema, action).get();
// // Original definition may live in a different module, make sure we account for that
import com.google.common.base.MoreObjects.ToStringHelper;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;
+import org.opendaylight.mdsal.binding.runtime.api.RuntimeType;
import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
/**
* Link to the original definition of an {@link AbstractExplicitGenerator}.
*/
// FIXME: sealed when we have JDK17+
-abstract class OriginalLink<T extends EffectiveStatement<?, ?>> {
- private static final class Complete<T extends EffectiveStatement<?, ?>> extends OriginalLink<T> {
- private final @NonNull AbstractExplicitGenerator<T> original;
+abstract class OriginalLink<T extends EffectiveStatement<?, ?>, R extends RuntimeType> {
+ private static final class Complete<T extends EffectiveStatement<?, ?>, R extends RuntimeType>
+ extends OriginalLink<T, R> {
+ private final @NonNull AbstractExplicitGenerator<T, R> original;
- Complete(final AbstractExplicitGenerator<T> original) {
+ Complete(final AbstractExplicitGenerator<T, R> original) {
this.original = requireNonNull(original);
}
@Override
- AbstractExplicitGenerator<T> previous() {
+ AbstractExplicitGenerator<T, R> previous() {
return original;
}
@Override
- @NonNull AbstractExplicitGenerator<T> original() {
+ @NonNull AbstractExplicitGenerator<T, R> original() {
return original;
}
}
}
- private static final class Partial<T extends EffectiveStatement<?, ?>> extends OriginalLink<T> {
- private final @NonNull AbstractExplicitGenerator<T> previous;
- private AbstractExplicitGenerator<T> original;
+ private static final class Partial<T extends EffectiveStatement<?, ?>, R extends RuntimeType>
+ extends OriginalLink<T, R> {
+ private final @NonNull AbstractExplicitGenerator<T, R> previous;
+ private AbstractExplicitGenerator<T, R> original;
- Partial(final AbstractExplicitGenerator<T> previous) {
+ Partial(final AbstractExplicitGenerator<T, R> previous) {
this.previous = requireNonNull(previous);
}
@Override
- AbstractExplicitGenerator<T> previous() {
+ AbstractExplicitGenerator<T, R> previous() {
return previous;
}
@Override
- AbstractExplicitGenerator<T> original() {
+ AbstractExplicitGenerator<T, R> original() {
if (original == null) {
final var link = previous.originalLink();
if (link instanceof Complete || link.previous() != previous) {
// Hidden on purpose
}
- static <T extends EffectiveStatement<?, ?>> @NonNull OriginalLink<T> complete(
- final AbstractExplicitGenerator<T> original) {
+ static <T extends EffectiveStatement<?, ?>, R extends RuntimeType> @NonNull OriginalLink<T, R> complete(
+ final AbstractExplicitGenerator<T, R> original) {
return new Complete<>(original);
}
- static <T extends EffectiveStatement<?, ?>> @NonNull OriginalLink<T> partial(
- final AbstractExplicitGenerator<T> previous) {
+ static <T extends EffectiveStatement<?, ?>, R extends RuntimeType> @NonNull OriginalLink<T, R> partial(
+ final AbstractExplicitGenerator<T, R> previous) {
return new Partial<>(previous);
}
- abstract @NonNull AbstractExplicitGenerator<T> previous();
+ abstract @NonNull AbstractExplicitGenerator<T, R> previous();
- abstract @Nullable AbstractExplicitGenerator<T> original();
+ abstract @Nullable AbstractExplicitGenerator<T, R> original();
abstract ToStringHelper addToStringAttributes(ToStringHelper helper);
--- /dev/null
+/*
+ * Copyright (c) 2022 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.generator.impl.reactor;
+
+import java.util.List;
+import org.opendaylight.mdsal.binding.generator.impl.rt.DefaultOutputRuntimeType;
+import org.opendaylight.mdsal.binding.model.api.GeneratedType;
+import org.opendaylight.mdsal.binding.model.ri.BindingTypes;
+import org.opendaylight.mdsal.binding.runtime.api.AugmentRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.OutputRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.RuntimeType;
+import org.opendaylight.yangtools.yang.model.api.stmt.OutputEffectiveStatement;
+
+/**
+ * Generator corresponding to an {@code input} statement.
+ */
+class OutputGenerator extends OperationContainerGenerator<OutputEffectiveStatement, OutputRuntimeType> {
+ OutputGenerator(final OutputEffectiveStatement statement, final AbstractCompositeGenerator<?, ?> parent) {
+ super(statement, parent, BindingTypes.RPC_OUTPUT);
+ }
+
+ @Override
+ final OutputRuntimeType createRuntimeType(final GeneratedType type, final OutputEffectiveStatement statement,
+ final List<RuntimeType> children, final List<AugmentRuntimeType> augments) {
+ return new DefaultOutputRuntimeType(type, statement, children, augments);
+ }
+}
*/
package org.opendaylight.mdsal.binding.generator.impl.reactor;
+import java.util.List;
import org.opendaylight.mdsal.binding.model.api.GeneratedType;
import org.opendaylight.mdsal.binding.model.api.type.builder.GeneratedTypeBuilderBase;
+import org.opendaylight.mdsal.binding.runtime.api.AugmentRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.RpcRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.RuntimeType;
import org.opendaylight.yangtools.yang.model.api.stmt.RpcEffectiveStatement;
import org.opendaylight.yangtools.yang.model.util.SchemaInferenceStack;
/**
* Generator corresponding to a {@code rpc} statement.
*/
-final class RpcGenerator extends CompositeSchemaTreeGenerator<RpcEffectiveStatement, RpcGenerator> {
- RpcGenerator(final RpcEffectiveStatement statement, final AbstractCompositeGenerator<?> parent) {
+// FIXME: hide this once we have RpcRuntimeType
+public final class RpcGenerator extends CompositeSchemaTreeGenerator<RpcEffectiveStatement, RpcRuntimeType> {
+ RpcGenerator(final RpcEffectiveStatement statement, final AbstractCompositeGenerator<?, ?> parent) {
super(statement, parent);
}
throw new UnsupportedOperationException();
}
+ @Override
+ RpcRuntimeType createRuntimeType(final GeneratedType type, final RpcEffectiveStatement statement,
+ final List<RuntimeType> children, final List<AugmentRuntimeType> augments) {
+ throw new UnsupportedOperationException();
+ }
+
@Override
void addAsGetterMethod(final GeneratedTypeBuilderBase<?> builder, final TypeBuilderFactory builderFactory) {
// RPCs are a separate concept
*/
package org.opendaylight.mdsal.binding.generator.impl.reactor;
-import org.eclipse.jdt.annotation.NonNull;
import org.opendaylight.mdsal.binding.generator.impl.reactor.CollisionDomain.Member;
-import org.opendaylight.mdsal.binding.spec.naming.BindingMapping;
import org.opendaylight.yangtools.yang.model.api.stmt.InputEffectiveStatement;
-import org.opendaylight.yangtools.yang.model.api.stmt.OutputEffectiveStatement;
/**
* Specialization for legacy RPC services.
*/
-final class RpcContainerGenerator extends OperationContainerGenerator {
- private final @NonNull String suffix;
-
- RpcContainerGenerator(final InputEffectiveStatement statement, final AbstractCompositeGenerator<?> parent) {
- super(statement, parent);
- suffix = BindingMapping.RPC_INPUT_SUFFIX;
- }
-
- RpcContainerGenerator(final OutputEffectiveStatement statement, final AbstractCompositeGenerator<?> parent) {
+// FIXME: hide this once we have RpcRuntimeType
+public final class RpcInputGenerator extends InputGenerator {
+ RpcInputGenerator(final InputEffectiveStatement statement, final AbstractCompositeGenerator<?, ?> parent) {
super(statement, parent);
- suffix = BindingMapping.RPC_OUTPUT_SUFFIX;
}
@Override
}
@Override
- AbstractCompositeGenerator<?> getPackageParent() {
+ AbstractCompositeGenerator<?, ?> getPackageParent() {
return getParent().getParent();
}
@Override
Member createMember(final CollisionDomain domain) {
- return domain.addSecondary(this, getParent().ensureMember(), suffix, statement().argument());
+ return domain.addSecondary(this, getParent().ensureMember());
}
}
--- /dev/null
+/*
+ * Copyright (c) 2022 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.generator.impl.reactor;
+
+import org.opendaylight.mdsal.binding.generator.impl.reactor.CollisionDomain.Member;
+import org.opendaylight.yangtools.yang.model.api.stmt.OutputEffectiveStatement;
+
+/**
+ * Specialization for legacy RPC services.
+ */
+// FIXME: hide this once we have RpcRuntimeType
+public final class RpcOutputGenerator extends OutputGenerator {
+ RpcOutputGenerator(final OutputEffectiveStatement statement, final AbstractCompositeGenerator<?, ?> parent) {
+ super(statement, parent);
+ }
+
+ @Override
+ CollisionDomain parentDomain() {
+ return getParent().parentDomain();
+ }
+
+ @Override
+ AbstractCompositeGenerator<?, ?> getPackageParent() {
+ return getParent().getParent();
+ }
+
+ @Override
+ Member createMember(final CollisionDomain domain) {
+ return domain.addSecondary(this, getParent().ensureMember());
+ }
+}
+++ /dev/null
-/*
- * Copyright (c) 2022 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.generator.impl.reactor;
-
-import static com.google.common.base.Verify.verify;
-import static com.google.common.base.Verify.verifyNotNull;
-import static java.util.Objects.requireNonNull;
-
-import org.eclipse.jdt.annotation.NonNull;
-import org.eclipse.jdt.annotation.Nullable;
-import org.opendaylight.mdsal.binding.generator.impl.tree.SchemaTreeChild;
-import org.opendaylight.yangtools.yang.model.api.stmt.SchemaTreeEffectiveStatement;
-
-/**
- * A placeholder {@link SchemaTreeChild}.
- *
- */
-final class SchemaTreePlaceholder<S extends SchemaTreeEffectiveStatement<?>,
- G extends AbstractExplicitGenerator<S> & SchemaTreeChild<S, G>> implements SchemaTreeChild<S, G> {
- private final @NonNull Class<G> generatorType;
- private final @NonNull S statement;
-
- private @Nullable G generator;
-
- SchemaTreePlaceholder(final S statement, final Class<G> generatorType) {
- this.statement = requireNonNull(statement);
- this.generatorType = requireNonNull(generatorType);
- }
-
- @Override
- public S statement() {
- return statement;
- }
-
- @Override
- public G generator() {
- final var local = generator;
- if (local == null) {
- throw new IllegalStateException("Unresolved generator in " + this);
- }
- return local;
- }
-
- void setGenerator(final AbstractCompositeGenerator<?> parent) {
- verify(generator == null, "Attempted to set generator for %s", this);
- final var qname = getIdentifier();
- generator = generatorType.cast(verifyNotNull(parent.findSchemaTreeGenerator(qname),
- "Failed to find generator for child %s in %s", qname, parent));
- }
-}
--- /dev/null
+/*
+ * Copyright (c) 2022 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.generator.impl.reactor;
+
+import static com.google.common.base.Verify.verify;
+import static java.util.Objects.requireNonNull;
+
+import com.google.common.collect.Collections2;
+import com.google.common.collect.ImmutableList;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import org.eclipse.jdt.annotation.NonNull;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.model.api.ActionDefinition;
+import org.opendaylight.yangtools.yang.model.api.AugmentationSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.GroupingDefinition;
+import org.opendaylight.yangtools.yang.model.api.NotificationDefinition;
+import org.opendaylight.yangtools.yang.model.api.Status;
+import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
+import org.opendaylight.yangtools.yang.model.api.UsesNode;
+import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.meta.IdentifierNamespace;
+import org.opendaylight.yangtools.yang.model.api.meta.StatementOrigin;
+import org.opendaylight.yangtools.yang.model.api.stmt.AugmentEffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.AugmentStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.SchemaNodeIdentifier;
+import org.opendaylight.yangtools.yang.model.api.stmt.SchemaTreeAwareEffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.SchemaTreeEffectiveStatement;
+import org.opendaylight.yangtools.yang.xpath.api.YangXPathExpression.QualifiedBound;
+
+final class TargetAugmentEffectiveStatement implements AugmentEffectiveStatement, AugmentationSchemaNode {
+ private final @NonNull List<EffectiveStatement<?, ?>> substatements;
+ private final @NonNull AugmentEffectiveStatement delegate;
+ private final @NonNull AugmentationSchemaNode schemaDelegate;
+
+ TargetAugmentEffectiveStatement(final AugmentEffectiveStatement augment,
+ final SchemaTreeAwareEffectiveStatement<?, ?> target) {
+ delegate = requireNonNull(augment);
+ verify(augment instanceof AugmentationSchemaNode, "Unsupported augment implementation %s", augment);
+ schemaDelegate = (AugmentationSchemaNode) augment;
+
+ final var stmts = augment.effectiveSubstatements();
+ final var builder = ImmutableList.<EffectiveStatement<?, ?>>builderWithExpectedSize(stmts.size());
+ for (var stmt : stmts) {
+ if (stmt instanceof SchemaTreeEffectiveStatement) {
+ final var qname = ((SchemaTreeEffectiveStatement<?>) stmt).getIdentifier();
+ final Optional<? extends SchemaTreeEffectiveStatement<?>> child =
+ target.get(SchemaTreeAwareEffectiveStatement.Namespace.class, qname);
+ child.ifPresent(builder::add);
+ } else {
+ builder.add(stmt);
+ }
+ }
+
+ substatements = builder.build();
+ }
+
+ @NonNull AugmentEffectiveStatement delegate() {
+ return delegate;
+ }
+
+ @Override
+ public AugmentStatement getDeclared() {
+ return delegate.getDeclared();
+ }
+
+ @Override
+ public SchemaNodeIdentifier argument() {
+ return delegate.argument();
+ }
+
+ @Override
+ public StatementOrigin statementOrigin() {
+ return delegate.statementOrigin();
+ }
+
+ @Override
+ public <K, V, N extends IdentifierNamespace<K, V>> Optional<? extends V> get(final Class<N> namespace,
+ final K identifier) {
+ return Optional.empty();
+ }
+
+ @Override
+ public <K, V, N extends IdentifierNamespace<K, V>> Map<K, V> getAll(final Class<N> namespace) {
+ return Map.of();
+ }
+
+ @Override
+ public Collection<? extends EffectiveStatement<?, ?>> effectiveSubstatements() {
+ return substatements;
+ }
+
+ @Override
+ public Collection<? extends TypeDefinition<?>> getTypeDefinitions() {
+ return schemaDelegate.getTypeDefinitions();
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public Collection<? extends DataSchemaNode> getChildNodes() {
+ return (Collection) Collections2.filter(substatements, DataSchemaNode.class::isInstance);
+ }
+
+ @Override
+ public Collection<? extends GroupingDefinition> getGroupings() {
+ return schemaDelegate.getGroupings();
+ }
+
+ @Override
+ public DataSchemaNode dataChildByName(final QName name) {
+ return getChildNodes().stream().filter(child -> name.equals(child.getQName())).findFirst().orElse(null);
+ }
+
+ @Override
+ public Collection<? extends UsesNode> getUses() {
+ return schemaDelegate.getUses();
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public Collection<? extends NotificationDefinition> getNotifications() {
+ return (Collection) Collections2.filter(substatements, NotificationDefinition.class::isInstance);
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public Collection<? extends ActionDefinition> getActions() {
+ return (Collection) Collections2.filter(substatements, ActionDefinition.class::isInstance);
+ }
+
+ @Override
+ public Optional<? extends QualifiedBound> getWhenCondition() {
+ return schemaDelegate.getWhenCondition();
+ }
+
+ @Override
+ public @NonNull Status getStatus() {
+ return schemaDelegate.getStatus();
+ }
+
+ @Override
+ public Optional<String> getDescription() {
+ return schemaDelegate.getDescription();
+ }
+
+ @Override
+ public Optional<String> getReference() {
+ return schemaDelegate.getReference();
+ }
+
+ @Override
+ public AugmentEffectiveStatement asEffectiveStatement() {
+ return this;
+ }
+
+ @Override
+ @Deprecated(forRemoval = true)
+ public Optional<AugmentationSchemaNode> getOriginalDefinition() {
+ return schemaDelegate.getOriginalDefinition();
+ }
+}
}
static final class ResolvedLeafref extends Leafref {
- private final AbstractTypeObjectGenerator<?> referencedGenerator;
+ private final AbstractTypeObjectGenerator<?, ?> referencedGenerator;
- private ResolvedLeafref(final AbstractTypeObjectGenerator<?> referencedGenerator) {
+ private ResolvedLeafref(final AbstractTypeObjectGenerator<?, ?> referencedGenerator) {
this.referencedGenerator = requireNonNull(referencedGenerator);
}
}
}
- static @NonNull TypeReference leafRef(final @Nullable AbstractTypeObjectGenerator<?> referencedGenerator) {
+ static @NonNull TypeReference leafRef(final @Nullable AbstractTypeObjectGenerator<?, ?> referencedGenerator) {
return referencedGenerator == null ? UnresolvedLeafref.INSTANCE : new ResolvedLeafref(referencedGenerator);
}
*/
package org.opendaylight.mdsal.binding.generator.impl.reactor;
+import static com.google.common.base.Verify.verify;
import static java.util.Objects.requireNonNull;
import java.util.ArrayList;
import java.util.List;
+import org.opendaylight.mdsal.binding.generator.impl.rt.DefaultTypedefRuntimeType;
import org.opendaylight.mdsal.binding.model.api.GeneratedTransferObject;
+import org.opendaylight.mdsal.binding.model.api.GeneratedType;
+import org.opendaylight.mdsal.binding.model.api.Type;
import org.opendaylight.mdsal.binding.model.api.type.builder.GeneratedTOBuilder;
import org.opendaylight.mdsal.binding.model.api.type.builder.GeneratedTypeBuilderBase;
+import org.opendaylight.mdsal.binding.runtime.api.TypedefRuntimeType;
import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
import org.opendaylight.yangtools.yang.model.api.stmt.TypedefEffectiveStatement;
import org.opendaylight.yangtools.yang.model.util.SchemaInferenceStack;
/**
* Generator corresponding to a {@code typedef} statement.
*/
-final class TypedefGenerator extends AbstractTypeObjectGenerator<TypedefEffectiveStatement> {
+final class TypedefGenerator extends AbstractTypeObjectGenerator<TypedefEffectiveStatement, TypedefRuntimeType> {
/**
* List of all generators for types directly derived from this typedef. We populate this list during initial type
* linking. It allows us to easily cascade inferences made by this typedef down the type derivation tree.
*/
- private List<AbstractTypeObjectGenerator<?>> derivedGenerators = null;
+ private List<AbstractTypeObjectGenerator<?, ?>> derivedGenerators = null;
- TypedefGenerator(final TypedefEffectiveStatement statement, final AbstractCompositeGenerator<?> parent) {
+ TypedefGenerator(final TypedefEffectiveStatement statement, final AbstractCompositeGenerator<?, ?> parent) {
super(statement, parent);
}
dataTree.enterTypedef(statement().argument());
}
- void addDerivedGenerator(final AbstractTypeObjectGenerator<?> derivedGenerator) {
+ void addDerivedGenerator(final AbstractTypeObjectGenerator<?, ?> derivedGenerator) {
if (derivedGenerators == null) {
derivedGenerators = new ArrayList<>(4);
}
void bindDerivedGenerators(final TypeReference reference) {
// Trigger any derived resolvers ...
if (derivedGenerators != null) {
- for (AbstractTypeObjectGenerator<?> derived : derivedGenerators) {
+ for (AbstractTypeObjectGenerator<?, ?> derived : derivedGenerators) {
derived.bindTypeDefinition(reference);
}
}
return builder.build();
}
+ @Override
+ TypedefRuntimeType createRuntimeType(final Type type) {
+ verify(type instanceof GeneratedType, "Unexpected type %s", type);
+ return new DefaultTypedefRuntimeType((GeneratedType) type, statement());
+ }
+
+ @Override
+ TypedefRuntimeType rebaseRuntimeType(final TypedefRuntimeType type, final TypedefEffectiveStatement statement) {
+ return new DefaultTypedefRuntimeType(type.javaType(), statement);
+ }
+
@Override
void addAsGetterMethod(final GeneratedTypeBuilderBase<?> builder, final TypeBuilderFactory builderFactory) {
// typedefs are a separate concept
import org.eclipse.jdt.annotation.NonNull;
import org.opendaylight.yangtools.yang.model.api.stmt.AugmentEffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.SchemaTreeEffectiveStatement;
import org.opendaylight.yangtools.yang.model.api.stmt.UsesEffectiveStatement;
/**
private GroupingGenerator grouping;
UsesAugmentGenerator(final AugmentEffectiveStatement statement, final UsesEffectiveStatement uses,
- final AbstractCompositeGenerator<?> parent) {
+ final AbstractCompositeGenerator<?, ?> parent) {
super(statement, parent);
this.uses = requireNonNull(uses);
+
+ // FIXME: use SchemaTreeAwareEffectiveStatement
+ var stmt = parent.statement();
+ for (var qname : statement.argument().getNodeIdentifiers()) {
+ final var tmp = stmt;
+ stmt = stmt.streamEffectiveSubstatements(SchemaTreeEffectiveStatement.class)
+ .filter(child -> qname.equals(child.argument()))
+ .findFirst()
+ .orElseThrow(() -> new IllegalStateException("Failed to find " + qname + " in " + tmp));
+ }
+ setTargetStatement(stmt);
}
void resolveGrouping(final UsesEffectiveStatement resolvedUses, final GroupingGenerator resolvedGrouping) {
--- /dev/null
+/*
+ * Copyright (c) 2022 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.generator.impl.rt;
+
+import java.util.List;
+import org.opendaylight.mdsal.binding.model.api.GeneratedType;
+import org.opendaylight.mdsal.binding.runtime.api.AugmentRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.CaseRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.RuntimeType;
+import org.opendaylight.yangtools.yang.model.api.stmt.CaseEffectiveStatement;
+
+abstract class AbstractCaseRuntimeType extends AbstractCompositeRuntimeType<CaseEffectiveStatement>
+ implements CaseRuntimeType {
+ AbstractCaseRuntimeType(final GeneratedType bindingType, final CaseEffectiveStatement statement,
+ final List<RuntimeType> children, final List<AugmentRuntimeType> augments) {
+ super(bindingType, statement, children, augments);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2022 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.generator.impl.rt;
+
+import com.google.common.collect.Collections2;
+import java.util.Collection;
+import java.util.List;
+import org.opendaylight.mdsal.binding.model.api.GeneratedType;
+import org.opendaylight.mdsal.binding.model.api.JavaTypeName;
+import org.opendaylight.mdsal.binding.runtime.api.AugmentRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.CaseRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.ChoiceRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.RuntimeType;
+import org.opendaylight.yangtools.yang.model.api.stmt.ChoiceEffectiveStatement;
+
+abstract class AbstractChoiceRuntimeType extends AbstractCompositeRuntimeType<ChoiceEffectiveStatement>
+ implements ChoiceRuntimeType {
+ AbstractChoiceRuntimeType(final GeneratedType bindingType, final ChoiceEffectiveStatement statement,
+ final List<RuntimeType> children, final List<AugmentRuntimeType> augments) {
+ super(bindingType, statement, children, augments);
+ }
+
+ @Override
+ public final Collection<CaseRuntimeType> validCaseChildren() {
+ return (Collection) Collections2.filter(schemaTreeChildren(), CaseRuntimeType.class::isInstance);
+ }
+
+ @Override
+ public final CaseRuntimeType bindingCaseChild(final JavaTypeName typeName) {
+ final var child = bindingChild(typeName);
+ return child instanceof CaseRuntimeType ? (CaseRuntimeType) child : null;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2021 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.generator.impl.rt;
+
+import static java.util.Objects.requireNonNull;
+
+import com.google.common.base.Functions;
+import com.google.common.collect.ImmutableCollection;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import java.util.List;
+import org.eclipse.jdt.annotation.NonNull;
+import org.opendaylight.mdsal.binding.model.api.GeneratedType;
+import org.opendaylight.mdsal.binding.model.api.JavaTypeName;
+import org.opendaylight.mdsal.binding.runtime.api.AugmentRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.CompositeRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.GeneratedRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.RuntimeType;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.SchemaTreeEffectiveStatement;
+
+abstract class AbstractCompositeRuntimeType<S extends EffectiveStatement<?, ?>>
+ extends AbstractRuntimeType<S, GeneratedType> implements CompositeRuntimeType {
+ private final ImmutableMap<JavaTypeName, GeneratedRuntimeType> byClass;
+ private final ImmutableMap<QName, RuntimeType> bySchemaTree;
+ private final @NonNull ImmutableList<AugmentRuntimeType> augments;
+ private final @NonNull ImmutableList<AugmentRuntimeType> mismatchedAugments;
+
+ AbstractCompositeRuntimeType(final GeneratedType bindingType, final S statement, final List<RuntimeType> children,
+ final List<AugmentRuntimeType> augments) {
+ super(bindingType, statement);
+
+ final var substatements = statement.effectiveSubstatements();
+ final var correctBuilder = ImmutableList.<AugmentRuntimeType>builder();
+ final var mismatchedBuilder = ImmutableList.<AugmentRuntimeType>builder();
+ for (var aug : augments) {
+ if (substatements.contains(aug.statement())) {
+ correctBuilder.add(aug);
+ } else {
+ mismatchedBuilder.add(aug);
+ }
+ }
+ this.augments = correctBuilder.build();
+ this.mismatchedAugments = mismatchedBuilder.build();
+
+ byClass = children.stream()
+ .filter(GeneratedRuntimeType.class::isInstance)
+ .map(GeneratedRuntimeType.class::cast)
+ .collect(ImmutableMap.toImmutableMap(GeneratedRuntimeType::getIdentifier, Functions.identity()));
+
+ // Note: this may be over-sized, but we typically deal with schema tree statements, hence it is kind of accurate
+ final var builder = ImmutableMap.<QName, RuntimeType>builderWithExpectedSize(children.size());
+ for (var child : children) {
+ final var stmt = child.statement();
+ if (stmt instanceof SchemaTreeEffectiveStatement) {
+ builder.put(((SchemaTreeEffectiveStatement<?>)stmt).argument(), child);
+ }
+ }
+ bySchemaTree = builder.build();
+ }
+
+ @Override
+ public final List<AugmentRuntimeType> augments() {
+ return augments;
+ }
+
+ @Override
+ public final List<AugmentRuntimeType> mismatchedAugments() {
+ return mismatchedAugments;
+ }
+
+ @Override
+ public final RuntimeType schemaTreeChild(final QName qname) {
+ return bySchemaTree.get(requireNonNull(qname));
+ }
+
+ @Override
+ public final GeneratedRuntimeType bindingChild(final JavaTypeName typeName) {
+ return byClass.get(requireNonNull(typeName));
+ }
+
+ final @NonNull ImmutableCollection<RuntimeType> schemaTreeChildren() {
+ return bySchemaTree.values();
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2022 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.generator.impl.rt;
+
+import org.opendaylight.mdsal.binding.model.api.GeneratedType;
+import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
+
+abstract class AbstractGeneratedRuntimeType<S extends EffectiveStatement<?, ?>>
+ extends AbstractRuntimeType<S, GeneratedType> {
+ AbstractGeneratedRuntimeType(final GeneratedType bindingType, final S statement) {
+ super(bindingType, statement);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2021 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.generator.impl.rt;
+
+import org.opendaylight.mdsal.binding.model.api.GeneratedTransferObject;
+import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
+
+abstract class AbstractObjectRuntimeType<S extends EffectiveStatement<?, ?>>
+ extends AbstractRuntimeType<S, GeneratedTransferObject> {
+ AbstractObjectRuntimeType(final GeneratedTransferObject bindingType, final S statement) {
+ super(bindingType, statement);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2021 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.generator.impl.rt;
+
+import static java.util.Objects.requireNonNull;
+
+import com.google.common.base.MoreObjects;
+import org.eclipse.jdt.annotation.NonNull;
+import org.opendaylight.mdsal.binding.model.api.Type;
+import org.opendaylight.mdsal.binding.runtime.api.RuntimeType;
+import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
+
+abstract class AbstractRuntimeType<S extends EffectiveStatement<?, ?>, T extends Type> implements RuntimeType {
+ private final @NonNull T javaType;
+ private final @NonNull S statement;
+
+ AbstractRuntimeType(final T bindingType, final S statement) {
+ this.javaType = requireNonNull(bindingType);
+ this.statement = requireNonNull(statement);
+ }
+
+ @Override
+ public final T javaType() {
+ return javaType;
+ }
+
+ @Override
+ public final S statement() {
+ return statement;
+ }
+
+ @Override
+ public final String toString() {
+ return MoreObjects.toStringHelper(this).add("javaType", javaType).add("statement", statement).toString();
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2021 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.generator.impl.rt;
+
+import com.google.common.annotations.Beta;
+import java.util.List;
+import org.eclipse.jdt.annotation.NonNull;
+import org.opendaylight.mdsal.binding.model.api.GeneratedType;
+import org.opendaylight.mdsal.binding.runtime.api.ActionRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.AugmentRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.InputRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.OutputRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.RuntimeType;
+import org.opendaylight.yangtools.yang.model.api.stmt.ActionEffectiveStatement;
+
+@Beta
+public final class DefaultActionRuntimeType extends AbstractCompositeRuntimeType<ActionEffectiveStatement>
+ implements ActionRuntimeType {
+ private final @NonNull InputRuntimeType input;
+ private final @NonNull OutputRuntimeType output;
+
+ public DefaultActionRuntimeType(final GeneratedType bindingType, final ActionEffectiveStatement statement,
+ final List<RuntimeType> children, final List<AugmentRuntimeType> augments) {
+ super(bindingType, statement, children, augments);
+ input = child(children, InputRuntimeType.class);
+ output = child(children, OutputRuntimeType.class);
+ }
+
+ @Override
+ public InputRuntimeType input() {
+ return input;
+ }
+
+ @Override
+ public OutputRuntimeType output() {
+ return output;
+ }
+
+ private static <T extends RuntimeType> @NonNull T child(final List<RuntimeType> list, final Class<T> clazz) {
+ return list.stream().filter(clazz::isInstance).map(clazz::cast).findFirst().orElseThrow();
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2021 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.generator.impl.rt;
+
+import com.google.common.annotations.Beta;
+import org.opendaylight.mdsal.binding.model.api.GeneratedType;
+import org.opendaylight.mdsal.binding.runtime.api.AnydataRuntimeType;
+import org.opendaylight.yangtools.yang.model.api.stmt.AnydataEffectiveStatement;
+
+@Beta
+public final class DefaultAnydataRuntimeType extends AbstractGeneratedRuntimeType<AnydataEffectiveStatement>
+ implements AnydataRuntimeType {
+ public DefaultAnydataRuntimeType(final GeneratedType bindingType, final AnydataEffectiveStatement statement) {
+ super(bindingType, statement);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2021 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.generator.impl.rt;
+
+import com.google.common.annotations.Beta;
+import org.opendaylight.mdsal.binding.model.api.GeneratedType;
+import org.opendaylight.mdsal.binding.runtime.api.AnyxmlRuntimeType;
+import org.opendaylight.yangtools.yang.model.api.stmt.AnyxmlEffectiveStatement;
+
+@Beta
+public final class DefaultAnyxmlRuntimeType extends AbstractGeneratedRuntimeType<AnyxmlEffectiveStatement>
+ implements AnyxmlRuntimeType {
+ public DefaultAnyxmlRuntimeType(final GeneratedType bindingType, final AnyxmlEffectiveStatement statement) {
+ super(bindingType, statement);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2021 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.generator.impl.rt;
+
+import com.google.common.annotations.Beta;
+import java.util.List;
+import org.opendaylight.mdsal.binding.model.api.GeneratedType;
+import org.opendaylight.mdsal.binding.runtime.api.AugmentRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.RuntimeType;
+import org.opendaylight.yangtools.yang.model.api.stmt.AugmentEffectiveStatement;
+
+@Beta
+public final class DefaultAugmentRuntimeType extends AbstractCompositeRuntimeType<AugmentEffectiveStatement>
+ implements AugmentRuntimeType {
+ public DefaultAugmentRuntimeType(final GeneratedType bindingType, final AugmentEffectiveStatement statement,
+ final List<RuntimeType> children, final List<AugmentRuntimeType> augments) {
+ super(bindingType, statement, children, augments);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2018 Pantheon Technologies, s.r.o. 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.generator.impl.rt;
+
+import static java.util.Objects.requireNonNull;
+
+import com.google.common.base.MoreObjects;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSortedMap;
+import com.google.common.collect.Maps;
+import java.util.Map;
+import java.util.Optional;
+import org.eclipse.jdt.annotation.NonNull;
+import org.opendaylight.mdsal.binding.model.api.JavaTypeName;
+import org.opendaylight.mdsal.binding.runtime.api.BindingRuntimeTypes;
+import org.opendaylight.mdsal.binding.runtime.api.GeneratedRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.IdentityRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.InputRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.ModuleRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.OutputRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.RuntimeType;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.common.QNameModule;
+import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
+
+/**
+ * The result of BindingGenerator run. Contains mapping between Types and SchemaNodes.
+ */
+public final class DefaultBindingRuntimeTypes implements BindingRuntimeTypes {
+ private final @NonNull EffectiveModelContext context;
+ private final ImmutableMap<QNameModule, ModuleRuntimeType> modulesByNamespace;
+ private final ImmutableSortedMap<String, ModuleRuntimeType> modulesByPackage;
+ private final ImmutableMap<QName, IdentityRuntimeType> identities;
+ private final ImmutableMap<QName, OutputRuntimeType> rpcOutputs;
+ private final ImmutableMap<QName, InputRuntimeType> rpcInputs;
+ private final ImmutableMap<JavaTypeName, RuntimeType> types;
+
+ public DefaultBindingRuntimeTypes(final EffectiveModelContext context,
+ final Map<QNameModule, ModuleRuntimeType> modules, final Map<JavaTypeName, RuntimeType> types,
+ final Map<QName, IdentityRuntimeType> identities, final Map<QName, InputRuntimeType> rpcInputs,
+ final Map<QName, OutputRuntimeType> rpcOutputs) {
+ this.context = requireNonNull(context);
+ this.identities = ImmutableMap.copyOf(identities);
+ this.types = ImmutableMap.copyOf(types);
+ this.rpcInputs = ImmutableMap.copyOf(rpcInputs);
+ this.rpcOutputs = ImmutableMap.copyOf(rpcOutputs);
+
+ modulesByNamespace = ImmutableMap.copyOf(modules);
+ modulesByPackage = ImmutableSortedMap.copyOf(Maps.uniqueIndex(modules.values(),
+ module -> module.getIdentifier().packageName()));
+ }
+
+ @Override
+ public EffectiveModelContext getEffectiveModelContext() {
+ return context;
+ }
+
+ @Override
+ public Optional<IdentityRuntimeType> findIdentity(final QName qname) {
+ return Optional.ofNullable(identities.get(requireNonNull(qname)));
+ }
+
+ @Override
+ public Optional<RuntimeType> findSchema(final JavaTypeName typeName) {
+ return Optional.ofNullable(types.get(requireNonNull(typeName)));
+ }
+
+ @Override
+ public GeneratedRuntimeType bindingChild(final JavaTypeName typeName) {
+ // The type can actually specify a sub-package, hence we to perform an inexact lookup
+ final var entry = modulesByPackage.floorEntry(typeName.packageName());
+ return entry == null ? null : entry.getValue().bindingChild(typeName);
+ }
+
+ @Override
+ public RuntimeType schemaTreeChild(final QName qname) {
+ final var module = modulesByNamespace.get(qname.getModule());
+ return module == null ? null : module.schemaTreeChild(qname);
+ }
+
+ @Override
+ public Optional<InputRuntimeType> findRpcInput(final QName rpcName) {
+ return Optional.ofNullable(rpcInputs.get(requireNonNull(rpcName)));
+ }
+
+ @Override
+ public Optional<OutputRuntimeType> findRpcOutput(final QName rpcName) {
+ return Optional.ofNullable(rpcOutputs.get(requireNonNull(rpcName)));
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(this)
+ .add("modules", modulesByNamespace.keySet())
+ .add("identities", identities.size())
+ .add("types", types.size())
+ .toString();
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2021 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.generator.impl.rt;
+
+import com.google.common.annotations.Beta;
+import java.util.List;
+import org.opendaylight.mdsal.binding.model.api.GeneratedType;
+import org.opendaylight.mdsal.binding.runtime.api.AugmentRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.ContainerRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.RuntimeType;
+import org.opendaylight.yangtools.yang.model.api.stmt.ContainerEffectiveStatement;
+
+@Beta
+public final class DefaultContainerRuntimeType extends AbstractCompositeRuntimeType<ContainerEffectiveStatement>
+ implements ContainerRuntimeType {
+ public DefaultContainerRuntimeType(final GeneratedType bindingType, final ContainerEffectiveStatement statement,
+ final List<RuntimeType> children, final List<AugmentRuntimeType> augments) {
+ super(bindingType, statement, children, augments);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2021 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.generator.impl.rt;
+
+import com.google.common.annotations.Beta;
+import java.util.List;
+import org.opendaylight.mdsal.binding.model.api.GeneratedType;
+import org.opendaylight.mdsal.binding.runtime.api.AugmentRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.GroupingRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.RuntimeType;
+import org.opendaylight.yangtools.yang.model.api.stmt.GroupingEffectiveStatement;
+
+@Beta
+public final class DefaultGroupingRuntimeType extends AbstractCompositeRuntimeType<GroupingEffectiveStatement>
+ implements GroupingRuntimeType {
+ public DefaultGroupingRuntimeType(final GeneratedType bindingType, final GroupingEffectiveStatement statement,
+ final List<RuntimeType> children, final List<AugmentRuntimeType> augments) {
+ super(bindingType, statement, children, augments);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2021 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.generator.impl.rt;
+
+import com.google.common.annotations.Beta;
+import org.opendaylight.mdsal.binding.model.api.GeneratedType;
+import org.opendaylight.mdsal.binding.runtime.api.IdentityRuntimeType;
+import org.opendaylight.yangtools.yang.model.api.stmt.IdentityEffectiveStatement;
+
+@Beta
+public final class DefaultIdentityRuntimeType extends AbstractGeneratedRuntimeType<IdentityEffectiveStatement>
+ implements IdentityRuntimeType {
+ public DefaultIdentityRuntimeType(final GeneratedType bindingType, final IdentityEffectiveStatement statement) {
+ super(bindingType, statement);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2021 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.generator.impl.rt;
+
+import com.google.common.annotations.Beta;
+import java.util.List;
+import org.opendaylight.mdsal.binding.model.api.GeneratedType;
+import org.opendaylight.mdsal.binding.runtime.api.AugmentRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.InputRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.RuntimeType;
+import org.opendaylight.yangtools.yang.model.api.stmt.InputEffectiveStatement;
+
+@Beta
+public final class DefaultInputRuntimeType extends AbstractCompositeRuntimeType<InputEffectiveStatement>
+ implements InputRuntimeType {
+ public DefaultInputRuntimeType(final GeneratedType bindingType, final InputEffectiveStatement statement,
+ final List<RuntimeType> children, final List<AugmentRuntimeType> augments) {
+ super(bindingType, statement, children, augments);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2021 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.generator.impl.rt;
+
+import com.google.common.annotations.Beta;
+import org.opendaylight.mdsal.binding.model.api.GeneratedTransferObject;
+import org.opendaylight.mdsal.binding.runtime.api.KeyRuntimeType;
+import org.opendaylight.yangtools.yang.model.api.stmt.KeyEffectiveStatement;
+
+@Beta
+public final class DefaultKeyRuntimeType extends AbstractObjectRuntimeType<KeyEffectiveStatement>
+ implements KeyRuntimeType {
+ public DefaultKeyRuntimeType(final GeneratedTransferObject bindingType, final KeyEffectiveStatement statement) {
+ super(bindingType, statement);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2021 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.generator.impl.rt;
+
+import com.google.common.annotations.Beta;
+import org.opendaylight.mdsal.binding.model.api.Type;
+import org.opendaylight.mdsal.binding.runtime.api.LeafListRuntimeType;
+import org.opendaylight.yangtools.yang.model.api.stmt.LeafListEffectiveStatement;
+
+@Beta
+public final class DefaultLeafListRuntimeType extends AbstractRuntimeType<LeafListEffectiveStatement, Type>
+ implements LeafListRuntimeType {
+ public DefaultLeafListRuntimeType(final Type bindingType, final LeafListEffectiveStatement statement) {
+ super(bindingType, statement);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2021 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.generator.impl.rt;
+
+import com.google.common.annotations.Beta;
+import org.opendaylight.mdsal.binding.model.api.Type;
+import org.opendaylight.mdsal.binding.runtime.api.LeafRuntimeType;
+import org.opendaylight.yangtools.yang.model.api.stmt.LeafEffectiveStatement;
+
+@Beta
+public final class DefaultLeafRuntimeType extends AbstractRuntimeType<LeafEffectiveStatement, Type>
+ implements LeafRuntimeType {
+ public DefaultLeafRuntimeType(final Type bindingType, final LeafEffectiveStatement statement) {
+ super(bindingType, statement);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2021 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.generator.impl.rt;
+
+import com.google.common.annotations.Beta;
+import java.util.List;
+import org.opendaylight.mdsal.binding.model.api.GeneratedType;
+import org.opendaylight.mdsal.binding.runtime.api.AugmentRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.KeyRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.ListRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.RuntimeType;
+import org.opendaylight.yangtools.yang.model.api.stmt.ListEffectiveStatement;
+
+@Beta
+public final class DefaultListRuntimeType extends AbstractCompositeRuntimeType<ListEffectiveStatement>
+ implements ListRuntimeType {
+ private final KeyRuntimeType keyType;
+
+ public DefaultListRuntimeType(final GeneratedType bindingType, final ListEffectiveStatement statement,
+ final List<RuntimeType> children, final List<AugmentRuntimeType> augments, final KeyRuntimeType keyType) {
+ super(bindingType, statement, children, augments);
+ this.keyType = keyType;
+ }
+
+ @Override
+ public KeyRuntimeType keyType() {
+ return keyType;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2021 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.generator.impl.rt;
+
+import com.google.common.annotations.Beta;
+import java.util.List;
+import org.opendaylight.mdsal.binding.model.api.GeneratedType;
+import org.opendaylight.mdsal.binding.runtime.api.AugmentRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.ModuleRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.RuntimeType;
+import org.opendaylight.yangtools.yang.model.api.stmt.ModuleEffectiveStatement;
+
+@Beta
+public final class DefaultModuleRuntimeType extends AbstractCompositeRuntimeType<ModuleEffectiveStatement>
+ implements ModuleRuntimeType {
+ public DefaultModuleRuntimeType(final GeneratedType bindingType, final ModuleEffectiveStatement statement,
+ final List<RuntimeType> children, final List<AugmentRuntimeType> augments) {
+ super(bindingType, statement, children, augments);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2021 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.generator.impl.rt;
+
+import com.google.common.annotations.Beta;
+import java.util.List;
+import org.opendaylight.mdsal.binding.model.api.GeneratedType;
+import org.opendaylight.mdsal.binding.runtime.api.AugmentRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.NotificationRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.RuntimeType;
+import org.opendaylight.yangtools.yang.model.api.stmt.NotificationEffectiveStatement;
+
+@Beta
+public final class DefaultNotificationRuntimeType extends AbstractCompositeRuntimeType<NotificationEffectiveStatement>
+ implements NotificationRuntimeType {
+ public DefaultNotificationRuntimeType(final GeneratedType bindingType,
+ final NotificationEffectiveStatement statement, final List<RuntimeType> children,
+ final List<AugmentRuntimeType> augments) {
+ super(bindingType, statement, children, augments);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2021 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.generator.impl.rt;
+
+import com.google.common.annotations.Beta;
+import java.util.List;
+import org.opendaylight.mdsal.binding.model.api.GeneratedType;
+import org.opendaylight.mdsal.binding.runtime.api.AugmentRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.OutputRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.RuntimeType;
+import org.opendaylight.yangtools.yang.model.api.stmt.OutputEffectiveStatement;
+
+@Beta
+public final class DefaultOutputRuntimeType extends AbstractCompositeRuntimeType<OutputEffectiveStatement>
+ implements OutputRuntimeType {
+ public DefaultOutputRuntimeType(final GeneratedType bindingType, final OutputEffectiveStatement statement,
+ final List<RuntimeType> children, final List<AugmentRuntimeType> augments) {
+ super(bindingType, statement, children, augments);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2022 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.generator.impl.rt;
+
+import com.google.common.annotations.Beta;
+import org.opendaylight.mdsal.binding.model.api.GeneratedType;
+import org.opendaylight.mdsal.binding.runtime.api.TypedefRuntimeType;
+import org.opendaylight.yangtools.yang.model.api.stmt.TypedefEffectiveStatement;
+
+@Beta
+public final class DefaultTypedefRuntimeType extends AbstractGeneratedRuntimeType<TypedefEffectiveStatement>
+ implements TypedefRuntimeType {
+ public DefaultTypedefRuntimeType(final GeneratedType bindingType, final TypedefEffectiveStatement statement) {
+ super(bindingType, statement);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2021 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.generator.impl.rt;
+
+import static java.util.Objects.requireNonNull;
+
+import com.google.common.annotations.Beta;
+import java.util.List;
+import org.eclipse.jdt.annotation.NonNull;
+import org.opendaylight.mdsal.binding.model.api.GeneratedType;
+import org.opendaylight.mdsal.binding.runtime.api.AugmentRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.CaseRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.RuntimeType;
+import org.opendaylight.yangtools.yang.model.api.stmt.CaseEffectiveStatement;
+
+@Beta
+public final class DerivedCaseRuntimeType extends AbstractCaseRuntimeType {
+ private final @NonNull CaseRuntimeType originalType;
+
+ public DerivedCaseRuntimeType(final GeneratedType bindingType, final CaseEffectiveStatement statement,
+ final List<RuntimeType> children, final List<AugmentRuntimeType> augments,
+ final CaseRuntimeType originalType) {
+ super(bindingType, statement, children, augments);
+ this.originalType = requireNonNull(originalType);
+ }
+
+ @Override
+ public @NonNull CaseRuntimeType originalType() {
+ return originalType;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2021 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.generator.impl.rt;
+
+import static java.util.Objects.requireNonNull;
+
+import com.google.common.annotations.Beta;
+import com.google.common.collect.Collections2;
+import com.google.common.collect.Iterables;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import org.eclipse.jdt.annotation.NonNull;
+import org.opendaylight.mdsal.binding.model.api.GeneratedType;
+import org.opendaylight.mdsal.binding.runtime.api.AugmentRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.CaseRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.ChoiceRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.RuntimeType;
+import org.opendaylight.yangtools.yang.model.api.stmt.ChoiceEffectiveStatement;
+
+@Beta
+public final class DerivedChoiceRuntimeType extends AbstractChoiceRuntimeType {
+ private final @NonNull ChoiceRuntimeType originalType;
+
+ public DerivedChoiceRuntimeType(final GeneratedType bindingType, final ChoiceEffectiveStatement statement,
+ final List<RuntimeType> children, final List<AugmentRuntimeType> augments,
+ final ChoiceRuntimeType originalType) {
+ super(bindingType, statement, children, augments);
+ this.originalType = requireNonNull(originalType);
+ }
+
+ @Override
+ public @NonNull ChoiceRuntimeType originalType() {
+ return originalType;
+ }
+
+ @Override
+ public Collection<CaseRuntimeType> additionalCaseChildren() {
+ final var myJavaTypes = Collections2.transform(validCaseChildren(), CaseRuntimeType::getIdentifier);
+ final var result = new ArrayList<CaseRuntimeType>();
+ for (var caseType : Iterables.concat(originalType.validCaseChildren(), originalType.additionalCaseChildren())) {
+ if (!myJavaTypes.contains(caseType.getIdentifier())) {
+ result.add(caseType);
+ }
+ }
+ return result;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2021 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.generator.impl.rt;
+
+import com.google.common.annotations.Beta;
+import java.util.List;
+import org.opendaylight.mdsal.binding.model.api.GeneratedType;
+import org.opendaylight.mdsal.binding.runtime.api.AugmentRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.CaseRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.RuntimeType;
+import org.opendaylight.yangtools.yang.model.api.stmt.CaseEffectiveStatement;
+
+@Beta
+public final class OriginalCaseRuntimeType extends AbstractCaseRuntimeType {
+ public OriginalCaseRuntimeType(final GeneratedType bindingType, final CaseEffectiveStatement statement,
+ final List<RuntimeType> children, final List<AugmentRuntimeType> augments) {
+ super(bindingType, statement, children, augments);
+ }
+
+ @Override
+ public CaseRuntimeType originalType() {
+ return null;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2021 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.generator.impl.rt;
+
+import com.google.common.annotations.Beta;
+import com.google.common.collect.ImmutableList;
+import java.util.Collection;
+import java.util.List;
+import org.eclipse.jdt.annotation.NonNull;
+import org.opendaylight.mdsal.binding.model.api.GeneratedType;
+import org.opendaylight.mdsal.binding.runtime.api.AugmentRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.CaseRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.ChoiceRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.RuntimeType;
+import org.opendaylight.yangtools.yang.model.api.stmt.ChoiceEffectiveStatement;
+
+@Beta
+public final class OriginalChoiceRuntimeType extends AbstractChoiceRuntimeType {
+ private final @NonNull ImmutableList<CaseRuntimeType> augmentedCases;
+
+ public OriginalChoiceRuntimeType(final GeneratedType bindingType, final ChoiceEffectiveStatement statement,
+ final List<RuntimeType> children, final List<AugmentRuntimeType> augments,
+ final List<CaseRuntimeType> augmentedCases) {
+ super(bindingType, statement, children, augments);
+ this.augmentedCases = ImmutableList.copyOf(augmentedCases);
+ }
+
+ @Override
+ public ChoiceRuntimeType originalType() {
+ return null;
+ }
+
+ @Override
+ public Collection<CaseRuntimeType> additionalCaseChildren() {
+ return augmentedCases;
+ }
+}
+++ /dev/null
-/*
- * Copyright (c) 2022 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.generator.impl.tree;
-
-import org.eclipse.jdt.annotation.NonNull;
-import org.opendaylight.mdsal.binding.generator.impl.reactor.AbstractExplicitGenerator;
-import org.opendaylight.yangtools.concepts.Identifiable;
-import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.model.api.stmt.SchemaTreeEffectiveStatement;
-
-/**
- * An object reflecting a YANG {@code schema node}.
- *
- * @param <S> Concrete {@link SchemaTreeEffectiveStatement} type
- * @param <G> Concrete {@link AbstractExplicitGenerator} type
- */
-// FIXME: do not reference Generator once we have the codegen and runtime views well-defined
-public interface SchemaTreeChild<S extends SchemaTreeEffectiveStatement<?>,
- G extends AbstractExplicitGenerator<S> & SchemaTreeChild<S, G>> extends Identifiable<QName> {
- @Override
- default QName getIdentifier() {
- return statement().argument();
- }
-
- /**
- * Return the effective YANG statement being represented by this object.
- *
- * @return A YANG statement
- */
- @NonNull S statement();
-
- /**
- * Return the generator responsible for handling the binding type view of this statement. Note that the statement
- * returned by {@code generator().statement()} may differ from the statement returned by {@link #statement()}.
- *
- * @return Underlying binding generator
- * @throws IllegalStateException if the generator has not been resolved yet
- */
- @NonNull G generator();
-}
+++ /dev/null
-/*
- * Copyright (c) 2022 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.generator.impl.tree;
-
-import java.util.List;
-import org.eclipse.jdt.annotation.NonNull;
-import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
-
-/**
- * A parent containing a number of {@link SchemaTreeChild} objects.
- *
- * @param <S> Concrete {@link EffectiveStatement} type
- */
-// FIXME: S extends SchemaTreeAwareStatement ... once AugmentEffectiveStatement implements that
-public interface SchemaTreeParent<S extends EffectiveStatement<?, ?>> {
- /*
- * Immutable view of children of this object along the {@code schema tree} child axis.
- *
- * @return Immutable view of this objects children along the {@code schema tree} child axis.
- */
- @NonNull List<SchemaTreeChild<?, ?>> schemaTreeChildren();
-}
--- /dev/null
+/*
+ * Copyright (c) 2022 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.generator.impl.tree;
+
+import org.eclipse.jdt.annotation.NonNull;
+import org.opendaylight.mdsal.binding.runtime.api.RuntimeType;
+import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
+
+/**
+ * An object representing a view on a particular {@link EffectiveStatement} with a potential to have a
+ * {@link RuntimeType} representation as well.
+ *
+ * @param <S> Statement type
+ * @param <R> Runtime type
+ */
+public interface StatementRepresentation<S extends EffectiveStatement<?, ?>> {
+ /**
+ * Return the effective YANG statement being represented by this object.
+ *
+ * @return A YANG statement
+ */
+ @NonNull S statement();
+}
// The real thing, used to kaboom
final var runtimeTypes = new DefaultBindingRuntimeGenerator().generateTypeMapping(models);
- // Verify schema-to-type lookup
- final var barType = runtimeTypes.findType(barTypeSchema).orElseThrow();
- final var bazType = runtimeTypes.findType(bazTypeSchema).orElseThrow();
- assertEquals(FOO.createEnclosed("Bar"), barType.getIdentifier());
- assertEquals(FOO.createEnclosed("Baz"), bazType.getIdentifier());
-
// Verify type-to-schema lookup
- assertSame(barTypeSchema, runtimeTypes.findSchema(barType).orElseThrow());
- assertSame(bazTypeSchema, runtimeTypes.findSchema(bazType).orElseThrow());
+ final var barType = runtimeTypes.findSchema(FOO.createEnclosed("Bar")).orElseThrow();
+ final var bazType = runtimeTypes.findSchema(FOO.createEnclosed("Baz")).orElseThrow();
+
+ // Verify underlying schema lookup
+ assertSame(barSchema, barType.statement());
+ assertSame(bazSchema, bazType.statement());
}
}
<packaging>bundle</packaging>
<dependencies>
+ <dependency>
+ <groupId>com.google.guava</groupId>
+ <artifactId>guava</artifactId>
+ </dependency>
<dependency>
<groupId>org.opendaylight.yangtools</groupId>
- <artifactId>yang-data-api</artifactId>
+ <artifactId>concepts</artifactId>
</dependency>
<dependency>
<groupId>org.opendaylight.yangtools</groupId>
- <artifactId>yang-repo-spi</artifactId>
+ <artifactId>yang-common</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>yang-model-api</artifactId>
</dependency>
<dependency>
<groupId>org.opendaylight.yangtools</groupId>
- <artifactId>yang-model-util</artifactId>
+ <artifactId>yang-repo-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>yang-repo-spi</artifactId>
</dependency>
<dependency>
<groupId>org.opendaylight.mdsal</groupId>
module org.opendaylight.mdsal.binding.runtime.api {
exports org.opendaylight.mdsal.binding.runtime.api;
- requires transitive org.opendaylight.yangtools.yang.data.api;
+ requires transitive org.opendaylight.yangtools.concepts;
+ requires transitive org.opendaylight.yangtools.yang.common;
requires transitive org.opendaylight.yangtools.yang.model.api;
requires transitive org.opendaylight.yangtools.yang.binding;
+ requires transitive org.opendaylight.yangtools.yang.repo.api;
+ requires transitive org.opendaylight.yangtools.yang.repo.spi;
requires transitive org.opendaylight.mdsal.binding.model.api;
- requires org.opendaylight.yangtools.yang.model.util;
- requires org.opendaylight.yangtools.yang.repo.spi;
requires org.slf4j;
// Annotations
package org.opendaylight.mdsal.binding.runtime.api;
import static com.google.common.base.Preconditions.checkArgument;
-import static com.google.common.base.Preconditions.checkState;
import com.google.common.annotations.Beta;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Iterables;
-import java.util.AbstractMap.SimpleEntry;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Optional;
-import java.util.Set;
-import org.eclipse.jdt.annotation.NonNull;
-import org.eclipse.jdt.annotation.Nullable;
-import org.opendaylight.mdsal.binding.model.api.GeneratedType;
-import org.opendaylight.mdsal.binding.model.api.MethodSignature;
-import org.opendaylight.mdsal.binding.model.api.ParameterizedType;
-import org.opendaylight.mdsal.binding.model.api.Type;
-import org.opendaylight.mdsal.binding.model.api.type.builder.GeneratedTypeBuilder;
+import org.opendaylight.mdsal.binding.model.api.JavaTypeName;
import org.opendaylight.yangtools.yang.binding.Action;
import org.opendaylight.yangtools.yang.binding.Augmentation;
import org.opendaylight.yangtools.yang.binding.Notification;
+import org.opendaylight.yangtools.yang.binding.RpcInput;
+import org.opendaylight.yangtools.yang.binding.RpcOutput;
import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.common.QNameModule;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.AugmentationIdentifier;
-import org.opendaylight.yangtools.yang.model.api.ActionDefinition;
-import org.opendaylight.yangtools.yang.model.api.AugmentationSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.AugmentationTarget;
-import org.opendaylight.yangtools.yang.model.api.CaseSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.ChoiceSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
-import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.DerivableSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.DocumentedNode.WithStatus;
-import org.opendaylight.yangtools.yang.model.api.SchemaNode;
-import org.opendaylight.yangtools.yang.model.util.EffectiveAugmentationSchema;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
+import org.opendaylight.yangtools.yang.model.api.stmt.SchemaNodeIdentifier.Absolute;
/**
* Runtime Context for Java YANG Binding classes. It provides information derived from the backing effective model,
* which is not captured in generated classes (and hence cannot be obtained from {@code BindingReflections}.
- *
- * <p>Some of this information are for example list of all available children for cases
- * {@link #getChoiceCaseChildren(DataNodeContainer)}, since choices are augmentable and new choices may be introduced
- * by additional models. Same goes for all possible augmentations.
*/
@Beta
public abstract class AbstractBindingRuntimeContext implements BindingRuntimeContext {
- private static final Logger LOG = LoggerFactory.getLogger(AbstractBindingRuntimeContext.class);
-
private final LoadingCache<QName, Class<?>> identityClasses = CacheBuilder.newBuilder().weakValues().build(
new CacheLoader<QName, Class<?>>() {
@Override
public Class<?> load(final QName key) {
- final Optional<Type> identityType = getTypes().findIdentity(key);
- checkArgument(identityType.isPresent(), "Supplied QName %s is not a valid identity", key);
+ final var type = getTypes().findIdentity(key).orElseThrow(
+ () -> new IllegalArgumentException("Supplied QName " + key + " is not a valid identity"));
try {
- return loadClass(identityType.get());
+ return loadClass(type.getIdentifier());
} catch (final ClassNotFoundException e) {
- throw new IllegalArgumentException("Required class " + identityType + "was not found.", e);
+ throw new IllegalArgumentException("Required class " + type + " was not found.", e);
}
}
});
@Override
- public final <T extends Augmentation<?>> AugmentationSchemaNode getAugmentationDefinition(final Class<T> augClass) {
- return getTypes().findAugmentation(Type.of(augClass)).orElse(null);
+ public final <T extends Augmentation<?>> AugmentRuntimeType getAugmentationDefinition(final Class<T> augClass) {
+ return getTypes().findSchema(JavaTypeName.create(augClass))
+ .filter(AugmentRuntimeType.class::isInstance)
+ .map(AugmentRuntimeType.class::cast)
+ .orElse(null);
}
@Override
- public final DataSchemaNode getSchemaDefinition(final Class<?> cls) {
+ public final CompositeRuntimeType getSchemaDefinition(final Class<?> cls) {
checkArgument(!Augmentation.class.isAssignableFrom(cls), "Supplied class must not be an augmentation (%s is)",
cls);
checkArgument(!Action.class.isAssignableFrom(cls), "Supplied class must not be an action (%s is)", cls);
checkArgument(!Notification.class.isAssignableFrom(cls), "Supplied class must not be a notification (%s is)",
cls);
- return (DataSchemaNode) getTypes().findSchema(Type.of(cls)).orElse(null);
- }
-
- @Override
- public final DataSchemaNode findChildSchemaDefinition(final DataNodeContainer parentSchema,
- final QNameModule parentNamespace, final Class<?> childClass) {
- final DataSchemaNode origDef = getSchemaDefinition(childClass);
- if (origDef == null) {
- // Weird, the child does not have an associated definition
- return null;
- }
-
- // Direct instantiation or use in same module in which grouping was defined.
- final QName origName = origDef.getQName();
- final DataSchemaNode sameName = parentSchema.dataChildByName(origName);
- if (sameName != null) {
- // Check if it is:
- // - exactly same schema node, or
- // - instantiated node was added via uses statement and is instantiation of same grouping
- if (origDef.equals(sameName) || origDef.equals(getRootOriginalIfPossible(sameName))) {
- return sameName;
- }
-
- // Node has same name, but clearly is different
- return null;
- }
-
- // We are looking for instantiation via uses in other module
- final DataSchemaNode potential = parentSchema.dataChildByName(origName.bindTo(parentNamespace));
- // We check if it is really instantiated from same definition as class was derived
- if (potential != null && origDef.equals(getRootOriginalIfPossible(potential))) {
- return potential;
- }
- return null;
- }
-
- private static @Nullable SchemaNode getRootOriginalIfPossible(final SchemaNode data) {
- SchemaNode previous = null;
- SchemaNode next = originalNodeOf(data);
- while (next != null) {
- previous = next;
- next = originalNodeOf(next);
- }
- return previous;
+ return (CompositeRuntimeType) getTypes().findSchema(JavaTypeName.create(cls)).orElse(null);
}
@Override
- public final ActionDefinition getActionDefinition(final Class<? extends Action<?, ?, ?>> cls) {
- return (ActionDefinition) getTypes().findSchema(Type.of(cls)).orElse(null);
+ public final ActionRuntimeType getActionDefinition(final Class<? extends Action<?, ?, ?>> cls) {
+ return (ActionRuntimeType) getTypes().findSchema(JavaTypeName.create(cls)).orElse(null);
}
@Override
- public final Entry<AugmentationIdentifier, AugmentationSchemaNode> getResolvedAugmentationSchema(
- final DataNodeContainer target, final Class<? extends Augmentation<?>> aug) {
- final AugmentationSchemaNode origSchema = getAugmentationDefinition(aug);
- checkArgument(origSchema != null, "Augmentation %s is not known in current schema context", aug);
- /*
- * FIXME: Validate augmentation schema lookup
- *
- * Currently this algorithm, does not verify if instantiated child nodes
- * are real one derived from augmentation schema. The problem with
- * full validation is, if user used copy builders, he may use
- * augmentation which was generated for different place.
- *
- * If this augmentations have same definition, we emit same identifier
- * with data and it is up to underlying user to validate data.
- *
- */
- final Set<QName> childNames = new HashSet<>();
- final Set<DataSchemaNode> realChilds = new HashSet<>();
- for (final DataSchemaNode child : origSchema.getChildNodes()) {
- final DataSchemaNode dataChildQNname = target.dataChildByName(child.getQName());
- final String childLocalName = child.getQName().getLocalName();
- if (dataChildQNname == null) {
- for (DataSchemaNode dataSchemaNode : target.getChildNodes()) {
- if (childLocalName.equals(dataSchemaNode.getQName().getLocalName())) {
- realChilds.add(dataSchemaNode);
- childNames.add(dataSchemaNode.getQName());
- }
- }
- } else {
- realChilds.add(dataChildQNname);
- childNames.add(child.getQName());
- }
- }
-
- final AugmentationIdentifier identifier = AugmentationIdentifier.create(childNames);
- final AugmentationSchemaNode proxy = new EffectiveAugmentationSchema(origSchema, realChilds);
- return new SimpleEntry<>(identifier, proxy);
+ public final RuntimeType getTypeWithSchema(final Class<?> type) {
+ return getTypes().findSchema(JavaTypeName.create(type))
+ .orElseThrow(() -> new IllegalArgumentException("Failed to find schema for " + type));
}
@Override
- public final Optional<CaseSchemaNode> getCaseSchemaDefinition(final ChoiceSchemaNode schema,
- final Class<?> childClass) {
- final DataSchemaNode origSchema = getSchemaDefinition(childClass);
- checkArgument(origSchema instanceof CaseSchemaNode, "Supplied schema %s is not case.", origSchema);
-
- /* FIXME: Make sure that if there are multiple augmentations of same
- * named case, with same structure we treat it as equals
- * this is due property of Binding specification and copy builders
- * that user may be unaware that he is using incorrect case
- * which was generated for choice inside grouping.
- */
- return findInstantiatedCase(schema, (CaseSchemaNode) origSchema);
+ public final Class<?> getClassForSchema(final Absolute schema) {
+ final var child = getTypes().schemaTreeChild(schema);
+ checkArgument(child != null, "Failed to find binding type for %s", schema);
+ return loadClass(child);
}
@Override
- public final Entry<GeneratedType, WithStatus> getTypeWithSchema(final Class<?> type) {
- return getTypeWithSchema(getTypes(), Type.of(type));
- }
-
- private static @NonNull Entry<GeneratedType, WithStatus> getTypeWithSchema(final BindingRuntimeTypes types,
- final Type referencedType) {
- final WithStatus schema = types.findSchema(referencedType).orElseThrow(
- () -> new NullPointerException("Failed to find schema for type " + referencedType));
- final Type definedType = types.findType(schema).orElseThrow(
- () -> new NullPointerException("Failed to find defined type for " + referencedType + " schema " + schema));
-
- if (definedType instanceof GeneratedTypeBuilder) {
- return new SimpleEntry<>(((GeneratedTypeBuilder) definedType).build(), schema);
- }
- checkArgument(definedType instanceof GeneratedType, "Type %s is not a GeneratedType", referencedType);
- return new SimpleEntry<>((GeneratedType) definedType, schema);
+ public final Class<?> getIdentityClass(final QName input) {
+ return identityClasses.getUnchecked(input);
}
@Override
- public final Map<Type, Entry<Type, Type>> getChoiceCaseChildren(final DataNodeContainer schema) {
- return getChoiceCaseChildren(getTypes(), schema);
- }
-
- private static @NonNull ImmutableMap<Type, Entry<Type, Type>> getChoiceCaseChildren(final BindingRuntimeTypes types,
- final DataNodeContainer schema) {
- final Map<Type, Entry<Type, Type>> childToCase = new HashMap<>();
-
- for (final ChoiceSchemaNode choice : Iterables.filter(schema.getChildNodes(), ChoiceSchemaNode.class)) {
- final ChoiceSchemaNode originalChoice = getOriginalSchema(choice);
- final Optional<Type> optType = types.findType(originalChoice);
- checkState(optType.isPresent(), "Failed to find generated type for choice %s", originalChoice);
- final Type choiceType = optType.get();
-
- for (Type caze : types.findCases(choiceType)) {
- final Entry<Type,Type> caseIdentifier = new SimpleEntry<>(choiceType, caze);
- final HashSet<Type> caseChildren = new HashSet<>();
- if (caze instanceof GeneratedTypeBuilder) {
- caze = ((GeneratedTypeBuilder) caze).build();
- }
- collectAllContainerTypes((GeneratedType) caze, caseChildren);
- for (final Type caseChild : caseChildren) {
- childToCase.put(caseChild, caseIdentifier);
- }
- }
- }
- return ImmutableMap.copyOf(childToCase);
+ public final Class<? extends RpcInput> getRpcInput(final QName rpcName) {
+ return loadClass(getTypes().findRpcInput(rpcName)
+ .orElseThrow(() -> new IllegalArgumentException("Failed to find RpcInput for " + rpcName)))
+ .asSubclass(RpcInput.class);
}
@Override
- public final Set<Class<?>> getCases(final Class<?> choice) {
- final Collection<Type> cazes = getTypes().findCases(Type.of(choice));
- final Set<Class<?>> ret = new HashSet<>(cazes.size());
- for (final Type caze : cazes) {
- try {
- ret.add(loadClass(caze));
- } catch (final ClassNotFoundException e) {
- LOG.warn("Failed to load class for case {}, ignoring it", caze, e);
- }
- }
- return ret;
+ public final Class<? extends RpcOutput> getRpcOutput(final QName rpcName) {
+ return loadClass(getTypes().findRpcOutput(rpcName)
+ .orElseThrow(() -> new IllegalArgumentException("Failed to find RpcOutput for " + rpcName)))
+ .asSubclass(RpcOutput.class);
}
- @Override
- public final Class<?> getClassForSchema(final SchemaNode childSchema) {
- final SchemaNode origSchema = getOriginalSchema(childSchema);
- final Optional<Type> clazzType = getTypes().findType(origSchema);
- checkArgument(clazzType.isPresent(), "Failed to find binding type for %s (original %s)",
- childSchema, origSchema);
-
+ private Class<?> loadClass(final RuntimeType type) {
try {
- return loadClass(clazzType.get());
+ return loadClass(type.javaType());
} catch (final ClassNotFoundException e) {
throw new IllegalStateException(e);
}
}
-
- @Override
- public final ImmutableMap<AugmentationIdentifier, Type> getAvailableAugmentationTypes(
- final DataNodeContainer container) {
- if (container instanceof AugmentationTarget) {
- final var augmentations = ((AugmentationTarget) container).getAvailableAugmentations();
- if (!augmentations.isEmpty()) {
- final var identifierToType = new HashMap<AugmentationIdentifier, Type>();
- final var types = getTypes();
- for (var augment : augmentations) {
- types.findOriginalAugmentationType(augment).ifPresent(augType -> {
- identifierToType.put(getAugmentationIdentifier(augment), augType);
- });
- }
- return ImmutableMap.copyOf(identifierToType);
- }
- }
- return ImmutableMap.of();
- }
-
- @Override
- public final Class<?> getIdentityClass(final QName input) {
- return identityClasses.getUnchecked(input);
- }
-
- private static AugmentationIdentifier getAugmentationIdentifier(final AugmentationSchemaNode augment) {
- // FIXME: use DataSchemaContextNode.augmentationIdentifierFrom() once it does caching
- return AugmentationIdentifier.create(augment.getChildNodes().stream().map(DataSchemaNode::getQName)
- .collect(ImmutableSet.toImmutableSet()));
- }
-
- private static Set<Type> collectAllContainerTypes(final GeneratedType type, final Set<Type> collection) {
- for (final MethodSignature definition : type.getMethodDefinitions()) {
- Type childType = definition.getReturnType();
- if (childType instanceof ParameterizedType) {
- childType = ((ParameterizedType) childType).getActualTypeArguments()[0];
- }
- if (childType instanceof GeneratedType || childType instanceof GeneratedTypeBuilder) {
- collection.add(childType);
- }
- }
- for (final Type parent : type.getImplements()) {
- if (parent instanceof GeneratedType) {
- collectAllContainerTypes((GeneratedType) parent, collection);
- }
- }
- return collection;
- }
-
- private static <T extends SchemaNode> T getOriginalSchema(final T choice) {
- @SuppressWarnings("unchecked")
- final T original = (T) originalNodeOf(choice);
- if (original != null) {
- return original;
- }
- return choice;
- }
-
- private static @NonNull Optional<CaseSchemaNode> findInstantiatedCase(final ChoiceSchemaNode instantiatedChoice,
- final CaseSchemaNode originalDefinition) {
- CaseSchemaNode potential = instantiatedChoice.findCase(originalDefinition.getQName()).orElse(null);
- if (originalDefinition.equals(potential)) {
- return Optional.of(potential);
- }
- if (potential != null) {
- SchemaNode potentialRoot = originalNodeOf(potential);
- if (originalDefinition.equals(potentialRoot)) {
- return Optional.of(potential);
- }
- }
-
- // We try to find case by name, then lookup its root definition
- // and compare it with original definition
- // This solves case, if choice was inside grouping
- // which was used in different module and thus namespaces are
- // different, but local names are still same.
- //
- // Still we need to check equality of definition, because local name is not
- // sufficient to uniquelly determine equality of cases
- //
- for (CaseSchemaNode caze : instantiatedChoice.findCaseNodes(originalDefinition.getQName().getLocalName())) {
- if (originalDefinition.equals(originalNodeOf(caze))) {
- return Optional.of(caze);
- }
- }
- return Optional.empty();
- }
-
- private static @Nullable SchemaNode originalNodeOf(final SchemaNode node) {
- return node instanceof DerivableSchemaNode ? ((DerivableSchemaNode) node).getOriginal().orElse(null) : null;
- }
}
--- /dev/null
+/*
+ * Copyright (c) 2021 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.runtime.api;
+
+import com.google.common.annotations.Beta;
+import org.opendaylight.yangtools.yang.model.api.stmt.ActionEffectiveStatement;
+
+/**
+ * A {@link RuntimeType} associated with an {@code action} statement.
+ */
+@Beta
+public interface ActionRuntimeType extends InvokableRuntimeType {
+ @Override
+ ActionEffectiveStatement statement();
+}
--- /dev/null
+/*
+ * Copyright (c) 2021 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.runtime.api;
+
+import com.google.common.annotations.Beta;
+import org.opendaylight.yangtools.yang.model.api.stmt.AnydataEffectiveStatement;
+
+/**
+ * A {@link RuntimeType} associated with a {@code anydata} statement.
+ */
+@Beta
+public interface AnydataRuntimeType extends OpaqueRuntimeType {
+ @Override
+ AnydataEffectiveStatement statement();
+}
--- /dev/null
+/*
+ * Copyright (c) 2021 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.runtime.api;
+
+import com.google.common.annotations.Beta;
+import org.opendaylight.yangtools.yang.model.api.stmt.AnyxmlEffectiveStatement;
+
+/**
+ * A {@link RuntimeType} associated with an {@code anyxml} statement.
+ */
+@Beta
+public interface AnyxmlRuntimeType extends OpaqueRuntimeType {
+ @Override
+ AnyxmlEffectiveStatement statement();
+}
--- /dev/null
+/*
+ * Copyright (c) 2021 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.runtime.api;
+
+import com.google.common.annotations.Beta;
+import org.opendaylight.yangtools.yang.model.api.stmt.AugmentEffectiveStatement;
+
+/**
+ * A {@link RuntimeType} associated with an {@code augment} statement.
+ */
+@Beta
+public interface AugmentRuntimeType extends CompositeRuntimeType, DataRuntimeType {
+ @Override
+ AugmentEffectiveStatement statement();
+}
package org.opendaylight.mdsal.binding.runtime.api;
import com.google.common.annotations.Beta;
-import com.google.common.collect.ImmutableMap;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Optional;
-import java.util.Set;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;
-import org.opendaylight.mdsal.binding.model.api.GeneratedType;
+import org.opendaylight.mdsal.binding.model.api.JavaTypeName;
import org.opendaylight.mdsal.binding.model.api.Type;
import org.opendaylight.yangtools.concepts.Immutable;
import org.opendaylight.yangtools.yang.binding.Action;
import org.opendaylight.yangtools.yang.binding.Augmentation;
+import org.opendaylight.yangtools.yang.binding.RpcInput;
+import org.opendaylight.yangtools.yang.binding.RpcOutput;
import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.common.QNameModule;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.AugmentationIdentifier;
-import org.opendaylight.yangtools.yang.model.api.ActionDefinition;
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.DataNodeContainer;
import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.DocumentedNode.WithStatus;
import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
import org.opendaylight.yangtools.yang.model.api.EffectiveModelContextProvider;
-import org.opendaylight.yangtools.yang.model.api.SchemaNode;
import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
+import org.opendaylight.yangtools.yang.model.api.stmt.SchemaNodeIdentifier.Absolute;
/**
* Runtime Context for Java YANG Binding classes. It provides information derived from the backing effective model,
* which is not captured in generated classes (and hence cannot be obtained from {@code BindingReflections}.
- *
- * <p>Some of this information are for example list of all available children for cases
- * {@link #getChoiceCaseChildren(DataNodeContainer)}, since choices are augmentable and new choices may be introduced
- * by additional models. Same goes for all possible augmentations.
*/
@Beta
// FIXME: refactor return to follow foo()/getFoo()/findFoo() naming
public interface BindingRuntimeContext extends EffectiveModelContextProvider, Immutable {
@NonNull BindingRuntimeTypes getTypes();
- @NonNull <T> Class<T> loadClass(Type type) throws ClassNotFoundException;
+ @NonNull <T> Class<T> loadClass(JavaTypeName type) throws ClassNotFoundException;
+
+ default @NonNull <T> Class<T> loadClass(final Type type) throws ClassNotFoundException {
+ return loadClass(type.getIdentifier());
+ }
@Override
default EffectiveModelContext getEffectiveModelContext() {
* which may be present in runtime for them, thus returned schema is unsuitable
* for use for validation of data.
*
- * <p>For retrieving {@link AugmentationSchemaNode}, which will contains
- * full model for child nodes, you should use method
- * {@link #getResolvedAugmentationSchema(DataNodeContainer, Class)}
- * which will return augmentation schema derived from supplied augmentation target
- * schema.
- *
+ * @param <T> Augmentation class type
* @param augClass Augmentation class
* @return Schema of augmentation or null if augmentation is not known in this context
+ * @throws NullPointerException if {@code augClass} is null
*/
- <T extends Augmentation<?>> @Nullable AugmentationSchemaNode getAugmentationDefinition(Class<T> augClass);
+ <T extends Augmentation<?>> @Nullable AugmentRuntimeType getAugmentationDefinition(Class<T> augClass);
/**
* Returns defining {@link DataSchemaNode} for supplied class.
* @param cls Class which represents list, container, choice or case.
* @return Schema node, from which class was generated.
*/
- @Nullable DataSchemaNode getSchemaDefinition(Class<?> cls);
-
- // FIXME: document this thing and perhaps move it to BindingRuntimeTypes?
- @Nullable DataSchemaNode findChildSchemaDefinition(DataNodeContainer parentSchema, QNameModule parentNamespace,
- Class<?> childClass);
-
- @Nullable ActionDefinition getActionDefinition(Class<? extends Action<?, ?, ?>> cls);
-
- @NonNull Entry<AugmentationIdentifier, AugmentationSchemaNode> getResolvedAugmentationSchema(
- DataNodeContainer target, Class<? extends Augmentation<?>> aug);
+ @Nullable CompositeRuntimeType getSchemaDefinition(Class<?> cls);
- /**
- * Returns resolved case schema for supplied class.
- *
- * @param schema Resolved parent choice schema
- * @param childClass Class representing case.
- * @return Optionally a resolved case schema,.empty if the choice is not legal in
- * the given context.
- * @throws IllegalArgumentException If supplied class does not represent case.
- */
- @NonNull Optional<CaseSchemaNode> getCaseSchemaDefinition(ChoiceSchemaNode schema, Class<?> childClass);
+ @Nullable ActionRuntimeType getActionDefinition(Class<? extends Action<?, ?, ?>> cls);
/**
* Returns schema ({@link DataSchemaNode}, {@link AugmentationSchemaNode} or {@link TypeDefinition})
* {@link DataSchemaNode}, {@link AugmentationSchemaNode} or {@link TypeDefinition}
* which was used to generate supplied class.
*/
- @NonNull Entry<GeneratedType, WithStatus> getTypeWithSchema(Class<?> type);
-
- @NonNull Map<Type, Entry<Type, Type>> getChoiceCaseChildren(DataNodeContainer schema);
+ @NonNull RuntimeType getTypeWithSchema(Class<?> type);
- @NonNull Set<Class<?>> getCases(Class<?> choice);
+ @NonNull Class<? extends RpcInput> getRpcInput(QName rpcName);
- @NonNull Class<?> getClassForSchema(SchemaNode childSchema);
+ @NonNull Class<? extends RpcOutput> getRpcOutput(QName rpcName);
- /**
- * Return the mapping of a particular {@link DataNodeContainer}'s available augmentations. This method deals with
- * resolving {@code uses foo { augment bar { ... } } } scenarios by returning the augmentation created for
- * {@code grouping foo}'s Binding representation.
- *
- * @param container {@link DataNodeContainer} to examine
- * @return a mapping from local {@link AugmentationIdentifier}s to their corresponding Binding augmentations
- */
- @NonNull ImmutableMap<AugmentationIdentifier, Type> getAvailableAugmentationTypes(DataNodeContainer container);
+ // FIXME: 9.0.0: this needs to accept an EffectiveStatementInference
+ @NonNull Class<?> getClassForSchema(Absolute schema);
@NonNull Class<?> getIdentityClass(QName input);
}
package org.opendaylight.mdsal.binding.runtime.api;
import com.google.common.annotations.Beta;
-import com.google.common.collect.Multimap;
-import java.util.Collection;
import java.util.Optional;
-import org.opendaylight.mdsal.binding.model.api.Type;
+import org.eclipse.jdt.annotation.Nullable;
+import org.opendaylight.mdsal.binding.model.api.JavaTypeName;
import org.opendaylight.yangtools.concepts.Immutable;
import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.model.api.AugmentationSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.DocumentedNode.WithStatus;
import org.opendaylight.yangtools.yang.model.api.EffectiveModelContextProvider;
+import org.opendaylight.yangtools.yang.model.api.stmt.SchemaNodeIdentifier.Absolute;
/**
* The result of BindingGenerator run. Contains mapping between Types and SchemaNodes.
*/
@Beta
-public interface BindingRuntimeTypes extends EffectiveModelContextProvider, Immutable {
+public interface BindingRuntimeTypes extends EffectiveModelContextProvider, RuntimeTypeContainer, Immutable {
- Optional<AugmentationSchemaNode> findAugmentation(Type type);
+ Optional<IdentityRuntimeType> findIdentity(QName qname);
- Optional<Type> findIdentity(QName qname);
+ Optional<RuntimeType> findSchema(JavaTypeName typeName);
- Optional<WithStatus> findSchema(Type type);
+ Optional<InputRuntimeType> findRpcInput(QName rpcName);
- Optional<Type> findType(WithStatus schema);
+ Optional<OutputRuntimeType> findRpcOutput(QName rpcName);
- Optional<Type> findOriginalAugmentationType(AugmentationSchemaNode augment);
-
- Multimap<Type, Type> getChoiceToCases();
-
- Collection<Type> findCases(Type choiceType);
+ default @Nullable RuntimeType schemaTreeChild(final Absolute path) {
+ final var it = path.getNodeIdentifiers().iterator();
+ var tmp = schemaTreeChild(it.next());
+ while (it.hasNext() && tmp instanceof RuntimeTypeContainer) {
+ tmp = ((RuntimeTypeContainer) tmp).schemaTreeChild(it.next());
+ }
+ return tmp;
+ }
}
--- /dev/null
+/*
+ * Copyright (c) 2021 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.runtime.api;
+
+import com.google.common.annotations.Beta;
+import org.eclipse.jdt.annotation.Nullable;
+import org.opendaylight.yangtools.yang.model.api.stmt.CaseEffectiveStatement;
+
+/**
+ * A {@link RuntimeType} associated with a {@code case} statement.
+ */
+@Beta
+public interface CaseRuntimeType extends CompositeRuntimeType, DataRuntimeType {
+ @Override
+ CaseEffectiveStatement statement();
+
+ /**
+ * Return the runtime type for the original manifestation of this type's {@code case} statement. Returns
+ * {@code null} if this type is the original.
+ *
+ * @return Original manifestatation, or {@code null} if this is the original manifestation.
+ */
+ @Nullable CaseRuntimeType originalType();
+}
--- /dev/null
+/*
+ * Copyright (c) 2021 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.runtime.api;
+
+import com.google.common.annotations.Beta;
+import java.util.Collection;
+import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.jdt.annotation.Nullable;
+import org.opendaylight.mdsal.binding.model.api.JavaTypeName;
+import org.opendaylight.yangtools.yang.model.api.stmt.ChoiceEffectiveStatement;
+
+/**
+ * A {@link RuntimeType} associated with a {@code choice} statement.
+ */
+@Beta
+public interface ChoiceRuntimeType extends CompositeRuntimeType, DataRuntimeType {
+ @Override
+ ChoiceEffectiveStatement statement();
+
+ /**
+ * Returns resolved {@link CaseRuntimeType} for specified binding class name.
+ *
+ * @param typeName Binding class name
+ * @return {@link CaseRuntimeType}, or null if absent
+ * @throws NullPointerException if {@code typeName} is null
+ */
+ @Nullable CaseRuntimeType bindingCaseChild(JavaTypeName typeName);
+
+ /**
+ * Return the runtime type for the original manifestation of this type's {@code choice} statement.
+ * Returns {@code null} if this type is the original.
+ *
+ * @return Original manifestatation, or {@code null} if this is the original manifestation.
+ */
+ @Nullable ChoiceRuntimeType originalType();
+
+ /**
+ * Return all {@link CaseRuntimeType} valid at this type's statement.
+ *
+ * @return Valid {@link CaseRuntimeType}s
+ */
+ @NonNull Collection<CaseRuntimeType> validCaseChildren();
+
+ /**
+ * Return any additional {@link CaseRuntimeType}s which may be encountered when dealing with DataObjects supported
+ * by this type. These are not strictly valid in YANG view of modeled data, but may have potentially-equivalent
+ * representation, such as in the following case:
+ * <pre>
+ * <code>
+ * grouping one {
+ * container foo {
+ * choice bar;
+ * }
+ * }
+ *
+ * container foo {
+ * uses grp;
+ * }
+ *
+ * container bar {
+ * uses grp;
+ * }
+ *
+ * augment /foo/foo/bar {
+ * case baz
+ * }
+ *
+ * augment /bar/foo/bar {
+ * case xyzzy;
+ * }
+ * </code>
+ * </pre>
+ * and, more notably, the two augments being in different modules. Since {@code choice bar}'s is part of a reusable
+ * construct, {@code grouping one}, DataObjects' copy builders can propagate them without translating them to the
+ * appropriate manifestation -- and they can do nothing about that as they lack the complete view of the effecitve
+ * model.
+ *
+ * @return Additional {@link CaseRuntimeType}s
+ */
+ @NonNull Collection<CaseRuntimeType> additionalCaseChildren();
+}
--- /dev/null
+/*
+ * Copyright (c) 2021 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.runtime.api;
+
+import com.google.common.annotations.Beta;
+import java.util.List;
+import org.eclipse.jdt.annotation.NonNull;
+
+/**
+ * A {@link RuntimeType} which is also a {@link RuntimeTypeContainer}.
+ */
+@Beta
+public interface CompositeRuntimeType extends GeneratedRuntimeType, RuntimeTypeContainer {
+ /**
+ * Return the {@link AugmentRuntimeType}s extending this type, matching the underlying {@link #statement()}.
+ *
+ * @return {@link AugmentRuntimeType}s extending this type.
+ */
+ @NonNull List<AugmentRuntimeType> augments();
+
+ /**
+ * Return the {@link AugmentRuntimeType}s extending extending a namesake of this type.
+ *
+ * @return {@link AugmentRuntimeType}s extending a namesake of this type.
+ */
+ @NonNull List<AugmentRuntimeType> mismatchedAugments();
+}
--- /dev/null
+/*
+ * Copyright (c) 2021 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.runtime.api;
+
+import com.google.common.annotations.Beta;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.model.api.meta.DeclaredStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.DataTreeAwareEffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.DataTreeEffectiveStatement;
+
+/**
+ * A {@link RuntimeType} associated with a statement with similar semantics as {@code container} statement.
+ */
+@Beta
+public interface ContainerLikeRuntimeType<D extends DeclaredStatement<QName>,
+ E extends DataTreeEffectiveStatement<D> & DataTreeAwareEffectiveStatement<QName, D>>
+ extends CompositeRuntimeType, DataRuntimeType {
+ @Override
+ E statement();
+}
--- /dev/null
+/*
+ * Copyright (c) 2021 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.runtime.api;
+
+import com.google.common.annotations.Beta;
+import org.opendaylight.yangtools.yang.model.api.stmt.ContainerEffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.ContainerStatement;
+
+/**
+ * A {@link RuntimeType} associated with a {@code container} statement.
+ */
+@Beta
+public interface ContainerRuntimeType
+ extends ContainerLikeRuntimeType<ContainerStatement, ContainerEffectiveStatement> {
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2022 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.runtime.api;
+
+import com.google.common.annotations.Beta;
+import org.opendaylight.mdsal.binding.model.api.JavaTypeName;
+
+/**
+ * Marker interface for concrete {@link RuntimeType}s relevant when dealing data hierarchy. This interface does not have
+ * a direct relationship with the {@code data tree} YANG construct, nor with {@code YangInstanceIdentifier} addressing.
+ * Its primary role is differentiating between various types when considered in the context of
+ * {@link RuntimeTypeContainer}'s child methods and related inferences. In particular, {@link DataRuntimeType}s are
+ * relevant when considering whether or not a particular RuntimeType child is part of the data encoding (according to
+ * the Binding Specification) to the {@code schema tree} layout.
+ *
+ * <p>
+ * DataRuntimeTypes are considered part of the {@code data tree} information encoded by the Binding Specification and
+ * thus need to be considered as child nodes when considering other data-bearing construct, such as
+ * {@code NormalizedNode}. That relationship may not be straightforward, but notably it excludes constructs like
+ * {@link NotificationRuntimeType}, {@link IdentityRuntimeType}, {@link ActionRuntimeType}, {@link GroupingRuntimeType},
+ * and similar, as those exist in outside of {@code data tree} contract, but are still part of what
+ * {@link RuntimeTypeContainer#bindingChild(JavaTypeName)} considers as child constructs.
+ */
+@Beta
+public interface DataRuntimeType extends RuntimeType {
+ // Marker interface, no further contract is specified
+}
import com.google.common.annotations.Beta;
import org.eclipse.jdt.annotation.NonNull;
-import org.opendaylight.mdsal.binding.model.api.Type;
-import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
+import org.opendaylight.mdsal.binding.model.api.JavaTypeName;
/**
* Runtime Context for Java YANG Binding classes. It provides information derived from the backing effective model,
* which is not captured in generated classes (and hence cannot be obtained from {@code BindingReflections}.
- *
- * <p>Some of this information are for example list of all available children for cases
- * {@link #getChoiceCaseChildren(DataNodeContainer)}, since choices are augmentable and new choices may be introduced
- * by additional models. Same goes for all possible augmentations.
*/
@Beta
public final class DefaultBindingRuntimeContext extends AbstractBindingRuntimeContext {
}
@Override
- public <T> Class<T> loadClass(Type type) throws ClassNotFoundException {
- return moduleInfos.loadClass(type.getFullyQualifiedName());
+ public <T> Class<T> loadClass(final JavaTypeName type) throws ClassNotFoundException {
+ return moduleInfos.loadClass(type.toString());
}
}
--- /dev/null
+/*
+ * Copyright (c) 2021 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.runtime.api;
+
+import com.google.common.annotations.Beta;
+import org.opendaylight.mdsal.binding.model.api.GeneratedType;
+import org.opendaylight.mdsal.binding.model.api.JavaTypeName;
+import org.opendaylight.yangtools.concepts.Identifiable;
+
+/**
+ * A {@link RuntimeType} associated with a {@link GeneratedType}.
+ */
+@Beta
+public interface GeneratedRuntimeType extends RuntimeType, Identifiable<JavaTypeName> {
+ @Override
+ GeneratedType javaType();
+
+ @Override
+ default JavaTypeName getIdentifier() {
+ return javaType().getIdentifier();
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2021 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.runtime.api;
+
+import com.google.common.annotations.Beta;
+import org.opendaylight.yangtools.yang.model.api.stmt.GroupingEffectiveStatement;
+
+/**
+ * A {@link RuntimeType} associated with a {@code grouping} statement.
+ */
+@Beta
+public interface GroupingRuntimeType extends CompositeRuntimeType {
+ @Override
+ GroupingEffectiveStatement statement();
+}
--- /dev/null
+/*
+ * Copyright (c) 2021 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.runtime.api;
+
+import com.google.common.annotations.Beta;
+import org.opendaylight.yangtools.yang.model.api.stmt.IdentityEffectiveStatement;
+
+/**
+ * A {@link RuntimeType} associated with a {@code identity} statement.
+ */
+@Beta
+public interface IdentityRuntimeType extends GeneratedRuntimeType {
+ @Override
+ IdentityEffectiveStatement statement();
+}
--- /dev/null
+/*
+ * Copyright (c) 2021 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.runtime.api;
+
+import com.google.common.annotations.Beta;
+import org.opendaylight.yangtools.yang.model.api.stmt.InputEffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.InputStatement;
+
+/**
+ * A {@link RuntimeType} associated with an {@code input} statement.
+ */
+@Beta
+public interface InputRuntimeType extends ContainerLikeRuntimeType<InputStatement, InputEffectiveStatement> {
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2022 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.runtime.api;
+
+import com.google.common.annotations.Beta;
+import org.eclipse.jdt.annotation.NonNull;
+
+/**
+ * Common interface for run-time types associated with invokable operations, such as those defined by {@code action} and
+ * {@code rpc} statements.
+ */
+@Beta
+public interface InvokableRuntimeType extends CompositeRuntimeType {
+ /**
+ * Return the run-time type for this action's input.
+ *
+ * @return Input run-time type
+ */
+ @NonNull InputRuntimeType input();
+
+ /**
+ * Return the run-time type for this action's output.
+ *
+ * @return Output run-time type
+ */
+ @NonNull OutputRuntimeType output();
+}
--- /dev/null
+/*
+ * Copyright (c) 2021 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.runtime.api;
+
+import com.google.common.annotations.Beta;
+import org.opendaylight.mdsal.binding.model.api.GeneratedTransferObject;
+import org.opendaylight.yangtools.yang.model.api.stmt.KeyEffectiveStatement;
+
+/**
+ * A {@link RuntimeType} associated with a {@code key} statement.
+ */
+@Beta
+public interface KeyRuntimeType extends GeneratedRuntimeType {
+ @Override
+ KeyEffectiveStatement statement();
+
+ @Override
+ GeneratedTransferObject javaType();
+}
--- /dev/null
+/*
+ * Copyright (c) 2021 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.runtime.api;
+
+import com.google.common.annotations.Beta;
+import org.opendaylight.yangtools.yang.model.api.stmt.LeafListEffectiveStatement;
+
+@Beta
+public interface LeafListRuntimeType extends DataRuntimeType {
+ @Override
+ LeafListEffectiveStatement statement();
+}
--- /dev/null
+/*
+ * Copyright (c) 2021 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.runtime.api;
+
+import com.google.common.annotations.Beta;
+import org.opendaylight.yangtools.yang.model.api.stmt.LeafEffectiveStatement;
+
+@Beta
+public interface LeafRuntimeType extends DataRuntimeType {
+ @Override
+ LeafEffectiveStatement statement();
+}
--- /dev/null
+/*
+ * Copyright (c) 2021 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.runtime.api;
+
+import com.google.common.annotations.Beta;
+import org.eclipse.jdt.annotation.Nullable;
+import org.opendaylight.yangtools.yang.model.api.stmt.ListEffectiveStatement;
+
+/**
+ * A {@link RuntimeType} associated with a {@code list} statement.
+ */
+@Beta
+public interface ListRuntimeType extends CompositeRuntimeType, DataRuntimeType {
+ @Override
+ ListEffectiveStatement statement();
+
+ /**
+ * Return the run-time type for this list's {@code key} statement, if present.
+ *
+ * @return This list's key run-time type, or null if not present
+ */
+ @Nullable KeyRuntimeType keyType();
+}
--- /dev/null
+/*
+ * Copyright (c) 2021 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.runtime.api;
+
+import com.google.common.annotations.Beta;
+import org.opendaylight.yangtools.yang.model.api.stmt.ModuleEffectiveStatement;
+
+/**
+ * A {@link RuntimeType} associated with a {@code module} statement.
+ */
+@Beta
+public interface ModuleRuntimeType extends CompositeRuntimeType {
+ @Override
+ ModuleEffectiveStatement statement();
+}
--- /dev/null
+/*
+ * Copyright (c) 2021 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.runtime.api;
+
+import com.google.common.annotations.Beta;
+import org.opendaylight.yangtools.yang.model.api.stmt.NotificationEffectiveStatement;
+
+/**
+ * A {@link RuntimeType} associated with a {@code notification} statement.
+ */
+@Beta
+public interface NotificationRuntimeType extends CompositeRuntimeType {
+ @Override
+ NotificationEffectiveStatement statement();
+}
--- /dev/null
+/*
+ * Copyright (c) 2021 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.runtime.api;
+
+import com.google.common.annotations.Beta;
+import org.opendaylight.mdsal.binding.model.api.GeneratedType;
+import org.opendaylight.yangtools.yang.model.api.stmt.DataTreeEffectiveStatement;
+
+/**
+ * A {@link RuntimeType} associated with an opaque construct, like {@code anydata} and {@code anyxml}.
+ */
+@Beta
+public interface OpaqueRuntimeType extends GeneratedRuntimeType, DataRuntimeType {
+ @Override
+ DataTreeEffectiveStatement<?> statement();
+
+ @Override
+ GeneratedType javaType();
+}
--- /dev/null
+/*
+ * Copyright (c) 2021 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.runtime.api;
+
+import com.google.common.annotations.Beta;
+import org.opendaylight.yangtools.yang.model.api.stmt.OutputEffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.OutputStatement;
+
+/**
+ * A {@link RuntimeType} associated with an {@code output} statement.
+ */
+@Beta
+public interface OutputRuntimeType extends ContainerLikeRuntimeType<OutputStatement, OutputEffectiveStatement> {
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2022 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.runtime.api;
+
+import com.google.common.annotations.Beta;
+import org.opendaylight.yangtools.yang.model.api.stmt.RpcEffectiveStatement;
+
+/**
+ * A {@link RuntimeType} associated with an {@code rpc} statement.
+ */
+@Beta
+public interface RpcRuntimeType extends InvokableRuntimeType {
+ @Override
+ RpcEffectiveStatement statement();
+}
--- /dev/null
+/*
+ * Copyright (c) 2021 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.runtime.api;
+
+import com.google.common.annotations.Beta;
+import org.eclipse.jdt.annotation.NonNull;
+import org.opendaylight.mdsal.binding.model.api.Type;
+import org.opendaylight.yangtools.concepts.Immutable;
+import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
+
+/**
+ * Base interface for all run-time type information about a particular {@link Type}.
+ */
+@Beta
+public interface RuntimeType extends Immutable {
+ /**
+ * Java type associated with this run-time type.
+ *
+ * @return Java Type
+ */
+ @NonNull Type javaType();
+
+ /**
+ * Return the {@link EffectiveStatement} associated with this run-time type.
+ *
+ * @return Effective statement
+ */
+ @NonNull EffectiveStatement<?, ?> statement();
+}
--- /dev/null
+/*
+ * Copyright (c) 2021 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.runtime.api;
+
+import com.google.common.annotations.Beta;
+import org.eclipse.jdt.annotation.Nullable;
+import org.opendaylight.mdsal.binding.model.api.JavaTypeName;
+import org.opendaylight.mdsal.binding.model.api.Type;
+import org.opendaylight.yangtools.concepts.Immutable;
+import org.opendaylight.yangtools.yang.common.QName;
+
+/**
+ * An object containing {@link RuntimeType}s.
+ */
+@Beta
+public interface RuntimeTypeContainer extends Immutable {
+ /**
+ * Look up a child {@link RuntimeType} by its {@code schema tree} {@link QName}. Note the returned child does not
+ * necessarily match usual data addressing rules and will resolve non-data tree statements, such as
+ * {@code notification}, {@code rpc} and {@code action}. Callers should check the traits exposed by the returned
+ * object before accepting it.
+ *
+ * <p>
+ * One important omission is this method <b>does not</b> resolve nodes which have been added via {@code augment}
+ * statement. Those are exposed indirectly as children of {@link AugmentRuntimeType}s returned via
+ * {@link CompositeRuntimeType#augments()}, if applicable.
+ *
+ * @param qname {@code schema node} identifier
+ * @return Corresponding {@link RuntimeType}, or null if not found
+ * @throws NullPointerException if {@code qname} is null
+ */
+ @Nullable RuntimeType schemaTreeChild(QName qname);
+
+ /**
+ * Look up a child by the {@link JavaTypeName} of its generated class. This lookup, while very similar to
+ * {@link #schemaTreeChild(QName)}, does not precisely match the {@code schema tree} nor does it match
+ * {@code YangInstanceIdentifier} addressing.
+ * It will resolve constructs generated for {@code choice}, {@code case}, {@code notification}, {@code rpc},
+ * {@code action} and most notably for {@code grouping}, {@code identity}, {@code typedef} and {@code augment}
+ * statements. Callers should check the traits exposed by the returned object before accepting it.
+ *
+ * @param typeName Java class name of the generated class.
+ * @return Corresponding {@link RuntimeType}, or null if not found
+ * @throws NullPointerException if {@code typeName} is null
+ */
+ @Nullable GeneratedRuntimeType bindingChild(JavaTypeName typeName);
+
+ // FIXME: consider removing this method
+ default @Nullable RuntimeType bindingChild(final Type type) {
+ return bindingChild(type.getIdentifier());
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2022 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.runtime.api;
+
+import org.opendaylight.mdsal.binding.model.api.GeneratedType;
+import org.opendaylight.yangtools.yang.model.api.stmt.TypedefEffectiveStatement;
+
+/**
+ * A {@link RuntimeType} associated with a {@code typedef} statement.
+ */
+public interface TypedefRuntimeType extends GeneratedRuntimeType {
+ @Override
+ TypedefEffectiveStatement statement();
+
+ @Override
+ GeneratedType javaType();
+}
requires transitive org.opendaylight.yangtools.yang.parser.api;
requires transitive org.opendaylight.mdsal.binding.runtime.api;
requires org.opendaylight.yangtools.concepts;
+ requires org.opendaylight.yangtools.util;
+ requires org.opendaylight.yangtools.yang.model.api;
requires org.opendaylight.yangtools.yang.parser.impl;
+ requires org.opendaylight.mdsal.binding.model.api;
requires org.opendaylight.mdsal.binding.spec.util;
- requires org.opendaylight.yangtools.util;
requires org.slf4j;
uses org.opendaylight.yangtools.yang.parser.api.YangParserFactory;
import com.google.common.annotations.Beta;
import com.google.common.collect.ForwardingObject;
-import com.google.common.collect.ImmutableMap;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Optional;
-import java.util.Set;
-import org.opendaylight.mdsal.binding.model.api.GeneratedType;
-import org.opendaylight.mdsal.binding.model.api.Type;
+import org.opendaylight.mdsal.binding.model.api.JavaTypeName;
+import org.opendaylight.mdsal.binding.runtime.api.ActionRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.AugmentRuntimeType;
import org.opendaylight.mdsal.binding.runtime.api.BindingRuntimeContext;
import org.opendaylight.mdsal.binding.runtime.api.BindingRuntimeTypes;
+import org.opendaylight.mdsal.binding.runtime.api.CompositeRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.RuntimeType;
import org.opendaylight.yangtools.yang.binding.Action;
import org.opendaylight.yangtools.yang.binding.Augmentation;
+import org.opendaylight.yangtools.yang.binding.RpcInput;
+import org.opendaylight.yangtools.yang.binding.RpcOutput;
import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.common.QNameModule;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.AugmentationIdentifier;
-import org.opendaylight.yangtools.yang.model.api.ActionDefinition;
-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.DataNodeContainer;
-import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.DocumentedNode.WithStatus;
-import org.opendaylight.yangtools.yang.model.api.SchemaNode;
+import org.opendaylight.yangtools.yang.model.api.stmt.SchemaNodeIdentifier.Absolute;
@Beta
public abstract class ForwardingBindingRuntimeContext extends ForwardingObject implements BindingRuntimeContext {
}
@Override
- public <T extends Augmentation<?>> AugmentationSchemaNode getAugmentationDefinition(final Class<T> augClass) {
+ public <T extends Augmentation<?>> AugmentRuntimeType getAugmentationDefinition(final Class<T> augClass) {
return delegate().getAugmentationDefinition(augClass);
}
@Override
- public DataSchemaNode getSchemaDefinition(final Class<?> cls) {
+ public CompositeRuntimeType getSchemaDefinition(final Class<?> cls) {
return delegate().getSchemaDefinition(cls);
}
@Override
- public DataSchemaNode findChildSchemaDefinition(final DataNodeContainer parentSchema,
- final QNameModule parentNamespace, final Class<?> childClass) {
- return delegate().findChildSchemaDefinition(parentSchema, parentNamespace, childClass);
- }
-
- @Override
- public ActionDefinition getActionDefinition(final Class<? extends Action<?, ?, ?>> cls) {
+ public ActionRuntimeType getActionDefinition(final Class<? extends Action<?, ?, ?>> cls) {
return delegate().getActionDefinition(cls);
}
@Override
- public Entry<AugmentationIdentifier, AugmentationSchemaNode> getResolvedAugmentationSchema(
- final DataNodeContainer target, final Class<? extends Augmentation<?>> aug) {
- return delegate().getResolvedAugmentationSchema(target, aug);
- }
-
- @Override
- public Optional<CaseSchemaNode> getCaseSchemaDefinition(final ChoiceSchemaNode schema, final Class<?> childClass) {
- return delegate().getCaseSchemaDefinition(schema, childClass);
- }
-
- @Override
- public Entry<GeneratedType, WithStatus> getTypeWithSchema(final Class<?> type) {
+ public RuntimeType getTypeWithSchema(final Class<?> type) {
return delegate().getTypeWithSchema(type);
}
@Override
- public Map<Type, Entry<Type, Type>> getChoiceCaseChildren(final DataNodeContainer schema) {
- return delegate().getChoiceCaseChildren(schema);
- }
-
- @Override
- public Set<Class<?>> getCases(final Class<?> choice) {
- return delegate().getCases(choice);
+ public Class<?> getClassForSchema(final Absolute schema) {
+ return delegate().getClassForSchema(schema);
}
@Override
- public Class<?> getClassForSchema(final SchemaNode childSchema) {
- return delegate().getClassForSchema(childSchema);
+ public Class<?> getIdentityClass(final QName input) {
+ return delegate().getIdentityClass(input);
}
@Override
- public ImmutableMap<AugmentationIdentifier, Type> getAvailableAugmentationTypes(final DataNodeContainer container) {
- return delegate().getAvailableAugmentationTypes(container);
+ public <T> Class<T> loadClass(final JavaTypeName typeName) throws ClassNotFoundException {
+ return delegate().loadClass(typeName);
}
@Override
- public Class<?> getIdentityClass(final QName input) {
- return delegate().getIdentityClass(input);
+ public Class<? extends RpcInput> getRpcInput(final QName rpcName) {
+ return delegate().getRpcInput(rpcName);
}
@Override
- public <T> Class<T> loadClass(final Type type) throws ClassNotFoundException {
- return delegate().loadClass(type);
+ public Class<? extends RpcOutput> getRpcOutput(final QName rpcName) {
+ return delegate().getRpcOutput(rpcName);
}
}