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%2FAbstractExplicitGenerator.java;h=67883f3f94d382f3cb9ad94428b978e07c7ddb1b;hb=2037a8c6e17b521c9ccf1ee3a1a965fa96cade3d;hp=9a59a88f1459c671ec8d6e8e4773b9050b4b320b;hpb=89a12a10b9573dcc84a5636c046cbd0610bc2111;p=mdsal.git 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 9a59a88f14..67883f3f94 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 @@ -12,24 +12,25 @@ import static com.google.common.base.Verify.verifyNotNull; import static java.util.Objects.requireNonNull; import com.google.common.base.MoreObjects.ToStringHelper; +import java.util.Optional; import org.eclipse.jdt.annotation.NonNull; import org.eclipse.jdt.annotation.Nullable; import org.opendaylight.mdsal.binding.generator.impl.reactor.CollisionDomain.Member; +import org.opendaylight.mdsal.binding.generator.impl.tree.StatementRepresentation; import org.opendaylight.mdsal.binding.model.api.MethodSignature.ValueMechanics; import org.opendaylight.mdsal.binding.model.api.Type; import org.opendaylight.mdsal.binding.model.api.TypeMemberComment; import org.opendaylight.mdsal.binding.model.api.type.builder.AnnotableTypeBuilder; import org.opendaylight.mdsal.binding.model.api.type.builder.GeneratedTypeBuilderBase; import org.opendaylight.mdsal.binding.model.api.type.builder.MethodSignatureBuilder; +import org.opendaylight.mdsal.binding.runtime.api.RuntimeType; import org.opendaylight.mdsal.binding.spec.naming.BindingMapping; import org.opendaylight.yangtools.yang.common.AbstractQName; import org.opendaylight.yangtools.yang.common.QName; -import org.opendaylight.yangtools.yang.common.QNameModule; import org.opendaylight.yangtools.yang.model.api.AddedByUsesAware; import org.opendaylight.yangtools.yang.model.api.CopyableNode; import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement; import org.opendaylight.yangtools.yang.model.api.stmt.DescriptionEffectiveStatement; -import org.opendaylight.yangtools.yang.model.api.stmt.SchemaNodeIdentifier; import org.opendaylight.yangtools.yang.model.api.stmt.SchemaTreeEffectiveStatement; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -37,37 +38,77 @@ import org.slf4j.LoggerFactory; /** * An explicit {@link Generator}, associated with a particular {@link EffectiveStatement}. */ -public abstract class AbstractExplicitGenerator> extends Generator - implements CopyableNode { +public abstract class AbstractExplicitGenerator, R extends RuntimeType> + extends Generator implements CopyableNode, StatementRepresentation { private static final Logger LOG = LoggerFactory.getLogger(AbstractExplicitGenerator.class); - private final @NonNull T statement; + private final @NonNull S statement; - // FIXME: this, along with AbstractTypeObjectGenerator's (and TypedefGenerator's) fields should be better-controlled - // with explicit sequencing guards. It it currently stands, we are expending two (or more) additional fields - // to express downstream linking. If we had the concept of resolution step (an enum), we could just get by - // with a simple queue of Step/Callback pairs, which would trigger as needed. For an example see how - // AbstractTypeObjectGenerator manages baseGen/inferred fields. - private AbstractExplicitGenerator prev; + /** + * Field tracking previous incarnation (along reverse of 'uses' and 'augment' axis) of this statement. This field + * can either be one of: + *
    + *
  • {@code null} when not resolved, i.e. access is not legal, or
  • + *
  • {@code this} object if this is the original definition, or
  • + *
  • a generator which is one step closer to the original definition
  • + *
+ */ + private AbstractExplicitGenerator prev; + /** + * Field holding the original incarnation, i.e. the terminal node along {@link #prev} links. + */ + private AbstractExplicitGenerator orig; + /** + * Field containing and indicator holding the runtime type, if applicable. + */ + private @Nullable R runtimeType; + private boolean runtimeTypeInitialized; - AbstractExplicitGenerator(final T statement) { + AbstractExplicitGenerator(final S statement) { this.statement = requireNonNull(statement); } - AbstractExplicitGenerator(final T statement, final AbstractCompositeGenerator parent) { + AbstractExplicitGenerator(final S statement, final AbstractCompositeGenerator parent) { super(parent); this.statement = requireNonNull(statement); } + @Override + public final @NonNull S statement() { + return statement; + } + /** - * Return the {@link EffectiveStatement} associated with this generator. + * Return the {@link RuntimeType} associated with this object, of applicable. * - * @return An EffectiveStatement + * @return Associated run-time type, or empty */ - public final @NonNull T statement() { - return statement; + public final Optional runtimeType() { + if (!runtimeTypeInitialized) { + runtimeType = createRuntimeType(); + runtimeTypeInitialized = true; + } + return Optional.ofNullable(runtimeType); + } + + final Optional runtimeTypeOf(final @NonNull S stmt) { + var gen = this; + do { + final var ret = gen.runtimeType(); + if (ret.isPresent()) { + return Optional.of(rebaseRuntimeType(ret.orElseThrow(), stmt)); + } + + gen = gen.previous(); + } while (gen != null); + + return Optional.empty(); } + abstract @Nullable R createRuntimeType(); + + abstract @NonNull R rebaseRuntimeType(@NonNull R type, @NonNull S statement); + @Override public final boolean isAddedByUses() { return statement instanceof AddedByUsesAware && ((AddedByUsesAware) statement).isAddedByUses(); @@ -78,26 +119,98 @@ public abstract class AbstractExplicitGeneratororiginalChild(getQName()); + if (link == null) { + LOG.trace("Cannot link {} yet", this); + return false; + } + + prev = link.previous(); + orig = link.original(); + if (orig != null) { + LOG.trace("Linked {} to {} original {}", this, prev, orig); + return true; + } + + LOG.trace("Linked {} to intermediate {}", this, prev); + return false; } + + orig = prev.originalLink().original(); + if (orig != null) { + LOG.trace("Linked {} to original {}", this, orig); + return true; + } + return false; + } + + /** + * Return the previous incarnation of this generator, or {@code null} if this is the original generator. + * + * @return Previous incarnation or {@code null} + */ + final @Nullable AbstractExplicitGenerator previous() { + final var local = verifyNotNull(prev, "Generator %s does not have linkage to previous instance resolved", this); + return local == this ? null : local; + } + + /** + * Return the original incarnation of this generator, or self if this is the original generator. + * + * @return Original incarnation of this generator + */ + @NonNull AbstractExplicitGenerator getOriginal() { + return verifyNotNull(orig, "Generator %s does not have linkage to original instance resolved", this); + } + + @Nullable AbstractExplicitGenerator tryOriginal() { + return orig; } - final @Nullable AbstractExplicitGenerator previous() { - return prev; + /** + * Return the link towards the original generator. + * + * @return Link towards the original generator. + */ + final @NonNull OriginalLink originalLink() { + final var local = prev; + if (local == null) { + return OriginalLink.partial(this); + } else if (local == this) { + return OriginalLink.complete(this); + } else { + return OriginalLink.partial(local); + } } - @NonNull AbstractExplicitGenerator getOriginal() { - return prev == null ? this : prev.getOriginal(); + @Nullable AbstractExplicitGenerator findSchemaTreeGenerator(final QName qname) { + return findLocalSchemaTreeGenerator(qname); } - @Nullable AbstractExplicitGenerator findSchemaTreeGenerator(final QName qname) { + final @Nullable AbstractExplicitGenerator findLocalSchemaTreeGenerator(final QName qname) { for (Generator child : this) { if (child instanceof AbstractExplicitGenerator) { - final AbstractExplicitGenerator gen = (AbstractExplicitGenerator) child; + final AbstractExplicitGenerator gen = (AbstractExplicitGenerator) child; final EffectiveStatement stmt = gen.statement(); if (stmt instanceof SchemaTreeEffectiveStatement && qname.equals(stmt.argument())) { return gen; @@ -107,27 +220,6 @@ public abstract class AbstractExplicitGenerator resolveSchemaNode(final @NonNull SchemaNodeIdentifier path, - final @Nullable QNameModule targetModule) { - AbstractExplicitGenerator current = this; - QNameModule currentModule = targetModule; - - for (QName next : path.getNodeIdentifiers()) { - final QName qname = currentModule == null ? next : next.bindTo(currentModule); - current = verifyNotNull(current.findSchemaTreeGenerator(qname), - "Failed to find %s as %s in %s", next, qname, current); - - final QNameModule foundNamespace = current.getQName().getModule(); - if (!foundNamespace.equals(qname.getModule())) { - // We have located a different QName than the one we were looking for. We need to make sure we adjust - // all subsequent QNames to this new namespace - currentModule = foundNamespace; - } - } - - return current; - } - final @NonNull QName getQName() { final Object arg = statement.argument(); verify(arg instanceof QName, "Unexpected argument %s", arg);