From feaecf128a14832eec9661057af4de6b3704a07f Mon Sep 17 00:00:00 2001 From: Robert Varga Date: Fri, 18 Feb 2022 11:49:16 +0100 Subject: [PATCH] Track schema tree generator linkage Runtime information requires looking up target generator for a schema tree particant, which means that AbstractCompositeGenerator needs to resolve QName to the original instantiation. We already have that mechanics for the most part, as we need to perform the lookup to resolve augment statements target. Introduce SchemaTree{Child,Parent} decomposition of the addressing problem, and retrofit generators to support them. This will allow us to support lookups along the schema tree axis. JIRA: MDSAL-696 Change-Id: I619fe9e7c0896d6d3f0f33b04d5200ca8ec30340 Signed-off-by: Robert Varga --- .../reactor/AbstractCompositeGenerator.java | 117 +++++++++++++----- .../reactor/AbstractTypeAwareGenerator.java | 16 ++- .../impl/reactor/ActionGenerator.java | 2 +- .../generator/impl/reactor/CaseGenerator.java | 2 +- .../impl/reactor/ChoiceGenerator.java | 2 +- .../reactor/CompositeSchemaTreeGenerator.java | 28 +++++ .../impl/reactor/ContainerGenerator.java | 2 +- .../impl/reactor/GeneratorReactor.java | 14 +-- .../generator/impl/reactor/LeafGenerator.java | 2 +- .../impl/reactor/LeafListGenerator.java | 2 +- .../generator/impl/reactor/ListGenerator.java | 2 +- .../impl/reactor/NotificationGenerator.java | 3 +- .../impl/reactor/OpaqueObjectGenerator.java | 9 +- .../reactor/OperationContainerGenerator.java | 3 +- .../generator/impl/reactor/RpcGenerator.java | 2 +- .../impl/reactor/SchemaTreePlaceholder.java | 55 ++++++++ .../generator/impl/tree/SchemaTreeChild.java | 45 +++++++ .../generator/impl/tree/SchemaTreeParent.java | 27 ++++ .../generator/impl/tree/package-info.java | 11 ++ 19 files changed, 292 insertions(+), 52 deletions(-) create mode 100644 binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/CompositeSchemaTreeGenerator.java create mode 100644 binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/SchemaTreePlaceholder.java create mode 100644 binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/tree/SchemaTreeChild.java create mode 100644 binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/tree/SchemaTreeParent.java create mode 100644 binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/tree/package-info.java 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 450dab4e2e..d4ed8314b0 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 @@ -13,9 +13,13 @@ import static java.util.Objects.requireNonNull; import java.util.ArrayList; import java.util.Iterator; import java.util.List; +import java.util.Map; +import java.util.Map.Entry; import java.util.stream.Collectors; import org.eclipse.jdt.annotation.NonNull; import org.eclipse.jdt.annotation.Nullable; +import org.opendaylight.mdsal.binding.generator.impl.tree.SchemaTreeChild; +import org.opendaylight.mdsal.binding.generator.impl.tree.SchemaTreeParent; import org.opendaylight.mdsal.binding.model.api.Enumeration; import org.opendaylight.mdsal.binding.model.api.GeneratedTransferObject; import org.opendaylight.mdsal.binding.model.api.GeneratedType; @@ -108,12 +112,17 @@ import org.slf4j.LoggerFactory; * 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> + extends AbstractExplicitGenerator implements SchemaTreeParent { 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; + /** + * {@link SchemaTreeChild} children of this generator. Generator linkage is ensured on first access. + */ + private final @NonNull List> schemaTreeChildren; /** * List of {@code augment} statements targeting this generator. This list is maintained only for the primary @@ -142,22 +151,38 @@ abstract class AbstractCompositeGenerator> ex AbstractCompositeGenerator(final T statement) { super(statement); - children = createChildren(statement); + + final var children = createChildren(statement); + childGenerators = children.getKey(); + schemaTreeChildren = children.getValue(); } AbstractCompositeGenerator(final T statement, final AbstractCompositeGenerator parent) { super(statement, parent); - children = createChildren(statement); + + final var children = createChildren(statement); + childGenerators = children.getKey(); + schemaTreeChildren = children.getValue(); } @Override public final Iterator iterator() { - return children.iterator(); + return childGenerators.iterator(); + } + + @Override + public List> schemaTreeChildren() { + for (var child : schemaTreeChildren) { + if (child instanceof SchemaTreePlaceholder) { + ((SchemaTreePlaceholder) child).setGenerator(this); + } + } + return schemaTreeChildren; } @Override final boolean isEmpty() { - return children.isEmpty(); + return childGenerators.isEmpty(); } final @Nullable AbstractExplicitGenerator findGenerator(final List> stmtPath) { @@ -170,7 +195,7 @@ abstract class AbstractCompositeGenerator> ex final EffectiveStatement stmt = stmtPath.get(offset); // Try direct children first, which is simple - AbstractExplicitGenerator ret = childStrategy.findGenerator(stmt, children); + AbstractExplicitGenerator ret = childStrategy.findGenerator(stmt, childGenerators); if (ret != null) { final int next = offset + 1; if (stmtPath.size() == next) { @@ -242,7 +267,7 @@ abstract class AbstractCompositeGenerator> ex } final void startUsesAugmentLinkage(final List requirements) { - for (Generator child : children) { + for (Generator child : childGenerators) { if (child instanceof UsesAugmentGenerator) { requirements.add(((UsesAugmentGenerator) child).startLinkage()); } @@ -272,7 +297,7 @@ abstract class AbstractCompositeGenerator> ex } if (unlinkedChildren == null) { - unlinkedChildren = children.stream() + unlinkedChildren = childGenerators.stream() .filter(AbstractExplicitGenerator.class::isInstance) .map(child -> (AbstractExplicitGenerator) child) .collect(Collectors.toList()); @@ -439,33 +464,50 @@ abstract class AbstractCompositeGenerator> ex } } - private List createChildren(final EffectiveStatement statement) { - final List tmp = new ArrayList<>(); - final List tmpAug = new ArrayList<>(); + private Entry, List>> createChildren( + final EffectiveStatement statement) { + final var tmp = new ArrayList(); + final var tmpAug = new ArrayList(); + final var tmpSchema = new ArrayList>(); - for (EffectiveStatement stmt : statement.effectiveSubstatements()) { + for (var stmt : statement.effectiveSubstatements()) { if (stmt instanceof ActionEffectiveStatement) { - if (!isAugmenting(stmt)) { - tmp.add(new ActionGenerator((ActionEffectiveStatement) stmt, this)); + final var cast = (ActionEffectiveStatement) stmt; + if (isAugmenting(cast)) { + tmpSchema.add(new SchemaTreePlaceholder<>(cast, ActionGenerator.class)); + } else { + tmp.add(new ActionGenerator(cast, this)); } } else if (stmt instanceof AnydataEffectiveStatement) { - if (!isAugmenting(stmt)) { - tmp.add(new OpaqueObjectGenerator<>((AnydataEffectiveStatement) stmt, this)); + final var cast = (AnydataEffectiveStatement) stmt; + if (isAugmenting(stmt)) { + tmpSchema.add(new SchemaTreePlaceholder<>(cast, OpaqueObjectGenerator.class)); + } else { + tmp.add(new OpaqueObjectGenerator<>(cast, this)); } } else if (stmt instanceof AnyxmlEffectiveStatement) { - if (!isAugmenting(stmt)) { - tmp.add(new OpaqueObjectGenerator<>((AnyxmlEffectiveStatement) stmt, this)); + final var cast = (AnyxmlEffectiveStatement) stmt; + if (isAugmenting(stmt)) { + tmpSchema.add(new SchemaTreePlaceholder<>(cast, OpaqueObjectGenerator.class)); + } else { + tmp.add(new OpaqueObjectGenerator<>(cast, this)); } } else if (stmt instanceof CaseEffectiveStatement) { tmp.add(new CaseGenerator((CaseEffectiveStatement) stmt, this)); } else if (stmt instanceof ChoiceEffectiveStatement) { + final var cast = (ChoiceEffectiveStatement) stmt; // FIXME: use isOriginalDeclaration() ? - if (!isAddedByUses(stmt)) { - tmp.add(new ChoiceGenerator((ChoiceEffectiveStatement) stmt, this)); + if (isAddedByUses(stmt)) { + tmpSchema.add(new SchemaTreePlaceholder<>(cast, ChoiceGenerator.class)); + } else { + tmp.add(new ChoiceGenerator(cast, this)); } } else if (stmt instanceof ContainerEffectiveStatement) { + final var cast = (ContainerEffectiveStatement) stmt; if (isOriginalDeclaration(stmt)) { tmp.add(new ContainerGenerator((ContainerEffectiveStatement) stmt, this)); + } else { + tmpSchema.add(new SchemaTreePlaceholder<>(cast, ContainerGenerator.class)); } } else if (stmt instanceof GroupingEffectiveStatement) { tmp.add(new GroupingGenerator((GroupingEffectiveStatement) stmt, this)); @@ -476,26 +518,38 @@ abstract class AbstractCompositeGenerator> ex 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)); + final var cast = (LeafEffectiveStatement) stmt; + if (isAugmenting(stmt)) { + tmpSchema.add(new SchemaTreePlaceholder<>(cast, LeafGenerator.class)); + } else { + tmp.add(new LeafGenerator(cast, this)); } } else if (stmt instanceof LeafListEffectiveStatement) { - if (!isAugmenting(stmt)) { + final var cast = (LeafListEffectiveStatement) stmt; + if (isAugmenting(stmt)) { + tmpSchema.add(new SchemaTreePlaceholder<>(cast, LeafListGenerator.class)); + } else { tmp.add(new LeafListGenerator((LeafListEffectiveStatement) stmt, this)); } } else if (stmt instanceof ListEffectiveStatement) { + final var cast = (ListEffectiveStatement) stmt; if (isOriginalDeclaration(stmt)) { - final ListGenerator listGen = new ListGenerator((ListEffectiveStatement) stmt, this); + final ListGenerator listGen = new ListGenerator(cast, this); tmp.add(listGen); final KeyGenerator keyGen = listGen.keyGenerator(); if (keyGen != null) { tmp.add(keyGen); } + } else { + tmpSchema.add(new SchemaTreePlaceholder<>(cast, ListGenerator.class)); } } else if (stmt instanceof NotificationEffectiveStatement) { - if (!isAugmenting(stmt)) { - tmp.add(new NotificationGenerator((NotificationEffectiveStatement) stmt, this)); + final var cast = (NotificationEffectiveStatement) stmt; + if (isAugmenting(stmt)) { + tmpSchema.add(new SchemaTreePlaceholder<>(cast, NotificationGenerator.class)); + } else { + tmp.add(new NotificationGenerator(cast, this)); } } else if (stmt instanceof OutputEffectiveStatement) { // FIXME: do not generate legacy RPC layout @@ -535,6 +589,13 @@ abstract class AbstractCompositeGenerator> ex } } + // Add any SchemaTreeChild generators to the list + for (var child : tmp) { + if (child instanceof SchemaTreeChild) { + tmpSchema.add((SchemaTreeChild) child); + } + } + // Sort augments and add them last. This ensures child iteration order always reflects potential // interdependencies, hence we do not need to worry about them. This is extremely important, as there are a // number of places where we would have to either move the logic to parent statement and explicitly filter/sort @@ -563,7 +624,7 @@ abstract class AbstractCompositeGenerator> ex } } - return List.copyOf(tmp); + return Map.entry(List.copyOf(tmp), List.copyOf(tmpSchema)); } // Utility equivalent of (!isAddedByUses(stmt) && !isAugmenting(stmt)). Takes advantage of relationship between diff --git a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/AbstractTypeAwareGenerator.java b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/AbstractTypeAwareGenerator.java index 6c0e9a3460..a93efef124 100644 --- a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/AbstractTypeAwareGenerator.java +++ b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/AbstractTypeAwareGenerator.java @@ -9,6 +9,7 @@ package org.opendaylight.mdsal.binding.generator.impl.reactor; import static com.google.common.base.Verify.verify; +import org.opendaylight.mdsal.binding.generator.impl.tree.SchemaTreeChild; import org.opendaylight.mdsal.binding.model.api.GeneratedTransferObject; import org.opendaylight.mdsal.binding.model.api.JavaTypeName; import org.opendaylight.mdsal.binding.model.api.Type; @@ -21,16 +22,13 @@ import org.opendaylight.yangtools.yang.model.api.TypeDefinition; import org.opendaylight.yangtools.yang.model.api.TypedDataSchemaNode; import org.opendaylight.yangtools.yang.model.api.stmt.DataTreeEffectiveStatement; import org.opendaylight.yangtools.yang.model.util.SchemaInferenceStack; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; /** * Common base class for {@link LeafGenerator} and {@link LeafListGenerator}. */ -abstract class AbstractTypeAwareGenerator> - extends AbstractTypeObjectGenerator { - private static final Logger LOG = LoggerFactory.getLogger(AbstractTypeAwareGenerator.class); - +abstract class AbstractTypeAwareGenerator, + G extends AbstractTypeAwareGenerator> + extends AbstractTypeObjectGenerator implements SchemaTreeChild { private IdentityGenerator contextType; AbstractTypeAwareGenerator(final T statement, final AbstractCompositeGenerator parent) { @@ -38,6 +36,12 @@ abstract class AbstractTypeAwareGenerator { +final class ActionGenerator extends CompositeSchemaTreeGenerator { ActionGenerator(final ActionEffectiveStatement statement, final AbstractCompositeGenerator parent) { super(statement, parent); } diff --git a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/CaseGenerator.java b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/CaseGenerator.java index ab7c79e863..84a29c0a85 100644 --- a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/CaseGenerator.java +++ b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/CaseGenerator.java @@ -18,7 +18,7 @@ import org.opendaylight.yangtools.yang.model.util.SchemaInferenceStack; /** * Generator corresponding to a {@code case} statement. */ -final class CaseGenerator extends AbstractCompositeGenerator { +final class CaseGenerator extends CompositeSchemaTreeGenerator { CaseGenerator(final CaseEffectiveStatement statement, final AbstractCompositeGenerator parent) { super(statement, parent); } 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 e43e2eff51..c45a099857 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 @@ -17,7 +17,7 @@ import org.opendaylight.yangtools.yang.model.util.SchemaInferenceStack; /** * Generator corresponding to a {@code choice} statement. */ -final class ChoiceGenerator extends AbstractCompositeGenerator { +final class ChoiceGenerator extends CompositeSchemaTreeGenerator { ChoiceGenerator(final ChoiceEffectiveStatement statement, final AbstractCompositeGenerator parent) { super(statement, parent); } diff --git a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/CompositeSchemaTreeGenerator.java b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/CompositeSchemaTreeGenerator.java new file mode 100644 index 0000000000..c92707d774 --- /dev/null +++ b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/CompositeSchemaTreeGenerator.java @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2022 PANTHEON.tech, s.r.o. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.mdsal.binding.generator.impl.reactor; + +import org.opendaylight.mdsal.binding.generator.impl.tree.SchemaTreeChild; +import org.opendaylight.yangtools.yang.model.api.stmt.SchemaTreeEffectiveStatement; + +/** + * Abstract base class for {@link AbstractCompositeGenerator}s which are also {@link SchemaTreeChild}ren. + */ +abstract class CompositeSchemaTreeGenerator, + G extends CompositeSchemaTreeGenerator> + extends AbstractCompositeGenerator implements SchemaTreeChild { + CompositeSchemaTreeGenerator(final S statement, final AbstractCompositeGenerator parent) { + super(statement, parent); + } + + @Override + @SuppressWarnings("unchecked") + public final G generator() { + return (G) this; + } +} diff --git a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/ContainerGenerator.java b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/ContainerGenerator.java index b2d490ca7c..cd2752f1ae 100644 --- a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/ContainerGenerator.java +++ b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/ContainerGenerator.java @@ -15,7 +15,7 @@ import org.opendaylight.yangtools.yang.model.util.SchemaInferenceStack; /** * Generator corresponding to a {@code container} statement. */ -final class ContainerGenerator extends AbstractCompositeGenerator { +final class ContainerGenerator extends CompositeSchemaTreeGenerator { ContainerGenerator(final ContainerEffectiveStatement statement, final AbstractCompositeGenerator parent) { super(statement, parent); } diff --git a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/GeneratorReactor.java b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/GeneratorReactor.java index 8a8feed099..f8214ad144 100644 --- a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/GeneratorReactor.java +++ b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/GeneratorReactor.java @@ -145,9 +145,9 @@ public final class GeneratorReactor extends GeneratorContext implements Mutable } LOG.trace("Processing linkage of {} augment generators", augments.size()); - // Step 1c: ... finally establish linkage along the reverse uses/augment axis. This is needed to route generated - // type manifestations (isAddedByUses/isAugmenting) to their type generation sites. Since generator - // tree iteration order does not match dependencies, we may need to perform multiple passes. + // Step 1c: Establish linkage along the reverse uses/augment axis. This is needed to route generated type + // manifestations (isAddedByUses/isAugmenting) to their type generation sites. Since generator tree + // iteration order does not match dependencies, we may need to perform multiple passes. for (ModuleGenerator module : children) { verify(module.linkOriginalGenerator(), "Module %s failed to link", module); } @@ -319,7 +319,7 @@ public final class GeneratorReactor extends GeneratorContext implements Mutable } } - private @NonNull AbstractTypeAwareGenerator strictResolvePath(final @NonNull PathExpression path) { + private @NonNull AbstractTypeAwareGenerator strictResolvePath(final @NonNull PathExpression path) { try { inferenceStack.resolvePathExpression(path); } catch (IllegalArgumentException e) { @@ -328,7 +328,7 @@ public final class GeneratorReactor extends GeneratorContext implements Mutable return mapToGenerator(); } - private @Nullable AbstractTypeAwareGenerator lenientResolveLeafref(final @NonNull PathExpression path) { + private @Nullable AbstractTypeAwareGenerator lenientResolveLeafref(final @NonNull PathExpression path) { try { inferenceStack.resolvePathExpression(path); } catch (IllegalArgumentException e) { @@ -339,7 +339,7 @@ public final class GeneratorReactor extends GeneratorContext implements Mutable } // Map a statement to the corresponding generator - private @NonNull AbstractTypeAwareGenerator mapToGenerator() { + private @NonNull AbstractTypeAwareGenerator mapToGenerator() { // Some preliminaries first: we need to be in the correct module to walk the path final ModuleEffectiveStatement module = inferenceStack.currentModule(); final ModuleGenerator gen = verifyNotNull(generators.get(module.localQNameModule()), @@ -349,7 +349,7 @@ public final class GeneratorReactor extends GeneratorContext implements Mutable final List> stmtPath = inferenceStack.toInference().statementPath(); final AbstractExplicitGenerator found = gen.findGenerator(stmtPath); if (found instanceof AbstractTypeAwareGenerator) { - return (AbstractTypeAwareGenerator) found; + return (AbstractTypeAwareGenerator) found; } throw new VerifyException("Statements " + stmtPath + " resulted in unexpected " + found); } diff --git a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/LeafGenerator.java b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/LeafGenerator.java index c28dbf0f1b..a872d94c46 100644 --- a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/LeafGenerator.java +++ b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/LeafGenerator.java @@ -12,7 +12,7 @@ import org.opendaylight.yangtools.yang.model.api.stmt.LeafEffectiveStatement; /** * Generator corresponding to a {@code leaf} statement. */ -final class LeafGenerator extends AbstractTypeAwareGenerator { +final class LeafGenerator extends AbstractTypeAwareGenerator { LeafGenerator(final LeafEffectiveStatement statement, final AbstractCompositeGenerator parent) { super(statement, parent); } diff --git a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/LeafListGenerator.java b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/LeafListGenerator.java index f20ad882aa..68727b69c3 100644 --- a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/LeafListGenerator.java +++ b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/LeafListGenerator.java @@ -16,7 +16,7 @@ import org.opendaylight.yangtools.yang.model.api.stmt.OrderedByEffectiveStatemen /** * Generator corresponding to a {@code leaf-list} statement. */ -final class LeafListGenerator extends AbstractTypeAwareGenerator { +final class LeafListGenerator extends AbstractTypeAwareGenerator { LeafListGenerator(final LeafListEffectiveStatement statement, final AbstractCompositeGenerator parent) { super(statement, parent); } diff --git a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/ListGenerator.java b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/ListGenerator.java index 5eca4ee13a..63a6e8d9af 100644 --- a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/ListGenerator.java +++ b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/ListGenerator.java @@ -27,7 +27,7 @@ import org.opendaylight.yangtools.yang.model.util.SchemaInferenceStack; /** * Generator corresponding to a {@code list} statement. */ -final class ListGenerator extends AbstractCompositeGenerator { +final class ListGenerator extends CompositeSchemaTreeGenerator { private final @Nullable KeyGenerator keyGen; ListGenerator(final ListEffectiveStatement statement, final AbstractCompositeGenerator parent) { diff --git a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/NotificationGenerator.java b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/NotificationGenerator.java index e169fb9f1e..1be7ae1112 100644 --- a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/NotificationGenerator.java +++ b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/NotificationGenerator.java @@ -18,7 +18,8 @@ import org.opendaylight.yangtools.yang.model.util.SchemaInferenceStack; /** * Generator corresponding to a {@code notification} statement. */ -final class NotificationGenerator extends AbstractCompositeGenerator { +final class NotificationGenerator + extends CompositeSchemaTreeGenerator { NotificationGenerator(final NotificationEffectiveStatement statement, final AbstractCompositeGenerator parent) { super(statement, parent); } 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 d05c9b55ed..f020779dca 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 @@ -7,6 +7,7 @@ */ package org.opendaylight.mdsal.binding.generator.impl.reactor; +import org.opendaylight.mdsal.binding.generator.impl.tree.SchemaTreeChild; 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; @@ -18,11 +19,17 @@ import org.opendaylight.yangtools.yang.model.util.SchemaInferenceStack; /** * Common generator for {@code anydata} and {@code anyxml}. */ -final class OpaqueObjectGenerator> extends AbstractExplicitGenerator { +final class OpaqueObjectGenerator> extends AbstractExplicitGenerator + implements SchemaTreeChild> { OpaqueObjectGenerator(final T statement, final AbstractCompositeGenerator parent) { super(statement, parent); } + @Override + public OpaqueObjectGenerator generator() { + return this; + } + @Override void pushToInference(final SchemaInferenceStack dataTree) { dataTree.enterDataTree(statement().getIdentifier()); diff --git a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/OperationContainerGenerator.java b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/OperationContainerGenerator.java index bd3ea607ae..e588743fda 100644 --- a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/OperationContainerGenerator.java +++ b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/OperationContainerGenerator.java @@ -19,7 +19,8 @@ import org.opendaylight.yangtools.yang.model.util.SchemaInferenceStack; /** * Generator corresponding to an {@code input} or an {@code output} statement. */ -class OperationContainerGenerator extends AbstractCompositeGenerator> { +class OperationContainerGenerator + extends CompositeSchemaTreeGenerator, OperationContainerGenerator> { private final ConcreteType baseInterface; OperationContainerGenerator(final InputEffectiveStatement statement, final AbstractCompositeGenerator parent) { diff --git a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/RpcGenerator.java b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/RpcGenerator.java index a79d27f3a3..39b934e18d 100644 --- a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/RpcGenerator.java +++ b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/RpcGenerator.java @@ -15,7 +15,7 @@ import org.opendaylight.yangtools.yang.model.util.SchemaInferenceStack; /** * Generator corresponding to a {@code rpc} statement. */ -final class RpcGenerator extends AbstractCompositeGenerator { +final class RpcGenerator extends CompositeSchemaTreeGenerator { RpcGenerator(final RpcEffectiveStatement statement, final AbstractCompositeGenerator parent) { super(statement, parent); } diff --git a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/SchemaTreePlaceholder.java b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/SchemaTreePlaceholder.java new file mode 100644 index 0000000000..9cfd59ef52 --- /dev/null +++ b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/SchemaTreePlaceholder.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2022 PANTHEON.tech, s.r.o. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.mdsal.binding.generator.impl.reactor; + +import static com.google.common.base.Verify.verify; +import static com.google.common.base.Verify.verifyNotNull; +import static java.util.Objects.requireNonNull; + +import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.jdt.annotation.Nullable; +import org.opendaylight.mdsal.binding.generator.impl.tree.SchemaTreeChild; +import org.opendaylight.yangtools.yang.model.api.stmt.SchemaTreeEffectiveStatement; + +/** + * A placeholder {@link SchemaTreeChild}. + * + */ +final class SchemaTreePlaceholder, + G extends AbstractExplicitGenerator & SchemaTreeChild> implements SchemaTreeChild { + private final @NonNull Class generatorType; + private final @NonNull S statement; + + private @Nullable G generator; + + SchemaTreePlaceholder(final S statement, final Class generatorType) { + this.statement = requireNonNull(statement); + this.generatorType = requireNonNull(generatorType); + } + + @Override + public S statement() { + return statement; + } + + @Override + public G generator() { + final var local = generator; + if (local == null) { + throw new IllegalStateException("Unresolved generator in " + this); + } + return local; + } + + void setGenerator(final AbstractCompositeGenerator parent) { + verify(generator == null, "Attempted to set generator for %s", this); + final var qname = getIdentifier(); + generator = generatorType.cast(verifyNotNull(parent.findSchemaTreeGenerator(qname), + "Failed to find generator for child %s in %s", qname, parent)); + } +} diff --git a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/tree/SchemaTreeChild.java b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/tree/SchemaTreeChild.java new file mode 100644 index 0000000000..e3c409c93f --- /dev/null +++ b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/tree/SchemaTreeChild.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2022 PANTHEON.tech, s.r.o. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.mdsal.binding.generator.impl.tree; + +import org.eclipse.jdt.annotation.NonNull; +import org.opendaylight.mdsal.binding.generator.impl.reactor.AbstractExplicitGenerator; +import org.opendaylight.yangtools.concepts.Identifiable; +import org.opendaylight.yangtools.yang.common.QName; +import org.opendaylight.yangtools.yang.model.api.stmt.SchemaTreeEffectiveStatement; + +/** + * An object reflecting a YANG {@code schema node}. + * + * @param Concrete {@link SchemaTreeEffectiveStatement} type + * @param Concrete {@link AbstractExplicitGenerator} type + */ +// FIXME: do not reference Generator once we have the codegen and runtime views well-defined +public interface SchemaTreeChild, + G extends AbstractExplicitGenerator & SchemaTreeChild> extends Identifiable { + @Override + default QName getIdentifier() { + return statement().argument(); + } + + /** + * Return the effective YANG statement being represented by this object. + * + * @return A YANG statement + */ + @NonNull S statement(); + + /** + * Return the generator responsible for handling the binding type view of this statement. Note that the statement + * returned by {@code generator().statement()} may differ from the statement returned by {@link #statement()}. + * + * @return Underlying binding generator + * @throws IllegalStateException if the generator has not been resolved yet + */ + @NonNull G generator(); +} diff --git a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/tree/SchemaTreeParent.java b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/tree/SchemaTreeParent.java new file mode 100644 index 0000000000..d846befd56 --- /dev/null +++ b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/tree/SchemaTreeParent.java @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2022 PANTHEON.tech, s.r.o. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.mdsal.binding.generator.impl.tree; + +import java.util.List; +import org.eclipse.jdt.annotation.NonNull; +import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement; + +/** + * A parent containing a number of {@link SchemaTreeChild} objects. + * + * @param Concrete {@link EffectiveStatement} type + */ +// FIXME: S extends SchemaTreeAwareStatement ... once AugmentEffectiveStatement implements that +public interface SchemaTreeParent> { + /* + * Immutable view of children of this object along the {@code schema tree} child axis. + * + * @return Immutable view of this objects children along the {@code schema tree} child axis. + */ + @NonNull List> schemaTreeChildren(); +} diff --git a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/tree/package-info.java b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/tree/package-info.java new file mode 100644 index 0000000000..35a97595de --- /dev/null +++ b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/tree/package-info.java @@ -0,0 +1,11 @@ +/* + * 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 + */ +/** + * Concepts relating to the organization of the tree backing the codegen and runtime type information generator. + */ +package org.opendaylight.mdsal.binding.generator.impl.tree; \ No newline at end of file -- 2.36.6