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.BindingRuntimeContext;
import org.opendaylight.mdsal.binding.runtime.api.CaseRuntimeType;
import org.opendaylight.mdsal.binding.runtime.api.ChoiceRuntimeType;
import org.opendaylight.mdsal.binding.spec.reflect.BindingReflections;
final Map<Class<?>, DataContainerCodecPrototype<?>> byClassBuilder = new HashMap<>();
final SetMultimap<Class<?>, DataContainerCodecPrototype<?>> childToCase =
SetMultimapBuilder.hashKeys().hashSetValues().build();
- final Set<Class<?>> potentialSubstitutions = new HashSet<>();
- // Walks all cases for supplied choice in current runtime context
- // 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<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) {
- byClassBuilder.put(cazeDef.getBindingClass(), cazeDef);
- // Updates collection of case children
- @SuppressWarnings("unchecked")
- final Class<? extends DataObject> cazeCls = (Class<? extends DataObject>) caze;
- for (final Class<? extends DataObject> cazeChild : BindingReflections.getChildrenClasses(cazeCls)) {
- childToCase.put(cazeChild, cazeDef);
- }
- // Updates collection of YANG instance identifier to case
- 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;
- }
+
+ // Load case statements valid in this choice and keep track of their names
+ final var choiceType = prototype.getType();
+ final var factory = prototype.getFactory();
+ final var localCases = new HashSet<JavaTypeName>();
+ for (var caseType : choiceType.validCaseChildren()) {
+ final var cazeDef = loadCase(factory, caseType);
+ localCases.add(caseType.getIdentifier());
+ byClassBuilder.put(cazeDef.getBindingClass(), cazeDef);
+
+ // Updates collection of case children
+ @SuppressWarnings("unchecked")
+ final Class<? extends DataObject> cazeCls = (Class<? extends DataObject>) cazeDef.getBindingClass();
+ for (final Class<? extends DataObject> cazeChild : BindingReflections.getChildrenClasses(cazeCls)) {
+ childToCase.put(cazeChild, cazeDef);
+ }
+ // Updates collection of YANG instance identifier to case
+ 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 {
- /*
- * If case definition is not available, we store it for
- * later check if it could be used as substitution of existing one.
- */
- potentialSubstitutions.add(caze);
}
}
byYangCaseChild = ImmutableMap.copyOf(byYangCaseChildBuilder);
ambiguousByCaseChildWarnings = ambiguousByCaseChildClass.isEmpty() ? ImmutableSet.of()
: ConcurrentHashMap.newKeySet();
- final Map<Class<?>, DataContainerCodecPrototype<?>> bySubstitutionBuilder = new HashMap<>();
/*
- * Walks all cases which are not directly instantiated and
- * tries to match them to instantiated cases - represent same data as instantiated case,
- * only case name or schema path is different. This is required due property of
- * binding specification, that if choice is in grouping schema path location is lost,
- * and users may use incorrect case class using copy builders.
+ * Choice/Case mapping across groupings is compile-time unsafe and we therefore need to also track any
+ * CaseRuntimeTypes added to the choice in other contexts. This is necessary to discover when a case represents
+ * equivalent data in a different instantiation context.
+ *
+ * This is required due property of binding specification, that if choice is in grouping schema path location is
+ * lost, and users may use incorrect case class using copy builders.
*/
- for (final Class<?> substitution : potentialSubstitutions) {
- search: for (final Entry<Class<?>, DataContainerCodecPrototype<?>> real : byClassBuilder.entrySet()) {
- if (BindingReflections.isSubstitutionFor(substitution, real.getKey())) {
- bySubstitutionBuilder.put(substitution, real.getValue());
- break search;
+ final Map<Class<?>, DataContainerCodecPrototype<?>> bySubstitutionBuilder = new HashMap<>();
+ final var context = factory.getRuntimeContext();
+ for (var caseType : context.getTypes().allCaseChildren(choiceType)) {
+ final var caseName = caseType.getIdentifier();
+ if (!localCases.contains(caseName)) {
+ // FIXME: do not rely on class loading here, the check we are performing should be possible on
+ // GeneratedType only -- or it can be provided by BindingRuntimeTypes -- i.e. rather than
+ // 'allCaseChildren()' it would calculate additional mappings we can use off-the-bat.
+ final Class<?> substitution = loadCase(context, caseType);
+
+ search: for (final Entry<Class<?>, DataContainerCodecPrototype<?>> real : byClassBuilder.entrySet()) {
+ if (BindingReflections.isSubstitutionFor(substitution, real.getKey())) {
+ bySubstitutionBuilder.put(substitution, real.getValue());
+ break search;
+ }
}
}
}
+
byClassBuilder.putAll(bySubstitutionBuilder);
byClass = ImmutableMap.copyOf(byClassBuilder);
}
- private List<Class<?>> loadCaseClasses() {
- final var context = factory().getRuntimeContext();
- final var type = getType();
+ private static DataContainerCodecPrototype<CaseRuntimeType> loadCase(final CodecContextFactory factory,
+ final CaseRuntimeType caseType) {
+ return DataContainerCodecPrototype.from(loadCase(factory.getRuntimeContext(), caseType), caseType, factory);
+ }
- 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());
+ private static Class<?> loadCase(final BindingRuntimeContext context, final CaseRuntimeType caseType) {
+ final var className = caseType.getIdentifier();
+ try {
+ return context.loadClass(className);
+ } catch (ClassNotFoundException e) {
+ throw new LinkageError("Failed to load class for " + className, e);
+ }
}
@Override
return Iterables.concat(byCaseChildClass.keySet(), ambiguousByCaseChildClass.keySet());
}
- 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;
- }
-
- return DataContainerCodecPrototype.from(childClass, child, factory());
- }
-
@Override
public NodeCodecContext yangPathArgumentChild(final YangInstanceIdentifier.PathArgument arg) {
final DataContainerCodecPrototype<?> cazeProto;
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.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.AugmentableRuntimeType;
import org.opendaylight.mdsal.binding.runtime.api.BindingRuntimeContext;
import org.opendaylight.mdsal.binding.runtime.api.ChoiceRuntimeType;
import org.opendaylight.mdsal.binding.runtime.api.CompositeRuntimeType;
this.byBindingArgClass = byStreamClassBuilder.equals(byBindingArgClassBuilder) ? this.byStreamClass
: ImmutableMap.copyOf(byBindingArgClassBuilder);
- final Iterable<AugmentRuntimeType> possibleAugmentations;
+ final List<AugmentRuntimeType> possibleAugmentations;
if (Augmentable.class.isAssignableFrom(bindingClass)) {
+ // Verify we have the appropriate backing runtimeType
final var type = getType();
- possibleAugmentations = Iterables.concat(type.augments(), type.mismatchedAugments());
+ verify(type instanceof AugmentableRuntimeType, "Unexpected type %s backing augmenable %s", type,
+ bindingClass);
+ possibleAugmentations = ((AugmentableRuntimeType) type).augments();
generatedClass = CodecDataObjectGenerator.generateAugmentable(prototype.getFactory().getLoader(),
bindingClass, tmpLeaves, tmpDataObjects, keyMethod);
} else {
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())) {
+ if (!map.containsKey(augClass)
+ && ((AugmentableRuntimeType) getType()).augments().contains(value.getType())) {
final NormalizedNode augData = data.childByArg(value.getYangArg());
if (augData != null) {
// ... make sure we do not replace an e
import static com.google.common.base.Verify.verify;
import com.google.common.base.Stopwatch;
+import com.google.common.collect.HashMultimap;
+import com.google.common.collect.SetMultimap;
import java.util.HashMap;
import java.util.Map;
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.BindingRuntimeTypes;
+import org.opendaylight.mdsal.binding.runtime.api.CaseRuntimeType;
import org.opendaylight.mdsal.binding.runtime.api.IdentityRuntimeType;
import org.opendaylight.mdsal.binding.runtime.api.InputRuntimeType;
import org.opendaylight.mdsal.binding.runtime.api.ModuleRuntimeType;
private final Map<QName, OutputRuntimeType> rpcOutputs = new HashMap<>();
// All RpcInputs, indexed by their RPC's QName
private final Map<QName, InputRuntimeType> rpcInputs = new HashMap<>();
+ // All known 'choice's to their corresponding cases
+ private final SetMultimap<JavaTypeName, CaseRuntimeType> choiceToCases = HashMultimap.create();
private BindingRuntimeTypesFactory() {
// Hidden on purpose
LOG.debug("Indexed {} generators in {}", moduleGens.size(), sw);
return new DefaultBindingRuntimeTypes(context, factory.modules, factory.allTypes, factory.identities,
- factory.rpcInputs, factory.rpcOutputs);
+ factory.rpcInputs, factory.rpcOutputs, factory.choiceToCases);
}
private void indexModules(final Map<QNameModule, ModuleGenerator> moduleGens) {
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);
+
+ // Global indexing of cases generated for a particular choice. We look at the Generated type
+ // and make assumptions about its shape -- which works just fine without touching the
+ // ChoiceRuntimeType for cases.
+ if (type instanceof CaseRuntimeType) {
+ final var ifaces = ((GeneratedType) javaType).getImplements();
+ // The appropriate choice and DataObject at the very least. The choice interface is the first
+ // one mentioned.
+ verify(ifaces.size() >= 2, "Unexpected implemented interfaces %s", ifaces);
+ choiceToCases.put(ifaces.get(0).getIdentifier(), (CaseRuntimeType) type);
+ }
}
}
indexRuntimeTypes(gen);
import static com.google.common.base.Verify.verifyNotNull;
import static java.util.Objects.requireNonNull;
+import com.google.common.collect.ImmutableList;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
+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.rt.DefaultAugmentRuntimeType;
import org.opendaylight.mdsal.binding.model.api.GeneratedType;
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.CaseRuntimeType;
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.ChoiceEffectiveStatement;
import org.opendaylight.yangtools.yang.model.api.stmt.SchemaTreeAwareEffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.SchemaTreeAwareEffectiveStatement.SchemaTreeNamespace;
+import org.opendaylight.yangtools.yang.model.api.stmt.SchemaTreeEffectiveStatement;
import org.opendaylight.yangtools.yang.model.util.SchemaInferenceStack;
/**
return otherIt.hasNext() ? -1 : 0;
};
- private AugmentEffectiveStatement effectiveStatement;
+ private SchemaTreeAwareEffectiveStatement<?, ?> targetStatement;
private AbstractCompositeGenerator<?, ?> targetGen;
+ private Optional<AugmentRuntimeType> internalRuntimeType;
AbstractAugmentGenerator(final AugmentEffectiveStatement statement, final AbstractCompositeGenerator<?, ?> parent) {
super(statement, parent);
return builder.build();
}
- @Override
- final AugmentEffectiveStatement effectiveStatement() {
- return verifyNotNull(effectiveStatement, "Effective statement not set in %s", this);
+ @NonNull List<CaseRuntimeType> augmentedCasesIn(final ChildLookup lookup, final ChoiceEffectiveStatement stmt) {
+ final var target = verifyNotNull(targetStatement);
+ if (!stmt.equals(target)) {
+ return List.of();
+ }
+
+ final var result = createBuilder(effectiveStatement(statement(), target))
+ .fillTypes(ChildLookup.of(target), this)
+ .getCaseChilden();
+ internalRuntimeType = Optional.empty();
+ return result;
}
- @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);
+ @Nullable AugmentRuntimeType runtimeTypeIn(final ChildLookup lookup, final EffectiveStatement<?, ?> stmt) {
+ final var target = verifyNotNull(targetStatement);
+ if (!stmt.equals(target)) {
+ return null;
+ }
+ if (internalRuntimeType != null) {
+ return internalRuntimeType.orElseThrow();
+ }
+
+ final var result = verifyNotNull(createInternalRuntimeType(ChildLookup.of(target),
+ effectiveStatement(statement(), target)));
+ internalRuntimeType = Optional.of(result);
+ return result;
+ }
+
+ private static @NonNull AugmentEffectiveStatement effectiveStatement(final AugmentEffectiveStatement augment,
+ final SchemaTreeAwareEffectiveStatement<?, ?> target) {
+ final var stmts = augment.effectiveSubstatements();
+ final var builder = ImmutableList.<EffectiveStatement<?, ?>>builderWithExpectedSize(stmts.size());
+ for (var child : stmts) {
+ if (child instanceof SchemaTreeEffectiveStatement) {
+ final var qname = ((SchemaTreeEffectiveStatement<?>) child).getIdentifier();
+ // FIXME: orElseThrow()?
+ target.get(SchemaTreeNamespace.class, qname).ifPresent(builder::add);
+ } else {
+ builder.add(child);
+ }
+ }
+ return new TargetAugmentEffectiveStatement(augment, target, builder.build());
+ }
+
+ final @Nullable AugmentRuntimeType getInternalRuntimeType() {
+ return verifyNotNull(internalRuntimeType, "Internal runtime not resolved in %s", this).orElse(null);
}
@Override
// Augments are never added as getters, as they are handled via Augmentable mechanics
}
+ @Override
+ CompositeRuntimeTypeBuilder<AugmentEffectiveStatement, AugmentRuntimeType> createBuilder(
+ final AugmentEffectiveStatement statement) {
+ return new CompositeRuntimeTypeBuilder<>(statement) {
+ @Override
+ AugmentRuntimeType build(final GeneratedType type, final AugmentEffectiveStatement statement,
+ final List<RuntimeType> children, final List<AugmentRuntimeType> augments) {
+ // 'augment' cannot be targeted by augment
+ verify(augments.isEmpty(), "Unexpected augments %s", augments);
+ return new DefaultAugmentRuntimeType(type, statement, children);
+ }
+ };
+ }
+
final void setTargetGenerator(final AbstractCompositeGenerator<?, ?> targetGenerator) {
verify(targetGen == null, "Attempted to relink %s, already have target %s", this, targetGen);
targetGen = requireNonNull(targetGenerator);
final void setTargetStatement(final EffectiveStatement<?, ?> targetStatement) {
verify(targetStatement instanceof SchemaTreeAwareEffectiveStatement, "Unexpected target statement %s",
targetStatement);
- effectiveStatement = new TargetAugmentEffectiveStatement(statement(),
- (SchemaTreeAwareEffectiveStatement<?, ?>) targetStatement);
+ this.targetStatement = (SchemaTreeAwareEffectiveStatement<?, ?>) targetStatement;
}
}
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.Optional;
import java.util.stream.Collectors;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;
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;
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;
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);
+ final GeneratedType runtimeJavaType() {
+ return generatedType().orElse(null);
}
- abstract @NonNull R createRuntimeType(@NonNull GeneratedType type, @NonNull S statement,
- @NonNull List<RuntimeType> children, @NonNull List<AugmentRuntimeType> augments);
-
- @Override
- final R rebaseRuntimeType(final R type, final S statement) {
- return createRuntimeType(type.javaType(), statement, indexChildren(statement), augmentRuntimeTypes());
+ final @NonNull List<AbstractAugmentGenerator> augments() {
+ return augments;
}
- 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 childMap;
+ final @NonNull List<GroupingGenerator> groupings() {
+ return verifyNotNull(groupings, "Groupings not initialized in %s", this);
}
- 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();
+ @Override
+ final R createExternalRuntimeType(final Type type) {
+ verify(type instanceof GeneratedType, "Unexpected type %s", type);
- 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);
+ // FIXME: we should be able to use internal cache IFF when all augments end up being local to our statement
+ final var statement = statement();
+ return createBuilder(statement)
+ .fillTypes(ChildLookup.of(statement), this)
+ .build((GeneratedType) type);
}
- final @NonNull List<AbstractAugmentGenerator> augments() {
- return augments;
- }
+ abstract @NonNull CompositeRuntimeTypeBuilder<S, R> createBuilder(S statement);
- 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
+ final R createInternalRuntimeType(final ChildLookup lookup, final S statement, final Type type) {
+ verify(type instanceof GeneratedType, "Unexpected type %s", type);
+ return createBuilder(statement)
+ .fillTypes(lookup.inStatement(statement), this)
+ .build((GeneratedType) type);
}
@Override
}
/**
- * Return the {@link RuntimeType} associated with this object, of applicable.
+ * Return the {@link RuntimeType} associated with this object, if applicable. This represents the
+ * externally-accessible view of this object when considered outside the schema tree or binding tree hierarchy.
*
* @return Associated run-time type, or empty
*/
public final Optional<R> runtimeType() {
if (!runtimeTypeInitialized) {
- runtimeType = createRuntimeType();
+ final var type = runtimeJavaType();
+ if (type != null) {
+ runtimeType = createExternalRuntimeType(type);
+ }
runtimeTypeInitialized = true;
}
return Optional.ofNullable(runtimeType);
}
- final Optional<R> runtimeTypeOf(final @NonNull S stmt) {
+ /**
+ * Return the {@link Type} associated with this object at run-time, if applicable. This method often synonymous
+ * with {@code generatedType().orElseNull()}, but not always. For example
+ * <pre>
+ * <code>
+ * leaf foo {
+ * type string;
+ * }
+ * </code>
+ * </pre>
+ * Results in an empty {@link #generatedType()}, but still produces a {@code java.lang.String}-based
+ * {@link RuntimeType}.
+ *
+ * @return Associated {@link Type}
+ */
+ // FIXME: this should be a generic class argument
+ // FIXME: this needs a better name, but 'runtimeType' is already taken.
+ abstract @Nullable Type runtimeJavaType();
+
+ /**
+ * Create the externally-accessible {@link RuntimeType} view of this object. The difference between
+ * this method and {@link #createInternalRuntimeType(EffectiveStatement)} is that this method represents the view
+ * attached to {@link #statement()} and contains a separate global view of all available augmentations attached to
+ * the GeneratedType.
+ *
+ * @param type {@link Type} associated with this object, as returned by {@link #runtimeJavaType()}
+ * @return Externally-accessible RuntimeType
+ */
+ abstract @NonNull R createExternalRuntimeType(@NonNull Type type);
+
+ /**
+ * Create the internally-accessible {@link RuntimeType} view of this object, if applicable. The difference between
+ * this method and {@link #createExternalRuntimeType()} is that this represents the view attached to the specified
+ * {@code stmt}, which is supplied by the parent statement. The returned {@link RuntimeType} always reports the
+ * global view of attached augmentations as empty.
+ *
+ * @param lookup context to use when looking up child statements
+ * @param stmt Statement for which to create the view
+ * @return Internally-accessible RuntimeType, or {@code null} if not applicable
+ */
+ final @Nullable R createInternalRuntimeType(final @NonNull ChildLookup lookup, final @NonNull S stmt) {
+ // FIXME: cache requests: if we visited this statement, we obviously know what it entails. Note that we walk
+ // towards the original definition. As such, the cache may have to live in the generator we look up,
+ // but should operate on this statement to reflect lookups. This needs a bit of figuring out.
var gen = this;
do {
- final var ret = gen.runtimeType();
- if (ret.isPresent()) {
- return Optional.of(rebaseRuntimeType(ret.orElseThrow(), stmt));
+ final var type = gen.runtimeJavaType();
+ if (type != null) {
+ return createInternalRuntimeType(lookup, stmt, type);
}
gen = gen.previous();
} while (gen != null);
- return Optional.empty();
+ return null;
}
- abstract @Nullable R createRuntimeType();
-
- abstract @NonNull R rebaseRuntimeType(@NonNull R type, @NonNull S statement);
+ abstract @NonNull R createInternalRuntimeType(@NonNull ChildLookup lookup, @NonNull S statement,
+ @NonNull Type type);
@Override
public final boolean isAddedByUses() {
}
@Override
- final R createRuntimeType() {
+ final Type runtimeJavaType() {
if (methodReturnTypeElement != null) {
- return createRuntimeType(methodReturnTypeElement);
+ return methodReturnTypeElement;
}
final var genType = generatedType();
if (genType.isPresent()) {
- return createRuntimeType(genType.orElseThrow());
+ return genType.orElseThrow();
}
final var prev = verifyNotNull(previous(), "No previous generator for %s", this);
- return prev.runtimeType().orElse(null);
+ return prev.runtimeJavaType();
}
- abstract @NonNull R createRuntimeType(Type type);
-
final @NonNull Type methodReturnElementType(final @NonNull TypeBuilderFactory builderFactory) {
var local = methodReturnTypeElement;
if (local == null) {
*/
package org.opendaylight.mdsal.binding.generator.impl.reactor;
+import static com.google.common.base.Verify.verify;
+
import java.util.List;
import org.eclipse.jdt.annotation.NonNull;
import org.opendaylight.mdsal.binding.generator.impl.rt.DefaultActionRuntimeType;
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);
void addAsGetterMethod(final GeneratedTypeBuilderBase<?> builder, final TypeBuilderFactory builderFactory) {
// actions are a separate concept
}
+
+ @Override
+ CompositeRuntimeTypeBuilder<ActionEffectiveStatement, ActionRuntimeType> createBuilder(
+ final ActionEffectiveStatement statement) {
+ return new CompositeRuntimeTypeBuilder<>(statement) {
+ @Override
+ ActionRuntimeType build(final GeneratedType generatedType, final ActionEffectiveStatement statement,
+ final List<RuntimeType> childTypes, final List<AugmentRuntimeType> augmentTypes) {
+ verify(augmentTypes.isEmpty(), "Unexpected augments %s", augmentTypes);
+ return new DefaultActionRuntimeType(generatedType, statement, childTypes);
+ }
+ };
+ }
}
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.generator.impl.rt.DefaultCaseRuntimeType;
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;
@Override
GeneratedType createTypeImpl(final TypeBuilderFactory builderFactory) {
- final GeneratedTypeBuilder builder = builderFactory.newGeneratedTypeBuilder(typeName());
- builder.addImplementsType(BindingTypes.DATA_OBJECT);
// 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)
// Most generators have a parent->child dependency due to parent methods' return types and therefore children
// must not request parent's type. That is not true for choice->case relationship and hence we do not need to
- // go through DefaultType here.
+ // go through DefaultType here
+ final GeneratedTypeBuilder builder = builderFactory.newGeneratedTypeBuilder(typeName());
+ // Note: this needs to be the first type we mention as we are relying on that fact for global runtime type
+ // choice/case indexing.
builder.addImplementsType(choice.getGeneratedType(builderFactory));
+
+ builder.addImplementsType(BindingTypes.DATA_OBJECT);
addAugmentable(builder);
addUsesInterfaces(builder, builderFactory);
addConcreteInterfaceMethods(builder);
}
@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());
+ CompositeRuntimeTypeBuilder<CaseEffectiveStatement, CaseRuntimeType> createBuilder(
+ final CaseEffectiveStatement statement) {
+ return new CompositeRuntimeTypeBuilder<>(statement) {
+ @Override
+ CaseRuntimeType build(final GeneratedType generatedType, final CaseEffectiveStatement statement,
+ final List<RuntimeType> childTypes, final List<AugmentRuntimeType> augmentTypes) {
+ return new DefaultCaseRuntimeType(generatedType, statement, childTypes, augmentTypes);
+ }
+ };
}
}
--- /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 com.google.common.base.MoreObjects;
+import com.google.common.collect.ImmutableSet;
+import java.util.stream.Stream;
+import org.eclipse.jdt.annotation.NonNull;
+import org.opendaylight.yangtools.concepts.Immutable;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.common.QNameModule;
+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.UsesEffectiveStatement;
+
+/**
+ * Lookup context for dealing with namespace translation during execution of {@link AbstractCompositeGenerator}'s
+ * createInternalRuntimeType(). It tracks which namespaces should be translated on account of crossing into source
+ * {@code grouping} statement.
+ */
+final class ChildLookup implements Immutable {
+ private final ImmutableSet<AugmentEffectiveStatement> validUsesAugments;
+ private final ImmutableSet<QNameModule> squashNamespaces;
+ private final QNameModule localNamespace;
+
+ private ChildLookup(final ImmutableSet<AugmentEffectiveStatement> validUsesAugments,
+ final ImmutableSet<QNameModule> squashNamespaces, final QNameModule localNamespace) {
+ this.validUsesAugments = requireNonNull(validUsesAugments);
+ this.squashNamespaces = requireNonNull(squashNamespaces);
+ this.localNamespace = localNamespace;
+ verify(localNamespace == null == squashNamespaces.isEmpty(), "Unexpected lookup state %s", this);
+ }
+
+ public static @NonNull ChildLookup of(final EffectiveStatement<?, ?> statement) {
+ return new ChildLookup(streamUsesAugments(statement).collect(ImmutableSet.toImmutableSet()), ImmutableSet.of(),
+ null);
+ }
+
+ @NonNull QName adjustQName(final @NonNull QName qname) {
+ return squashNamespaces.contains(qname.getModule()) ? qname.bindTo(verifyNotNull(localNamespace)) : qname;
+ }
+
+ boolean contains(final AugmentEffectiveStatement augment) {
+ return validUsesAugments.contains(augment);
+ }
+
+ @NonNull ChildLookup inStatement(final EffectiveStatement<?, ?> statememt) {
+ return hasUsesAugments(statememt)
+ ? new ChildLookup(concatUsesAugments(statememt), squashNamespaces, localNamespace) : this;
+ }
+
+ @NonNull ChildLookup inGrouping(final QName qname, final GroupingGenerator grouping) {
+ final var statement = grouping.statement();
+ final var grpNamespace = statement.argument().getModule();
+ final var itemNamespace = qname.getModule();
+
+ final ImmutableSet<QNameModule> newSquashNamespaces;
+ if (squashNamespaces.contains(itemNamespace)) {
+ newSquashNamespaces = squashNamespaces;
+ } else {
+ newSquashNamespaces = ImmutableSet.<QNameModule>builderWithExpectedSize(squashNamespaces.size() + 1)
+ .addAll(squashNamespaces).add(itemNamespace).build();
+ }
+
+ return new ChildLookup(hasUsesAugments(statement) ? concatUsesAugments(statement) : validUsesAugments,
+ newSquashNamespaces, grpNamespace);
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(this).omitNullValues()
+ .add("augments", validUsesAugments)
+ .add("squash", squashNamespaces)
+ .add("local", localNamespace)
+ .toString();
+ }
+
+ private ImmutableSet<AugmentEffectiveStatement> concatUsesAugments(final EffectiveStatement<?, ?> stmt) {
+ final var concat = ImmutableSet.<AugmentEffectiveStatement>builder().addAll(validUsesAugments);
+ streamUsesAugments(stmt).forEach(concat::add);
+ return concat.build();
+ }
+
+ private static boolean hasUsesAugments(final EffectiveStatement<?, ?> stmt) {
+ return streamUsesAugments(stmt).findAny().isPresent();
+ }
+
+ private static Stream<AugmentEffectiveStatement> streamUsesAugments(final EffectiveStatement<?, ?> stmt) {
+ return stmt.streamEffectiveSubstatements(UsesEffectiveStatement.class)
+ .flatMap(uses -> uses.streamEffectiveSubstatements(AugmentEffectiveStatement.class));
+ }
+}
*/
package org.opendaylight.mdsal.binding.generator.impl.reactor;
-import com.google.common.collect.Iterables;
-import java.util.ArrayList;
+import static com.google.common.base.Verify.verify;
+
+import com.google.common.collect.ImmutableList;
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.generator.impl.rt.DefaultChoiceRuntimeType;
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.runtime.api.CaseRuntimeType;
import org.opendaylight.mdsal.binding.runtime.api.ChoiceRuntimeType;
import org.opendaylight.mdsal.binding.runtime.api.RuntimeType;
+import org.opendaylight.yangtools.yang.common.QName;
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, ChoiceRuntimeType> {
+ static final class ChoiceBuilder extends CompositeRuntimeTypeBuilder<ChoiceEffectiveStatement, ChoiceRuntimeType> {
+ private ImmutableList<CaseRuntimeType> augmentedCases;
+
+ ChoiceBuilder(final ChoiceEffectiveStatement statement) {
+ super(statement);
+ }
+
+ @Override
+ CompositeRuntimeTypeBuilder<ChoiceEffectiveStatement, ChoiceRuntimeType> fillTypes(
+ final ChildLookup lookup,
+ final AbstractCompositeGenerator<ChoiceEffectiveStatement, ChoiceRuntimeType> generator) {
+ fillAugmentedCases(lookup, generator.augments());
+ return super.fillTypes(lookup, generator);
+ }
+
+ @Override
+ boolean isAugmentedChild(final ChildLookup lookup, final QName qname) {
+ for (var augmented : augmentedCases) {
+ if (qname.equals(augmented.statement().argument())) {
+ return true;
+ }
+ }
+ return super.isAugmentedChild(lookup, qname);
+ }
+
+ @Override
+ ChoiceRuntimeType build(final GeneratedType type, final ChoiceEffectiveStatement statement,
+ final List<RuntimeType> children, final List<AugmentRuntimeType> augments) {
+ verify(augments.isEmpty(), "Unexpected augments %s", augments);
+ children.addAll(augmentedCases);
+ return new DefaultChoiceRuntimeType(type, statement, children);
+ }
+
+ private void fillAugmentedCases(final ChildLookup lookup, final List<AbstractAugmentGenerator> augments) {
+ final var builder = ImmutableList.<CaseRuntimeType>builder();
+ for (var augment : augments) {
+ builder.addAll(augment.augmentedCasesIn(lookup, statement()));
+ }
+ augmentedCases = builder.build();
+ }
+ }
+
ChoiceGenerator(final ChoiceEffectiveStatement statement, final AbstractCompositeGenerator<?, ?> parent) {
super(statement, parent);
}
}
@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);
+ ChoiceBuilder createBuilder(final ChoiceEffectiveStatement statement) {
+ return new ChoiceBuilder(statement);
}
}
--- /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 java.util.ArrayList;
+import java.util.List;
+import java.util.stream.Collectors;
+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.runtime.api.AugmentRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.CaseRuntimeType;
+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.meta.EffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.SchemaTreeEffectiveStatement;
+
+abstract class CompositeRuntimeTypeBuilder<S extends EffectiveStatement<?, ?>, R extends CompositeRuntimeType> {
+ private final List<AugmentRuntimeType> augmentTypes = new ArrayList<>();
+ private final List<RuntimeType> childTypes = new ArrayList<>();
+ private final @NonNull S statement;
+
+ CompositeRuntimeTypeBuilder(final S statement) {
+ this.statement = requireNonNull(statement);
+ }
+
+ final @NonNull S statement() {
+ return statement;
+ }
+
+ final @NonNull List<CaseRuntimeType> getCaseChilden() {
+ return childTypes.stream()
+ .map(child -> {
+ verify(child instanceof CaseRuntimeType, "Unexpected child %s in %s", child, statement);
+ return (CaseRuntimeType) child;
+ })
+ .collect(Collectors.toUnmodifiableList());
+ }
+
+ final @NonNull R build(final @NonNull GeneratedType generatedType) {
+ return build(generatedType, statement, childTypes, augmentTypes);
+ }
+
+ abstract @NonNull R build(GeneratedType type, S statement, List<RuntimeType> children,
+ List<AugmentRuntimeType> augments);
+
+ CompositeRuntimeTypeBuilder<S, R> fillTypes(final ChildLookup lookup,
+ final AbstractCompositeGenerator<S, R> generator) {
+ // Figure out which augments are valid in target statement and record their RuntimeTypes.
+ // We will pass the latter to create method. We will use the former to perform replacement lookups instead
+ // of 'this.augments'. That is necessary because 'this.augments' holds all augments targeting the GeneratedType,
+ // hence equivalent augmentations from differing places would match our lookup and the reverse search would be
+ // lead astray.
+ //
+ // Augments targeting 'choice' statement are handled by a separate class and need to be skipped here
+ if (!(generator instanceof ChoiceGenerator)) {
+ for (var augment : generator.augments()) {
+ final var augmentRuntimeType = augment.runtimeTypeIn(lookup, statement);
+ if (augmentRuntimeType != null) {
+ augmentTypes.add(augmentRuntimeType);
+ }
+ }
+ }
+
+ // Now construct RuntimeTypes for each schema tree child of stmt
+ for (var stmt : statement.effectiveSubstatements()) {
+ if (stmt instanceof SchemaTreeEffectiveStatement) {
+ final var child = (SchemaTreeEffectiveStatement<?>) stmt;
+ final var qname = child.getIdentifier();
+
+ // Try valid augments first: they should be empty most of the time and filter all the cases where we
+ // would not find the streamChild among our local and grouping statements. Note that unlike all others,
+ // such matches are not considered to be children in Binding DataObject tree, they are only considered
+ // such in the schema tree.
+ if (isAugmentedChild(lookup, qname)) {
+ continue;
+ }
+
+ final var childRuntimeType = findChildRuntimeType(lookup, generator, child);
+ if (childRuntimeType != null) {
+ childTypes.add(childRuntimeType);
+ }
+ }
+ }
+
+ return this;
+ }
+
+ @SuppressWarnings("unchecked")
+ final <X extends SchemaTreeEffectiveStatement<?>> @Nullable RuntimeType findChildRuntimeType(
+ final @NonNull ChildLookup lookup, final AbstractCompositeGenerator<?, ?> parent, final @NonNull X stmt) {
+ final var qname = stmt.getIdentifier();
+ // First try our local items without adjustment ...
+ @SuppressWarnings("rawtypes")
+ AbstractExplicitGenerator childGen = findChild(parent, qname);
+ if (childGen == null) {
+ // No luck, let's see if any of the groupings can find it
+ for (GroupingGenerator grouping : parent.groupings()) {
+ final var gen = grouping.findSchemaTreeGenerator(
+ qname.bindTo(grouping.statement().argument().getModule()));
+ if (gen != null) {
+ return findChildRuntimeType(lookup.inGrouping(qname, grouping), grouping, stmt);
+ }
+ }
+
+ // Finally attempt to find adjusted QName: this has to succeed
+ final var adjusted = lookup.adjustQName(qname);
+ childGen = verifyNotNull(findChild(parent, adjusted),
+ "Failed to find %s as %s in %s", stmt, adjusted, this);
+ }
+
+ return childGen.createInternalRuntimeType(lookup, stmt);
+ }
+
+ boolean isAugmentedChild(final ChildLookup lookup, final QName qname) {
+ // Note we are dealing with two different kinds of augments and they behave differently with respect
+ // to namespaces. Top-level augments do not make an adjustment, while uses-augments do.
+ return augmentTypes.stream().anyMatch(augment -> augment.schemaTreeChild(qname) != null);
+ }
+
+ private static @Nullable AbstractExplicitGenerator<?, ?> findChild(final AbstractCompositeGenerator<?, ?> parent,
+ final QName qname) {
+ for (var child : parent) {
+ if (child instanceof AbstractExplicitGenerator) {
+ final AbstractExplicitGenerator<?, ?> gen = (AbstractExplicitGenerator<?, ?>) child;
+ final EffectiveStatement<?, ?> stmt = gen.statement();
+ if (stmt instanceof SchemaTreeEffectiveStatement && qname.equals(stmt.argument())) {
+ return gen;
+ }
+ }
+ }
+ return null;
+ }
+}
}
@Override
- ContainerRuntimeType createRuntimeType(final GeneratedType type, final ContainerEffectiveStatement statement,
- final List<RuntimeType> children, final List<AugmentRuntimeType> augments) {
- return new DefaultContainerRuntimeType(type, statement, children, augments);
+ CompositeRuntimeTypeBuilder<ContainerEffectiveStatement, ContainerRuntimeType> createBuilder(
+ final ContainerEffectiveStatement statement) {
+ return new CompositeRuntimeTypeBuilder<>(statement) {
+ @Override
+ ContainerRuntimeType build(final GeneratedType type, final ContainerEffectiveStatement statement,
+ final List<RuntimeType> children, final List<AugmentRuntimeType> augments) {
+ return new DefaultContainerRuntimeType(type, statement, children, augments);
+ }
+ };
}
}
*/
package org.opendaylight.mdsal.binding.generator.impl.reactor;
+import static com.google.common.base.Verify.verify;
+
import java.util.List;
import org.opendaylight.mdsal.binding.generator.impl.rt.DefaultGroupingRuntimeType;
import org.opendaylight.mdsal.binding.model.api.GeneratedType;
}
@Override
- GroupingRuntimeType createRuntimeType(final GeneratedType type, final GroupingEffectiveStatement statement,
- final List<RuntimeType> children, final List<AugmentRuntimeType> augments) {
- return new DefaultGroupingRuntimeType(type, statement, children, augments);
+ void addAsGetterMethod(final GeneratedTypeBuilderBase<?> builder, final TypeBuilderFactory builderFactory) {
+ // groupings are a separate concept
}
@Override
- void addAsGetterMethod(final GeneratedTypeBuilderBase<?> builder, final TypeBuilderFactory builderFactory) {
- // groupings are a separate concept
+ CompositeRuntimeTypeBuilder<GroupingEffectiveStatement, GroupingRuntimeType> createBuilder(
+ final GroupingEffectiveStatement statement) {
+ return new CompositeRuntimeTypeBuilder<>(statement) {
+ @Override
+ GroupingRuntimeType build(final GeneratedType type, final GroupingEffectiveStatement statement,
+ final List<RuntimeType> children, final List<AugmentRuntimeType> augments) {
+ // Groupings cannot be targeted by 'augment'
+ verify(augments.isEmpty(), "Unexpected augments %s", augments);
+ return new DefaultGroupingRuntimeType(type, statement, children);
+ }
+ };
}
+
}
*/
package org.opendaylight.mdsal.binding.generator.impl.reactor;
+import static com.google.common.base.Verify.verify;
import static org.opendaylight.mdsal.binding.model.ri.BindingTypes.BASE_IDENTITY;
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;
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;
}
@Override
- IdentityRuntimeType createRuntimeType() {
- return generatedType().map(type -> new DefaultIdentityRuntimeType(type, statement())).orElse(null);
+ GeneratedType runtimeJavaType() {
+ return generatedType().orElse(null);
}
@Override
- IdentityRuntimeType rebaseRuntimeType(final IdentityRuntimeType type, final IdentityEffectiveStatement statement) {
- return new DefaultIdentityRuntimeType(type.javaType(), statement);
+ IdentityRuntimeType createExternalRuntimeType(final Type type) {
+ verify(type instanceof GeneratedType, "Unexpected type %s", type);
+ return new DefaultIdentityRuntimeType((GeneratedType) type, statement());
+ }
+
+ @Override
+ IdentityRuntimeType createInternalRuntimeType(final ChildLookup lookup, final IdentityEffectiveStatement statement,
+ final Type type) {
+ // 'identity' statements are not part of schema tree and hence should never an internal reference
+ throw new UnsupportedOperationException("Should never be called");
}
@Override
}
@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);
+ final CompositeRuntimeTypeBuilder<InputEffectiveStatement, InputRuntimeType> createBuilder(
+ final InputEffectiveStatement statement) {
+ return new CompositeRuntimeTypeBuilder<>(statement) {
+ @Override
+ InputRuntimeType build(final GeneratedType type, final InputEffectiveStatement statement,
+ final List<RuntimeType> children, final List<AugmentRuntimeType> augments) {
+ return new DefaultInputRuntimeType(type, statement, children, augments);
+ }
+ };
}
}
import org.opendaylight.mdsal.binding.generator.impl.reactor.CollisionDomain.Member;
import org.opendaylight.mdsal.binding.generator.impl.rt.DefaultKeyRuntimeType;
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.GeneratedPropertyBuilder;
import org.opendaylight.mdsal.binding.model.api.type.builder.GeneratedTOBuilder;
}
@Override
- KeyRuntimeType createRuntimeType() {
- return generatedType().map(type -> {
- verify(type instanceof GeneratedTransferObject, "Unexpected type %s", type);
- return new DefaultKeyRuntimeType((GeneratedTransferObject) type, statement());
- }).orElse(null);
+ GeneratedType runtimeJavaType() {
+ return generatedType().orElse(null);
}
@Override
- KeyRuntimeType rebaseRuntimeType(final KeyRuntimeType type, final KeyEffectiveStatement statement) {
- return new DefaultKeyRuntimeType(type.javaType(), statement);
+ KeyRuntimeType createExternalRuntimeType(final Type type) {
+ verify(type instanceof GeneratedTransferObject, "Unexpected type %s", type);
+ return new DefaultKeyRuntimeType((GeneratedTransferObject) type, statement());
+ }
+
+ @Override
+ KeyRuntimeType createInternalRuntimeType(final ChildLookup lookup,final KeyEffectiveStatement statement,
+ final Type type) {
+ // The only reference to this runtime type is from ListGenerator which is always referencing the external type
+ throw new UnsupportedOperationException("Should never be called");
}
@Override
}
@Override
- LeafRuntimeType createRuntimeType(final Type type) {
+ LeafRuntimeType createExternalRuntimeType(final Type type) {
return new DefaultLeafRuntimeType(type, statement());
}
@Override
- LeafRuntimeType rebaseRuntimeType(final LeafRuntimeType type, final LeafEffectiveStatement statement) {
- return new DefaultLeafRuntimeType(type.javaType(), statement);
+ LeafRuntimeType createInternalRuntimeType(final ChildLookup lookup, final LeafEffectiveStatement statement,
+ final Type type) {
+ return new DefaultLeafRuntimeType(type, statement);
}
}
}
@Override
- LeafListRuntimeType createRuntimeType(final Type type) {
+ LeafListRuntimeType createExternalRuntimeType(final Type type) {
return new DefaultLeafListRuntimeType(type, statement());
}
@Override
- LeafListRuntimeType rebaseRuntimeType(final LeafListRuntimeType type, final LeafListEffectiveStatement statement) {
- return new DefaultLeafListRuntimeType(type.javaType(), statement);
+ LeafListRuntimeType createInternalRuntimeType(final ChildLookup lookup, final LeafListEffectiveStatement statement,
+ final Type type) {
+ return new DefaultLeafListRuntimeType(type, statement);
}
}
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.KeyRuntimeType;
import org.opendaylight.mdsal.binding.runtime.api.ListRuntimeType;
import org.opendaylight.mdsal.binding.runtime.api.RuntimeType;
import org.opendaylight.mdsal.binding.spec.naming.BindingMapping;
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);
+ private @Nullable KeyRuntimeType keyRuntimeType() {
+ final var gen = keyGen;
+ return gen != null ? gen.runtimeType().orElseThrow() : null;
}
@Override
return ret;
}
+
+ @Override
+ CompositeRuntimeTypeBuilder<ListEffectiveStatement, ListRuntimeType> createBuilder(
+ final ListEffectiveStatement statement) {
+ return new CompositeRuntimeTypeBuilder<>(statement) {
+ @Override
+ ListRuntimeType build(final GeneratedType type, final ListEffectiveStatement statement,
+ final List<RuntimeType> children, final List<AugmentRuntimeType> augments) {
+ // FIXME: the key here is not rebased correctly :(
+ return new DefaultListRuntimeType(type, statement, children, augments, keyRuntimeType());
+ }
+ };
+ }
}
*/
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 java.util.List;
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);
}
builder.addConstant(BindingTypes.QNAME, BindingMapping.QNAME_STATIC_FIELD_NAME,
Map.entry(yangModuleInfo, localName.getLocalName()));
}
+
+ @Override
+ CompositeRuntimeTypeBuilder<ModuleEffectiveStatement, ModuleRuntimeType> createBuilder(
+ final ModuleEffectiveStatement statement) {
+ return new CompositeRuntimeTypeBuilder<>(statement) {
+ @Override
+ ModuleRuntimeType build(final GeneratedType type, final ModuleEffectiveStatement statement,
+ final List<RuntimeType> children, final List<AugmentRuntimeType> augments) {
+ verify(augments.isEmpty(), "Unexpected augments %s", augments);
+ return new DefaultModuleRuntimeType(type, statement, children);
+ }
+ };
+ }
}
}
@Override
- NotificationRuntimeType createRuntimeType(final GeneratedType type, final NotificationEffectiveStatement statement,
- final List<RuntimeType> children, final List<AugmentRuntimeType> augments) {
- return new DefaultNotificationRuntimeType(type, statement, children, augments);
+ void addAsGetterMethod(final GeneratedTypeBuilderBase<?> builder, final TypeBuilderFactory builderFactory) {
+ // Notifications are a distinct concept
}
@Override
- void addAsGetterMethod(final GeneratedTypeBuilderBase<?> builder, final TypeBuilderFactory builderFactory) {
- // Notifications are a distinct concept
+ CompositeRuntimeTypeBuilder<NotificationEffectiveStatement, NotificationRuntimeType> createBuilder(
+ final NotificationEffectiveStatement statement) {
+ return new CompositeRuntimeTypeBuilder<>(statement) {
+ @Override
+ NotificationRuntimeType build(final GeneratedType type, final NotificationEffectiveStatement statement,
+ final List<RuntimeType> children, final List<AugmentRuntimeType> augments) {
+ return new DefaultNotificationRuntimeType(type, statement, children, augments);
+ }
+ };
}
private Type notificationType(final GeneratedTypeBuilder builder, final TypeBuilderFactory builderFactory) {
*/
package org.opendaylight.mdsal.binding.generator.impl.reactor;
+import static com.google.common.base.Verify.verify;
+
+import org.eclipse.jdt.annotation.NonNull;
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;
}
@Override
- AnydataRuntimeType createRuntimeType() {
- return generatedType().map(type -> new DefaultAnydataRuntimeType(type, statement())).orElse(null);
+ AnydataRuntimeType createExternalRuntimeType(final GeneratedType type) {
+ return new DefaultAnydataRuntimeType(type, statement());
}
@Override
- AnydataRuntimeType rebaseRuntimeType(final AnydataRuntimeType type, final AnydataEffectiveStatement statement) {
- return new DefaultAnydataRuntimeType(type.javaType(), statement);
+ AnydataRuntimeType createInternalRuntimeType(final AnydataEffectiveStatement statement,
+ final GeneratedType type) {
+ return new DefaultAnydataRuntimeType(type, statement);
}
}
}
@Override
- AnyxmlRuntimeType createRuntimeType() {
- return generatedType().map(type -> new DefaultAnyxmlRuntimeType(type, statement())).orElse(null);
+ AnyxmlRuntimeType createExternalRuntimeType(final GeneratedType type) {
+ return new DefaultAnyxmlRuntimeType(type, statement());
}
@Override
- AnyxmlRuntimeType rebaseRuntimeType(final AnyxmlRuntimeType type, final AnyxmlEffectiveStatement statement) {
- return new DefaultAnyxmlRuntimeType(type.javaType(), statement);
+ AnyxmlRuntimeType createInternalRuntimeType(final AnyxmlEffectiveStatement statement,
+ final GeneratedType type) {
+ return new DefaultAnyxmlRuntimeType(type, statement);
}
}
void constructRequire(final GeneratedTypeBuilderBase<?> builder, final Type returnType) {
constructRequireImpl(builder, returnType);
}
+
+ @Override
+ final GeneratedType runtimeJavaType() {
+ return generatedType().orElse(null);
+ }
+
+ @Override
+ final @NonNull R createExternalRuntimeType(final Type type) {
+ verify(type instanceof GeneratedType, "Unexpected type %s", type);
+ return createExternalRuntimeType((GeneratedType) type);
+ }
+
+ abstract @NonNull R createExternalRuntimeType(@NonNull GeneratedType type);
+
+ @Override
+ final R createInternalRuntimeType(final ChildLookup lookup, final S statement, final Type type) {
+ verify(type instanceof GeneratedType, "Unexpected type %s", type);
+ return createInternalRuntimeType(statement, (GeneratedType) type);
+ }
+
+ abstract @NonNull R createInternalRuntimeType(@NonNull S statement, @NonNull GeneratedType type);
}
}
@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);
+ final CompositeRuntimeTypeBuilder<OutputEffectiveStatement, OutputRuntimeType> createBuilder(
+ final OutputEffectiveStatement statement) {
+ return new CompositeRuntimeTypeBuilder<>(statement) {
+ @Override
+ OutputRuntimeType build(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;
}
@Override
- RpcRuntimeType createRuntimeType(final GeneratedType type, final RpcEffectiveStatement statement,
- final List<RuntimeType> children, final List<AugmentRuntimeType> augments) {
- throw new UnsupportedOperationException();
+ void addAsGetterMethod(final GeneratedTypeBuilderBase<?> builder, final TypeBuilderFactory builderFactory) {
+ // RPCs are a separate concept
}
@Override
- void addAsGetterMethod(final GeneratedTypeBuilderBase<?> builder, final TypeBuilderFactory builderFactory) {
- // RPCs are a separate concept
+ CompositeRuntimeTypeBuilder<RpcEffectiveStatement, RpcRuntimeType> createBuilder(
+ final RpcEffectiveStatement statement) {
+ // RPCs do not have a dedicated interface
+ throw new UnsupportedOperationException("Should never be called");
}
}
import static com.google.common.base.Verify.verify;
import static java.util.Objects.requireNonNull;
+import com.google.common.base.MoreObjects;
import com.google.common.collect.Collections2;
import com.google.common.collect.ImmutableList;
import java.util.Collection;
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 AugmentationSchemaNode schemaDelegate;
TargetAugmentEffectiveStatement(final AugmentEffectiveStatement augment,
- final SchemaTreeAwareEffectiveStatement<?, ?> target) {
+ final SchemaTreeAwareEffectiveStatement<?, ?> target,
+ final ImmutableList<EffectiveStatement<?, ?>> substatements) {
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();
- target.get(SchemaTreeNamespace.class, qname).ifPresent(builder::add);
- } else {
- builder.add(stmt);
- }
- }
-
- substatements = builder.build();
+ this.substatements = requireNonNull(substatements);
}
@NonNull AugmentEffectiveStatement delegate() {
public AugmentEffectiveStatement asEffectiveStatement() {
return this;
}
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(this)
+ .add("delegate", delegate)
+ .add("substatements", substatements.size())
+ .toString();
+ }
}
}
@Override
- TypedefRuntimeType createRuntimeType(final Type type) {
+ TypedefRuntimeType createExternalRuntimeType(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);
+ TypedefRuntimeType createInternalRuntimeType(final ChildLookup lookup, final TypedefEffectiveStatement statement,
+ final Type type) {
+ // 'typedef' statements are not schema tree statements, they should not have internal references
+ throw new UnsupportedOperationException("Should never be called");
}
@Override
import static com.google.common.base.Verify.verifyNotNull;
import static java.util.Objects.requireNonNull;
+import com.google.common.collect.ImmutableList;
+import java.util.List;
import org.eclipse.jdt.annotation.NonNull;
+import org.opendaylight.mdsal.binding.runtime.api.AugmentRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.CaseRuntimeType;
+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.ChoiceEffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.SchemaTreeAwareEffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.SchemaTreeAwareEffectiveStatement.SchemaTreeNamespace;
import org.opendaylight.yangtools.yang.model.api.stmt.SchemaTreeEffectiveStatement;
import org.opendaylight.yangtools.yang.model.api.stmt.UsesEffectiveStatement;
// Our parent here is *not* the 'uses' statement, but rather the statement which contains it.
return new AugmentRequirement(this, verifyNotNull(grouping, "Unresolved grouping in %s", this));
}
+
+ @Override
+ List<CaseRuntimeType> augmentedCasesIn(final ChildLookup lookup, final ChoiceEffectiveStatement stmt) {
+ final var result = super.augmentedCasesIn(lookup, stmt);
+ if (result != null) {
+ return result;
+ }
+ final var augment = statement();
+ if (!lookup.contains(augment)) {
+ return List.of();
+ }
+
+ final var effectiveStatement = effectiveStatement(augment, stmt);
+ return createBuilder(effectiveStatement)
+ .fillTypes(lookup.inStatement(effectiveStatement), this)
+ .getCaseChilden();
+ }
+
+ @Override
+ AugmentRuntimeType runtimeTypeIn(final ChildLookup lookup, final EffectiveStatement<?, ?> target) {
+ final var result = super.runtimeTypeIn(lookup, target);
+ if (result != null) {
+ return result;
+ }
+ final var augment = statement();
+ if (!lookup.contains(augment)) {
+ return null;
+ }
+
+ verify(target instanceof SchemaTreeAwareEffectiveStatement && target instanceof SchemaTreeEffectiveStatement,
+ "Unexpected statement %s", target);
+ final var effectiveStatement = effectiveStatement(augment, (SchemaTreeAwareEffectiveStatement<?, ?>) target);
+ return verifyNotNull(createInternalRuntimeType(lookup.inStatement(effectiveStatement), effectiveStatement));
+ }
+
+ private static @NonNull AugmentEffectiveStatement effectiveStatement(final AugmentEffectiveStatement augment,
+ final SchemaTreeAwareEffectiveStatement<?, ?> target) {
+ verify(target instanceof SchemaTreeEffectiveStatement, "Unexpected statement %s", target);
+ // 'uses'/'augment': our children are binding to target's namespace
+ final var targetNamespace = ((SchemaTreeEffectiveStatement<?>) target).argument().getModule();
+
+ 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().bindTo(targetNamespace);
+ target.get(SchemaTreeNamespace.class, qname).ifPresent(builder::add);
+ } else {
+ builder.add(stmt);
+ }
+ }
+
+ return new TargetAugmentEffectiveStatement(augment, target, builder.build());
+ }
}
--- /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.ImmutableList;
+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.AugmentableRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.RuntimeType;
+import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
+
+/**
+ * Abstract base class for {@link AbstractCompositeRuntimeType}s which support augmentations.
+ */
+abstract class AbstractAugmentableRuntimeType<S extends EffectiveStatement<?, ?>>
+ extends AbstractCompositeRuntimeType<S> implements AugmentableRuntimeType {
+ private final @NonNull ImmutableList<AugmentRuntimeType> augments;
+
+ AbstractAugmentableRuntimeType(final GeneratedType bindingType, final S statement, final List<RuntimeType> children,
+ final List<AugmentRuntimeType> augments) {
+ super(bindingType, statement, children);
+ this.augments = ImmutableList.copyOf(augments);
+ }
+
+ @Override
+ public final List<AugmentRuntimeType> augments() {
+ return augments;
+ }
+}
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;
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) {
+ AbstractCompositeRuntimeType(final GeneratedType bindingType, final S statement, final List<RuntimeType> children) {
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)
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 String toString() {
- return MoreObjects.toStringHelper(this).add("javaType", javaType).add("statement", statement).toString();
+ return MoreObjects.toStringHelper(this)
+ .add("javaType", javaType.getIdentifier())
+ .add("statement", statement)
+ .toString();
}
}
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;
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);
+ final List<RuntimeType> children) {
+ super(bindingType, statement, children);
input = child(children, InputRuntimeType.class);
output = child(children, OutputRuntimeType.class);
}
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);
+ final List<RuntimeType> children) {
+ super(bindingType, statement, children);
}
}
import com.google.common.base.MoreObjects;
import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSetMultimap;
import com.google.common.collect.ImmutableSortedMap;
import com.google.common.collect.Maps;
+import com.google.common.collect.SetMultimap;
import java.util.Map;
import java.util.Optional;
+import java.util.Set;
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.CaseRuntimeType;
+import org.opendaylight.mdsal.binding.runtime.api.ChoiceRuntimeType;
import org.opendaylight.mdsal.binding.runtime.api.GeneratedRuntimeType;
import org.opendaylight.mdsal.binding.runtime.api.IdentityRuntimeType;
import org.opendaylight.mdsal.binding.runtime.api.InputRuntimeType;
*/
public final class DefaultBindingRuntimeTypes implements BindingRuntimeTypes {
private final @NonNull EffectiveModelContext context;
+ private final ImmutableSetMultimap<JavaTypeName, CaseRuntimeType> choiceToCases;
private final ImmutableMap<QNameModule, ModuleRuntimeType> modulesByNamespace;
private final ImmutableSortedMap<String, ModuleRuntimeType> modulesByPackage;
private final ImmutableMap<QName, IdentityRuntimeType> identities;
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) {
+ final Map<QName, OutputRuntimeType> rpcOutputs,
+ final SetMultimap<JavaTypeName, CaseRuntimeType> choiceToCases) {
this.context = requireNonNull(context);
this.identities = ImmutableMap.copyOf(identities);
this.types = ImmutableMap.copyOf(types);
this.rpcInputs = ImmutableMap.copyOf(rpcInputs);
this.rpcOutputs = ImmutableMap.copyOf(rpcOutputs);
+ this.choiceToCases = ImmutableSetMultimap.copyOf(choiceToCases);
modulesByNamespace = ImmutableMap.copyOf(modules);
modulesByPackage = ImmutableSortedMap.copyOf(Maps.uniqueIndex(modules.values(),
return Optional.ofNullable(rpcOutputs.get(requireNonNull(rpcName)));
}
+ @Override
+ public Set<CaseRuntimeType> allCaseChildren(final ChoiceRuntimeType choiceType) {
+ return choiceToCases.get(choiceType.getIdentifier());
+ }
+
@Override
public String toString() {
return MoreObjects.toStringHelper(this)
*/
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.CaseEffectiveStatement;
-abstract class AbstractCaseRuntimeType extends AbstractCompositeRuntimeType<CaseEffectiveStatement>
+@Beta
+public final class DefaultCaseRuntimeType extends AbstractAugmentableRuntimeType<CaseEffectiveStatement>
implements CaseRuntimeType {
- AbstractCaseRuntimeType(final GeneratedType bindingType, final CaseEffectiveStatement statement,
+ public DefaultCaseRuntimeType(final GeneratedType bindingType, final CaseEffectiveStatement statement,
final List<RuntimeType> children, final List<AugmentRuntimeType> augments) {
super(bindingType, statement, children, augments);
}
*/
package org.opendaylight.mdsal.binding.generator.impl.rt;
+import com.google.common.annotations.Beta;
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>
+@Beta
+public final class DefaultChoiceRuntimeType 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);
+ public DefaultChoiceRuntimeType(final GeneratedType bindingType, final ChoiceEffectiveStatement statement,
+ final List<RuntimeType> children) {
+ super(bindingType, statement, children);
}
@Override
- public final Collection<CaseRuntimeType> validCaseChildren() {
+ public Collection<CaseRuntimeType> validCaseChildren() {
return (Collection) Collections2.filter(schemaTreeChildren(), CaseRuntimeType.class::isInstance);
}
@Override
- public final CaseRuntimeType bindingCaseChild(final JavaTypeName typeName) {
+ public CaseRuntimeType bindingCaseChild(final JavaTypeName typeName) {
final var child = bindingChild(typeName);
return child instanceof CaseRuntimeType ? (CaseRuntimeType) child : null;
}
import org.opendaylight.yangtools.yang.model.api.stmt.ContainerEffectiveStatement;
@Beta
-public final class DefaultContainerRuntimeType extends AbstractCompositeRuntimeType<ContainerEffectiveStatement>
+public final class DefaultContainerRuntimeType extends AbstractAugmentableRuntimeType<ContainerEffectiveStatement>
implements ContainerRuntimeType {
public DefaultContainerRuntimeType(final GeneratedType bindingType, final ContainerEffectiveStatement statement,
final List<RuntimeType> children, final List<AugmentRuntimeType> augments) {
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;
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);
+ final List<RuntimeType> children) {
+ super(bindingType, statement, children);
}
}
import org.opendaylight.yangtools.yang.model.api.stmt.InputEffectiveStatement;
@Beta
-public final class DefaultInputRuntimeType extends AbstractCompositeRuntimeType<InputEffectiveStatement>
+public class DefaultInputRuntimeType extends AbstractAugmentableRuntimeType<InputEffectiveStatement>
implements InputRuntimeType {
public DefaultInputRuntimeType(final GeneratedType bindingType, final InputEffectiveStatement statement,
final List<RuntimeType> children, final List<AugmentRuntimeType> augments) {
import com.google.common.annotations.Beta;
import java.util.List;
+import org.eclipse.jdt.annotation.Nullable;
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.yangtools.yang.model.api.stmt.ListEffectiveStatement;
@Beta
-public final class DefaultListRuntimeType extends AbstractCompositeRuntimeType<ListEffectiveStatement>
+public final class DefaultListRuntimeType extends AbstractAugmentableRuntimeType<ListEffectiveStatement>
implements ListRuntimeType {
- private final KeyRuntimeType keyType;
+ private final @Nullable KeyRuntimeType keyType;
public DefaultListRuntimeType(final GeneratedType bindingType, final ListEffectiveStatement statement,
final List<RuntimeType> children, final List<AugmentRuntimeType> augments, final KeyRuntimeType keyType) {
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;
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);
+ final List<RuntimeType> children) {
+ super(bindingType, statement, children);
}
}
import org.opendaylight.yangtools.yang.model.api.stmt.NotificationEffectiveStatement;
@Beta
-public final class DefaultNotificationRuntimeType extends AbstractCompositeRuntimeType<NotificationEffectiveStatement>
+public final class DefaultNotificationRuntimeType extends AbstractAugmentableRuntimeType<NotificationEffectiveStatement>
implements NotificationRuntimeType {
public DefaultNotificationRuntimeType(final GeneratedType bindingType,
final NotificationEffectiveStatement statement, final List<RuntimeType> children,
import org.opendaylight.yangtools.yang.model.api.stmt.OutputEffectiveStatement;
@Beta
-public final class DefaultOutputRuntimeType extends AbstractCompositeRuntimeType<OutputEffectiveStatement>
+public class DefaultOutputRuntimeType extends AbstractAugmentableRuntimeType<OutputEffectiveStatement>
implements OutputRuntimeType {
public DefaultOutputRuntimeType(final GeneratedType bindingType, final OutputEffectiveStatement statement,
final List<RuntimeType> children, final List<AugmentRuntimeType> 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 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.runtime.api;
+
+import com.google.common.annotations.Beta;
+import java.util.List;
+import org.eclipse.jdt.annotation.NonNull;
+
+/**
+ * A {@link CompositeRuntimeType} which is also can be targeted by {@code augment} statements.
+ */
+@Beta
+public interface AugmentableRuntimeType extends CompositeRuntimeType {
+ /**
+ * Return the {@link AugmentRuntimeType}s extending this type, matching the underlying {@link #statement()}.
+ *
+ * @return {@link AugmentRuntimeType}s extending this type.
+ */
+ @NonNull List<AugmentRuntimeType> augments();
+}
import com.google.common.annotations.Beta;
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.yangtools.concepts.Immutable;
import org.opendaylight.yangtools.yang.common.QName;
}
return tmp;
}
+
+ /**
+ * Lookup to all {@link CaseRuntimeType}s related to a {@link ChoiceRuntimeType}. This is important when dealing
+ * with sharing incurred by Binding Spec's reuse of constructs defined in a {@code grouping}.
+ *
+ * <p>
+ * As an example, consider {@link ChoiceRuntimeType} and {@link CaseRuntimeType} relationship to
+ * {@link GeneratedType}s in the following model:
+ * <pre>
+ * <code>
+ * grouping grp {
+ * 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>
+ * YANG view of what is valid in {@code /foo/foo/bar} differs from what is valid in {@code /bar/foo/bar}, but this
+ * difference is not reflected in generated Java constructs. 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 effective model.
+ *
+ * <p>
+ * This method provides a bridge between a particular instantiation of a {@code choice} to {@link CaseRuntimeType}s
+ * valid in all instantiations.
+ *
+ * @param choiceType A ChoiceRuntimeType
+ * @return The set of {@link CaseRuntimeType}s known to this instance
+ * @throws NullPointerException if {@code ChoiceRuntimeType} is null
+ */
+ @NonNull Set<CaseRuntimeType> allCaseChildren(ChoiceRuntimeType choiceType);
}
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 {
+public interface CaseRuntimeType extends AugmentableRuntimeType, 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();
}
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.binding.Augmentable;
import org.opendaylight.yangtools.yang.model.api.stmt.ChoiceEffectiveStatement;
/**
- * A {@link RuntimeType} associated with a {@code choice} statement.
+ * A {@link RuntimeType} associated with a {@code choice} statement. Note that unlike YANG semantics, in Binding Spec
+ * semantics a type generated for a 'choice' statement is <b>does not</b> implement {@link Augmentable}.
*/
@Beta
public interface ChoiceRuntimeType extends CompositeRuntimeType, DataRuntimeType {
*/
@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();
}
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}.
+ * A {@link RuntimeType} which is also a {@link RuntimeTypeContainer}. This is a pure composition interface and does not
+ * imply further contract.
*/
@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();
+ // Pure contract composition
}
@Beta
public interface ContainerLikeRuntimeType<D extends DeclaredStatement<QName>,
E extends DataTreeEffectiveStatement<D> & DataTreeAwareEffectiveStatement<QName, D>>
- extends CompositeRuntimeType, DataRuntimeType {
+ extends AugmentableRuntimeType, DataRuntimeType {
@Override
E statement();
}
* A {@link RuntimeType} associated with a {@code list} statement.
*/
@Beta
-public interface ListRuntimeType extends CompositeRuntimeType, DataRuntimeType {
+public interface ListRuntimeType extends AugmentableRuntimeType, DataRuntimeType {
@Override
ListEffectiveStatement statement();
* A {@link RuntimeType} associated with a {@code notification} statement.
*/
@Beta
-public interface NotificationRuntimeType extends CompositeRuntimeType {
+public interface NotificationRuntimeType extends AugmentableRuntimeType {
@Override
NotificationEffectiveStatement statement();
}
* <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.
+ * {@link AugmentableRuntimeType#augments()}, if applicable.
*
* @param qname {@code schema node} identifier
* @return Corresponding {@link RuntimeType}, or null if not found
* Class which should be used at particular subtree
* @return true if and only if classes represents same data.
*/
+ // FIXME: this really should live in BindingRuntimeTypes and should not be based on reflection. The only user is
+ // binding-dom-codec and the logic could easily be performed on GeneratedType instead. For a particular
+ // world this boils down to a matrix, which can be calculated either on-demand or when we create
+ // BindingRuntimeTypes. Achieving that will bring us one step closer to being able to have a pre-compiled
+ // Binding Runtime.
@SuppressWarnings({ "rawtypes", "unchecked" })
public static boolean isSubstitutionFor(final Class potential, final Class target) {
Set<Class> subImplemented = new HashSet<>(Arrays.asList(potential.getInterfaces()));