Do not use InstanceIdentifier.getPathArguments()
[yangtools.git] / parser / yang-parser-reactor / src / main / java / org / opendaylight / yangtools / yang / parser / stmt / reactor / SourceSpecificContext.java
index 676966472a3c7eb8099e3892686830269caed099..5819631828edb0a3ee520d837b9be6a4cef164f5 100644 (file)
@@ -27,65 +27,79 @@ 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;
-import org.opendaylight.yangtools.yang.common.XMLNamespace;
+import org.opendaylight.yangtools.yang.common.UnresolvedQName.Unqualified;
 import org.opendaylight.yangtools.yang.common.YangVersion;
-import org.opendaylight.yangtools.yang.model.repo.api.SourceIdentifier;
+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.StatementSourceException;
+import org.opendaylight.yangtools.yang.model.api.meta.StatementSourceReference;
+import org.opendaylight.yangtools.yang.model.api.source.SourceIdentifier;
+import org.opendaylight.yangtools.yang.parser.spi.ParserNamespaces;
 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.NamespaceBehaviour;
-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.NamespaceKeyCriterion;
+import org.opendaylight.yangtools.yang.parser.spi.meta.NamespaceStorage;
 import org.opendaylight.yangtools.yang.parser.spi.meta.ParserNamespace;
-import org.opendaylight.yangtools.yang.parser.spi.meta.StatementDefinitionNamespace;
+import org.opendaylight.yangtools.yang.parser.spi.meta.StatementDefinitions;
 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.StatementSupportNamespace;
-import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext;
-import org.opendaylight.yangtools.yang.parser.spi.source.BelongsToModuleContext;
-import org.opendaylight.yangtools.yang.parser.spi.source.BelongsToPrefixToModuleCtx;
-import org.opendaylight.yangtools.yang.parser.spi.source.ImpPrefixToNamespace;
-import org.opendaylight.yangtools.yang.parser.spi.source.ImportPrefixToModuleCtx;
-import org.opendaylight.yangtools.yang.parser.spi.source.ImportedModuleContext;
-import org.opendaylight.yangtools.yang.parser.spi.source.ModuleCtxToModuleQName;
-import org.opendaylight.yangtools.yang.parser.spi.source.PrefixToModule;
-import org.opendaylight.yangtools.yang.parser.spi.source.PrefixToModuleMap;
+import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContextUtils;
+import org.opendaylight.yangtools.yang.parser.spi.source.PrefixResolver;
 import org.opendaylight.yangtools.yang.parser.spi.source.QNameToStatementDefinition;
 import org.opendaylight.yangtools.yang.parser.spi.source.QNameToStatementDefinitionMap;
 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.StatementStreamSource;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-final class SourceSpecificContext implements NamespaceStorageNode, NamespaceBehaviour.Registry, Mutable {
+final class SourceSpecificContext implements NamespaceStorage, Mutable {
     enum PhaseCompletionProgress {
         NO_PROGRESS,
         PROGRESS,
         FINISHED
     }
 
-    private static final class SupportedStatements
-            extends NamespaceBehaviour<QName, StatementSupport<?, ?, ?>, StatementSupportNamespace> {
+    private static final class SupportedStatements extends NamespaceAccess<QName, StatementSupport<?, ?, ?>> {
         private final QNameToStatementDefinitionMap statementDefinitions;
 
         SupportedStatements(final QNameToStatementDefinitionMap statementDefinitions) {
-            super(StatementSupportNamespace.class);
             this.statementDefinitions = requireNonNull(statementDefinitions);
         }
 
         @Override
-        public StatementSupport<?, ?, ?> getFrom(final NamespaceStorageNode storage, final QName key) {
+        ParserNamespace<QName, StatementSupport<?, ?, ?>> namespace() {
+            return StatementSupport.NAMESPACE;
+        }
+
+        @Override
+        StatementSupport<?, ?, ?> valueFrom(final NamespaceStorage storage, final QName key) {
             return statementDefinitions.getSupport(key);
         }
 
         @Override
-        public Map<QName, StatementSupport<?, ?, ?>> getAllFrom(final NamespaceStorageNode storage) {
+        void valueTo(final NamespaceStorage storage, final QName key, final StatementSupport<?, ?, ?> value) {
+            throw uoe();
+        }
+
+        @Override
+        Map<QName, StatementSupport<?, ?, ?>> allFrom(final NamespaceStorage storage) {
+            throw uoe();
+        }
+
+        @Override
+        Entry<QName, StatementSupport<?, ?, ?>> entryFrom(final NamespaceStorage storage,
+                final NamespaceKeyCriterion<QName> criterion) {
+            throw uoe();
+        }
+
+        @Override
+        void addListener(final QName key, final KeyedValueAddedListener<QName, StatementSupport<?, ?, ?>> listener) {
             throw uoe();
         }
 
         @Override
-        public void addTo(final NamespaceStorageNode storage, final QName key, final StatementSupport<?, ?, ?> value) {
+        void addListener(final PredicateValueAddedListener<QName, StatementSupport<?, ?, ?>> listener) {
             throw uoe();
         }
 
@@ -99,8 +113,8 @@ final class SourceSpecificContext implements NamespaceStorageNode, NamespaceBeha
     // TODO: consider keying by Byte equivalent of ExecutionOrder
     private final Multimap<ModelProcessingPhase, ModifierImpl> modifiers = HashMultimap.create();
     private final QNameToStatementDefinitionMap qnameToStmtDefMap = new QNameToStatementDefinitionMap();
-    private final SupportedStatements statementSupports = new SupportedStatements(qnameToStmtDefMap);
-    private final PrefixToModuleMap prefixToModuleMap = new PrefixToModuleMap();
+    private final @NonNull SupportedStatements statementSupports = new SupportedStatements(qnameToStmtDefMap);
+    private final HashMapPrefixResolver prefixToModuleMap = new HashMapPrefixResolver();
     private final @NonNull BuildGlobalContext globalContext;
 
     // Freed as soon as we complete ModelProcessingPhase.EFFECTIVE_MODEL
@@ -111,7 +125,7 @@ final class SourceSpecificContext implements NamespaceStorageNode, NamespaceBeha
      * - modules imported via 'import' statement
      * - parent module, declared via 'belongs-to' statement
      */
-    private Collection<RootStatementContext<?, ?, ?>> importedNamespaces = ImmutableList.of();
+    private List<RootStatementContext<?, ?, ?>> importedNamespaces = ImmutableList.of();
     private RootStatementContext<?, ?, ?> root;
     // TODO: consider using ExecutionOrder byte for these two
     private ModelProcessingPhase finishedPhase = ModelProcessingPhase.INIT;
@@ -190,8 +204,28 @@ final class SourceSpecificContext implements NamespaceStorageNode, NamespaceBeha
         return root;
     }
 
-    RootStatementContext<?, ?, ?> getRoot() {
-        return root;
+    @NonNull SourceIdentifier identifySource() {
+        final var arg = root.getArgument();
+        verify(arg instanceof Unqualified, "Unexpected argument %s", arg);
+        final var unqualified = (Unqualified) arg;
+
+        final var module = root.namespaceItem(ParserNamespaces.MODULECTX_TO_QNAME, root);
+        if (module != null) {
+            // creates SourceIdentifier for a module
+            return new SourceIdentifier(unqualified, module.revision());
+        }
+
+        // creates SourceIdentifier for a submodule
+        return new SourceIdentifier(unqualified,
+            StmtContextUtils.getLatestRevision(root.declaredSubstatements()).orElse(null));
+    }
+
+    @NonNull DeclaredStatement<?> declaredRoot() {
+        return root.declared();
+    }
+
+    @NonNull EffectiveStatement<?, ?> effectiveRoot() {
+        return root.buildEffective();
     }
 
     /**
@@ -199,7 +233,7 @@ final class SourceSpecificContext implements NamespaceStorageNode, NamespaceBeha
      *
      * @return version of root statement context
      */
-    YangVersion getRootVersion() {
+    private YangVersion getRootVersion() {
         return root != null ? root.yangVersion() : RootStatementContext.DEFAULT_VERSION;
     }
 
@@ -217,32 +251,31 @@ final class SourceSpecificContext implements NamespaceStorageNode, NamespaceBeha
         LOG.debug("Source {} started phase {}", source, phase);
     }
 
-    private void updateImportedNamespaces(final Class<?> type, final Object value) {
-        if (BelongsToModuleContext.class.isAssignableFrom(type) || ImportedModuleContext.class.isAssignableFrom(type)) {
+    private void updateImportedNamespaces(final ParserNamespace<?, ?> type, final Object value) {
+        if (ParserNamespaces.BELONGSTO_PREFIX_TO_MODULECTX.equals(type)
+            || ParserNamespaces.IMPORTED_MODULE.equals(type)) {
+            verify(value instanceof RootStatementContext, "Unexpected imported value %s", value);
+
             if (importedNamespaces.isEmpty()) {
                 importedNamespaces = new ArrayList<>(1);
             }
-
-            verify(value instanceof RootStatementContext);
             importedNamespaces.add((RootStatementContext<?, ?, ?>) value);
         }
     }
 
     @Override
-    public <K, V, N extends ParserNamespace<K, V>> V putToLocalStorage(final Class<N> type, final K key,
-           final V value) {
+    public <K, V> V putToLocalStorage(final ParserNamespace<K, V> type, final K key, final V value) {
         // RootStatementContext takes care of IncludedModuleContext and the rest...
-        final V ret = getRoot().putToLocalStorage(type, key, value);
+        final V ret = root.putToLocalStorage(type, key, value);
         // FIXME: what about duplicates?
         updateImportedNamespaces(type, value);
         return ret;
     }
 
     @Override
-    public <K, V, N extends ParserNamespace<K, V>> V putToLocalStorageIfAbsent(final Class<N> type, final K key,
-           final V value) {
+    public <K, V> V putToLocalStorageIfAbsent(final ParserNamespace<K, V> type, final K key, final V value) {
         // RootStatementContext takes care of IncludedModuleContext and the rest...
-        final V ret = getRoot().putToLocalStorageIfAbsent(type, key, value);
+        final V ret = root.putToLocalStorageIfAbsent(type, key, value);
         if (ret == null) {
             updateImportedNamespaces(type, value);
         }
@@ -250,18 +283,18 @@ final class SourceSpecificContext implements NamespaceStorageNode, NamespaceBeha
     }
 
     @Override
-    public StorageNodeType getStorageNodeType() {
-        return StorageNodeType.SOURCE_LOCAL_SPECIAL;
+    public StorageType getStorageType() {
+        return StorageType.SOURCE_LOCAL_SPECIAL;
     }
 
     @Override
-    public <K, V, N extends ParserNamespace<K, V>> V getFromLocalStorage(final Class<N> type, final K key) {
-        final V potentialLocal = getRoot().getFromLocalStorage(type, key);
+    public <K, V> V getFromLocalStorage(final ParserNamespace<K, V> type, final K key) {
+        final V potentialLocal = root.getFromLocalStorage(type, key);
         if (potentialLocal != null) {
             return potentialLocal;
         }
 
-        for (final NamespaceStorageNode importedSource : importedNamespaces) {
+        for (final NamespaceStorage importedSource : importedNamespaces) {
             final V potential = importedSource.getFromLocalStorage(type, key);
             if (potential != null) {
                 return potential;
@@ -271,13 +304,13 @@ final class SourceSpecificContext implements NamespaceStorageNode, NamespaceBeha
     }
 
     @Override
-    public <K, V, N extends ParserNamespace<K, V>> Map<K, V> getAllFromLocalStorage(final Class<N> type) {
-        final Map<K, V> potentialLocal = getRoot().getAllFromLocalStorage(type);
+    public <K, V> Map<K, V> getAllFromLocalStorage(final ParserNamespace<K, V> type) {
+        final Map<K, V> potentialLocal = root.getAllFromLocalStorage(type);
         if (potentialLocal != null) {
             return potentialLocal;
         }
 
-        for (final NamespaceStorageNode importedSource : importedNamespaces) {
+        for (final NamespaceStorage importedSource : importedNamespaces) {
             final Map<K, V> potential = importedSource.getAllFromLocalStorage(type);
 
             if (potential != null) {
@@ -287,18 +320,17 @@ final class SourceSpecificContext implements NamespaceStorageNode, NamespaceBeha
         return null;
     }
 
-    @Override
-    @SuppressWarnings("unchecked")
-    public <K, V, N extends ParserNamespace<K, V>> NamespaceBehaviour<K, V, N> getNamespaceBehaviour(
-            final Class<N> type) {
-        if (StatementSupportNamespace.class.equals(type)) {
-            return (NamespaceBehaviour<K, V, N>) statementSupports;
+    <K, V> NamespaceAccess<K, V> accessNamespace(final ParserNamespace<K, V> type) {
+        if (StatementSupport.NAMESPACE.equals(type)) {
+            @SuppressWarnings("unchecked")
+            final var ret = (NamespaceAccess<K, V>) statementSupports;
+            return ret;
         }
-        return globalContext.getNamespaceBehaviour(type);
+        return globalContext.accessNamespace(type);
     }
 
     @Override
-    public BuildGlobalContext getParentNamespaceStorage() {
+    public GlobalStorage getParentStorage() {
         return globalContext;
     }
 
@@ -380,12 +412,12 @@ final class SourceSpecificContext implements NamespaceStorageNode, NamespaceBeha
                 + finishedPhase + "]";
     }
 
-    Optional<SourceException> failModifiers(final ModelProcessingPhase identifier) {
-        final List<SourceException> exceptions = new ArrayList<>();
-        for (final ModifierImpl mod : modifiers.get(identifier)) {
+    Optional<StatementSourceException> failModifiers(final ModelProcessingPhase identifier) {
+        final var exceptions = new ArrayList<StatementSourceException>();
+        for (var mod : modifiers.get(identifier)) {
             try {
                 mod.failModifier();
-            } catch (final SourceException e) {
+            } catch (StatementSourceException e) {
                 exceptions.add(e);
             }
         }
@@ -394,8 +426,8 @@ final class SourceSpecificContext implements NamespaceStorageNode, NamespaceBeha
             case 0 -> Optional.empty();
             case 1 -> Optional.of(exceptions.get(0));
             default -> {
-                final String message = String.format("Yang model processing phase %s failed", identifier);
-                final InferenceException ex = new InferenceException(message, root, exceptions.get(0));
+                final var ex = new InferenceException("Yang model processing phase " + identifier + " failed", root,
+                    exceptions.get(0));
                 exceptions.listIterator(1).forEachRemaining(ex::addSuppressed);
                 yield Optional.of(ex);
             }
@@ -426,31 +458,29 @@ final class SourceSpecificContext implements NamespaceStorageNode, NamespaceBeha
         }
     }
 
-    private PrefixToModule preLinkagePrefixes() {
-        final PrefixToModuleMap preLinkagePrefixes = new PrefixToModuleMap();
-        final Map<String, XMLNamespace> prefixToNamespaceMap = getAllFromLocalStorage(ImpPrefixToNamespace.class);
+    private PrefixResolver preLinkagePrefixes() {
+        final HashMapPrefixResolver preLinkagePrefixes = new HashMapPrefixResolver();
+        final var prefixToNamespaceMap = getAllFromLocalStorage(ParserNamespaces.IMP_PREFIX_TO_NAMESPACE);
         if (prefixToNamespaceMap == null) {
             //:FIXME if it is a submodule without any import, the map is null. Handle also submodules and includes...
             return null;
         }
 
-        prefixToNamespaceMap.forEach((key, value) -> preLinkagePrefixes.put(key, QNameModule.create(value)));
+        prefixToNamespaceMap.forEach((key, value) -> preLinkagePrefixes.put(key, QNameModule.of(value)));
         return preLinkagePrefixes;
     }
 
-    private PrefixToModule prefixes() {
-        final Map<String, StmtContext<?, ?, ?>> allImports = getRoot().getAllFromNamespace(
-            ImportPrefixToModuleCtx.class);
+    private PrefixResolver prefixes() {
+        final var allImports = root.namespace(ParserNamespaces.IMPORT_PREFIX_TO_MODULECTX);
         if (allImports != null) {
             allImports.forEach((key, value) ->
-                prefixToModuleMap.put(key, getRoot().getFromNamespace(ModuleCtxToModuleQName.class, value)));
+                prefixToModuleMap.put(key, root.namespaceItem(ParserNamespaces.MODULECTX_TO_QNAME, value)));
         }
 
-        final Map<String, StmtContext<?, ?, ?>> allBelongsTo = getRoot().getAllFromNamespace(
-            BelongsToPrefixToModuleCtx.class);
+        final var allBelongsTo = root.namespace(ParserNamespaces.BELONGSTO_PREFIX_TO_MODULECTX);
         if (allBelongsTo != null) {
             allBelongsTo.forEach((key, value) ->
-                prefixToModuleMap.put(key, getRoot().getFromNamespace(ModuleCtxToModuleQName.class, value)));
+                prefixToModuleMap.put(key, root.namespaceItem(ParserNamespaces.MODULECTX_TO_QNAME, value)));
         }
 
         return prefixToModuleMap;
@@ -469,7 +499,7 @@ final class SourceSpecificContext implements NamespaceStorageNode, NamespaceBeha
 
         // We need to any and all extension statements which have been declared in the context
         final Map<QName, StatementSupport<?, ?, ?>> extensions = globalContext.getNamespace(
-                StatementDefinitionNamespace.class);
+            StatementDefinitions.NAMESPACE);
         if (extensions != null) {
             extensions.forEach((qname, support) -> {
                 final StatementSupport<?, ?, ?> existing = qnameToStmtDefMap.putIfAbsent(qname, support);