From: Robert Varga Date: Fri, 18 Mar 2022 18:37:28 +0000 (+0100) Subject: Use declared statements to resolve augments X-Git-Tag: v9.0.0~3 X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?p=mdsal.git;a=commitdiff_plain;h=da12199fb82be75eccc92367f387c45f7679d222 Use declared statements to resolve augments When trying to map effective instantiated model back to our Generator hierarchy we need to not get confused by namespaces. The simplest way to do that is to pick out augmentations first -- as those are the only ones what can actually differ in namespace. The rest can be taken care of just based on localName, as we are dealing with SchemaTreeEffectiveStatements. In general we can make the connection by tracing back the path we have taken towards the instantiation site when seeing an AugmentEffectiveStatement and match it to the corresponding AbstractAugmentGenerator. Normally we could do this via straight comparison of AugmentEffectiveStatements, but unfortunately their equality contract does not give us that. The reason for that is that we reuse things across groupings, whereas YANG parser creates separate instantiations -- hence this breaks down with UsesAugmentGenerator. We deal with that by comparing the declared view of the two statements -- and those are guaranteed to be unique. JIRA: MDSAL-735 Change-Id: I4d8f0e50541b53620cc5b0a2170484e85e9cf717 Signed-off-by: Robert Varga --- diff --git a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/AbstractAugmentGenerator.java b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/AbstractAugmentGenerator.java index d52d09632b..c25e6f867f 100644 --- a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/AbstractAugmentGenerator.java +++ b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/AbstractAugmentGenerator.java @@ -11,13 +11,10 @@ import static com.google.common.base.Verify.verify; import static com.google.common.base.Verify.verifyNotNull; import static java.util.Objects.requireNonNull; -import com.google.common.collect.ImmutableList; import java.util.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; @@ -34,8 +31,6 @@ 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; /** @@ -92,9 +87,7 @@ abstract class AbstractAugmentGenerator return otherIt.hasNext() ? -1 : 0; }; - private SchemaTreeAwareEffectiveStatement targetStatement; private AbstractCompositeGenerator targetGen; - private Optional internalRuntimeType; AbstractAugmentGenerator(final AugmentEffectiveStatement statement, final AbstractCompositeGenerator parent) { super(statement, parent); @@ -155,53 +148,23 @@ abstract class AbstractAugmentGenerator return builder.build(); } - @NonNull List 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; + boolean matchesInstantiated(final AugmentEffectiveStatement statement) { + return statement().equals(statement); } - @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; + final void fillRuntimeCasesIn(final AugmentResolver resolver, final ChoiceEffectiveStatement stmt, + final List toList) { + toList.addAll(createBuilder(effectiveIn(stmt)).populate(resolver, this).getCaseChilden()); } - private static @NonNull AugmentEffectiveStatement effectiveStatement(final AugmentEffectiveStatement augment, - final SchemaTreeAwareEffectiveStatement target) { - final var stmts = augment.effectiveSubstatements(); - final var builder = ImmutableList.>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 @NonNull AugmentRuntimeType runtimeTypeIn(final AugmentResolver resolver, + final EffectiveStatement stmt) { + verify(stmt instanceof SchemaTreeAwareEffectiveStatement, "Unexpected target statement %s", stmt); + return verifyNotNull(createInternalRuntimeType(resolver, + effectiveIn((SchemaTreeAwareEffectiveStatement) stmt))); } - final @Nullable AugmentRuntimeType getInternalRuntimeType() { - return verifyNotNull(internalRuntimeType, "Internal runtime not resolved in %s", this).orElse(null); - } + abstract @NonNull TargetAugmentEffectiveStatement effectiveIn(SchemaTreeAwareEffectiveStatement target); @Override final void addAsGetterMethod(final GeneratedTypeBuilderBase builder, final TypeBuilderFactory builderFactory) { @@ -230,10 +193,4 @@ abstract class AbstractAugmentGenerator final @NonNull AbstractCompositeGenerator targetGenerator() { return verifyNotNull(targetGen, "No target for %s", this); } - - final void setTargetStatement(final EffectiveStatement targetStatement) { - verify(targetStatement instanceof SchemaTreeAwareEffectiveStatement, "Unexpected target statement %s", - targetStatement); - this.targetStatement = (SchemaTreeAwareEffectiveStatement) targetStatement; - } } diff --git a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/AbstractCompositeGenerator.java b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/AbstractCompositeGenerator.java index 769830433f..a675e03656 100644 --- a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/AbstractCompositeGenerator.java +++ b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/AbstractCompositeGenerator.java @@ -176,22 +176,15 @@ public abstract class AbstractCompositeGenerator createBuilder(S statement); @Override - final R createInternalRuntimeType(final ChildLookup lookup, final S statement, final Type type) { + final R createInternalRuntimeType(final AugmentResolver resolver, 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); + return createBuilder(statement).populate(resolver, this).build((GeneratedType) type); } @Override diff --git a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/AbstractExplicitGenerator.java b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/AbstractExplicitGenerator.java index 5219378e39..39456cbbaa 100644 --- a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/AbstractExplicitGenerator.java +++ b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/AbstractExplicitGenerator.java @@ -135,7 +135,7 @@ public abstract class AbstractExplicitGenerator> stack = new ArrayDeque<>(); + + void enter(final AbstractCompositeGenerator generator) { + stack.push(requireNonNull(generator)); + } + + void exit() { + stack.pop(); + } + + @NonNull AbstractAugmentGenerator getAugment(final AugmentEffectiveStatement statement) { + for (var generator : stack) { + final var found = findAugment(generator, statement); + if (found != null) { + return found; + } + } + throw new IllegalStateException("Failed to resolve " + statement + " in " + stack); + } + + private @Nullable AbstractAugmentGenerator findAugment(final AbstractCompositeGenerator generator, + final AugmentEffectiveStatement statement) { + for (var augment : generator.augments()) { + if (augment.matchesInstantiated(statement)) { + return augment; + } + } + for (var grouping : generator.groupings()) { + final var found = findAugment(grouping, statement); + if (found != null) { + return found; + } + } + return null; + } +} diff --git a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/ChildLookup.java b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/ChildLookup.java deleted file mode 100644 index 083bf08f93..0000000000 --- a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/ChildLookup.java +++ /dev/null @@ -1,101 +0,0 @@ -/* - * 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 validUsesAugments; - private final ImmutableSet squashNamespaces; - private final QNameModule localNamespace; - - private ChildLookup(final ImmutableSet validUsesAugments, - final ImmutableSet 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 newSquashNamespaces; - if (squashNamespaces.contains(itemNamespace)) { - newSquashNamespaces = squashNamespaces; - } else { - newSquashNamespaces = ImmutableSet.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 concatUsesAugments(final EffectiveStatement stmt) { - final var concat = ImmutableSet.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 streamUsesAugments(final EffectiveStatement stmt) { - return stmt.streamEffectiveSubstatements(UsesEffectiveStatement.class) - .flatMap(uses -> uses.streamEffectiveSubstatements(AugmentEffectiveStatement.class)); - } -} diff --git a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/ChoiceGenerator.java b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/ChoiceGenerator.java index 1b73a7d4d5..f0290e4485 100644 --- a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/ChoiceGenerator.java +++ b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/ChoiceGenerator.java @@ -9,7 +9,7 @@ package org.opendaylight.mdsal.binding.generator.impl.reactor; import static com.google.common.base.Verify.verify; -import com.google.common.collect.ImmutableList; +import java.util.ArrayList; import java.util.List; import org.opendaylight.mdsal.binding.generator.impl.rt.DefaultChoiceRuntimeType; import org.opendaylight.mdsal.binding.model.api.GeneratedType; @@ -29,28 +29,25 @@ import org.opendaylight.yangtools.yang.model.util.SchemaInferenceStack; */ final class ChoiceGenerator extends CompositeSchemaTreeGenerator { static final class ChoiceBuilder extends CompositeRuntimeTypeBuilder { - private ImmutableList augmentedCases; + private final List augmentedCases = new ArrayList<>(); ChoiceBuilder(final ChoiceEffectiveStatement statement) { super(statement); } @Override - CompositeRuntimeTypeBuilder fillTypes( - final ChildLookup lookup, - final AbstractCompositeGenerator generator) { - fillAugmentedCases(lookup, generator.augments()); - return super.fillTypes(lookup, generator); + void processAugment(final AugmentResolver resolver, final AbstractAugmentGenerator augment) { + augment.fillRuntimeCasesIn(resolver, statement(), augmentedCases); } @Override - boolean isAugmentedChild(final ChildLookup lookup, final QName qname) { + boolean isAugmentedChild(final QName qname) { for (var augmented : augmentedCases) { if (qname.equals(augmented.statement().argument())) { return true; } } - return super.isAugmentedChild(lookup, qname); + return false; } @Override @@ -60,14 +57,6 @@ final class ChoiceGenerator extends CompositeSchemaTreeGenerator augments) { - final var builder = ImmutableList.builder(); - for (var augment : augments) { - builder.addAll(augment.augmentedCasesIn(lookup, statement())); - } - augmentedCases = builder.build(); - } } ChoiceGenerator(final ChoiceEffectiveStatement statement, final AbstractCompositeGenerator parent) { diff --git a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/CompositeRuntimeTypeBuilder.java b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/CompositeRuntimeTypeBuilder.java index 57af55851f..763f04ab94 100644 --- a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/CompositeRuntimeTypeBuilder.java +++ b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/CompositeRuntimeTypeBuilder.java @@ -15,7 +15,6 @@ 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; @@ -23,6 +22,8 @@ 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.AugmentEffectiveStatement; +import org.opendaylight.yangtools.yang.model.api.stmt.ModuleEffectiveStatement; import org.opendaylight.yangtools.yang.model.api.stmt.SchemaTreeEffectiveStatement; abstract class CompositeRuntimeTypeBuilder, R extends CompositeRuntimeType> { @@ -34,10 +35,24 @@ abstract class CompositeRuntimeTypeBuilder, R this.statement = requireNonNull(statement); } - final @NonNull S statement() { - return statement; + final CompositeRuntimeTypeBuilder populate(final AugmentResolver resolver, + final AbstractCompositeGenerator generator) { + resolver.enter(generator); + try { + processGenerator(resolver, generator); + } finally { + resolver.exit(); + } + return this; + } + + final @NonNull R build(final @NonNull GeneratedType generatedType) { + return build(generatedType, statement, childTypes, augmentTypes); } + abstract @NonNull R build(GeneratedType type, S statement, List children, + List augments); + final @NonNull List getCaseChilden() { return childTypes.stream() .map(child -> { @@ -47,27 +62,38 @@ abstract class CompositeRuntimeTypeBuilder, R .collect(Collectors.toUnmodifiableList()); } - final @NonNull R build(final @NonNull GeneratedType generatedType) { - return build(generatedType, statement, childTypes, augmentTypes); + final @NonNull S statement() { + return statement; } - abstract @NonNull R build(GeneratedType type, S statement, List children, - List augments); + boolean isAugmentedChild(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. + for (var augment : augmentTypes) { + if (augment.schemaTreeChild(qname) != null) { + return true; + } + } + return false; + } - CompositeRuntimeTypeBuilder fillTypes(final ChildLookup lookup, - final AbstractCompositeGenerator generator) { + void processAugment(final AugmentResolver resolver, final AbstractAugmentGenerator augment) { + augmentTypes.add(augment.runtimeTypeIn(resolver, statement)); + } + + private void processGenerator(final AugmentResolver resolver, final AbstractCompositeGenerator 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); + // Note we should not do this for 'module' and 'uses' statements, as those are not valid augment targets. Of + // those two we only generate things for 'module'. + if (!(statement instanceof ModuleEffectiveStatement)) { + for (var stmt : statement.effectiveSubstatements()) { + if (stmt instanceof AugmentEffectiveStatement) { + processAugment(resolver, resolver.getAugment((AugmentEffectiveStatement) stmt)); } } } @@ -76,69 +102,51 @@ abstract class CompositeRuntimeTypeBuilder, R 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 > @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); + // + // That is in general -- 'choice' statements are doing their own thing separately. + if (!isAugmentedChild(child.getIdentifier())) { + final var childGen = verifyNotNull(findChildGenerator(generator, child.argument().getLocalName()), + "Cannot find child for %s in %s", child, generator); + final var childRuntimeType = childGen.createInternalRuntimeType(resolver, child); + if (childRuntimeType != null) { + childTypes.add(childRuntimeType); + } } } - - // 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) { + // When we reach here we have dealt with all known augments in this scope, hence the only option is that the + // statement is either local or added via 'uses' -- in either case it has namespace equal to whatever the local + // namespace is and there can be no conflicts on QName.getLocalName(). That simplifies things a ton. + private static > AbstractExplicitGenerator findChildGenerator( + final AbstractCompositeGenerator parent, final String localName) { + // Search direct children first ... 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())) { + @SuppressWarnings("unchecked") + final AbstractExplicitGenerator gen = (AbstractExplicitGenerator) child; + final EffectiveStatement genStmt = gen.statement(); + if (genStmt instanceof SchemaTreeEffectiveStatement + && localName.equals(((SchemaTreeEffectiveStatement) genStmt).argument().getLocalName())) { return gen; } } } + + // ... and groupings recursively last + for (var grouping : parent.groupings()) { + final AbstractExplicitGenerator found = findChildGenerator(grouping, localName); + if (found != null) { + return found; + } + } + return null; } } diff --git a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/IdentityGenerator.java b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/IdentityGenerator.java index ccd88efc57..95e7db5dab 100644 --- a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/IdentityGenerator.java +++ b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/IdentityGenerator.java @@ -84,8 +84,8 @@ public final class IdentityGenerator } @Override - IdentityRuntimeType createInternalRuntimeType(final ChildLookup lookup, final IdentityEffectiveStatement statement, - final Type type) { + IdentityRuntimeType createInternalRuntimeType(final AugmentResolver resolver, + 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"); } diff --git a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/KeyGenerator.java b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/KeyGenerator.java index a45c1dcb35..d1c59d5e65 100644 --- a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/KeyGenerator.java +++ b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/KeyGenerator.java @@ -89,7 +89,7 @@ final class KeyGenerator extends AbstractExplicitGenerator target) { + final var augment = statement(); + final var stmts = augment.effectiveSubstatements(); + final var builder = ImmutableList.>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()); + } + @NonNull AugmentRequirement startLinkage(final GeneratorContext context) { return new AugmentRequirement(this, context.resolveModule(statement().argument().firstNodeIdentifier().getModule())); } diff --git a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/OpaqueObjectGenerator.java b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/OpaqueObjectGenerator.java index 2e7da2abbb..ce10cd1877 100644 --- a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/OpaqueObjectGenerator.java +++ b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/OpaqueObjectGenerator.java @@ -110,7 +110,7 @@ abstract class OpaqueObjectGenerator, R abstract @NonNull R createExternalRuntimeType(@NonNull GeneratedType type); @Override - final R createInternalRuntimeType(final ChildLookup lookup, final S statement, final Type type) { + final R createInternalRuntimeType(final AugmentResolver resolver, final S statement, final Type type) { verify(type instanceof GeneratedType, "Unexpected type %s", type); return createInternalRuntimeType(statement, (GeneratedType) type); } diff --git a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/TypedefGenerator.java b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/TypedefGenerator.java index e3cfd4d594..bcebb15b34 100644 --- a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/TypedefGenerator.java +++ b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/TypedefGenerator.java @@ -101,8 +101,8 @@ final class TypedefGenerator extends AbstractTypeObjectGenerator parent) { super(statement, parent); this.uses = requireNonNull(uses); - - // FIXME: use SchemaTreeAwareEffectiveStatement - var stmt = parent.statement(); - for (var qname : statement.argument().getNodeIdentifiers()) { - final var tmp = stmt; - stmt = stmt.streamEffectiveSubstatements(SchemaTreeEffectiveStatement.class) - .filter(child -> qname.equals(child.argument())) - .findFirst() - .orElseThrow(() -> new IllegalStateException("Failed to find " + qname + " in " + tmp)); - } - setTargetStatement(stmt); } void resolveGrouping(final UsesEffectiveStatement resolvedUses, final GroupingGenerator resolvedGrouping) { @@ -68,50 +54,28 @@ final class UsesAugmentGenerator extends AbstractAugmentGenerator { } @Override - List 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(); + boolean matchesInstantiated(final AugmentEffectiveStatement statement) { + return super.matchesInstantiated(statement) || declared(statement()).equals(declared(statement)); } - @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 AugmentStatement declared(final AugmentEffectiveStatement statement) { + // We are generating Augmentation interfaces on declared model, hence this is accurate + return verifyNotNull(statement.getDeclared(), " %s does not have a declared view", statement); } - private static @NonNull AugmentEffectiveStatement effectiveStatement(final AugmentEffectiveStatement augment, - final SchemaTreeAwareEffectiveStatement target) { + @Override + TargetAugmentEffectiveStatement effectiveIn(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 augment = statement(); final var stmts = augment.effectiveSubstatements(); final var builder = ImmutableList.>builderWithExpectedSize(stmts.size()); for (var stmt : stmts) { if (stmt instanceof SchemaTreeEffectiveStatement) { final var qname = ((SchemaTreeEffectiveStatement) stmt).getIdentifier().bindTo(targetNamespace); + // FIXME: orElseThrow()? target.get(SchemaTreeNamespace.class, qname).ifPresent(builder::add); } else { builder.add(stmt);