Clarify NamespaceStorageSupport.getParentNamespaceStorage()
[yangtools.git] / yang / yang-parser-reactor / src / main / java / org / opendaylight / yangtools / yang / parser / stmt / reactor / SourceSpecificContext.java
index 6a526bf581669c78e7c5c91b19143631f6548c0d..7b717fbeec4794f6cace2584cb57eadd9e5af1ff 100644 (file)
@@ -7,8 +7,11 @@
  */
 package org.opendaylight.yangtools.yang.parser.stmt.reactor;
 
-import com.google.common.base.Preconditions;
-import com.google.common.base.Verify;
+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.collect.HashMultimap;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.Multimap;
@@ -20,8 +23,7 @@ import java.util.List;
 import java.util.Map;
 import java.util.Objects;
 import java.util.Optional;
-import java.util.Set;
-import javax.annotation.Nullable;
+import org.eclipse.jdt.annotation.NonNull;
 import org.opendaylight.yangtools.concepts.Mutable;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.common.QNameModule;
@@ -29,12 +31,10 @@ import org.opendaylight.yangtools.yang.common.YangVersion;
 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.StatementSource;
 import org.opendaylight.yangtools.yang.model.repo.api.SourceIdentifier;
 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.NamespaceStorageNode;
 import org.opendaylight.yangtools.yang.parser.spi.meta.NamespaceBehaviour.StorageNodeType;
@@ -59,9 +59,8 @@ import org.opendaylight.yangtools.yang.parser.spi.source.StatementStreamSource;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-public class SourceSpecificContext implements NamespaceStorageNode, NamespaceBehaviour.Registry, Mutable {
-
-    public enum PhaseCompletionProgress {
+final class SourceSpecificContext implements NamespaceStorageNode, NamespaceBehaviour.Registry, Mutable {
+    enum PhaseCompletionProgress {
         NO_PROGRESS,
         PROGRESS,
         FINISHED
@@ -72,8 +71,10 @@ public class SourceSpecificContext implements NamespaceStorageNode, NamespaceBeh
     private final Multimap<ModelProcessingPhase, ModifierImpl> modifiers = HashMultimap.create();
     private final QNameToStatementDefinitionMap qnameToStmtDefMap = new QNameToStatementDefinitionMap();
     private final PrefixToModuleMap prefixToModuleMap = new PrefixToModuleMap();
-    private final BuildGlobalContext currentContext;
-    private final StatementStreamSource source;
+    private final @NonNull BuildGlobalContext globalContext;
+
+    // Freed as soon as we complete ModelProcessingPhase.EFFECTIVE_MODEL
+    private StatementStreamSource source;
 
     /*
      * "imported" namespaces in this source -- this points to RootStatementContexts of
@@ -85,44 +86,29 @@ public class SourceSpecificContext implements NamespaceStorageNode, NamespaceBeh
     private ModelProcessingPhase inProgressPhase;
     private RootStatementContext<?, ?, ?> root;
 
-    SourceSpecificContext(final BuildGlobalContext currentContext, final StatementStreamSource source) {
-        this.currentContext = Preconditions.checkNotNull(currentContext);
-        this.source = Preconditions.checkNotNull(source);
+    SourceSpecificContext(final BuildGlobalContext globalContext, final StatementStreamSource source) {
+        this.globalContext = requireNonNull(globalContext);
+        this.source = requireNonNull(source);
     }
 
-    boolean isEnabledSemanticVersioning() {
-        return currentContext.isEnabledSemanticVersioning();
+    @NonNull BuildGlobalContext globalContext() {
+        return globalContext;
     }
 
     ModelProcessingPhase getInProgressPhase() {
         return inProgressPhase;
     }
 
-    Optional<StatementContextBase<?, ?, ?>> lookupDeclaredChild(final StatementContextBase<?, ?, ?> 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);
-        while (existing != null && StatementSource.CONTEXT == existing.getStatementSource()) {
-            existing = existing.lookupSubstatement(childId);
-        }
-
-        return Optional.ofNullable(existing);
-    }
-
-    StatementContextBase<?, ?, ?> createDeclaredChild(final StatementContextBase<?, ?, ?> current, final int childId,
-            final QName name, final String argument, final StatementSourceReference ref) {
-        StatementDefinitionContext<?, ?, ?> def = currentContext.getStatementDefinition(getRootVersion(), name);
+    AbstractResumedStatement<?, ?, ?> createDeclaredChild(final AbstractResumedStatement<?, ?, ?> current,
+            final int childId, final QName name, final String argument, final StatementSourceReference ref) {
+        StatementDefinitionContext<?, ?, ?> def = globalContext.getStatementDefinition(getRootVersion(), name);
         if (def == null) {
-            def = currentContext.getModelDefinedStatementDefinition(name);
+            def = globalContext.getModelDefinedStatementDefinition(name);
             if (def == null) {
                 final StatementSupport<?, ?, ?> extension = qnameToStmtDefMap.get(name);
                 if (extension != null) {
                     def = new StatementDefinitionContext<>(extension);
-                    currentContext.putModelDefinedStatementDefinition(name, def);
+                    globalContext.putModelDefinedStatementDefinition(name, def);
                 }
             }
         } else if (current != null && StmtContextUtils.isUnrecognizedStatement(current)) {
@@ -130,13 +116,13 @@ public class SourceSpecificContext implements NamespaceStorageNode, NamespaceBeh
              * This code wraps statements encountered inside an extension so
              * they do not get confused with regular statements.
              */
-            def = Preconditions.checkNotNull(current.definition().getAsUnknownStatementDefinition(def),
+            def = checkNotNull(current.definition().getAsUnknownStatementDefinition(def),
                     "Unable to create unknown statement definition of yang statement %s in unknown statement %s", def,
                     current);
         }
 
-        InferenceException.throwIfNull(def, ref, "Statement %s does not have type mapping defined.", name);
-        if (def.hasArgument()) {
+        if (InferenceException.throwIfNull(def, ref, "Statement %s does not have type mapping defined.", name)
+                .getArgumentDefinition().isPresent()) {
             SourceException.throwIfNull(argument, ref, "Statement %s requires an argument", name);
         } else {
             SourceException.throwIf(argument != null, ref, "Statement %s does not take argument", name);
@@ -170,9 +156,8 @@ public class SourceSpecificContext implements NamespaceStorageNode, NamespaceBeh
             final QName rootStatement = root.definition().getStatementName();
             final String rootArgument = root.rawStatementArgument();
 
-            Preconditions.checkState(Objects.equals(def.getStatementName(), rootStatement)
-                && Objects.equals(argument, rootArgument), "Root statement was already defined as '%s %s'.",
-                rootStatement, rootArgument);
+            checkState(Objects.equals(def.getStatementName(), rootStatement) && Objects.equals(argument, rootArgument),
+                "Root statement was already defined as '%s %s'.", rootStatement, rootArgument);
         }
         return root;
     }
@@ -199,14 +184,14 @@ public class SourceSpecificContext implements NamespaceStorageNode, NamespaceBeh
     }
 
     void startPhase(final ModelProcessingPhase phase) {
-        @Nullable final ModelProcessingPhase previousPhase = phase.getPreviousPhase();
-        Verify.verify(Objects.equals(previousPhase, finishedPhase),
+        final ModelProcessingPhase previousPhase = phase.getPreviousPhase();
+        verify(Objects.equals(previousPhase, finishedPhase),
             "Phase sequencing violation: previous phase should be %s, source %s has %s", previousPhase, source,
             finishedPhase);
 
         final Collection<ModifierImpl> previousModifiers = modifiers.get(previousPhase);
-        Preconditions.checkState(previousModifiers.isEmpty(),
-            "Previous phase %s has unresolved modifiers %s in source %s", previousPhase, previousModifiers, source);
+        checkState(previousModifiers.isEmpty(), "Previous phase %s has unresolved modifiers %s in source %s",
+            previousPhase, previousModifiers, source);
 
         inProgressPhase = phase;
         LOG.debug("Source {} started phase {}", source, phase);
@@ -218,7 +203,7 @@ public class SourceSpecificContext implements NamespaceStorageNode, NamespaceBeh
                 importedNamespaces = new ArrayList<>(1);
             }
 
-            Verify.verify(value instanceof RootStatementContext);
+            verify(value instanceof RootStatementContext);
             importedNamespaces.add((RootStatementContext<?, ?, ?>) value);
         }
     }
@@ -265,7 +250,6 @@ public class SourceSpecificContext implements NamespaceStorageNode, NamespaceBeh
         return null;
     }
 
-    @Nullable
     @Override
     public <K, V, N extends IdentifierNamespace<K, V>> Map<K, V> getAllFromLocalStorage(final Class<N> type) {
         final Map<K, V> potentialLocal = getRoot().getAllFromLocalStorage(type);
@@ -286,29 +270,32 @@ public class SourceSpecificContext implements NamespaceStorageNode, NamespaceBeh
     @Override
     public <K, V, N extends IdentifierNamespace<K, V>> NamespaceBehaviour<K, V, N> getNamespaceBehaviour(
             final Class<N> type) {
-        return currentContext.getNamespaceBehaviour(type);
+        return globalContext.getNamespaceBehaviour(type);
     }
 
     @Override
-    public NamespaceStorageNode getParentNamespaceStorage() {
-        return currentContext;
+    public BuildGlobalContext getParentNamespaceStorage() {
+        return globalContext;
     }
 
-    PhaseCompletionProgress tryToCompletePhase(final ModelProcessingPhase phase) throws SourceException {
+    PhaseCompletionProgress tryToCompletePhase(final ModelProcessingPhase phase) {
         final Collection<ModifierImpl> currentPhaseModifiers = modifiers.get(phase);
 
         boolean hasProgressed = tryToProgress(currentPhaseModifiers);
-
-        Preconditions.checkNotNull(this.root, "Malformed source. Valid root element is missing.");
-        final boolean phaseCompleted = root.tryToCompletePhase(phase);
+        final boolean phaseCompleted = requireNonNull(root, "Malformed source. Valid root element is missing.")
+                .tryToCompletePhase(phase);
 
         hasProgressed |= tryToProgress(currentPhaseModifiers);
 
         if (phaseCompleted && currentPhaseModifiers.isEmpty()) {
             finishedPhase = phase;
             LOG.debug("Source {} finished phase {}", source, phase);
+            if (phase == ModelProcessingPhase.EFFECTIVE_MODEL) {
+                // We have the effective model acquired, which is the final phase of source interaction.
+                LOG.trace("Releasing source {}", source);
+                source = null;
+            }
             return PhaseCompletionProgress.FINISHED;
-
         }
 
         return hasProgressed ? PhaseCompletionProgress.PROGRESS : PhaseCompletionProgress.NO_PROGRESS;
@@ -329,7 +316,7 @@ public class SourceSpecificContext implements NamespaceStorageNode, NamespaceBeh
         return hasProgressed;
     }
 
-    ModelActionBuilder newInferenceAction(final ModelProcessingPhase phase) {
+    @NonNull ModelActionBuilder newInferenceAction(final @NonNull ModelProcessingPhase phase) {
         final ModifierImpl action = new ModifierImpl();
         modifiers.put(phase, action);
         return action;
@@ -363,7 +350,7 @@ public class SourceSpecificContext implements NamespaceStorageNode, NamespaceBeh
         return Optional.of(e);
     }
 
-    void loadStatements() throws SourceException {
+    void loadStatements() {
         LOG.trace("Source {} loading statements for phase {}", source, inProgressPhase);
 
         switch (inProgressPhase) {
@@ -388,7 +375,7 @@ public class SourceSpecificContext implements NamespaceStorageNode, NamespaceBeh
     }
 
     private PrefixToModule preLinkagePrefixes() {
-        final PrefixToModuleMap preLinkagePrefixes = new PrefixToModuleMap(true);
+        final PrefixToModuleMap preLinkagePrefixes = new PrefixToModuleMap();
         final Map<String, URI> prefixToNamespaceMap = getAllFromLocalStorage(ImpPrefixToNamespace.class);
         if (prefixToNamespaceMap == null) {
             //:FIXME if it is a submodule without any import, the map is null. Handle also submodules and includes...
@@ -419,7 +406,7 @@ public class SourceSpecificContext implements NamespaceStorageNode, NamespaceBeh
 
     private QNameToStatementDefinition stmtDef() {
         // regular YANG statements and extension supports added
-        final StatementSupportBundle supportsForPhase = currentContext.getSupportsForPhase(inProgressPhase);
+        final StatementSupportBundle supportsForPhase = globalContext.getSupportsForPhase(inProgressPhase);
         qnameToStmtDefMap.putAll(supportsForPhase.getCommonDefinitions());
         qnameToStmtDefMap.putAll(supportsForPhase.getDefinitionsSpecificForVersion(getRootVersion()));
 
@@ -429,7 +416,7 @@ public class SourceSpecificContext implements NamespaceStorageNode, NamespaceBeh
         }
 
         // We need to any and all extension statements which have been declared in the context
-        final Map<QName, StatementSupport<?, ?, ?>> extensions = currentContext.getAllFromNamespace(
+        final Map<QName, StatementSupport<?, ?, ?>> extensions = globalContext.getNamespace(
                 StatementDefinitionNamespace.class);
         if (extensions != null) {
             extensions.forEach((qname, support) -> {
@@ -445,14 +432,6 @@ public class SourceSpecificContext implements NamespaceStorageNode, NamespaceBeh
         return qnameToStmtDefMap;
     }
 
-    public Set<YangVersion> getSupportedVersions() {
-        return currentContext.getSupportedVersions();
-    }
-
-    void addMutableStmtToSeal(final MutableStatement mutableStatement) {
-        currentContext.addMutableStmtToSeal(mutableStatement);
-    }
-
     Collection<SourceIdentifier> getRequiredSources() {
         return root.getRequiredSources();
     }