Extract AbstractResumedStatement 75/87275/2
authorRobert Varga <robert.varga@pantheon.tech>
Sat, 25 Jan 2020 11:43:44 +0000 (12:43 +0100)
committerRobert Varga <robert.varga@pantheon.tech>
Thu, 30 Jan 2020 09:35:45 +0000 (10:35 +0100)
Separate out data structures related to statement source traversal
into a dedicated class.

This lowers the footprint required to implement StatementContextBase,
as well as lowering clutter around which functionality is related
to which part.

JIRA: YANGTOOLS-652
Change-Id: I811c6fcf3bfba83421609af13dfed8fe445184b9
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
(cherry picked from commit d3425a5bdd83c76d186d59f711d3c41cd24c1fee)
(cherry picked from commit 735f3c1d9c2243eac0976e0db7af9d62a4e88f98)

yang/yang-parser-reactor/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/AbstractResumedStatement.java [new file with mode: 0644]
yang/yang-parser-reactor/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/RootStatementContext.java
yang/yang-parser-reactor/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/SourceSpecificContext.java
yang/yang-parser-reactor/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/StatementContextBase.java
yang/yang-parser-reactor/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/StatementContextWriter.java
yang/yang-parser-reactor/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/StatementMap.java
yang/yang-parser-reactor/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/SubstatementContext.java
yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/action/ActionStatementSupport.java
yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/rpc/AbstractRpcStatementSupport.java

diff --git a/yang/yang-parser-reactor/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/AbstractResumedStatement.java b/yang/yang-parser-reactor/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/AbstractResumedStatement.java
new file mode 100644 (file)
index 0000000..c3a62b8
--- /dev/null
@@ -0,0 +1,143 @@
+/*
+ * Copyright (c) 2020 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.yangtools.yang.parser.stmt.reactor;
+
+import static com.google.common.base.Preconditions.checkState;
+
+import java.util.Collection;
+import java.util.Optional;
+import org.eclipse.jdt.annotation.NonNull;
+import org.opendaylight.yangtools.yang.model.api.meta.DeclaredStatement;
+import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.meta.StatementDefinition;
+import org.opendaylight.yangtools.yang.parser.spi.meta.CopyType;
+import org.opendaylight.yangtools.yang.parser.spi.meta.ModelProcessingPhase;
+import org.opendaylight.yangtools.yang.parser.spi.meta.StatementSupport;
+import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext;
+import org.opendaylight.yangtools.yang.parser.spi.source.ImplicitSubstatement;
+import org.opendaylight.yangtools.yang.parser.spi.source.StatementSourceReference;
+import org.opendaylight.yangtools.yang.parser.spi.source.StatementWriter.ResumedStatement;
+
+/**
+ * Intermediate subclass of StatementContextBase facing the parser stream via implementation of ResumedStatement. This
+ * shields inference-type substatements from these details.
+ *
+ * @param <A> Argument type
+ * @param <D> Declared Statement representation
+ * @param <E> Effective Statement representation
+ */
+abstract class AbstractResumedStatement<A, D extends DeclaredStatement<A>, E extends EffectiveStatement<A, D>>
+        extends StatementContextBase<A, D, E> implements ResumedStatement {
+    private StatementMap substatements = StatementMap.empty();
+
+    AbstractResumedStatement(final StatementDefinitionContext<A, D, E> def, final StatementSourceReference ref,
+            final String rawArgument) {
+        super(def, ref, rawArgument);
+    }
+
+    AbstractResumedStatement(final StatementDefinitionContext<A, D, E> def, final StatementSourceReference ref,
+            final String rawArgument, final CopyType copyType) {
+        super(def, ref, rawArgument, copyType);
+    }
+
+    AbstractResumedStatement(final StatementContextBase<A, D, E> original, final CopyType copyType) {
+        super(original, copyType);
+    }
+
+    AbstractResumedStatement(final AbstractResumedStatement<A, D, E> original) {
+        super(original);
+        this.substatements = original.substatements;
+    }
+
+    @Override
+    public Collection<? extends StmtContext<?, ?, ?>> declaredSubstatements() {
+        return substatements.values();
+    }
+
+    @Override
+    public Collection<? extends StatementContextBase<?, ?, ?>> mutableDeclaredSubstatements() {
+        return substatements.values();
+    }
+
+    @Override
+    public @NonNull StatementDefinition getDefinition() {
+        return getPublicDefinition();
+    }
+
+    @Override
+    public @NonNull StatementSourceReference getSourceReference() {
+        return getStatementSourceReference();
+    }
+
+    @Override
+    public boolean isFullyDefined() {
+        return fullyDefined();
+    }
+
+    /**
+     * Create a new substatement at the specified offset.
+     *
+     * @param offset Substatement offset
+     * @param def definition context
+     * @param ref source reference
+     * @param argument statement argument
+     * @param <X> new substatement argument type
+     * @param <Y> new substatement declared type
+     * @param <Z> new substatement effective type
+     * @return A new substatement
+     */
+    @SuppressWarnings("checkstyle:methodTypeParameterName")
+    final <X, Y extends DeclaredStatement<X>, Z extends EffectiveStatement<X, Y>>
+            AbstractResumedStatement<X, Y, Z> createSubstatement(final int offset,
+                    final StatementDefinitionContext<X, Y, Z> def, final StatementSourceReference ref,
+                    final String argument) {
+        final ModelProcessingPhase inProgressPhase = getRoot().getSourceContext().getInProgressPhase();
+        checkState(inProgressPhase != ModelProcessingPhase.EFFECTIVE_MODEL,
+                "Declared statement cannot be added in effective phase at: %s", getStatementSourceReference());
+
+        final Optional<StatementSupport<?, ?, ?>> implicitParent =
+                definition().getImplicitParentFor(def.getPublicView());
+        if (implicitParent.isPresent()) {
+            return createImplicitParent(offset, implicitParent.get(), ref, argument).createSubstatement(offset, def,
+                    ref, argument);
+        }
+
+        final AbstractResumedStatement<X, Y, Z> ret = new SubstatementContext<>(this, def, ref, argument);
+        substatements = substatements.put(offset, ret);
+        def.onStatementAdded(ret);
+        return ret;
+    }
+
+    /**
+     * Lookup substatement by its offset in this statement.
+     *
+     * @param offset Substatement offset
+     * @return Substatement, or null if substatement does not exist.
+     */
+    final AbstractResumedStatement<?, ?, ?> lookupSubstatement(final int offset) {
+        return substatements.get(offset);
+    }
+
+    final void resizeSubstatements(final int expectedSize) {
+        substatements = substatements.ensureCapacity(expectedSize);
+    }
+
+    final void walkChildren(final ModelProcessingPhase phase) {
+        checkState(isFullyDefined());
+        substatements.values().forEach(stmt -> {
+            stmt.walkChildren(phase);
+            stmt.endDeclared(phase);
+        });
+    }
+
+    private AbstractResumedStatement<?, ?, ?> createImplicitParent(final int offset,
+            final StatementSupport<?, ?, ?> implicitParent, final StatementSourceReference ref, final String argument) {
+        final StatementDefinitionContext<?, ?, ?> def = new StatementDefinitionContext<>(implicitParent);
+        return createSubstatement(offset, def, ImplicitSubstatement.of(ref), argument);
+    }
+}
index ab5b9f9348933b59369c1d5f4e3a22a3b60948ea..e0c7cf26365ed5a1afa7dc52195157f4bb3000ad 100644 (file)
@@ -41,7 +41,7 @@ import org.opendaylight.yangtools.yang.parser.spi.source.StatementSourceReferenc
  * of this class, hence recursive lookups from them cross this class.
  */
 public class RootStatementContext<A, D extends DeclaredStatement<A>, E extends EffectiveStatement<A, D>> extends
-        StatementContextBase<A, D, E> {
+        AbstractResumedStatement<A, D, E> {
 
     public static final YangVersion DEFAULT_VERSION = YangVersion.VERSION_1;
 
@@ -256,4 +256,9 @@ public class RootStatementContext<A, D extends DeclaredStatement<A>, E extends E
     protected boolean isParentSupportedByFeatures() {
         return true;
     }
+
+    @Override
+    StatementContextBase<A, D, E> reparent(final StatementContextBase<?, ?, ?> newParent) {
+        throw new UnsupportedOperationException("Root statement cannot be reparented to" + newParent);
+    }
 }
index 279a03ac5cb41fcea7bda9b77a4d1ad47c43e923..9efd3a70e478cbf6d8a72429e9dd357c7c4ede1f 100644 (file)
@@ -101,14 +101,14 @@ public class SourceSpecificContext implements NamespaceStorageNode, NamespaceBeh
         return inProgressPhase;
     }
 
-    Optional<StatementContextBase<?, ?, ?>> lookupDeclaredChild(final StatementContextBase<?, ?, ?> current,
+    Optional<AbstractResumedStatement<?, ?, ?>> lookupDeclaredChild(final AbstractResumedStatement<?, ?, ?> current,
             final int childId) {
         if (current == null) {
             return Optional.empty();
         }
 
         // Fast path: we are entering a statement which was emitted in previous phase
-        StatementContextBase<?, ?, ?> existing = current.lookupSubstatement(childId);
+        AbstractResumedStatement<?, ?, ?> existing = current.lookupSubstatement(childId);
         while (existing != null && StatementSource.CONTEXT == existing.getStatementSource()) {
             existing = existing.lookupSubstatement(childId);
         }
@@ -116,8 +116,8 @@ public class SourceSpecificContext implements NamespaceStorageNode, NamespaceBeh
         return Optional.ofNullable(existing);
     }
 
-    StatementContextBase<?, ?, ?> createDeclaredChild(final StatementContextBase<?, ?, ?> current, final int childId,
-            final QName name, final String argument, final StatementSourceReference ref) {
+    AbstractResumedStatement<?, ?, ?> createDeclaredChild(final AbstractResumedStatement<?, ?, ?> current,
+            final int childId, final QName name, final String argument, final StatementSourceReference ref) {
         StatementDefinitionContext<?, ?, ?> def = currentContext.getStatementDefinition(getRootVersion(), name);
         if (def == null) {
             def = currentContext.getModelDefinedStatementDefinition(name);
index abf79fde20240d82562e8546a13e4257887dacef..e66d84b89349200d449cd8eccd43bf1c7d231549 100644 (file)
@@ -59,7 +59,6 @@ import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContextUtils;
 import org.opendaylight.yangtools.yang.parser.spi.source.ImplicitSubstatement;
 import org.opendaylight.yangtools.yang.parser.spi.source.SourceException;
 import org.opendaylight.yangtools.yang.parser.spi.source.StatementSourceReference;
-import org.opendaylight.yangtools.yang.parser.spi.source.StatementWriter.ResumedStatement;
 import org.opendaylight.yangtools.yang.parser.spi.source.SupportedFeaturesNamespace;
 import org.opendaylight.yangtools.yang.parser.spi.source.SupportedFeaturesNamespace.SupportedFeatures;
 import org.opendaylight.yangtools.yang.parser.stmt.reactor.NamespaceBehaviourWithListeners.KeyedValueAddedListener;
@@ -75,7 +74,7 @@ import org.slf4j.LoggerFactory;
  * @param <E> Effective Statement representation
  */
 public abstract class StatementContextBase<A, D extends DeclaredStatement<A>, E extends EffectiveStatement<A, D>>
-        extends NamespaceStorageSupport implements Mutable<A, D, E>, ResumedStatement {
+        extends NamespaceStorageSupport implements Mutable<A, D, E> {
     /**
      * Event listener when an item is added to model namespace.
      */
@@ -135,17 +134,20 @@ public abstract class StatementContextBase<A, D extends DeclaredStatement<A>, E
     private Multimap<ModelProcessingPhase, ContextMutation> phaseMutation = ImmutableMultimap.of();
     private List<Mutable<?, ?, ?>> effective = ImmutableList.of();
     private List<StmtContext<?, ?, ?>> effectOfStatement = ImmutableList.of();
-    private StatementMap substatements = StatementMap.empty();
 
     private @Nullable ModelProcessingPhase completedPhase;
     private @Nullable D declaredInstance;
     private @Nullable E effectiveInstance;
 
-    // Common state bits
+    // Master flag controlling whether this context can yield an effective statement
+    // FIXME: investigate the mechanics that are being supported by this, as it would be beneficial if we can get rid
+    //        of this flag -- eliminating the initial alignment shadow used by below gap-filler fields.
     private boolean isSupportedToBuildEffective = true;
+
+    // Flag for use with AbstractResumedStatement. This is hiding in the alignment shadow created by above boolean
     private boolean fullyDefined;
 
-    // Flags for use with SubstatementContext. These are hiding in the alignment shadow created by above booleans and
+    // Flags for use with SubstatementContext. These are hiding in the alignment shadow created by above boolean and
     // hence improve memory layout.
     private byte flags;
 
@@ -185,7 +187,6 @@ public abstract class StatementContextBase<A, D extends DeclaredStatement<A>, E
         this.copyHistory = original.getCopyHistory();
         this.originalCtx = original.getOriginalCtx().orElse(original);
         this.prevCopyCtx = original;
-        this.substatements = original.substatements;
         this.effective = original.effective;
     }
 
@@ -307,14 +308,7 @@ public abstract class StatementContextBase<A, D extends DeclaredStatement<A>, E
     }
 
     @Override
-    public Collection<? extends StmtContext<?, ?, ?>> declaredSubstatements() {
-        return substatements.values();
-    }
-
-    @Override
-    public Collection<? extends Mutable<?, ?, ?>> mutableDeclaredSubstatements() {
-        return substatements.values();
-    }
+    public abstract Collection<? extends StatementContextBase<?, ?, ?>> mutableDeclaredSubstatements();
 
     @Override
     public Collection<? extends StmtContext<?, ?, ?>> effectiveSubstatements() {
@@ -402,6 +396,19 @@ public abstract class StatementContextBase<A, D extends DeclaredStatement<A>, E
         shrinkEffective();
     }
 
+    // YANG example: RPC/action statements always have 'input' and 'output' defined
+    @Beta
+    public <X, Y extends DeclaredStatement<X>, Z extends EffectiveStatement<X, Y>> @NonNull Mutable<X, Y, Z>
+            appendImplicitSubstatement(final StatementSupport<X, Y, Z> support, final String rawArg) {
+        // FIXME: YANGTOOLS-652: This does not need to be a SubstatementContext, in can be a specialized
+        //                       StatementContextBase subclass.
+        final Mutable<X, Y, Z> ret = new SubstatementContext<>(this, new StatementDefinitionContext<>(support),
+                ImplicitSubstatement.of(getStatementSourceReference()), rawArg);
+        support.onStatementAdded(ret);
+        addEffectiveSubstatement(ret);
+        return ret;
+    }
+
     /**
      * Adds an effective statement to collection of substatements.
      *
@@ -446,74 +453,14 @@ public abstract class StatementContextBase<A, D extends DeclaredStatement<A>, E
         }
     }
 
-    /**
-     * Create a new substatement at the specified offset.
-     *
-     * @param offset Substatement offset
-     * @param def definition context
-     * @param ref source reference
-     * @param argument statement argument
-     * @param <X> new substatement argument type
-     * @param <Y> new substatement declared type
-     * @param <Z> new substatement effective type
-     * @return A new substatement
-     */
-    @SuppressWarnings("checkstyle:methodTypeParameterName")
-    public final <X, Y extends DeclaredStatement<X>, Z extends EffectiveStatement<X, Y>>
-            StatementContextBase<X, Y, Z> createSubstatement(final int offset,
-                    final StatementDefinitionContext<X, Y, Z> def, final StatementSourceReference ref,
-                    final String argument) {
-        final ModelProcessingPhase inProgressPhase = getRoot().getSourceContext().getInProgressPhase();
-        checkState(inProgressPhase != ModelProcessingPhase.EFFECTIVE_MODEL,
-                "Declared statement cannot be added in effective phase at: %s", getStatementSourceReference());
-
-        final Optional<StatementSupport<?, ?, ?>> implicitParent = definition.getImplicitParentFor(def.getPublicView());
-        if (implicitParent.isPresent()) {
-            return createImplicitParent(offset, implicitParent.get(), ref, argument).createSubstatement(offset, def,
-                    ref, argument);
-        }
-
-        final StatementContextBase<X, Y, Z> ret = new SubstatementContext<>(this, def, ref, argument);
-        substatements = substatements.put(offset, ret);
-        def.onStatementAdded(ret);
-        return ret;
-    }
-
-    private StatementContextBase<?, ?, ?> createImplicitParent(final int offset,
-            final StatementSupport<?, ?, ?> implicitParent, final StatementSourceReference ref, final String argument) {
-        final StatementDefinitionContext<?, ?, ?> def = new StatementDefinitionContext<>(implicitParent);
-        return createSubstatement(offset, def, ImplicitSubstatement.of(ref), argument);
-    }
-
-    public void appendImplicitStatement(final StatementSupport<?, ?, ?> statementToAdd) {
-        createSubstatement(substatements.capacity(), new StatementDefinitionContext<>(statementToAdd),
-                ImplicitSubstatement.of(getStatementSourceReference()), null);
-    }
-
-    /**
-     * Lookup substatement by its offset in this statement.
-     *
-     * @param offset Substatement offset
-     * @return Substatement, or null if substatement does not exist.
-     */
-    final StatementContextBase<?, ?, ?> lookupSubstatement(final int offset) {
-        return substatements.get(offset);
+    // Exists only due to memory optimization
+    final boolean fullyDefined() {
+        return fullyDefined;
     }
 
+    // Exists only due to memory optimization, should live in AbstractResumedStatement
     final void setFullyDefined() {
-        this.fullyDefined = true;
-    }
-
-    final void resizeSubstatements(final int expectedSize) {
-        substatements = substatements.ensureCapacity(expectedSize);
-    }
-
-    final void walkChildren(final ModelProcessingPhase phase) {
-        checkState(fullyDefined);
-        substatements.values().forEach(stmt -> {
-            stmt.walkChildren(phase);
-            stmt.endDeclared(phase);
-        });
+        fullyDefined = true;
     }
 
     @Override
@@ -566,7 +513,7 @@ public abstract class StatementContextBase<A, D extends DeclaredStatement<A>, E
             }
         }
 
-        for (final StatementContextBase<?, ?, ?> child : substatements.values()) {
+        for (final StatementContextBase<?, ?, ?> child : mutableDeclaredSubstatements()) {
             finished &= child.tryToCompletePhase(phase);
         }
         for (final Mutable<?, ?, ?> child : effective) {
@@ -796,7 +743,7 @@ public abstract class StatementContextBase<A, D extends DeclaredStatement<A>, E
 
         if (implicitParent.isPresent()) {
             final StatementDefinitionContext<?, ?, ?> def = new StatementDefinitionContext<>(implicitParent.get());
-            result = new SubstatementContext(this, def, original.getSourceReference(),
+            result = new SubstatementContext(this, def, original.getStatementSourceReference(),
                 original.rawStatementArgument(), original.getStatementArgument(), type);
 
             final CopyType childCopyType;
@@ -824,21 +771,6 @@ public abstract class StatementContextBase<A, D extends DeclaredStatement<A>, E
         return result;
     }
 
-    @Override
-    public @NonNull StatementDefinition getDefinition() {
-        return getPublicDefinition();
-    }
-
-    @Override
-    public @NonNull StatementSourceReference getSourceReference() {
-        return getStatementSourceReference();
-    }
-
-    @Override
-    public boolean isFullyDefined() {
-        return fullyDefined;
-    }
-
     @Beta
     public final boolean hasImplicitParentSupport() {
         return definition.getFactory() instanceof ImplicitParentAwareStatementSupport;
@@ -858,11 +790,13 @@ public abstract class StatementContextBase<A, D extends DeclaredStatement<A>, E
             original.getStatementSourceReference(), original.rawStatementArgument(), original.getStatementArgument(),
             type);
 
-        result.addEffectiveSubstatement(new SubstatementContext<>(original, result));
+        result.addEffectiveSubstatement(original.reparent(result));
         result.setCompletedPhase(original.getCompletedPhase());
         return result;
     }
 
+    abstract StatementContextBase<A, D, E> reparent(StatementContextBase<?, ?, ?> newParent);
+
     /**
      * Config statements are not all that common which means we are performing a recursive search towards the root
      * every time {@link #isConfiguration()} is invoked. This is quite expensive because it causes a linear search
@@ -954,14 +888,14 @@ public abstract class StatementContextBase<A, D extends DeclaredStatement<A>, E
 
     final void copyTo(final StatementContextBase<?, ?, ?> target, final CopyType typeOfCopy,
             @Nullable final QNameModule targetModule) {
-        final Collection<Mutable<?, ?, ?>> buffer = new ArrayList<>(substatements.size() + effective.size());
+        final Collection<? extends StatementContextBase<?, ?, ?>> declared = mutableDeclaredSubstatements();
+        final Collection<Mutable<?, ?, ?>> buffer = new ArrayList<>(declared.size() + effective.size());
 
-        for (final Mutable<?, ?, ?> stmtContext : substatements.values()) {
+        for (final Mutable<?, ?, ?> stmtContext : declared) {
             if (stmtContext.isSupportedByFeatures()) {
                 copySubstatement(stmtContext, target, typeOfCopy, targetModule, buffer);
             }
         }
-
         for (final Mutable<?, ?, ?> stmtContext : effective) {
             copySubstatement(stmtContext, target, typeOfCopy, targetModule, buffer);
         }
index 34e27ea8b5f6b729df9def9d40512d9bae9c771f..27bd70f2c6d37bb4cbe86a05b17833789bfc5284 100644 (file)
@@ -9,6 +9,7 @@ package org.opendaylight.yangtools.yang.parser.stmt.reactor;
 
 import static com.google.common.base.Preconditions.checkArgument;
 import static com.google.common.base.Preconditions.checkState;
+import static com.google.common.base.Verify.verify;
 import static com.google.common.base.Verify.verifyNotNull;
 import static java.util.Objects.requireNonNull;
 
@@ -23,7 +24,7 @@ final class StatementContextWriter implements StatementWriter {
     private final ModelProcessingPhase phase;
     private final SourceSpecificContext ctx;
 
-    private StatementContextBase<?, ?, ?> current;
+    private AbstractResumedStatement<?, ?, ?> current;
 
     StatementContextWriter(final SourceSpecificContext ctx, final ModelProcessingPhase phase) {
         this.ctx = requireNonNull(ctx);
@@ -32,12 +33,12 @@ final class StatementContextWriter implements StatementWriter {
 
     @Override
     public Optional<? extends ResumedStatement> resumeStatement(final int childId) {
-        final Optional<StatementContextBase<?, ?, ?>> existing = ctx.lookupDeclaredChild(current, childId);
+        final Optional<AbstractResumedStatement<?, ?, ?>> existing = ctx.lookupDeclaredChild(current, childId);
         existing.ifPresent(this::resumeStatement);
         return existing;
     }
 
-    private void resumeStatement(final StatementContextBase<?, ?, ?> child) {
+    private void resumeStatement(final AbstractResumedStatement<?, ?, ?> child) {
         if (child.isFullyDefined()) {
             child.walkChildren(phase);
             child.endDeclared(phase);
@@ -60,7 +61,7 @@ final class StatementContextWriter implements StatementWriter {
     @Override
     public void startStatement(final int childId, final QName name, final String argument,
             final StatementSourceReference ref) {
-        final Optional<StatementContextBase<?, ?, ?>> existing = ctx.lookupDeclaredChild(current, childId);
+        final Optional<AbstractResumedStatement<?, ?, ?>> existing = ctx.lookupDeclaredChild(current, childId);
         current = existing.isPresent() ? existing.get()
                 :  verifyNotNull(ctx.createDeclaredChild(current, childId, name, argument, ref));
     }
@@ -78,11 +79,20 @@ final class StatementContextWriter implements StatementWriter {
     }
 
     private void exitStatement() {
+        // TODO: AbstractResumedStatement should only ever have AbstractResumedStatement parents, which would:
+        //       - remove the StatementSource check
+        //       - allow endDeclared() to be moved to AbstractResumedStatement
+        //       - remove the need for verify()
         StatementContextBase<?, ?, ?> parentContext = current.getParentContext();
         while (parentContext != null && StatementSource.CONTEXT == parentContext.getStatementSource()) {
             parentContext.endDeclared(phase);
             parentContext = parentContext.getParentContext();
         }
-        current = parentContext;
+        if (parentContext != null) {
+            verify(parentContext instanceof AbstractResumedStatement, "Unexpected parent context %s", parentContext);
+            current = (AbstractResumedStatement<?, ?, ?>) parentContext;
+        } else {
+            current = null;
+        }
     }
 }
index a901cdce4b759b5e4752a65b858ecbe88321dd21..58ef4b57d316483309299ee3c8a3b297b499aff1 100644 (file)
@@ -30,17 +30,17 @@ import org.eclipse.jdt.annotation.Nullable;
 abstract class StatementMap {
     private static final class Empty extends StatementMap {
         @Override
-        StatementContextBase<?, ?, ?> get(final int index) {
+        AbstractResumedStatement<?, ?, ?> get(final int index) {
             return null;
         }
 
         @Override
-        StatementMap put(final int index, final StatementContextBase<?, ?, ?> obj) {
+        StatementMap put(final int index, final AbstractResumedStatement<?, ?, ?> obj) {
             return index == 0 ? new Singleton(obj) : new Regular(index, obj);
         }
 
         @Override
-        Collection<StatementContextBase<?, ?, ?>> values() {
+        Collection<AbstractResumedStatement<?, ?, ?>> values() {
             return ImmutableList.of();
         }
 
@@ -61,37 +61,37 @@ abstract class StatementMap {
     }
 
     private static final class Regular extends StatementMap {
-        private StatementContextBase<?, ?, ?>[] elements;
+        private AbstractResumedStatement<?, ?, ?>[] elements;
         private int size;
 
         Regular(final int expectedLimit) {
-            elements = new StatementContextBase<?, ?, ?>[expectedLimit];
+            elements = new AbstractResumedStatement<?, ?, ?>[expectedLimit];
         }
 
-        Regular(final int index, final StatementContextBase<?, ?, ?> object) {
+        Regular(final int index, final AbstractResumedStatement<?, ?, ?> object) {
             this(index + 1, index, object);
         }
 
-        Regular(final StatementContextBase<?, ?, ?> object0, final int index,
-                final StatementContextBase<?, ?, ?> object) {
+        Regular(final AbstractResumedStatement<?, ?, ?> object0, final int index,
+                final AbstractResumedStatement<?, ?, ?> object) {
             this(index + 1, 0, object0);
             elements[index] = requireNonNull(object);
             size = 2;
         }
 
-        Regular(final int expectedLimit, final int index, final StatementContextBase<?, ?, ?> object) {
+        Regular(final int expectedLimit, final int index, final AbstractResumedStatement<?, ?, ?> object) {
             this(expectedLimit);
             elements[index] = requireNonNull(object);
             size = 1;
         }
 
         @Override
-        StatementContextBase<?, ?, ?> get(final int index) {
+        AbstractResumedStatement<?, ?, ?> get(final int index) {
             return index >= elements.length ? null : elements[index];
         }
 
         @Override
-        StatementMap put(final int index, final StatementContextBase<?, ?, ?> obj) {
+        StatementMap put(final int index, final AbstractResumedStatement<?, ?, ?> obj) {
             if (index < elements.length) {
                 checkArgument(elements[index] == null);
             } else {
@@ -105,7 +105,7 @@ abstract class StatementMap {
         }
 
         @Override
-        Collection<StatementContextBase<?, ?, ?>> values() {
+        Collection<AbstractResumedStatement<?, ?, ?>> values() {
             return new RegularAsCollection<>(elements, size);
         }
 
@@ -172,25 +172,25 @@ abstract class StatementMap {
     }
 
     private static final class Singleton extends StatementMap {
-        private final StatementContextBase<?, ?, ?> object;
+        private final AbstractResumedStatement<?, ?, ?> object;
 
-        Singleton(final StatementContextBase<?, ?, ?> object) {
+        Singleton(final AbstractResumedStatement<?, ?, ?> object) {
             this.object = requireNonNull(object);
         }
 
         @Override
-        StatementContextBase<?, ?, ?> get(final int index) {
+        AbstractResumedStatement<?, ?, ?> get(final int index) {
             return index == 0 ? object : null;
         }
 
         @Override
-        StatementMap put(final int index, final StatementContextBase<?, ?, ?> obj) {
+        StatementMap put(final int index, final AbstractResumedStatement<?, ?, ?> obj) {
             checkArgument(index != 0);
             return new Regular(this.object, index, obj);
         }
 
         @Override
-        Collection<StatementContextBase<?, ?, ?>> values() {
+        Collection<AbstractResumedStatement<?, ?, ?>> values() {
             return ImmutableList.of(object);
         }
 
@@ -222,7 +222,7 @@ abstract class StatementMap {
      * @param index Element index, must be non-negative
      * @return Requested element or null if there is no element at that index
      */
-    abstract @Nullable StatementContextBase<?, ?, ?> get(int index);
+    abstract @Nullable AbstractResumedStatement<?, ?, ?> get(int index);
 
     /**
      * Add a statement at specified index.
@@ -232,7 +232,7 @@ abstract class StatementMap {
      * @return New statement map
      * @throws IllegalArgumentException if the index is already occupied
      */
-    abstract @NonNull StatementMap put(int index, @NonNull StatementContextBase<?, ?, ?> obj);
+    abstract @NonNull StatementMap put(int index, @NonNull AbstractResumedStatement<?, ?, ?> obj);
 
     /**
      * Return a read-only view of the elements in this map. Unlike other maps, this view does not detect concurrent
@@ -241,7 +241,7 @@ abstract class StatementMap {
      *
      * @return Read-only view of available statements.
      */
-    abstract @NonNull Collection<StatementContextBase<?, ?, ?>> values();
+    abstract @NonNull Collection<AbstractResumedStatement<?, ?, ?>> values();
 
     abstract int size();
 
index 205fb36fdbddec9e0d89f6d0f01ae43e54c20d66..ea4fa1b91e142a21dd5234c5742eb11bff9c184f 100644 (file)
@@ -33,7 +33,7 @@ import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContextUtils;
 import org.opendaylight.yangtools.yang.parser.spi.source.StatementSourceReference;
 
 final class SubstatementContext<A, D extends DeclaredStatement<A>, E extends EffectiveStatement<A, D>> extends
-        StatementContextBase<A, D, E> {
+        AbstractResumedStatement<A, D, E> {
     private final StatementContextBase<?, ?, ?> parent;
     private final A argument;
 
@@ -61,10 +61,11 @@ final class SubstatementContext<A, D extends DeclaredStatement<A>, E extends Eff
                 : original.definition().adaptArgumentValue(original, targetModule);
     }
 
-    SubstatementContext(final StatementContextBase<A, D, E> original, final StatementContextBase<?, ?, ?> parent) {
+    private SubstatementContext(final SubstatementContext<A, D, E> original,
+            final StatementContextBase<?, ?, ?> parent) {
         super(original);
         this.parent = requireNonNull(parent, "Parent must not be null");
-        this.argument = original.getStatementArgument();
+        this.argument = original.argument;
     }
 
     @Override
@@ -196,4 +197,9 @@ final class SubstatementContext<A, D extends DeclaredStatement<A>, E extends Eff
     protected boolean isParentSupportedByFeatures() {
         return parent.isSupportedByFeatures();
     }
+
+    @Override
+    SubstatementContext<A, D, E> reparent(final StatementContextBase<?, ?, ?> newParent) {
+        return new SubstatementContext<>(this, newParent);
+    }
 }
index d97b1b9ad50cef365dd2ae633e99fd4343595b1e..1ec1fab2842d9c0c62265c2a946d2629c538ee81 100644 (file)
@@ -91,11 +91,12 @@ public final class ActionStatementSupport
         super.onFullDefinitionDeclared(stmt);
 
         if (StmtContextUtils.findFirstDeclaredSubstatement(stmt, InputStatement.class) == null) {
-            ((StatementContextBase<?, ?, ?>) stmt).appendImplicitStatement(InputStatementRFC7950Support.getInstance());
+            ((StatementContextBase<?, ?, ?>) stmt).appendImplicitSubstatement(
+                InputStatementRFC7950Support.getInstance(), null);
         }
-
         if (StmtContextUtils.findFirstDeclaredSubstatement(stmt, OutputStatement.class) == null) {
-            ((StatementContextBase<?, ?, ?>) stmt).appendImplicitStatement(OutputStatementRFC7950Support.getInstance());
+            ((StatementContextBase<?, ?, ?>) stmt).appendImplicitSubstatement(
+                OutputStatementRFC7950Support.getInstance(), null);
         }
     }
 
@@ -103,4 +104,4 @@ public final class ActionStatementSupport
     protected SubstatementValidator getSubstatementValidator() {
         return SUBSTATEMENT_VALIDATOR;
     }
-}
\ No newline at end of file
+}
index f6027b85de46ba104534d933764f50d250f9f7ba..fbcd14d265d22c3659ea99d52a69f306ce726a0e 100644 (file)
@@ -66,11 +66,10 @@ abstract class AbstractRpcStatementSupport
         super.onFullDefinitionDeclared(stmt);
 
         if (StmtContextUtils.findFirstDeclaredSubstatement(stmt, InputStatement.class) == null) {
-            ((StatementContextBase<?, ?, ?>) stmt).appendImplicitStatement(implictInput());
+            ((StatementContextBase<?, ?, ?>) stmt).appendImplicitSubstatement(implictInput(), null);
         }
-
         if (StmtContextUtils.findFirstDeclaredSubstatement(stmt, OutputStatement.class) == null) {
-            ((StatementContextBase<?, ?, ?>) stmt).appendImplicitStatement(implictOutput());
+            ((StatementContextBase<?, ?, ?>) stmt).appendImplicitSubstatement(implictOutput(), null);
         }
     }