Remove a RecursiveObjectLeaker reference
[yangtools.git] / yang / yang-parser-reactor / src / main / java / org / opendaylight / yangtools / yang / parser / stmt / reactor / BuildGlobalContext.java
index 980a17ead348ebc0f2a4950a8ca77b06ffd63d01..aca640a1a124d79eef3fd3f683778ebce449c278 100644 (file)
@@ -12,9 +12,10 @@ import static java.util.Objects.requireNonNull;
 
 import com.google.common.base.Verify;
 import com.google.common.collect.HashBasedTable;
-import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.ImmutableSetMultimap;
+import com.google.common.collect.SetMultimap;
 import com.google.common.collect.Table;
 import com.google.common.collect.TreeBasedTable;
 import java.util.ArrayList;
@@ -24,20 +25,18 @@ import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
-import java.util.Map.Entry;
 import java.util.Objects;
 import java.util.Optional;
 import java.util.Set;
 import java.util.SortedMap;
-import javax.annotation.Nonnull;
-import org.opendaylight.yangtools.util.RecursiveObjectLeaker;
+import org.eclipse.jdt.annotation.NonNull;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.common.QNameModule;
 import org.opendaylight.yangtools.yang.common.Revision;
 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.repo.api.RevisionSourceIdentifier;
 import org.opendaylight.yangtools.yang.model.repo.api.SourceIdentifier;
 import org.opendaylight.yangtools.yang.model.repo.api.StatementParserMode;
 import org.opendaylight.yangtools.yang.parser.spi.meta.DerivedNamespaceBehaviour;
@@ -48,11 +47,14 @@ import org.opendaylight.yangtools.yang.parser.spi.meta.NamespaceBehaviour.Namesp
 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.NamespaceNotAvailableException;
+import org.opendaylight.yangtools.yang.parser.spi.meta.ParserNamespace;
 import org.opendaylight.yangtools.yang.parser.spi.meta.ReactorException;
 import org.opendaylight.yangtools.yang.parser.spi.meta.SomeModifiersUnresolvedException;
 import org.opendaylight.yangtools.yang.parser.spi.meta.StatementSupport;
 import org.opendaylight.yangtools.yang.parser.spi.meta.StatementSupportBundle;
+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.ModuleCtxToModuleQName;
 import org.opendaylight.yangtools.yang.parser.spi.source.ModulesDeviatedByModules;
 import org.opendaylight.yangtools.yang.parser.spi.source.ModulesDeviatedByModules.SupportedModules;
 import org.opendaylight.yangtools.yang.parser.spi.source.SourceException;
@@ -65,29 +67,32 @@ import org.opendaylight.yangtools.yang.parser.stmt.reactor.SourceSpecificContext
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-class BuildGlobalContext extends NamespaceStorageSupport implements Registry {
+final class BuildGlobalContext extends NamespaceStorageSupport implements Registry {
     private static final Logger LOG = LoggerFactory.getLogger(BuildGlobalContext.class);
 
-    private static final List<ModelProcessingPhase> PHASE_EXECUTION_ORDER =
-            ImmutableList.<ModelProcessingPhase>builder().add(ModelProcessingPhase.SOURCE_PRE_LINKAGE)
-            .add(ModelProcessingPhase.SOURCE_LINKAGE).add(ModelProcessingPhase.STATEMENT_DEFINITION)
-            .add(ModelProcessingPhase.FULL_DECLARATION).add(ModelProcessingPhase.EFFECTIVE_MODEL).build();
+    private static final ModelProcessingPhase[] PHASE_EXECUTION_ORDER = {
+        ModelProcessingPhase.SOURCE_PRE_LINKAGE,
+        ModelProcessingPhase.SOURCE_LINKAGE,
+        ModelProcessingPhase.STATEMENT_DEFINITION,
+        ModelProcessingPhase.FULL_DECLARATION,
+        ModelProcessingPhase.EFFECTIVE_MODEL
+    };
 
     private final Table<YangVersion, QName, StatementDefinitionContext<?, ?, ?>> definitions = HashBasedTable.create();
     private final Map<QName, StatementDefinitionContext<?, ?, ?>> modelDefinedStmtDefs = new HashMap<>();
     private final Map<Class<?>, NamespaceBehaviourWithListeners<?, ?, ?>> supportedNamespaces = new HashMap<>();
     private final List<MutableStatement> mutableStatementsToSeal = new ArrayList<>();
-    private final Map<ModelProcessingPhase, StatementSupportBundle> supports;
+    private final ImmutableMap<ModelProcessingPhase, StatementSupportBundle> supports;
     private final Set<SourceSpecificContext> sources = new HashSet<>();
-    private final Set<YangVersion> supportedVersions;
+    private final ImmutableSet<YangVersion> supportedVersions;
     private final boolean enabledSemanticVersions;
 
     private Set<SourceSpecificContext> libSources = new HashSet<>();
     private ModelProcessingPhase currentPhase = ModelProcessingPhase.INIT;
     private ModelProcessingPhase finishedPhase = ModelProcessingPhase.INIT;
 
-    BuildGlobalContext(final Map<ModelProcessingPhase, StatementSupportBundle> supports,
-            final Map<ValidationBundleType, Collection<?>> supportedValidation,
+    BuildGlobalContext(final ImmutableMap<ModelProcessingPhase, StatementSupportBundle> supports,
+            final ImmutableMap<ValidationBundleType, Collection<?>> supportedValidation,
             final StatementParserMode statementParserMode) {
         this.supports = requireNonNull(supports, "BuildGlobalContext#supports cannot be null");
 
@@ -102,9 +107,7 @@ class BuildGlobalContext extends NamespaceStorageSupport implements Registry {
                 throw new IllegalArgumentException("Unhandled parser mode " + statementParserMode);
         }
 
-        for (final Entry<ValidationBundleType, Collection<?>> validationBundle : supportedValidation.entrySet()) {
-            addToNs(ValidationBundlesNamespace.class, validationBundle.getKey(), validationBundle.getValue());
-        }
+        addToNamespace(ValidationBundlesNamespace.class, supportedValidation);
 
         this.supportedVersions = ImmutableSet.copyOf(supports.get(ModelProcessingPhase.INIT).getSupportedVersions());
     }
@@ -113,15 +116,15 @@ class BuildGlobalContext extends NamespaceStorageSupport implements Registry {
         return enabledSemanticVersions;
     }
 
-    StatementSupportBundle getSupportsForPhase(final ModelProcessingPhase currentPhase) {
-        return supports.get(currentPhase);
+    StatementSupportBundle getSupportsForPhase(final ModelProcessingPhase phase) {
+        return supports.get(phase);
     }
 
-    void addSource(@Nonnull final StatementStreamSource source) {
+    void addSource(final @NonNull StatementStreamSource source) {
         sources.add(new SourceSpecificContext(this, source));
     }
 
-    void addLibSource(@Nonnull final StatementStreamSource libSource) {
+    void addLibSource(final @NonNull StatementStreamSource libSource) {
         checkState(!isEnabledSemanticVersioning(),
             "Library sources are not supported in semantic version mode currently.");
         checkState(currentPhase == ModelProcessingPhase.INIT,
@@ -130,13 +133,13 @@ class BuildGlobalContext extends NamespaceStorageSupport implements Registry {
     }
 
     void setSupportedFeatures(final Set<QName> supportedFeatures) {
-        addToNs(SupportedFeaturesNamespace.class, SupportedFeatures.SUPPORTED_FEATURES,
+        addToNamespace(SupportedFeaturesNamespace.class, SupportedFeatures.SUPPORTED_FEATURES,
                     ImmutableSet.copyOf(supportedFeatures));
     }
 
-    void setModulesDeviatedByModules(final Map<QNameModule, Set<QNameModule>> modulesDeviatedByModules) {
-        addToNs(ModulesDeviatedByModules.class, SupportedModules.SUPPORTED_MODULES,
-                    ImmutableMap.copyOf(modulesDeviatedByModules));
+    void setModulesDeviatedByModules(final SetMultimap<QNameModule, QNameModule> modulesDeviatedByModules) {
+        addToNamespace(ModulesDeviatedByModules.class, SupportedModules.SUPPORTED_MODULES,
+                    ImmutableSetMultimap.copyOf(modulesDeviatedByModules));
     }
 
     @Override
@@ -155,7 +158,7 @@ class BuildGlobalContext extends NamespaceStorageSupport implements Registry {
     }
 
     @Override
-    public <K, V, N extends IdentifierNamespace<K, V>> NamespaceBehaviourWithListeners<K, V, N> getNamespaceBehaviour(
+    public <K, V, N extends ParserNamespace<K, V>> NamespaceBehaviourWithListeners<K, V, N> getNamespaceBehaviour(
             final Class<N> type) {
         NamespaceBehaviourWithListeners<?, ?, ?> potential = supportedNamespaces.get(type);
         if (potential == null) {
@@ -178,7 +181,7 @@ class BuildGlobalContext extends NamespaceStorageSupport implements Registry {
     }
 
     @SuppressWarnings({ "unchecked", "rawtypes" })
-    private <K, V, N extends IdentifierNamespace<K, V>> NamespaceBehaviourWithListeners<K, V, N> createNamespaceContext(
+    private <K, V, N extends ParserNamespace<K, V>> NamespaceBehaviourWithListeners<K, V, N> createNamespaceContext(
             final NamespaceBehaviour<K, V, N> potentialRaw) {
         if (potentialRaw instanceof DerivedNamespaceBehaviour) {
             final VirtualNamespaceContext derivedContext = new VirtualNamespaceContext(
@@ -220,7 +223,7 @@ class BuildGlobalContext extends NamespaceStorageSupport implements Registry {
         }
     }
 
-    EffectiveModelContext build() throws ReactorException {
+    ReactorDeclaredModel build() throws ReactorException {
         executePhases();
         return transform();
     }
@@ -230,18 +233,18 @@ class BuildGlobalContext extends NamespaceStorageSupport implements Registry {
         return transformEffective();
     }
 
-    private EffectiveModelContext transform() {
+    private ReactorDeclaredModel transform() {
         checkState(finishedPhase == ModelProcessingPhase.EFFECTIVE_MODEL);
         final List<DeclaredStatement<?>> rootStatements = new ArrayList<>(sources.size());
         for (final SourceSpecificContext source : sources) {
-            rootStatements.add(source.getRoot().buildDeclared());
+            rootStatements.add(source.getRoot().declared());
         }
-        return new EffectiveModelContext(rootStatements);
+        return new ReactorDeclaredModel(rootStatements);
     }
 
     private SomeModifiersUnresolvedException propagateException(final SourceSpecificContext source,
             final RuntimeException cause) throws SomeModifiersUnresolvedException {
-        final SourceIdentifier sourceId = StmtContextUtils.createSourceIdentifier(source.getRoot());
+        final SourceIdentifier sourceId = createSourceIdentifier(source.getRoot());
         if (!(cause instanceof SourceException)) {
             /*
              * This should not be happening as all our processing should provide SourceExceptions.
@@ -255,24 +258,32 @@ class BuildGlobalContext extends NamespaceStorageSupport implements Registry {
         throw new SomeModifiersUnresolvedException(currentPhase, sourceId, cause);
     }
 
+    private static SourceIdentifier createSourceIdentifier(final StmtContext<?, ?, ?> root) {
+        final QNameModule qNameModule = root.getFromNamespace(ModuleCtxToModuleQName.class, root);
+        final String arg = root.getRawArgument();
+        if (qNameModule != null) {
+            // creates SourceIdentifier for a module
+            return RevisionSourceIdentifier.create(arg, qNameModule.getRevision());
+        }
+
+        // creates SourceIdentifier for a submodule
+        return RevisionSourceIdentifier.create(arg, StmtContextUtils.getLatestRevision(root.declaredSubstatements()));
+    }
+
     @SuppressWarnings("checkstyle:illegalCatch")
     private EffectiveSchemaContext transformEffective() throws ReactorException {
         checkState(finishedPhase == ModelProcessingPhase.EFFECTIVE_MODEL);
         final List<DeclaredStatement<?>> rootStatements = new ArrayList<>(sources.size());
         final List<EffectiveStatement<?, ?>> rootEffectiveStatements = new ArrayList<>(sources.size());
 
-        try {
-            for (final SourceSpecificContext source : sources) {
-                final RootStatementContext<?, ?, ?> root = source.getRoot();
-                try {
-                    rootStatements.add(root.buildDeclared());
-                    rootEffectiveStatements.add(root.buildEffective());
-                } catch (final RuntimeException ex) {
-                    throw propagateException(source, ex);
-                }
+        for (final SourceSpecificContext source : sources) {
+            final RootStatementContext<?, ?, ?> root = source.getRoot();
+            try {
+                rootStatements.add(root.declared());
+                rootEffectiveStatements.add(root.buildEffective());
+            } catch (final RuntimeException ex) {
+                throw propagateException(source, ex);
             }
-        } finally {
-            RecursiveObjectLeaker.cleanup();
         }
 
         sealMutableStatements();
@@ -301,8 +312,8 @@ class BuildGlobalContext extends NamespaceStorageSupport implements Registry {
     }
 
     @SuppressWarnings("checkstyle:illegalCatch")
-    private void loadPhaseStatementsFor(final Set<SourceSpecificContext> sources) throws ReactorException {
-        for (final SourceSpecificContext source : sources) {
+    private void loadPhaseStatementsFor(final Set<SourceSpecificContext> srcs) throws ReactorException {
+        for (final SourceSpecificContext source : srcs) {
             try {
                 source.loadStatements();
             } catch (final RuntimeException ex) {
@@ -316,7 +327,7 @@ class BuildGlobalContext extends NamespaceStorageSupport implements Registry {
         SomeModifiersUnresolvedException buildFailure = null;
         for (final SourceSpecificContext failedSource : sourcesToProgress) {
             final Optional<SourceException> optSourceEx = failedSource.failModifiers(currentPhase);
-            if (!optSourceEx.isPresent()) {
+            if (optSourceEx.isEmpty()) {
                 continue;
             }
 
@@ -336,20 +347,14 @@ class BuildGlobalContext extends NamespaceStorageSupport implements Registry {
 
                 int count = 1;
                 for (final Throwable t : suppressed) {
-                    // FIXME: this should be configured in the appender, really
-                    if (LOG.isDebugEnabled()) {
-                        LOG.error("Error {}: {}", count, t.getMessage(), t);
-                    } else {
-                        LOG.error("Error {}: {}", count, t.getMessage());
-                    }
-
+                    LOG.error("Error {}: {}", count, t.getMessage());
                     count++;
                 }
             }
 
             if (!addedCause) {
                 addedCause = true;
-                final SourceIdentifier sourceId = StmtContextUtils.createSourceIdentifier(failedSource.getRoot());
+                final SourceIdentifier sourceId = createSourceIdentifier(failedSource.getRoot());
                 buildFailure = new SomeModifiersUnresolvedException(currentPhase, sourceId, sourceEx);
             } else {
                 buildFailure.addSuppressed(sourceEx);