X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=binding%2Fmdsal-binding-generator%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fmdsal%2Fbinding%2Fgenerator%2Fimpl%2Freactor%2FAbstractCompositeGenerator.java;h=37918184d9472df5afb4cc504b2e9d8d13916e0a;hb=32fec636ad3113a3acc52d56410c5e1b90d647e0;hp=14889c53dd0642a6a34f7988564375a506ce72a6;hpb=73f9223a21ad3c7f42290af10f793723f5d10784;p=mdsal.git 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 14889c53dd..37918184d9 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 @@ -19,9 +19,12 @@ 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.CompositeRuntimeType; +import org.opendaylight.mdsal.binding.runtime.api.RuntimeType; +import org.opendaylight.yangtools.rfc8040.model.api.YangDataEffectiveStatement; import org.opendaylight.yangtools.yang.common.QName; import org.opendaylight.yangtools.yang.model.api.AddedByUsesAware; import org.opendaylight.yangtools.yang.model.api.CopyableNode; @@ -33,6 +36,7 @@ import org.opendaylight.yangtools.yang.model.api.stmt.AugmentEffectiveStatement; import org.opendaylight.yangtools.yang.model.api.stmt.CaseEffectiveStatement; import org.opendaylight.yangtools.yang.model.api.stmt.ChoiceEffectiveStatement; import org.opendaylight.yangtools.yang.model.api.stmt.ContainerEffectiveStatement; +import org.opendaylight.yangtools.yang.model.api.stmt.FeatureEffectiveStatement; import org.opendaylight.yangtools.yang.model.api.stmt.GroupingEffectiveStatement; import org.opendaylight.yangtools.yang.model.api.stmt.IdentityEffectiveStatement; import org.opendaylight.yangtools.yang.model.api.stmt.InputEffectiveStatement; @@ -53,56 +57,155 @@ import org.slf4j.LoggerFactory; * A composite generator. Composite generators may contain additional children, which end up being mapped into * the naming hierarchy 'under' the composite generator. To support this use case, each composite has a Java package * name assigned. + * + *

+ * State tracking for resolution of children to their original declaration, i.e. back along the 'uses' and 'augment' + * axis. This is quite convoluted because we are traversing the generator tree recursively in the iteration order of + * children, but actual dependencies may require resolution in a different order, for example in the case of: + *

+ *   container foo {
+ *     uses bar {             // A
+ *       augment bar {        // B
+ *         container xyzzy;   // C
+ *       }
+ *     }
+ *
+ *     grouping bar {
+ *       container bar {      // D
+ *         uses baz;          // E
+ *       }
+ *     }
+ *
+ *     grouping baz {
+ *       leaf baz {           // F
+ *         type string;
+ *       }
+ *     }
+ *   }
+ *
+ *   augment /foo/bar/xyzzy { // G
+ *     leaf xyzzy {           // H
+ *       type string;
+ *     }
+ *   }
+ * 
+ * + *

+ * In this case we have three manifestations of 'leaf baz' -- marked A, E and F in the child iteration order. In order + * to perform a resolution, we first have to determine that F is the original definition, then establish that E is using + * the definition made by F and finally establish that A is using the definition made by F. + * + *

+ * Dealing with augmentations is harder still, because we need to attach them to the original definition, hence for the + * /foo/bar container at A, we need to understand that its original definition is at D and we need to attach the augment + * at B to D. Futhermore we also need to establish that the augmentation at G attaches to container defined in C, so + * that the 'leaf xyzzy' existing as /foo/bar/xyzzy/xyzzy under C has its original definition at H. + * + *

+ * Finally realize that the augment at G can actually exist in a different module and is shown in this example only + * the simplified form. That also means we could encounter G well before 'container foo' as well as we can have multiple + * such augments sprinkled across multiple modules having the same dependency rules as between C and G -- but they still + * have to form a directed acyclic graph and we partially deal with those complexities by having modules sorted by their + * dependencies. + * + *

+ * For further details see {@link #linkOriginalGenerator()} and {@link #linkOriginalGeneratorRecursive()}, which deal + * with linking original instances in the tree iteration order. The part dealing with augment attachment lives mostly + * in {@link AugmentRequirement}. */ -abstract class AbstractCompositeGenerator> extends AbstractExplicitGenerator { +public abstract class AbstractCompositeGenerator, R extends CompositeRuntimeType> + extends AbstractExplicitGenerator { private static final Logger LOG = LoggerFactory.getLogger(AbstractCompositeGenerator.class); + // FIXME: we want to allocate this lazily to lower memory footprint private final @NonNull CollisionDomain domain = new CollisionDomain(this); - private final List children; + private final @NonNull List childGenerators; + + /** + * List of {@code augment} statements targeting this generator. This list is maintained only for the primary + * incarnation. This list is an evolving entity until after we have finished linkage of original statements. It is + * expected to be stable at the start of {@code step 2} in {@link GeneratorReactor#execute(TypeBuilderFactory)}. + */ + private @NonNull List augments = List.of(); - private List augments = List.of(); + /** + * List of {@code grouping} statements this statement references. This field is set once by + * {@link #linkUsesDependencies(GeneratorContext)}. + */ private List groupings; - AbstractCompositeGenerator(final T statement) { + /** + * List of composite children which have not been recursively processed. This may become a mutable list when we + * have some children which have not completed linking. Once we have completed linking of all children, including + * {@link #unlinkedChildren}, this will be set to {@code null}. + */ + private List> unlinkedComposites = List.of(); + /** + * List of children which have not had their original linked. This list starts of as null. When we first attempt + * linkage, it becomes non-null. + */ + private List unlinkedChildren; + + AbstractCompositeGenerator(final S statement) { super(statement); - children = createChildren(statement); + childGenerators = createChildren(statement); } - AbstractCompositeGenerator(final T statement, final AbstractCompositeGenerator parent) { + AbstractCompositeGenerator(final S statement, final AbstractCompositeGenerator parent) { super(statement, parent); - children = createChildren(statement); + childGenerators = createChildren(statement); } @Override public final Iterator iterator() { - return children.iterator(); + return childGenerators.iterator(); + } + + final @NonNull List augments() { + return augments; + } + + final @NonNull List groupings() { + return verifyNotNull(groupings, "Groupings not initialized in %s", this); + } + + @Override + final R createExternalRuntimeType(final Type type) { + return createBuilder(statement()).populate(new AugmentResolver(), this).build(verifyGeneratedType(type)); + } + + abstract @NonNull CompositeRuntimeTypeBuilder createBuilder(S statement); + + @Override + final R createInternalRuntimeType(final AugmentResolver resolver, final S statement, final Type type) { + return createBuilder(statement).populate(resolver, this).build(verifyGeneratedType(type)); } @Override final boolean isEmpty() { - return children.isEmpty(); + return childGenerators.isEmpty(); } - final @Nullable AbstractExplicitGenerator findGenerator(final List> stmtPath) { + final @Nullable AbstractExplicitGenerator findGenerator(final List> stmtPath) { return findGenerator(MatchStrategy.identity(), stmtPath, 0); } - final @Nullable AbstractExplicitGenerator findGenerator(final MatchStrategy childStrategy, + final @Nullable AbstractExplicitGenerator findGenerator(final MatchStrategy childStrategy, // TODO: Wouldn't this method be nicer with Deque> ? final List> stmtPath, final int offset) { - final EffectiveStatement stmt = stmtPath.get(offset); + final var stmt = stmtPath.get(offset); // Try direct children first, which is simple - AbstractExplicitGenerator ret = childStrategy.findGenerator(stmt, children); + var ret = childStrategy.findGenerator(stmt, childGenerators); if (ret != null) { final int next = offset + 1; if (stmtPath.size() == next) { // Final step, return child return ret; } - if (ret instanceof AbstractCompositeGenerator) { + if (ret instanceof AbstractCompositeGenerator composite) { // We know how to descend down - return ((AbstractCompositeGenerator) ret).findGenerator(childStrategy, stmtPath, next); + return composite.findGenerator(childStrategy, stmtPath, next); } // Yeah, don't know how to continue here return null; @@ -142,17 +245,20 @@ abstract class AbstractCompositeGenerator> ex final void linkUsesDependencies(final GeneratorContext context) { // We are establishing two linkages here: // - we are resolving 'uses' statements to their corresponding 'grouping' definitions - // - we propagate those groupings as anchors to any augment statements - final List tmp = new ArrayList<>(); - for (EffectiveStatement stmt : statement().effectiveSubstatements()) { - if (stmt instanceof UsesEffectiveStatement) { - final UsesEffectiveStatement uses = (UsesEffectiveStatement) stmt; - final GroupingGenerator grouping = context.resolveTreeScoped(GroupingGenerator.class, uses.argument()); + // - we propagate those groupings as anchors to any augment statements, which takes out some amount of guesswork + // from augment+uses resolution case, as groupings know about their immediate augments as soon as uses linkage + // is resolved + final var tmp = new ArrayList(); + for (var stmt : statement().effectiveSubstatements()) { + if (stmt instanceof UsesEffectiveStatement uses) { + final var grouping = context.resolveTreeScoped(GroupingGenerator.class, uses.argument()); tmp.add(grouping); + // Trigger resolution of uses/augment statements. This looks like guesswork, but there may be multiple + // 'augment' statements in a 'uses' statement and keeping a ListMultimap here seems wasteful. for (Generator gen : this) { - if (gen instanceof UsesAugmentGenerator) { - ((UsesAugmentGenerator) gen).linkGroupingDependency(uses, grouping); + if (gen instanceof UsesAugmentGenerator usesGen) { + usesGen.resolveGrouping(uses, grouping); } } } @@ -160,6 +266,17 @@ abstract class AbstractCompositeGenerator> ex groupings = List.copyOf(tmp); } + final void startUsesAugmentLinkage(final List requirements) { + for (var child : childGenerators) { + if (child instanceof UsesAugmentGenerator uses) { + requirements.add(uses.startLinkage()); + } + if (child instanceof AbstractCompositeGenerator composite) { + composite.startUsesAugmentLinkage(requirements); + } + } + } + final void addAugment(final AbstractAugmentGenerator augment) { if (augments.isEmpty()) { augments = new ArrayList<>(2); @@ -167,45 +284,140 @@ abstract class AbstractCompositeGenerator> ex augments.add(requireNonNull(augment)); } + /** + * Attempt to link the generator corresponding to the original definition for this generator's statements as well as + * to all child generators. + * + * @return Progress indication + */ + final @NonNull LinkageProgress linkOriginalGeneratorRecursive() { + if (unlinkedComposites == null) { + // We have unset this list (see below), and there is nothing left to do + return LinkageProgress.DONE; + } + + if (unlinkedChildren == null) { + unlinkedChildren = childGenerators.stream() + .filter(AbstractExplicitGenerator.class::isInstance) + .map(child -> (AbstractExplicitGenerator) child) + .collect(Collectors.toList()); + } + + var progress = LinkageProgress.NONE; + if (!unlinkedChildren.isEmpty()) { + // Attempt to make progress on child linkage + final var it = unlinkedChildren.iterator(); + while (it.hasNext()) { + if (it.next() instanceof AbstractExplicitGenerator explicit && explicit.linkOriginalGenerator()) { + progress = LinkageProgress.SOME; + it.remove(); + + // If this is a composite generator we need to process is further + if (explicit instanceof AbstractCompositeGenerator composite) { + if (unlinkedComposites.isEmpty()) { + unlinkedComposites = new ArrayList<>(); + } + unlinkedComposites.add(composite); + } + } + } + + if (unlinkedChildren.isEmpty()) { + // Nothing left to do, make sure any previously-allocated list can be scavenged + unlinkedChildren = List.of(); + } + } + + // Process children of any composite children we have. + final var it = unlinkedComposites.iterator(); + while (it.hasNext()) { + final var tmp = it.next().linkOriginalGeneratorRecursive(); + if (tmp != LinkageProgress.NONE) { + progress = LinkageProgress.SOME; + } + if (tmp == LinkageProgress.DONE) { + it.remove(); + } + } + + if (unlinkedChildren.isEmpty() && unlinkedComposites.isEmpty()) { + // All done, set the list to null to indicate there is nothing left to do in this generator or any of our + // children. + unlinkedComposites = null; + return LinkageProgress.DONE; + } + + return progress; + } + + @Override + final AbstractCompositeGenerator getOriginal() { + return (AbstractCompositeGenerator) super.getOriginal(); + } + @Override - final AbstractCompositeGenerator getOriginal() { - return (AbstractCompositeGenerator) super.getOriginal(); + final AbstractCompositeGenerator tryOriginal() { + return (AbstractCompositeGenerator) super.tryOriginal(); } - final @NonNull AbstractExplicitGenerator getOriginalChild(final QName childQName) { + final , Y extends RuntimeType> @Nullable OriginalLink originalChild( + final QName childQName) { // First try groupings/augments ... - final AbstractExplicitGenerator found = findInferredGenerator(childQName); + var found = findInferredGenerator(childQName); if (found != null) { - return found; + return (OriginalLink) OriginalLink.partial(found); } // ... no luck, we really need to start looking at our origin - final AbstractExplicitGenerator prev = verifyNotNull(previous(), - "Failed to find %s in scope of %s", childQName, this); + final var prev = previous(); + if (prev != null) { + final QName prevQName = childQName.bindTo(prev.getQName().getModule()); + found = prev.findSchemaTreeGenerator(prevQName); + if (found != null) { + return (OriginalLink) found.originalLink(); + } + } - final QName prevQName = childQName.bindTo(prev.getQName().getModule()); - return verifyNotNull(prev.findSchemaTreeGenerator(prevQName), - "Failed to find child %s (proxy for %s) in %s", prevQName, childQName, prev).getOriginal(); + return null; } @Override - final @Nullable AbstractExplicitGenerator findSchemaTreeGenerator(final QName qname) { - final AbstractExplicitGenerator found = super.findSchemaTreeGenerator(qname); + final AbstractExplicitGenerator findSchemaTreeGenerator(final QName qname) { + final var found = super.findSchemaTreeGenerator(qname); return found != null ? found : findInferredGenerator(qname); } - private @Nullable AbstractExplicitGenerator findInferredGenerator(final QName qname) { + final @Nullable AbstractAugmentGenerator findAugmentForGenerator(final QName qname) { + for (var augment : augments) { + final var gen = augment.findSchemaTreeGenerator(qname); + if (gen != null) { + return augment; + } + } + return null; + } + + final @Nullable GroupingGenerator findGroupingForGenerator(final QName qname) { + for (var grouping : groupings) { + final var gen = grouping.findSchemaTreeGenerator(qname.bindTo(grouping.statement().argument().getModule())); + if (gen != null) { + return grouping; + } + } + return null; + } + + private @Nullable AbstractExplicitGenerator findInferredGenerator(final QName qname) { // First search our local groupings ... - for (GroupingGenerator grouping : groupings) { - final AbstractExplicitGenerator gen = grouping.findSchemaTreeGenerator( - qname.bindTo(grouping.statement().argument().getModule())); + for (var grouping : groupings) { + final var gen = grouping.findSchemaTreeGenerator(qname.bindTo(grouping.statement().argument().getModule())); if (gen != null) { return gen; } } // ... next try local augments, which may have groupings themselves - for (AbstractAugmentGenerator augment : augments) { - final AbstractExplicitGenerator gen = augment.findSchemaTreeGenerator(qname); + for (var augment : augments) { + final var gen = augment.findSchemaTreeGenerator(qname); if (gen != null) { return gen; } @@ -222,7 +434,7 @@ abstract class AbstractCompositeGenerator> ex * @return The number of groupings this type uses. */ final int addUsesInterfaces(final GeneratedTypeBuilder builder, final TypeBuilderFactory builderFactory) { - for (GroupingGenerator grp : groupings) { + for (var grp : groupings) { builder.addImplementsType(grp.getGeneratedType(builderFactory)); } return groupings.size(); @@ -233,152 +445,146 @@ abstract class AbstractCompositeGenerator> ex } final void addGetterMethods(final GeneratedTypeBuilder builder, final TypeBuilderFactory builderFactory) { - for (Generator child : this) { + for (var child : this) { // Only process explicit generators here - if (child instanceof AbstractExplicitGenerator) { - ((AbstractExplicitGenerator) child).addAsGetterMethod(builder, builderFactory); + if (child instanceof AbstractExplicitGenerator explicit) { + explicit.addAsGetterMethod(builder, builderFactory); } - final GeneratedType enclosedType = child.enclosedType(builderFactory); - if (enclosedType instanceof GeneratedTransferObject) { - builder.addEnclosingTransferObject((GeneratedTransferObject) enclosedType); - } else if (enclosedType instanceof Enumeration) { - builder.addEnumeration((Enumeration) enclosedType); + final var enclosedType = child.enclosedType(builderFactory); + if (enclosedType instanceof GeneratedTransferObject gto) { + builder.addEnclosingTransferObject(gto); + } else if (enclosedType instanceof Enumeration enumeration) { + builder.addEnumeration(enumeration); } else { verify(enclosedType == null, "Unhandled enclosed type %s in %s", enclosedType, child); } } } - private List createChildren(final EffectiveStatement statement) { - final List tmp = new ArrayList<>(); - final List tmpAug = new ArrayList<>(); + private @NonNull List createChildren(final EffectiveStatement statement) { + final var tmp = new ArrayList(); + final var tmpAug = new ArrayList(); - for (EffectiveStatement stmt : statement.effectiveSubstatements()) { - if (stmt instanceof ActionEffectiveStatement) { - if (!isAugmenting(stmt)) { - tmp.add(new ActionGenerator((ActionEffectiveStatement) stmt, this)); + for (var stmt : statement.effectiveSubstatements()) { + if (stmt instanceof ActionEffectiveStatement action) { + if (!isAugmenting(action)) { + tmp.add(new ActionGenerator(action, this)); } - } else if (stmt instanceof AnydataEffectiveStatement) { - if (!isAugmenting(stmt)) { - tmp.add(new OpaqueObjectGenerator<>((AnydataEffectiveStatement) stmt, this)); + } else if (stmt instanceof AnydataEffectiveStatement anydata) { + if (!isAugmenting(anydata)) { + tmp.add(new OpaqueObjectGenerator.Anydata(anydata, this)); } - } else if (stmt instanceof AnyxmlEffectiveStatement) { - if (!isAugmenting(stmt)) { - tmp.add(new OpaqueObjectGenerator<>((AnyxmlEffectiveStatement) stmt, this)); + } else if (stmt instanceof AnyxmlEffectiveStatement anyxml) { + if (!isAugmenting(anyxml)) { + tmp.add(new OpaqueObjectGenerator.Anyxml(anyxml, this)); } - } else if (stmt instanceof CaseEffectiveStatement) { - tmp.add(new CaseGenerator((CaseEffectiveStatement) stmt, this)); - } else if (stmt instanceof ChoiceEffectiveStatement) { + } else if (stmt instanceof CaseEffectiveStatement cast) { + tmp.add(new CaseGenerator(cast, this)); + } else if (stmt instanceof ChoiceEffectiveStatement choice) { // FIXME: use isOriginalDeclaration() ? - if (!isAddedByUses(stmt)) { - tmp.add(new ChoiceGenerator((ChoiceEffectiveStatement) stmt, this)); + if (!isAddedByUses(choice)) { + tmp.add(new ChoiceGenerator(choice, this)); } - } else if (stmt instanceof ContainerEffectiveStatement) { - if (isOriginalDeclaration(stmt)) { - tmp.add(new ContainerGenerator((ContainerEffectiveStatement) stmt, this)); + } else if (stmt instanceof ContainerEffectiveStatement container) { + if (isOriginalDeclaration(container)) { + tmp.add(new ContainerGenerator(container, this)); } - } else if (stmt instanceof GroupingEffectiveStatement) { - tmp.add(new GroupingGenerator((GroupingEffectiveStatement) stmt, this)); - } else if (stmt instanceof IdentityEffectiveStatement) { - tmp.add(new IdentityGenerator((IdentityEffectiveStatement) stmt, this)); - } else if (stmt instanceof InputEffectiveStatement) { - // FIXME: do not generate legacy RPC layout - tmp.add(this instanceof RpcGenerator ? new RpcContainerGenerator((InputEffectiveStatement) stmt, this) - : new OperationContainerGenerator((InputEffectiveStatement) stmt, this)); - } else if (stmt instanceof LeafEffectiveStatement) { - if (!isAugmenting(stmt)) { - tmp.add(new LeafGenerator((LeafEffectiveStatement) stmt, this)); + } else if (stmt instanceof FeatureEffectiveStatement feature && this instanceof ModuleGenerator parent) { + tmp.add(new FeatureGenerator(feature, parent)); + } else if (stmt instanceof GroupingEffectiveStatement grouping) { + tmp.add(new GroupingGenerator(grouping, this)); + } else if (stmt instanceof IdentityEffectiveStatement identity) { + tmp.add(new IdentityGenerator(identity, this)); + } else if (stmt instanceof InputEffectiveStatement input) { + tmp.add(new InputGenerator(input, this)); + } else if (stmt instanceof LeafEffectiveStatement leaf) { + if (!isAugmenting(leaf)) { + tmp.add(new LeafGenerator(leaf, this)); } - } else if (stmt instanceof LeafListEffectiveStatement) { - if (!isAugmenting(stmt)) { - tmp.add(new LeafListGenerator((LeafListEffectiveStatement) stmt, this)); + } else if (stmt instanceof LeafListEffectiveStatement leafList) { + if (!isAugmenting(leafList)) { + tmp.add(new LeafListGenerator(leafList, this)); } - } else if (stmt instanceof ListEffectiveStatement) { - if (isOriginalDeclaration(stmt)) { - final ListGenerator listGen = new ListGenerator((ListEffectiveStatement) stmt, this); + } else if (stmt instanceof ListEffectiveStatement list) { + if (isOriginalDeclaration(list)) { + final var listGen = new ListGenerator(list, this); tmp.add(listGen); - final KeyGenerator keyGen = listGen.keyGenerator(); + final var keyGen = listGen.keyGenerator(); if (keyGen != null) { tmp.add(keyGen); } } - } else if (stmt instanceof NotificationEffectiveStatement) { - if (!isAugmenting(stmt)) { - tmp.add(new NotificationGenerator((NotificationEffectiveStatement) stmt, this)); + } else if (stmt instanceof NotificationEffectiveStatement notification) { + if (!isAugmenting(notification)) { + tmp.add(new NotificationGenerator(notification, this)); } - } else if (stmt instanceof OutputEffectiveStatement) { - // FIXME: do not generate legacy RPC layout - tmp.add(this instanceof RpcGenerator ? new RpcContainerGenerator((OutputEffectiveStatement) stmt, this) - : new OperationContainerGenerator((OutputEffectiveStatement) stmt, this)); - } else if (stmt instanceof RpcEffectiveStatement) { - tmp.add(new RpcGenerator((RpcEffectiveStatement) stmt, this)); - } else if (stmt instanceof TypedefEffectiveStatement) { - tmp.add(new TypedefGenerator((TypedefEffectiveStatement) stmt, this)); - } else if (stmt instanceof AugmentEffectiveStatement) { - if (this instanceof ModuleGenerator) { - tmpAug.add(new ModuleAugmentGenerator((AugmentEffectiveStatement) stmt, this)); + } else if (stmt instanceof OutputEffectiveStatement output) { + tmp.add(new OutputGenerator(output, this)); + } else if (stmt instanceof RpcEffectiveStatement rpc) { + if (this instanceof ModuleGenerator module) { + tmp.add(new RpcGenerator(rpc, module)); } - } else if (stmt instanceof UsesEffectiveStatement) { - final UsesEffectiveStatement uses = (UsesEffectiveStatement) stmt; - for (EffectiveStatement usesSub : uses.effectiveSubstatements()) { - if (usesSub instanceof AugmentEffectiveStatement) { - tmpAug.add(new UsesAugmentGenerator((AugmentEffectiveStatement) usesSub, this, uses)); + } else if (stmt instanceof TypedefEffectiveStatement typedef) { + tmp.add(new TypedefGenerator(typedef, this)); + } else if (stmt instanceof AugmentEffectiveStatement augment) { + // FIXME: MDSAL-695: So here we are ignoring any augment which is not in a module, while the 'uses' + // processing takes care of the rest. There are two problems here: + // + // 1) this could be an augment introduced through uses -- in this case we are picking + // confusing it with this being its declaration site, we should probably be + // ignoring it, but then + // + // 2) we are losing track of AugmentEffectiveStatement for which we do not generate + // interfaces -- and recover it at runtime through explicit walk along the + // corresponding AugmentationSchemaNode.getOriginalDefinition() pointer + // + // So here is where we should decide how to handle this augment, and make sure we + // retain information about this being an alias. That will serve as the base for keys + // in the augment -> original map we provide to BindingRuntimeTypes. + if (this instanceof ModuleGenerator module) { + tmpAug.add(new ModuleAugmentGenerator(augment, module)); + } + } else if (stmt instanceof UsesEffectiveStatement uses) { + for (var usesSub : uses.effectiveSubstatements()) { + if (usesSub instanceof AugmentEffectiveStatement usesAug) { + tmpAug.add(new UsesAugmentGenerator(usesAug, uses, this)); } } + } else if (stmt instanceof YangDataEffectiveStatement yangData) { + if (this instanceof ModuleGenerator moduleGen) { + tmp.add(YangDataGenerator.of(yangData, moduleGen)); + } } else { LOG.trace("Ignoring statement {}", stmt); - continue; } } // Sort augments and add them last. This ensures child iteration order always reflects potential - // interdependencies, hence we do not need to worry about them. + // interdependencies, hence we do not need to worry about them. This is extremely important, as there are a + // number of places where we would have to either move the logic to parent statement and explicitly filter/sort + // substatements to establish this order. tmpAug.sort(AbstractAugmentGenerator.COMPARATOR); tmp.addAll(tmpAug); - - // Compatibility FooService and FooListener interfaces, only generated for modules. - if (this instanceof ModuleGenerator) { - final ModuleGenerator moduleGen = (ModuleGenerator) this; - - final List notifs = tmp.stream() - .filter(NotificationGenerator.class::isInstance) - .map(NotificationGenerator.class::cast) - .collect(Collectors.toUnmodifiableList()); - if (!notifs.isEmpty()) { - tmp.add(new NotificationServiceGenerator(moduleGen, notifs)); - } - - final List rpcs = tmp.stream() - .filter(RpcGenerator.class::isInstance) - .map(RpcGenerator.class::cast) - .collect(Collectors.toUnmodifiableList()); - if (!rpcs.isEmpty()) { - tmp.add(new RpcServiceGenerator(moduleGen, rpcs)); - } - } - return List.copyOf(tmp); } // Utility equivalent of (!isAddedByUses(stmt) && !isAugmenting(stmt)). Takes advantage of relationship between // CopyableNode and AddedByUsesAware private static boolean isOriginalDeclaration(final EffectiveStatement stmt) { - if (stmt instanceof AddedByUsesAware) { - if (((AddedByUsesAware) stmt).isAddedByUses() - || stmt instanceof CopyableNode && ((CopyableNode) stmt).isAugmenting()) { - return false; - } + if (stmt instanceof AddedByUsesAware aware + && (aware.isAddedByUses() || stmt instanceof CopyableNode copyable && copyable.isAugmenting())) { + return false; } return true; } private static boolean isAddedByUses(final EffectiveStatement stmt) { - return stmt instanceof AddedByUsesAware && ((AddedByUsesAware) stmt).isAddedByUses(); + return stmt instanceof AddedByUsesAware aware && aware.isAddedByUses(); } private static boolean isAugmenting(final EffectiveStatement stmt) { - return stmt instanceof CopyableNode && ((CopyableNode) stmt).isAugmenting(); + return stmt instanceof CopyableNode copyable && copyable.isAugmenting(); } }