Add InferredStatementContext 76/87276/2
authorRobert Varga <robert.varga@pantheon.tech>
Sat, 25 Jan 2020 13:24:53 +0000 (14:24 +0100)
committerRobert Varga <robert.varga@pantheon.tech>
Thu, 30 Jan 2020 09:35:57 +0000 (10:35 +0100)
SubstatementContext implies definition in source, which adds state
which is not necessary. Introduce a separate class to hold statement
contexts which are created during inference.

In order to prevent code duplication, StmtContext methods whose
implementation is relevant only in RootStatementContext are refactored
to dispatch to specialized implementations, making them final in
the process. This also happens to improve inference speed, as lookups
like getBehaviourRegistry() used to iterate over parent axis to root,
now they are taking a direct shortcut to root (which may be 'this').

Since InferredStatementContext derives a number of methods from
its prototype (such as raw argument, etc.), these details are taken
out of StatementContextBase and moved to AbstractResumedStatement.

InferredStatementContext is about 10% smaller than an equivalent
SubstatementContext, leading to smaller inference memory footprint.

JIRA: YANGTOOLS-784
Change-Id: I62eea1dc92756536444676e8765fedd73375933e
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
(cherry picked from commit 3880c99eefb4d8104236fdd17da6d5014f61f63e)
(cherry picked from commit a677c0b472ea2b9eaeeb0dbd32af4ae0f1671ec8)

yang/yang-parser-reactor/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/AbstractResumedStatement.java
yang/yang-parser-reactor/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/InferredStatementContext.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/StatementContextBase.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/uses/UsesStatementImpl.java
yang/yang-parser-spi/src/main/java/org/opendaylight/yangtools/yang/parser/spi/meta/StmtContext.java

index c3a62b8f883c34a99e80302a7b16a6677f994608..ddfe0123dd89efb2000922cb6ea908d159917aaf 100644 (file)
@@ -8,6 +8,7 @@
 package org.opendaylight.yangtools.yang.parser.stmt.reactor;
 
 import static com.google.common.base.Preconditions.checkState;
+import static java.util.Objects.requireNonNull;
 
 import java.util.Collection;
 import java.util.Optional;
@@ -15,6 +16,7 @@ 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.CopyHistory;
 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;
@@ -33,30 +35,58 @@ import org.opendaylight.yangtools.yang.parser.spi.source.StatementWriter.Resumed
  */
 abstract class AbstractResumedStatement<A, D extends DeclaredStatement<A>, E extends EffectiveStatement<A, D>>
         extends StatementContextBase<A, D, E> implements ResumedStatement {
+    private final @NonNull StatementSourceReference statementDeclSource;
+    private final StmtContext<?, ?, ?> originalCtx;
+    private final StmtContext<?, ?, ?> prevCopyCtx;
+    private final String rawArgument;
+
     private StatementMap substatements = StatementMap.empty();
 
+    AbstractResumedStatement(final AbstractResumedStatement<A, D, E> original) {
+        super(original);
+        this.statementDeclSource = original.statementDeclSource;
+        this.rawArgument = original.rawArgument;
+        this.originalCtx = original.getOriginalCtx().orElse(original);
+        this.prevCopyCtx = original;
+        this.substatements = original.substatements;
+    }
+
     AbstractResumedStatement(final StatementDefinitionContext<A, D, E> def, final StatementSourceReference ref,
             final String rawArgument) {
-        super(def, ref, rawArgument);
+        super(def);
+        this.statementDeclSource = requireNonNull(ref);
+        this.rawArgument = def.internArgument(rawArgument);
+        this.originalCtx = null;
+        this.prevCopyCtx = null;
     }
 
     AbstractResumedStatement(final StatementDefinitionContext<A, D, E> def, final StatementSourceReference ref,
             final String rawArgument, final CopyType copyType) {
-        super(def, ref, rawArgument, copyType);
+        super(def, CopyHistory.of(copyType, CopyHistory.original()));
+        this.statementDeclSource = requireNonNull(ref);
+        this.rawArgument = rawArgument;
+        this.originalCtx = null;
+        this.prevCopyCtx = null;
     }
 
-    AbstractResumedStatement(final StatementContextBase<A, D, E> original, final CopyType copyType) {
-        super(original, copyType);
+    @Override
+    public final Optional<StmtContext<?, ?, ?>> getOriginalCtx() {
+        return Optional.ofNullable(originalCtx);
     }
 
-    AbstractResumedStatement(final AbstractResumedStatement<A, D, E> original) {
-        super(original);
-        this.substatements = original.substatements;
+    @Override
+    public final Optional<? extends StmtContext<?, ?, ?>> getPreviousCopyCtx() {
+        return Optional.ofNullable(prevCopyCtx);
     }
 
     @Override
-    public Collection<? extends StmtContext<?, ?, ?>> declaredSubstatements() {
-        return substatements.values();
+    public final StatementSourceReference getStatementSourceReference() {
+        return statementDeclSource;
+    }
+
+    @Override
+    public final String rawStatementArgument() {
+        return rawArgument;
     }
 
     @Override
diff --git a/yang/yang-parser-reactor/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/InferredStatementContext.java b/yang/yang-parser-reactor/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/InferredStatementContext.java
new file mode 100644 (file)
index 0000000..f624560
--- /dev/null
@@ -0,0 +1,235 @@
+/*
+ * 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 java.util.Objects.requireNonNull;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.Optional;
+import java.util.stream.Stream;
+import org.eclipse.jdt.annotation.NonNull;
+import org.opendaylight.yangtools.yang.common.QNameModule;
+import org.opendaylight.yangtools.yang.model.api.SchemaPath;
+import org.opendaylight.yangtools.yang.model.api.YangStmtMapping;
+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.CopyHistory;
+import org.opendaylight.yangtools.yang.parser.spi.meta.CopyType;
+import org.opendaylight.yangtools.yang.parser.spi.meta.NamespaceBehaviour.NamespaceStorageNode;
+import org.opendaylight.yangtools.yang.parser.spi.meta.NamespaceBehaviour.StorageNodeType;
+import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext;
+import org.opendaylight.yangtools.yang.parser.spi.source.StatementSourceReference;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * A statement which has been inferred to exist. Functionally it is equivalent to a SubstatementContext, but it is not
+ * backed by a declaration (and declared statements). It is backed by a prototype StatementContextBase and has only
+ * effective substatements, which are either transformed from that prototype or added by inference.
+ */
+final class InferredStatementContext<A, D extends DeclaredStatement<A>, E extends EffectiveStatement<A, D>>
+        extends StatementContextBase<A, D, E> {
+    private static final Logger LOG = LoggerFactory.getLogger(InferredStatementContext.class);
+
+    private final @NonNull StatementContextBase<A, D, E> prototype;
+    private final @NonNull StatementContextBase<?, ?, ?> parent;
+    private final @NonNull CopyType childCopyType;
+    private final QNameModule targetModule;
+    private final A argument;
+
+    private InferredStatementContext(final InferredStatementContext<A, D, E> original,
+            final StatementContextBase<?, ?, ?> parent) {
+        super(original);
+        this.parent = requireNonNull(parent);
+        this.childCopyType = original.childCopyType;
+        this.targetModule = original.targetModule;
+        this.prototype = original.prototype;
+        this.argument = original.argument;
+    }
+
+    InferredStatementContext(final StatementContextBase<?, ?, ?> parent, final StatementContextBase<A, D, E> prototype,
+            final CopyType myCopyType, final CopyType childCopyType, final QNameModule targetModule) {
+        super(prototype.definition(), CopyHistory.of(myCopyType, prototype.getCopyHistory()));
+        this.parent = requireNonNull(parent);
+        this.prototype = requireNonNull(prototype);
+        this.argument = targetModule == null ? prototype.getStatementArgument()
+                : prototype.definition().adaptArgumentValue(prototype, targetModule);
+        this.childCopyType = requireNonNull(childCopyType);
+        this.targetModule = targetModule;
+
+        // FIXME: YANGTOOLS-784: instantiate these lazily
+        addEffectiveSubstatements(createEffective());
+    }
+
+    @Override
+    public Collection<? extends StatementContextBase<?, ?, ?>> mutableDeclaredSubstatements() {
+        return ImmutableList.of();
+    }
+
+    @Override
+    public Iterable<? extends StmtContext<?, ?, ?>> allSubstatements() {
+        // No need to concat with declared
+        return effectiveSubstatements();
+    }
+
+    @Override
+    public Stream<? extends StmtContext<?, ?, ?>> allSubstatementsStream() {
+        // No need to concat with declared
+        return effectiveSubstatements().stream();
+    }
+
+    @Override
+    public StatementSourceReference getStatementSourceReference() {
+        return prototype.getStatementSourceReference();
+    }
+
+    @Override
+    public String rawStatementArgument() {
+        return prototype.rawStatementArgument();
+    }
+
+    @Override
+    public Optional<StmtContext<?, ?, ?>> getOriginalCtx() {
+        final Optional<StmtContext<?, ?, ?>> orig = prototype.getOriginalCtx();
+        return orig.isPresent() ? orig : Optional.of(prototype);
+    }
+
+    @Override
+    public Optional<? extends StmtContext<?, ?, ?>> getPreviousCopyCtx() {
+        return Optional.of(prototype);
+    }
+
+    @Override
+    InferredStatementContext<A, D, E> reparent(final StatementContextBase<?, ?, ?> newParent) {
+        return new InferredStatementContext<>(this, newParent);
+    }
+
+    // Instantiate this statement's effective substatements. Note this method has side-effects in namespaces and overall
+    // BuildGlobalContext, hence it must be called at most once.
+    private List<Mutable<?, ?, ?>> createEffective() {
+        final Collection<? extends StatementContextBase<?, ?, ?>> declared = prototype.mutableDeclaredSubstatements();
+        final Collection<? extends Mutable<?, ?, ?>> effective = prototype.mutableEffectiveSubstatements();
+        final List<Mutable<?, ?, ?>> buffer = new ArrayList<>(declared.size() + effective.size());
+
+        for (final Mutable<?, ?, ?> stmtContext : declared) {
+            if (stmtContext.isSupportedByFeatures()) {
+                copySubstatement(stmtContext, buffer);
+            }
+        }
+        for (final Mutable<?, ?, ?> stmtContext : effective) {
+            copySubstatement(stmtContext, buffer);
+        }
+
+        return buffer;
+    }
+
+    // Statement copy mess starts here
+    //
+    // FIXME: This is messy and is probably wrong in some corner case. Even if it is correct, the way how it is correct
+    //        relies on hard-coded maps. At the end of the day, the logic needs to be controlled by statement's
+    //        StatementSupport.
+    // FIXME: YANGTOOLS-652: these maps look very much like those in UsesStatementImpl
+    private static final ImmutableSet<YangStmtMapping> REUSED_DEF_SET = ImmutableSet.of(
+        YangStmtMapping.TYPE,
+        YangStmtMapping.TYPEDEF,
+        YangStmtMapping.USES);
+    private static final ImmutableSet<YangStmtMapping> NOCOPY_FROM_GROUPING_SET = ImmutableSet.of(
+        YangStmtMapping.DESCRIPTION,
+        YangStmtMapping.REFERENCE,
+        YangStmtMapping.STATUS);
+
+    private void copySubstatement(final Mutable<?, ?, ?> substatement, final Collection<Mutable<?, ?, ?>> buffer) {
+        final StatementDefinition def = substatement.getPublicDefinition();
+
+        // FIXME: YANGTOOLS-652: formerly known as "isReusedByUses"
+        if (REUSED_DEF_SET.contains(def)) {
+            LOG.debug("Reusing substatement {} for {}", substatement, this);
+            buffer.add(substatement);
+            return;
+        }
+        // FIXME: YANGTOOLS-652: formerly known as "needToCopyByUses" (note inverted check, though)
+        if (NOCOPY_FROM_GROUPING_SET.contains(def)) {
+            // This is to say: if parent of source context is a grouping, ignore this statement.
+            if (YangStmtMapping.GROUPING.equals(substatement.coerceParentContext().getPublicDefinition())) {
+                LOG.debug("Skipping grouping statement {}", substatement);
+                return;
+            }
+        }
+
+        // FIXME: YANGTOOLS-694: we are forcing a copy here, hence even statements not affected by parent, copyType
+        //                       or targetModule (and don't forget its substatements!). This really should be a callout
+        //                       to StatementSupport. Note if that callout is allowed to return an Optional, it can
+        //                       take care at least of the 'grouping from uses' case above.
+        final Mutable<?, ?, ?> copy = childCopyOf(substatement, childCopyType, targetModule);
+        LOG.debug("Copying substatement {} for {} as {}", substatement, this, copy);
+        buffer.add(copy);
+    }
+
+    // Statement copy mess ends here
+
+    /*
+     * KEEP THINGS ORGANIZED!
+     *
+     * below methods exist in the same form in SubstatementContext. If any adjustment is made here, make sure it is
+     * properly updated there.
+     */
+    @Override
+    public Optional<SchemaPath> getSchemaPath() {
+        return substatementGetSchemaPath();
+    }
+
+    @Override
+    public A getStatementArgument() {
+        return argument;
+    }
+
+    @Override
+    public StatementContextBase<?, ?, ?> getParentContext() {
+        return parent;
+    }
+
+    @Override
+    public StorageNodeType getStorageNodeType() {
+        return StorageNodeType.STATEMENT_LOCAL;
+    }
+
+    @Override
+    public NamespaceStorageNode getParentNamespaceStorage() {
+        return parent;
+    }
+
+    @Override
+    public RootStatementContext<?, ?, ?> getRoot() {
+        return parent.getRoot();
+    }
+
+    @Override
+    public boolean isConfiguration() {
+        return isConfiguration(parent);
+    }
+
+    @Override
+    protected boolean isIgnoringIfFeatures() {
+        return isIgnoringIfFeatures(parent);
+    }
+
+    @Override
+    protected boolean isIgnoringConfig() {
+        return isIgnoringConfig(parent);
+    }
+
+    @Override
+    protected boolean isParentSupportedByFeatures() {
+        return parent.isSupportedByFeatures();
+    }
+}
index e0c7cf26365ed5a1afa7dc52195157f4bb3000ad..f10533b5cfb2c3ecf646608a7ea198ba386fcf83 100644 (file)
@@ -21,6 +21,7 @@ import java.util.List;
 import java.util.Map;
 import java.util.Optional;
 import java.util.Set;
+import org.eclipse.jdt.annotation.NonNull;
 import org.eclipse.jdt.annotation.Nullable;
 import org.opendaylight.yangtools.yang.common.YangVersion;
 import org.opendaylight.yangtools.yang.model.api.SchemaPath;
@@ -45,7 +46,7 @@ public class RootStatementContext<A, D extends DeclaredStatement<A>, E extends E
 
     public static final YangVersion DEFAULT_VERSION = YangVersion.VERSION_1;
 
-    private final SourceSpecificContext sourceContext;
+    private final @NonNull SourceSpecificContext sourceContext;
     private final A argument;
 
     private YangVersion rootVersion;
@@ -84,11 +85,6 @@ public class RootStatementContext<A, D extends DeclaredStatement<A>, E extends E
         return sourceContext;
     }
 
-    @Override
-    public Registry getBehaviourRegistry() {
-        return sourceContext;
-    }
-
     @Override
     public StorageNodeType getStorageNodeType() {
         return StorageNodeType.ROOT_STATEMENT_LOCAL;
@@ -119,11 +115,6 @@ public class RootStatementContext<A, D extends DeclaredStatement<A>, E extends E
         return true;
     }
 
-    @Override
-    public boolean isEnabledSemanticVersioning() {
-        return sourceContext.isEnabledSemanticVersioning();
-    }
-
     @Override
     public <K, V, N extends IdentifierNamespace<K, V>> V putToLocalStorage(final Class<N> type, final K key,
             final V value) {
@@ -195,35 +186,6 @@ public class RootStatementContext<A, D extends DeclaredStatement<A>, E extends E
         return null;
     }
 
-    @Override
-    public YangVersion getRootVersion() {
-        return rootVersion == null ? DEFAULT_VERSION : rootVersion;
-    }
-
-    @Override
-    public void setRootVersion(final YangVersion version) {
-        checkArgument(sourceContext.getSupportedVersions().contains(version),
-                "Unsupported yang version %s in %s", version, getStatementSourceReference());
-        checkState(this.rootVersion == null, "Version of root %s has been already set to %s", argument,
-                this.rootVersion);
-        this.rootVersion = requireNonNull(version);
-    }
-
-    @Override
-    public void addMutableStmtToSeal(final MutableStatement mutableStatement) {
-        sourceContext.addMutableStmtToSeal(mutableStatement);
-    }
-
-    @Override
-    public void addRequiredSource(final SourceIdentifier dependency) {
-        checkState(sourceContext.getInProgressPhase() == ModelProcessingPhase.SOURCE_PRE_LINKAGE,
-                "Add required module is allowed only in ModelProcessingPhase.SOURCE_PRE_LINKAGE phase");
-        if (requiredSources.isEmpty()) {
-            requiredSources = new HashSet<>();
-        }
-        requiredSources.add(dependency);
-    }
-
     /**
      * Return the set of required sources.
      *
@@ -233,11 +195,6 @@ public class RootStatementContext<A, D extends DeclaredStatement<A>, E extends E
         return ImmutableSet.copyOf(requiredSources);
     }
 
-    @Override
-    public void setRootIdentifier(final SourceIdentifier identifier) {
-        this.rootIdentifier = requireNonNull(identifier);
-    }
-
     SourceIdentifier getRootIdentifier() {
         return rootIdentifier;
     }
@@ -257,6 +214,43 @@ public class RootStatementContext<A, D extends DeclaredStatement<A>, E extends E
         return true;
     }
 
+    void setRootIdentifierImpl(final SourceIdentifier identifier) {
+        this.rootIdentifier = requireNonNull(identifier);
+    }
+
+    @NonNull Registry getBehaviourRegistryImpl() {
+        return sourceContext;
+    }
+
+    boolean isEnabledSemanticVersioningImpl() {
+        return sourceContext.isEnabledSemanticVersioning();
+    }
+
+    @NonNull YangVersion getRootVersionImpl() {
+        return rootVersion == null ? DEFAULT_VERSION : rootVersion;
+    }
+
+    void setRootVersionImpl(final YangVersion version) {
+        checkArgument(sourceContext.getSupportedVersions().contains(version),
+                "Unsupported yang version %s in %s", version, getStatementSourceReference());
+        checkState(this.rootVersion == null, "Version of root %s has been already set to %s", argument,
+                this.rootVersion);
+        this.rootVersion = requireNonNull(version);
+    }
+
+    void addMutableStmtToSealImpl(final MutableStatement mutableStatement) {
+        sourceContext.addMutableStmtToSeal(mutableStatement);
+    }
+
+    void addRequiredSourceImpl(final SourceIdentifier dependency) {
+        checkState(sourceContext.getInProgressPhase() == ModelProcessingPhase.SOURCE_PRE_LINKAGE,
+                "Add required module is allowed only in ModelProcessingPhase.SOURCE_PRE_LINKAGE phase");
+        if (requiredSources.isEmpty()) {
+            requiredSources = new HashSet<>();
+        }
+        requiredSources.add(dependency);
+    }
+
     @Override
     StatementContextBase<A, D, E> reparent(final StatementContextBase<?, ?, ?> newParent) {
         throw new UnsupportedOperationException("Root statement cannot be reparented to" + newParent);
index e66d84b89349200d449cd8eccd43bf1c7d231549..be0948c463e1a9cbd758f51574de9a0f93e42a6d 100644 (file)
@@ -10,6 +10,7 @@ package org.opendaylight.yangtools.yang.parser.stmt.reactor;
 import static com.google.common.base.Preconditions.checkArgument;
 import static com.google.common.base.Preconditions.checkNotNull;
 import static com.google.common.base.Preconditions.checkState;
+import static com.google.common.base.Verify.verify;
 import static java.util.Objects.requireNonNull;
 
 import com.google.common.annotations.Beta;
@@ -18,7 +19,6 @@ import com.google.common.base.MoreObjects.ToStringHelper;
 import com.google.common.collect.ImmutableCollection;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMultimap;
-import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.Multimap;
 import com.google.common.collect.Multimaps;
 import java.util.ArrayList;
@@ -36,20 +36,29 @@ import org.eclipse.jdt.annotation.NonNull;
 import org.eclipse.jdt.annotation.Nullable;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.common.QNameModule;
-import org.opendaylight.yangtools.yang.model.api.YangStmtMapping;
+import org.opendaylight.yangtools.yang.common.YangVersion;
+import org.opendaylight.yangtools.yang.model.api.SchemaPath;
 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.IdentifierNamespace;
 import org.opendaylight.yangtools.yang.model.api.meta.StatementDefinition;
 import org.opendaylight.yangtools.yang.model.api.meta.StatementSource;
+import org.opendaylight.yangtools.yang.model.api.stmt.AugmentStatement;
 import org.opendaylight.yangtools.yang.model.api.stmt.ConfigStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.DeviationStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.RefineStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.SchemaNodeIdentifier;
+import org.opendaylight.yangtools.yang.model.api.stmt.UsesStatement;
+import org.opendaylight.yangtools.yang.model.repo.api.SourceIdentifier;
 import org.opendaylight.yangtools.yang.parser.spi.meta.CopyHistory;
 import org.opendaylight.yangtools.yang.parser.spi.meta.CopyType;
 import org.opendaylight.yangtools.yang.parser.spi.meta.ImplicitParentAwareStatementSupport;
 import org.opendaylight.yangtools.yang.parser.spi.meta.InferenceException;
 import org.opendaylight.yangtools.yang.parser.spi.meta.ModelActionBuilder;
 import org.opendaylight.yangtools.yang.parser.spi.meta.ModelProcessingPhase;
+import org.opendaylight.yangtools.yang.parser.spi.meta.MutableStatement;
 import org.opendaylight.yangtools.yang.parser.spi.meta.NamespaceBehaviour;
+import org.opendaylight.yangtools.yang.parser.spi.meta.NamespaceBehaviour.Registry;
 import org.opendaylight.yangtools.yang.parser.spi.meta.NamespaceKeyCriterion;
 import org.opendaylight.yangtools.yang.parser.spi.meta.StatementNamespace;
 import org.opendaylight.yangtools.yang.parser.spi.meta.StatementSupport;
@@ -58,7 +67,6 @@ import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext.Mutable;
 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.SupportedFeaturesNamespace;
 import org.opendaylight.yangtools.yang.parser.spi.source.SupportedFeaturesNamespace.SupportedFeatures;
 import org.opendaylight.yangtools.yang.parser.stmt.reactor.NamespaceBehaviourWithListeners.KeyedValueAddedListener;
@@ -123,12 +131,10 @@ public abstract class StatementContextBase<A, D extends DeclaredStatement<A>, E
     private static final int SET_IGNORE_CONFIG = HAVE_IGNORE_CONFIG | IS_IGNORE_CONFIG | SET_CONFIGURATION;
     private static final int SET_IGNORE_IF_FEATURE = HAVE_IGNORE_IF_FEATURE | IS_IGNORE_IF_FEATURE;
 
-    private final @NonNull StatementDefinitionContext<A, D, E> definition;
-    private final @NonNull StatementSourceReference statementDeclSource;
-    private final StmtContext<?, ?, ?> originalCtx;
-    private final StmtContext<?, ?, ?> prevCopyCtx;
     private final CopyHistory copyHistory;
-    private final String rawArgument;
+    // Note: this field can strictly be derived in InferredStatementContext, but it forms the basis of many of our
+    //       operations, hence we want to keep it close by.
+    private final @NonNull StatementDefinitionContext<A, D, E> definition;
 
     private Multimap<ModelProcessingPhase, OnPhaseFinished> phaseListeners = ImmutableMultimap.of();
     private Multimap<ModelProcessingPhase, ContextMutation> phaseMutation = ImmutableMultimap.of();
@@ -151,43 +157,23 @@ public abstract class StatementContextBase<A, D extends DeclaredStatement<A>, E
     // hence improve memory layout.
     private byte flags;
 
-    StatementContextBase(final StatementDefinitionContext<A, D, E> def, final StatementSourceReference ref,
-            final String rawArgument) {
-        this.definition = requireNonNull(def);
-        this.statementDeclSource = requireNonNull(ref);
-        this.rawArgument = def.internArgument(rawArgument);
-        this.copyHistory = CopyHistory.original();
-        this.originalCtx = null;
-        this.prevCopyCtx = null;
-    }
+    // SchemaPath cache for use with SubstatementContext and InferredStatementContext. This hurts RootStatementContext
+    // a bit in terms of size -- but those are only a few and SchemaPath is on its way out anyway.
+    private volatile SchemaPath schemaPath;
 
-    StatementContextBase(final StatementDefinitionContext<A, D, E> def, final StatementSourceReference ref,
-        final String rawArgument, final CopyType copyType) {
-        this.definition = requireNonNull(def);
-        this.statementDeclSource = requireNonNull(ref);
-        this.rawArgument = rawArgument;
-        this.copyHistory = CopyHistory.of(copyType, CopyHistory.original());
-        this.originalCtx = null;
-        this.prevCopyCtx = null;
+    StatementContextBase(final StatementContextBase<A, D, E> original) {
+        this.copyHistory = original.copyHistory;
+        this.definition = original.definition;
     }
 
-    StatementContextBase(final StatementContextBase<A, D, E> original, final CopyType copyType) {
-        this.definition = original.definition;
-        this.statementDeclSource = original.statementDeclSource;
-        this.rawArgument = original.rawArgument;
-        this.copyHistory = CopyHistory.of(copyType, original.getCopyHistory());
-        this.originalCtx = original.getOriginalCtx().orElse(original);
-        this.prevCopyCtx = original;
+    StatementContextBase(final StatementDefinitionContext<A, D, E> def) {
+        this.definition = requireNonNull(def);
+        this.copyHistory = CopyHistory.original();
     }
 
-    StatementContextBase(final StatementContextBase<A, D, E> original) {
-        this.definition = original.definition;
-        this.statementDeclSource = original.statementDeclSource;
-        this.rawArgument = original.rawArgument;
-        this.copyHistory = original.getCopyHistory();
-        this.originalCtx = original.getOriginalCtx().orElse(original);
-        this.prevCopyCtx = original;
-        this.effective = original.effective;
+    StatementContextBase(final StatementDefinitionContext<A, D, E> def, final CopyHistory copyHistory) {
+        this.definition = requireNonNull(def);
+        this.copyHistory = requireNonNull(copyHistory);
     }
 
     @Override
@@ -261,16 +247,6 @@ public abstract class StatementContextBase<A, D extends DeclaredStatement<A>, E
         return copyHistory;
     }
 
-    @Override
-    public Optional<StmtContext<?, ?, ?>> getOriginalCtx() {
-        return Optional.ofNullable(originalCtx);
-    }
-
-    @Override
-    public Optional<? extends StmtContext<?, ?, ?>> getPreviousCopyCtx() {
-        return Optional.ofNullable(prevCopyCtx);
-    }
-
     @Override
     public ModelProcessingPhase getCompletedPhase() {
         return completedPhase;
@@ -293,28 +269,48 @@ public abstract class StatementContextBase<A, D extends DeclaredStatement<A>, E
     public abstract RootStatementContext<?, ?, ?> getRoot();
 
     @Override
-    public StatementSource getStatementSource() {
-        return statementDeclSource.getStatementSource();
+    public final @NonNull Registry getBehaviourRegistry() {
+        return getRoot().getBehaviourRegistryImpl();
     }
 
     @Override
-    public StatementSourceReference getStatementSourceReference() {
-        return statementDeclSource;
+    public final YangVersion getRootVersion() {
+        return getRoot().getRootVersionImpl();
     }
 
     @Override
-    public final String rawStatementArgument() {
-        return rawArgument;
+    public final void setRootVersion(final YangVersion version) {
+        getRoot().setRootVersionImpl(version);
     }
 
     @Override
-    public abstract Collection<? extends StatementContextBase<?, ?, ?>> mutableDeclaredSubstatements();
+    public final void addMutableStmtToSeal(final MutableStatement mutableStatement) {
+        getRoot().addMutableStmtToSealImpl(mutableStatement);
+    }
 
     @Override
-    public Collection<? extends StmtContext<?, ?, ?>> effectiveSubstatements() {
-        return mutableEffectiveSubstatements();
+    public final void addRequiredSource(final SourceIdentifier dependency) {
+        getRoot().addRequiredSourceImpl(dependency);
     }
 
+    @Override
+    public final void setRootIdentifier(final SourceIdentifier identifier) {
+        getRoot().setRootIdentifierImpl(identifier);
+    }
+
+    @Override
+    public final boolean isEnabledSemanticVersioning() {
+        return getRoot().isEnabledSemanticVersioningImpl();
+    }
+
+    @Override
+    public StatementSource getStatementSource() {
+        return getStatementSourceReference().getStatementSource();
+    }
+
+    @Override
+    public abstract Collection<? extends StatementContextBase<?, ?, ?>> mutableDeclaredSubstatements();
+
     @Override
     public Collection<? extends Mutable<?, ?, ?>> mutableEffectiveSubstatements() {
         if (effective instanceof ImmutableCollection) {
@@ -468,7 +464,7 @@ public abstract class StatementContextBase<A, D extends DeclaredStatement<A>, E
         checkArgument(completedPhase == ModelProcessingPhase.FULL_DECLARATION
                 || completedPhase == ModelProcessingPhase.EFFECTIVE_MODEL);
         if (declaredInstance == null) {
-            declaredInstance = definition().getFactory().createDeclared(this);
+            declaredInstance = definition.getFactory().createDeclared(this);
         }
         return declaredInstance;
     }
@@ -476,7 +472,7 @@ public abstract class StatementContextBase<A, D extends DeclaredStatement<A>, E
     @Override
     public E buildEffective() {
         if (effectiveInstance == null) {
-            effectiveInstance = definition().getFactory().createEffective(this);
+            effectiveInstance = definition.getFactory().createEffective(this);
         }
         return effectiveInstance;
     }
@@ -565,7 +561,7 @@ public abstract class StatementContextBase<A, D extends DeclaredStatement<A>, E
      * Ends declared section of current node.
      */
     void endDeclared(final ModelProcessingPhase phase) {
-        definition().onDeclarationFinished(this, phase);
+        definition.onDeclarationFinished(this, phase);
     }
 
     /**
@@ -579,7 +575,7 @@ public abstract class StatementContextBase<A, D extends DeclaredStatement<A>, E
 
     @Override
     protected void checkLocalNamespaceAllowed(final Class<? extends IdentifierNamespace<?, ?>> type) {
-        definition().checkNamespaceAllowed(type);
+        definition.checkNamespaceAllowed(type);
     }
 
     @Override
@@ -661,7 +657,7 @@ public abstract class StatementContextBase<A, D extends DeclaredStatement<A>, E
 
     @Override
     public StatementDefinition getPublicDefinition() {
-        return definition().getPublicView();
+        return definition.getPublicView();
     }
 
     @Override
@@ -732,14 +728,17 @@ public abstract class StatementContextBase<A, D extends DeclaredStatement<A>, E
         checkState(stmt.getCompletedPhase() == ModelProcessingPhase.EFFECTIVE_MODEL,
                 "Attempted to copy statement %s which has completed phase %s", stmt, stmt.getCompletedPhase());
 
-        checkArgument(stmt instanceof SubstatementContext, "Unsupported statement %s", stmt);
+        checkArgument(stmt instanceof StatementContextBase, "Unsupported statement %s", stmt);
+        return childCopyOf((StatementContextBase<X, Y, Z>)stmt, type, targetModule);
+    }
 
-        final SubstatementContext<X, Y, Z> original = (SubstatementContext<X, Y, Z>)stmt;
+    private <X, Y extends DeclaredStatement<X>, Z extends EffectiveStatement<X, Y>> Mutable<X, Y, Z> childCopyOf(
+            final StatementContextBase<X, Y, Z> original, final CopyType type, final QNameModule targetModule) {
         final Optional<StatementSupport<?, ?, ?>> implicitParent = definition.getImplicitParentFor(
             original.getPublicDefinition());
 
-        final SubstatementContext<X, Y, Z> result;
-        final SubstatementContext<X, Y, Z> copy;
+        final StatementContextBase<X, Y, Z> result;
+        final InferredStatementContext<X, Y, Z> copy;
 
         if (implicitParent.isPresent()) {
             final StatementDefinitionContext<?, ?, ?> def = new StatementDefinitionContext<>(implicitParent.get());
@@ -760,14 +759,13 @@ public abstract class StatementContextBase<A, D extends DeclaredStatement<A>, E
                     childCopyType = type;
             }
 
-            copy = new SubstatementContext<>(original, result, childCopyType, targetModule);
+            copy = new InferredStatementContext<>(result, original, childCopyType, type, targetModule);
             result.addEffectiveSubstatement(copy);
         } else {
-            result = copy = new SubstatementContext<>(original, this, type, targetModule);
+            result = copy = new InferredStatementContext<>(this, original, type, type, targetModule);
         }
 
-        original.definition().onStatementAdded(copy);
-        original.copyTo(copy, type, targetModule);
+        original.definition.onStatementAdded(copy);
         return result;
     }
 
@@ -856,7 +854,7 @@ public abstract class StatementContextBase<A, D extends DeclaredStatement<A>, E
         if (fl != 0) {
             return fl == SET_IGNORE_CONFIG;
         }
-        if (definition().isIgnoringConfig() || parent.isIgnoringConfig()) {
+        if (definition.isIgnoringConfig() || parent.isIgnoringConfig()) {
             flags |= SET_IGNORE_CONFIG;
             return true;
         }
@@ -877,7 +875,7 @@ public abstract class StatementContextBase<A, D extends DeclaredStatement<A>, E
         if (fl != 0) {
             return fl == SET_IGNORE_IF_FEATURE;
         }
-        if (definition().isIgnoringIfFeatures() || parent.isIgnoringIfFeatures()) {
+        if (definition.isIgnoringIfFeatures() || parent.isIgnoringIfFeatures()) {
             flags |= SET_IGNORE_IF_FEATURE;
             return true;
         }
@@ -886,63 +884,55 @@ public abstract class StatementContextBase<A, D extends DeclaredStatement<A>, E
         return false;
     }
 
-    final void copyTo(final StatementContextBase<?, ?, ?> target, final CopyType typeOfCopy,
-            @Nullable final QNameModule targetModule) {
-        final Collection<? extends StatementContextBase<?, ?, ?>> declared = mutableDeclaredSubstatements();
-        final Collection<Mutable<?, ?, ?>> buffer = new ArrayList<>(declared.size() + effective.size());
-
-        for (final Mutable<?, ?, ?> stmtContext : declared) {
-            if (stmtContext.isSupportedByFeatures()) {
-                copySubstatement(stmtContext, target, typeOfCopy, targetModule, buffer);
+    // Exists only to support SubstatementContext/InferredStatementContext
+    final @NonNull Optional<SchemaPath> substatementGetSchemaPath() {
+        SchemaPath local = schemaPath;
+        if (local == null) {
+            synchronized (this) {
+                local = schemaPath;
+                if (local == null) {
+                    local = createSchemaPath(coerceParentContext());
+                    schemaPath = local;
+                }
             }
         }
-        for (final Mutable<?, ?, ?> stmtContext : effective) {
-            copySubstatement(stmtContext, target, typeOfCopy, targetModule, buffer);
-        }
 
-        target.addEffectiveSubstatements(buffer);
+        return Optional.ofNullable(local);
     }
 
-    private void copySubstatement(final Mutable<?, ?, ?> stmtContext,  final Mutable<?, ?, ?> target,
-            final CopyType typeOfCopy, final QNameModule newQNameModule, final Collection<Mutable<?, ?, ?>> buffer) {
-        if (needToCopyByUses(stmtContext)) {
-            final Mutable<?, ?, ?> copy = target.childCopyOf(stmtContext, typeOfCopy, newQNameModule);
-            LOG.debug("Copying substatement {} for {} as {}", stmtContext, this, copy);
-            buffer.add(copy);
-        } else if (isReusedByUses(stmtContext)) {
-            LOG.debug("Reusing substatement {} for {}", stmtContext, this);
-            buffer.add(stmtContext);
-        } else {
-            LOG.debug("Skipping statement {}", stmtContext);
-        }
-    }
+    private SchemaPath createSchemaPath(final Mutable<?, ?, ?> parent) {
+        final Optional<SchemaPath> maybeParentPath = parent.getSchemaPath();
+        verify(maybeParentPath.isPresent(), "Parent %s does not have a SchemaPath", parent);
+        final SchemaPath parentPath = maybeParentPath.get();
 
-    // FIXME: revise this, as it seems to be wrong
-    private static final ImmutableSet<YangStmtMapping> NOCOPY_FROM_GROUPING_SET = ImmutableSet.of(
-        YangStmtMapping.DESCRIPTION,
-        YangStmtMapping.REFERENCE,
-        YangStmtMapping.STATUS);
-    private static final ImmutableSet<YangStmtMapping> REUSED_DEF_SET = ImmutableSet.of(
-        YangStmtMapping.TYPE,
-        YangStmtMapping.TYPEDEF,
-        YangStmtMapping.USES);
+        if (StmtContextUtils.isUnknownStatement(this)) {
+            return parentPath.createChild(getPublicDefinition().getStatementName());
+        }
+        final Object argument = getStatementArgument();
+        if (argument instanceof QName) {
+            final QName qname = (QName) argument;
+            if (StmtContextUtils.producesDeclared(this, UsesStatement.class)) {
+                return maybeParentPath.orElse(null);
+            }
 
-    private static boolean needToCopyByUses(final StmtContext<?, ?, ?> stmtContext) {
-        final StatementDefinition def = stmtContext.getPublicDefinition();
-        if (REUSED_DEF_SET.contains(def)) {
-            LOG.debug("Will reuse {} statement {}", def, stmtContext);
-            return false;
+            return parentPath.createChild(qname);
         }
-        if (NOCOPY_FROM_GROUPING_SET.contains(def)) {
-            return !YangStmtMapping.GROUPING.equals(stmtContext.coerceParentContext().getPublicDefinition());
+        if (argument instanceof String) {
+            // FIXME: This may yield illegal argument exceptions
+            final Optional<StmtContext<?, ?, ?>> originalCtx = getOriginalCtx();
+            final QName qname = StmtContextUtils.qnameFromArgument(originalCtx.orElse(this), (String) argument);
+            return parentPath.createChild(qname);
         }
+        if (argument instanceof SchemaNodeIdentifier
+                && (StmtContextUtils.producesDeclared(this, AugmentStatement.class)
+                        || StmtContextUtils.producesDeclared(this, RefineStatement.class)
+                        || StmtContextUtils.producesDeclared(this, DeviationStatement.class))) {
 
-        LOG.debug("Will copy {} statement {}", def, stmtContext);
-        return true;
-    }
+            return parentPath.createChild(((SchemaNodeIdentifier) argument).getPathFromRoot());
+        }
 
-    private static boolean isReusedByUses(final StmtContext<?, ?, ?> stmtContext) {
-        return REUSED_DEF_SET.contains(stmtContext.getPublicDefinition());
+        // FIXME: this does not look right
+        return maybeParentPath.orElse(null);
     }
 
     @Override
@@ -951,6 +941,6 @@ public abstract class StatementContextBase<A, D extends DeclaredStatement<A>, E
     }
 
     protected ToStringHelper addToStringAttributes(final ToStringHelper toStringHelper) {
-        return toStringHelper.add("definition", definition).add("rawArgument", rawArgument);
+        return toStringHelper.add("definition", definition).add("rawArgument", rawStatementArgument());
     }
 }
index ea4fa1b91e142a21dd5234c5742eb11bff9c184f..503cd821d96ed82e8c70e00dae491559808f5f41 100644 (file)
@@ -9,27 +9,13 @@ package org.opendaylight.yangtools.yang.parser.stmt.reactor;
 
 import static java.util.Objects.requireNonNull;
 
-import com.google.common.base.Verify;
 import java.util.Optional;
-import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.common.QNameModule;
-import org.opendaylight.yangtools.yang.common.YangVersion;
 import org.opendaylight.yangtools.yang.model.api.SchemaPath;
 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.stmt.AugmentStatement;
-import org.opendaylight.yangtools.yang.model.api.stmt.DeviationStatement;
-import org.opendaylight.yangtools.yang.model.api.stmt.RefineStatement;
-import org.opendaylight.yangtools.yang.model.api.stmt.SchemaNodeIdentifier;
-import org.opendaylight.yangtools.yang.model.api.stmt.UsesStatement;
-import org.opendaylight.yangtools.yang.model.repo.api.SourceIdentifier;
 import org.opendaylight.yangtools.yang.parser.spi.meta.CopyType;
-import org.opendaylight.yangtools.yang.parser.spi.meta.MutableStatement;
 import org.opendaylight.yangtools.yang.parser.spi.meta.NamespaceBehaviour.NamespaceStorageNode;
-import org.opendaylight.yangtools.yang.parser.spi.meta.NamespaceBehaviour.Registry;
 import org.opendaylight.yangtools.yang.parser.spi.meta.NamespaceBehaviour.StorageNodeType;
-import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext;
-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
@@ -37,7 +23,12 @@ final class SubstatementContext<A, D extends DeclaredStatement<A>, E extends Eff
     private final StatementContextBase<?, ?, ?> parent;
     private final A argument;
 
-    private volatile SchemaPath schemaPath;
+    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.argument;
+    }
 
     SubstatementContext(final StatementContextBase<?, ?, ?> parent, final StatementDefinitionContext<A, D, E> def,
             final StatementSourceReference ref, final String rawArgument) {
@@ -46,26 +37,34 @@ final class SubstatementContext<A, D extends DeclaredStatement<A>, E extends Eff
         this.argument = def.parseArgumentValue(this, rawStatementArgument());
     }
 
+    // FIXME: YANGTOOLS-784: this constructor is only called in contexts where a different implementation
+    //                       would be more appropriate
     SubstatementContext(final StatementContextBase<?, ?, ?> parent, final StatementDefinitionContext<A, D, E> def,
-        final StatementSourceReference ref, final String rawArgument, final A argument, final CopyType copyType) {
+            final StatementSourceReference ref, final String rawArgument, final A argument, final CopyType copyType) {
         super(def, ref, rawArgument, copyType);
         this.parent = requireNonNull(parent, "Parent must not be null");
         this.argument = argument;
     }
 
-    SubstatementContext(final StatementContextBase<A, D, E> original, final StatementContextBase<?, ?, ?> parent,
-            final CopyType copyType, final QNameModule targetModule) {
-        super(original, copyType);
-        this.parent = requireNonNull(parent, "Parent must not be null");
-        this.argument = targetModule == null ? original.getStatementArgument()
-                : original.definition().adaptArgumentValue(original, targetModule);
+    @Override
+    SubstatementContext<A, D, E> reparent(final StatementContextBase<?, ?, ?> newParent) {
+        return new SubstatementContext<>(this, newParent);
     }
 
-    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.argument;
+    /*
+     * KEEP THINGS ORGANIZED!
+     *
+     * below methods exist in the same form in InferredStatementContext. If any adjustment is made here, make sure it is
+     * properly updated there.
+     */
+    @Override
+    public Optional<SchemaPath> getSchemaPath() {
+        return substatementGetSchemaPath();
+    }
+
+    @Override
+    public A getStatementArgument() {
+        return argument;
     }
 
     @Override
@@ -83,106 +82,16 @@ final class SubstatementContext<A, D extends DeclaredStatement<A>, E extends Eff
         return parent;
     }
 
-    @Override
-    public Registry getBehaviourRegistry() {
-        return parent.getBehaviourRegistry();
-    }
-
     @Override
     public RootStatementContext<?, ?, ?> getRoot() {
         return parent.getRoot();
     }
 
-    @Override
-    public A getStatementArgument() {
-        return argument;
-    }
-
-    private SchemaPath createSchemaPath() {
-        final Optional<SchemaPath> maybeParentPath = parent.getSchemaPath();
-        Verify.verify(maybeParentPath.isPresent(), "Parent %s does not have a SchemaPath", parent);
-        final SchemaPath parentPath = maybeParentPath.get();
-
-        if (StmtContextUtils.isUnknownStatement(this)) {
-            return parentPath.createChild(getPublicDefinition().getStatementName());
-        }
-        if (argument instanceof QName) {
-            final QName qname = (QName) argument;
-            if (StmtContextUtils.producesDeclared(this, UsesStatement.class)) {
-                return maybeParentPath.orElse(null);
-            }
-
-            return parentPath.createChild(qname);
-        }
-        if (argument instanceof String) {
-            // FIXME: This may yield illegal argument exceptions
-            final Optional<StmtContext<?, ?, ?>> originalCtx = getOriginalCtx();
-            final QName qname = StmtContextUtils.qnameFromArgument(originalCtx.orElse(this), (String) argument);
-            return parentPath.createChild(qname);
-        }
-        if (argument instanceof SchemaNodeIdentifier
-                && (StmtContextUtils.producesDeclared(this, AugmentStatement.class)
-                        || StmtContextUtils.producesDeclared(this, RefineStatement.class)
-                        || StmtContextUtils.producesDeclared(this, DeviationStatement.class))) {
-
-            return parentPath.createChild(((SchemaNodeIdentifier) argument).getPathFromRoot());
-        }
-
-        // FIXME: this does not look right
-        return maybeParentPath.orElse(null);
-    }
-
-    @Override
-    public Optional<SchemaPath> getSchemaPath() {
-        SchemaPath local = schemaPath;
-        if (local == null) {
-            synchronized (this) {
-                local = schemaPath;
-                if (local == null) {
-                    local = createSchemaPath();
-                    schemaPath = local;
-                }
-            }
-        }
-
-        return Optional.ofNullable(local);
-    }
-
     @Override
     public boolean isConfiguration() {
         return isConfiguration(parent);
     }
 
-    @Override
-    public boolean isEnabledSemanticVersioning() {
-        return parent.isEnabledSemanticVersioning();
-    }
-
-    @Override
-    public YangVersion getRootVersion() {
-        return getRoot().getRootVersion();
-    }
-
-    @Override
-    public void setRootVersion(final YangVersion version) {
-        getRoot().setRootVersion(version);
-    }
-
-    @Override
-    public void addMutableStmtToSeal(final MutableStatement mutableStatement) {
-        getRoot().addMutableStmtToSeal(mutableStatement);
-    }
-
-    @Override
-    public void addRequiredSource(final SourceIdentifier dependency) {
-        getRoot().addRequiredSource(dependency);
-    }
-
-    @Override
-    public void setRootIdentifier(final SourceIdentifier identifier) {
-        getRoot().setRootIdentifier(identifier);
-    }
-
     @Override
     protected boolean isIgnoringIfFeatures() {
         return isIgnoringIfFeatures(parent);
@@ -197,9 +106,4 @@ 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 8e5df96d3e4126866f3273d0df33476a3630f436..922e296857f758a2ccd45ecc58203348622fb031 100644 (file)
@@ -89,6 +89,7 @@ final class UsesStatementImpl extends AbstractDeclaredStatement<QName> implement
         }
     }
 
+    // FIXME: YANGTOOLS-652: these maps look very much like those in InferredStatementContext
     private static final ImmutableSet<YangStmtMapping> TOP_REUSED_DEF_SET = ImmutableSet.of(
         YangStmtMapping.TYPE,
         YangStmtMapping.TYPEDEF);
index e8269a3ca7a2daadfbf3d277387a13bf604650dd..6ce51ab3a21478a96adcfb7b246427339e7fe696 100644 (file)
@@ -281,8 +281,18 @@ public interface StmtContext<A, D extends DeclaredStatement<A>, E extends Effect
             return childCopyOf(stmt, type, null);
         }
 
+        @Override
+        default Collection<? extends StmtContext<?, ?, ?>> declaredSubstatements() {
+            return mutableDeclaredSubstatements();
+        }
+
         @NonNull Collection<? extends Mutable<?, ?, ?>> mutableDeclaredSubstatements();
 
+        @Override
+        default Collection<? extends StmtContext<?, ?, ?>> effectiveSubstatements() {
+            return mutableEffectiveSubstatements();
+        }
+
         @NonNull Collection<? extends Mutable<?, ?, ?>> mutableEffectiveSubstatements();
 
         /**