Rework BindingRuntimeTypes
[mdsal.git] / binding / mdsal-binding-generator / src / main / java / org / opendaylight / mdsal / binding / generator / impl / reactor / AbstractExplicitGenerator.java
index 10cac0c71c5d2b669934ae1e86689a40bb15acb0..3ca83a023da644a1810f1292f44bb8a3cf01eeec 100644 (file)
@@ -12,15 +12,18 @@ 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;
@@ -35,11 +38,11 @@ import org.slf4j.LoggerFactory;
 /**
  * An explicit {@link Generator}, associated with a particular {@link EffectiveStatement}.
  */
-public abstract class AbstractExplicitGenerator<T extends EffectiveStatement<?, ?>> extends Generator
-        implements CopyableNode {
+public abstract class AbstractExplicitGenerator<S extends EffectiveStatement<?, ?>, R extends RuntimeType>
+        extends Generator implements CopyableNode, StatementRepresentation<S> {
     private static final Logger LOG = LoggerFactory.getLogger(AbstractExplicitGenerator.class);
 
-    private final @NonNull T statement;
+    private final @NonNull S statement;
 
     /**
      * Field tracking previous incarnation (along reverse of 'uses' and 'augment' axis) of this statement. This field
@@ -50,30 +53,66 @@ public abstract class AbstractExplicitGenerator<T extends EffectiveStatement<?,
      *   <li>a generator which is one step closer to the original definition</li>
      * </ul>
      */
-    private AbstractExplicitGenerator<T> prev;
+    private AbstractExplicitGenerator<S, R> prev;
     /**
      * Field holding the original incarnation, i.e. the terminal node along {@link #prev} links.
      */
-    private AbstractExplicitGenerator<T> orig;
+    private AbstractExplicitGenerator<S, R> 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<R> runtimeType() {
+        if (!runtimeTypeInitialized) {
+            runtimeType = createRuntimeType();
+            runtimeTypeInitialized = true;
+        }
+        return Optional.ofNullable(runtimeType);
     }
 
+    final Optional<R> runtimeTypeOf(final @NonNull S stmt) {
+        return recursiveRuntimeType().map(childType -> rebaseRuntimeType(childType, stmt));
+    }
+
+    public final Optional<R> recursiveRuntimeType() {
+        AbstractExplicitGenerator<S, R> gen = this;
+        do {
+            final var ret = gen.runtimeType();
+            if (ret.isPresent()) {
+                return ret;
+            }
+
+            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();
@@ -104,7 +143,7 @@ public abstract class AbstractExplicitGenerator<T extends EffectiveStatement<?,
                 return true;
             }
 
-            final var link = getParent().<T>originalChild(getQName());
+            final var link = getParent().<S, R>originalChild(getQName());
             if (link == null) {
                 LOG.trace("Cannot link {} yet", this);
                 return false;
@@ -134,7 +173,7 @@ public abstract class AbstractExplicitGenerator<T extends EffectiveStatement<?,
      *
      * @return Previous incarnation or {@code null}
      */
-    final @Nullable AbstractExplicitGenerator<T> previous() {
+    final @Nullable AbstractExplicitGenerator<S, R> previous() {
         final var local = verifyNotNull(prev, "Generator %s does not have linkage to previous instance resolved", this);
         return local == this ? null : local;
     }
@@ -144,11 +183,11 @@ public abstract class AbstractExplicitGenerator<T extends EffectiveStatement<?,
      *
      * @return Original incarnation of this generator
      */
-    @NonNull AbstractExplicitGenerator<T> getOriginal() {
+    @NonNull AbstractExplicitGenerator<S, R> getOriginal() {
         return verifyNotNull(orig, "Generator %s does not have linkage to original instance resolved", this);
     }
 
-    @Nullable AbstractExplicitGenerator<T> tryOriginal() {
+    @Nullable AbstractExplicitGenerator<S, R> tryOriginal() {
         return orig;
     }
 
@@ -157,7 +196,7 @@ public abstract class AbstractExplicitGenerator<T extends EffectiveStatement<?,
      *
      * @return Link towards the original generator.
      */
-    final @NonNull OriginalLink<T> originalLink() {
+    final @NonNull OriginalLink<S, R> originalLink() {
         final var local = prev;
         if (local == null) {
             return OriginalLink.partial(this);
@@ -168,14 +207,14 @@ public abstract class AbstractExplicitGenerator<T extends EffectiveStatement<?,
         }
     }
 
-    @Nullable AbstractExplicitGenerator<?> findSchemaTreeGenerator(final QName qname) {
+    @Nullable AbstractExplicitGenerator<?, ?> findSchemaTreeGenerator(final QName qname) {
         return findLocalSchemaTreeGenerator(qname);
     }
 
-    final @Nullable AbstractExplicitGenerator<?> findLocalSchemaTreeGenerator(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;