Resolve PrefixToModule cognitive dissonance 43/102143/6
authorRobert Varga <robert.varga@pantheon.tech>
Wed, 17 Aug 2022 18:38:36 +0000 (20:38 +0200)
committerRobert Varga <robert.varga@pantheon.tech>
Wed, 17 Aug 2022 19:40:45 +0000 (21:40 +0200)
This class serves two purposes: a namespace for reactor interactions
and XML source lookup. The second purpose is really a resolver
interface, split it out and clean up api/impl mess.

JIRA: YANGTOOLS-1452
Change-Id: I0fdfaee784a9c95bad0a64f746f0a1fe6412646e
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
parser/yang-parser-reactor/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/HashMapPrefixResolver.java [new file with mode: 0644]
parser/yang-parser-reactor/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/SourceSpecificContext.java
parser/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/repo/StatementContextVisitor.java
parser/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/repo/YangStatementStreamSource.java
parser/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/repo/YinStatementStreamSource.java
parser/yang-parser-spi/src/main/java/org/opendaylight/yangtools/yang/parser/spi/source/PrefixResolver.java [new file with mode: 0644]
parser/yang-parser-spi/src/main/java/org/opendaylight/yangtools/yang/parser/spi/source/PrefixToModule.java
parser/yang-parser-spi/src/main/java/org/opendaylight/yangtools/yang/parser/spi/source/PrefixToModuleMap.java [deleted file]
parser/yang-parser-spi/src/main/java/org/opendaylight/yangtools/yang/parser/spi/source/StatementStreamSource.java

diff --git a/parser/yang-parser-reactor/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/HashMapPrefixResolver.java b/parser/yang-parser-reactor/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/HashMapPrefixResolver.java
new file mode 100644 (file)
index 0000000..8bb1711
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2015 Cisco Systems, Inc. and others.  All rights reserved.
+ * Copyright (c) 2022 PANTHEON.tech, s.r.o.
+ *
+ * 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 java.util.HashMap;
+import java.util.Map;
+import org.opendaylight.yangtools.yang.common.QNameModule;
+import org.opendaylight.yangtools.yang.parser.spi.source.PrefixResolver;
+
+/**
+ * Map-based {@link PrefixResolver}. This class is NOT thread-safe.
+ */
+final class HashMapPrefixResolver implements PrefixResolver {
+    private final Map<String, QNameModule> prefixToModuleMap = new HashMap<>();
+
+    @Override
+    public QNameModule resolvePrefix(final String prefix) {
+        return prefixToModuleMap.get(requireNonNull(prefix));
+    }
+
+    void put(final String prefix, final QNameModule module) {
+        // FIXME: enforce non-nulls
+        // FIXME: enforce no duplicates
+        prefixToModuleMap.put(prefix, module);
+    }
+}
index 2bb9cae87ef4668488d58f9d19a8d182b2239f8e..fdbe9d81d654f918dfce7e65156bb79a7550c034 100644 (file)
@@ -47,8 +47,7 @@ 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.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;
@@ -99,7 +98,7 @@ final class SourceSpecificContext implements NamespaceStorageNode, NamespaceBeha
     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 HashMapPrefixResolver prefixToModuleMap = new HashMapPrefixResolver();
     private final @NonNull BuildGlobalContext globalContext;
 
     // Freed as soon as we complete ModelProcessingPhase.EFFECTIVE_MODEL
@@ -426,8 +425,8 @@ final class SourceSpecificContext implements NamespaceStorageNode, NamespaceBeha
         }
     }
 
-    private PrefixToModule preLinkagePrefixes() {
-        final PrefixToModuleMap preLinkagePrefixes = new PrefixToModuleMap();
+    private PrefixResolver preLinkagePrefixes() {
+        final HashMapPrefixResolver preLinkagePrefixes = new HashMapPrefixResolver();
         final Map<String, XMLNamespace> 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...
@@ -438,7 +437,7 @@ final class SourceSpecificContext implements NamespaceStorageNode, NamespaceBeha
         return preLinkagePrefixes;
     }
 
-    private PrefixToModule prefixes() {
+    private PrefixResolver prefixes() {
         final Map<String, StmtContext<?, ?, ?>> allImports = getRoot().getAllFromNamespace(
             ImportPrefixToModuleCtx.class);
         if (allImports != null) {
index 0637c3c1500b8b26ff5b574eaf67c17afcaf4a3c..6839525e8301cbda291369fd5ad6ddf239dc861b 100644 (file)
@@ -20,7 +20,7 @@ import org.opendaylight.yangtools.yang.parser.rfc7950.ir.IRKeyword;
 import org.opendaylight.yangtools.yang.parser.rfc7950.ir.IRKeyword.Qualified;
 import org.opendaylight.yangtools.yang.parser.rfc7950.ir.IRStatement;
 import org.opendaylight.yangtools.yang.parser.spi.source.ExplicitStatement;
-import org.opendaylight.yangtools.yang.parser.spi.source.PrefixToModule;
+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.StatementSourceReference;
 import org.opendaylight.yangtools.yang.parser.spi.source.StatementWriter;
@@ -29,15 +29,15 @@ import org.opendaylight.yangtools.yang.parser.spi.source.StatementWriter.Resumed
 class StatementContextVisitor {
     private final QNameToStatementDefinition stmtDef;
     private final ArgumentContextUtils utils;
+    private final PrefixResolver prefixes;
     private final StatementWriter writer;
-    private final PrefixToModule prefixes;
     private final String sourceName;
 
     StatementContextVisitor(final String sourceName, final StatementWriter writer,
-            final QNameToStatementDefinition stmtDef, final PrefixToModule prefixes, final YangVersion yangVersion) {
+            final QNameToStatementDefinition stmtDef, final PrefixResolver prefixes, final YangVersion yangVersion) {
         this.writer = requireNonNull(writer);
         this.stmtDef = requireNonNull(stmtDef);
-        this.utils = ArgumentContextUtils.forVersion(yangVersion);
+        utils = ArgumentContextUtils.forVersion(yangVersion);
         this.sourceName = sourceName;
         this.prefixes = prefixes;
     }
@@ -72,7 +72,7 @@ class StatementContextVisitor {
             return null;
         }
 
-        final QNameModule qNameModule = prefixes.get(keyword.prefix());
+        final QNameModule qNameModule = prefixes.resolvePrefix(keyword.prefix());
         if (qNameModule == null) {
             // Failed to look the namespace
             return null;
index 956ab49ab5cfbb4125793df63de1d2641c4c6067..5d6e8ef2301c73fbe02dcbeb623b20c95b063f86 100644 (file)
@@ -32,7 +32,7 @@ import org.opendaylight.yangtools.yang.parser.rfc7950.ir.AntlrSupport;
 import org.opendaylight.yangtools.yang.parser.rfc7950.ir.IRKeyword;
 import org.opendaylight.yangtools.yang.parser.rfc7950.ir.IRSchemaSource;
 import org.opendaylight.yangtools.yang.parser.rfc7950.ir.IRStatement;
-import org.opendaylight.yangtools.yang.parser.spi.source.PrefixToModule;
+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.SourceException;
 import org.opendaylight.yangtools.yang.parser.spi.source.StatementSourceReference;
@@ -95,7 +95,7 @@ public final class YangStatementStreamSource extends AbstractSimpleIdentifiable<
 
     @Override
     public void writeLinkage(final StatementWriter writer, final QNameToStatementDefinition stmtDef,
-            final PrefixToModule preLinkagePrefixes, final YangVersion yangVersion) {
+            final PrefixResolver preLinkagePrefixes, final YangVersion yangVersion) {
         new StatementContextVisitor(sourceName, writer, stmtDef, preLinkagePrefixes, yangVersion) {
             @Override
             StatementDefinition resolveStatement(final QNameModule module, final String localName) {
@@ -106,13 +106,13 @@ public final class YangStatementStreamSource extends AbstractSimpleIdentifiable<
 
     @Override
     public void writeLinkageAndStatementDefinitions(final StatementWriter writer,
-            final QNameToStatementDefinition stmtDef, final PrefixToModule prefixes, final YangVersion yangVersion) {
+            final QNameToStatementDefinition stmtDef, final PrefixResolver prefixes, final YangVersion yangVersion) {
         new StatementContextVisitor(sourceName, writer, stmtDef, prefixes, yangVersion).visit(rootStatement);
     }
 
     @Override
     public void writeFull(final StatementWriter writer, final QNameToStatementDefinition stmtDef,
-            final PrefixToModule prefixes, final YangVersion yangVersion) {
+            final PrefixResolver prefixes, final YangVersion yangVersion) {
         new StatementContextVisitor(sourceName, writer, stmtDef, prefixes, yangVersion) {
             @Override
             QName getValidStatementDefinition(final IRKeyword keyword, final StatementSourceReference ref) {
index c52802f29e922817afb9b7454278260ec470d10f..6d04e50fcb99924ee435b8ff7710ba2051e95063 100644 (file)
@@ -27,7 +27,7 @@ import org.opendaylight.yangtools.yang.model.repo.api.SourceIdentifier;
 import org.opendaylight.yangtools.yang.model.repo.api.YinDomSchemaSource;
 import org.opendaylight.yangtools.yang.model.repo.api.YinXmlSchemaSource;
 import org.opendaylight.yangtools.yang.parser.spi.meta.ModelProcessingPhase;
-import org.opendaylight.yangtools.yang.parser.spi.source.PrefixToModule;
+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.SourceException;
 import org.opendaylight.yangtools.yang.parser.spi.source.StatementSourceReference;
@@ -235,19 +235,19 @@ public final class YinStatementStreamSource extends AbstractSimpleIdentifiable<S
 
     @Override
     public void writeLinkage(final StatementWriter writer, final QNameToStatementDefinition stmtDef,
-            final PrefixToModule preLinkagePrefixes, final YangVersion yangVersion) {
+            final PrefixResolver preLinkagePrefixes, final YangVersion yangVersion) {
         walkTree(writer, stmtDef);
     }
 
     @Override
     public void writeLinkageAndStatementDefinitions(final StatementWriter writer,
-            final QNameToStatementDefinition stmtDef, final PrefixToModule prefixes,  final YangVersion yangVersion) {
+            final QNameToStatementDefinition stmtDef, final PrefixResolver prefixes, final YangVersion yangVersion) {
         walkTree(writer, stmtDef);
     }
 
     @Override
     public void writeFull(final StatementWriter writer, final QNameToStatementDefinition stmtDef,
-            final PrefixToModule prefixes, final YangVersion yangVersion) {
+            final PrefixResolver prefixes, final YangVersion yangVersion) {
         walkTree(writer, stmtDef);
     }
 }
diff --git a/parser/yang-parser-spi/src/main/java/org/opendaylight/yangtools/yang/parser/spi/source/PrefixResolver.java b/parser/yang-parser-spi/src/main/java/org/opendaylight/yangtools/yang/parser/spi/source/PrefixResolver.java
new file mode 100644 (file)
index 0000000..f54a097
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2022 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.spi.source;
+
+import org.eclipse.jdt.annotation.Nullable;
+import org.opendaylight.yangtools.yang.common.QNameModule;
+import org.opendaylight.yangtools.yang.common.Revision;
+
+/**
+ * Interface for resolving XML prefixes to their bound {@link QNameModule}s. This resolution entails determining
+ * the correct {@link Revision} bound at the use site.
+ */
+public interface PrefixResolver {
+    /**
+     * Returns QNameModule (namespace + revision) associated with supplied prefix.
+     *
+     * @param prefix Prefix
+     * @return QNameModule associated with supplied prefix, or null if prefix is not defined.
+     */
+    @Nullable QNameModule resolvePrefix(String prefix);
+}
index e9ccadb47fdb8393cef5d1ea0cadb2720ec2d3ee..965bfc16cd330b6d2a1fd014da72329a13db8fc4 100644 (file)
@@ -8,32 +8,18 @@
 package org.opendaylight.yangtools.yang.parser.spi.source;
 
 import org.eclipse.jdt.annotation.NonNull;
-import org.eclipse.jdt.annotation.Nullable;
 import org.opendaylight.yangtools.yang.common.QNameModule;
 import org.opendaylight.yangtools.yang.parser.spi.meta.NamespaceBehaviour;
 import org.opendaylight.yangtools.yang.parser.spi.meta.ParserNamespace;
 
 /**
- * Source-specific mapping of prefixes to namespaces.
+ * Source-specific mapping of prefixes to namespaces. This namespace is populated by all statements which have impact
+ * on the XML namespace, for example {@code import}, {@code belongs-to} and really anywhere a {@code prefix} statement
+ * is present.
+ *
+ * @see PrefixResolver
  */
 public interface PrefixToModule extends ParserNamespace<String, QNameModule> {
     NamespaceBehaviour<String, QNameModule, @NonNull PrefixToModule> BEHAVIOUR =
             NamespaceBehaviour.global(PrefixToModule.class);
-
-    /**
-     * Returns QNameModule (namespace + revision) associated with supplied prefix.
-     *
-     * @param prefix Prefix
-     * @return QNameModule associated with supplied prefix, or null if prefix is not defined.
-     */
-    QNameModule get(String prefix);
-
-    /**
-     * Returns QNameModule (namespace + revision) associated with XML namespace (URI).
-     *
-     * @param namespace XML Namespace
-     * @return QNameModule associated with supplied namespace, or null if prefix is not defined.
-     * @throws IllegalArgumentException if the input string is not valid URI
-     */
-    @Nullable QNameModule getByNamespace(String namespace);
 }
diff --git a/parser/yang-parser-spi/src/main/java/org/opendaylight/yangtools/yang/parser/spi/source/PrefixToModuleMap.java b/parser/yang-parser-spi/src/main/java/org/opendaylight/yangtools/yang/parser/spi/source/PrefixToModuleMap.java
deleted file mode 100644 (file)
index 009ffbb..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (c) 2015 Cisco Systems, Inc. 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.spi.source;
-
-import java.util.HashMap;
-import java.util.Map;
-import org.opendaylight.yangtools.yang.common.QNameModule;
-import org.opendaylight.yangtools.yang.common.XMLNamespace;
-
-/**
- * Map-based {@link PrefixToModule} namespace. This class is NOT thread-safe.
- */
-public class PrefixToModuleMap implements PrefixToModule {
-    private final Map<String, QNameModule> prefixToModuleMap = new HashMap<>();
-    private final Map<XMLNamespace, QNameModule> namespaceToModuleMap = new HashMap<>();
-
-    public void put(final String prefix, final QNameModule module) {
-        prefixToModuleMap.put(prefix, module);
-        namespaceToModuleMap.put(module.getNamespace(), module);
-    }
-
-    @Override
-    public QNameModule get(final String prefix) {
-        return prefixToModuleMap.get(prefix);
-    }
-
-    @Override
-    public QNameModule getByNamespace(final String namespace) {
-        return namespaceToModuleMap.get(XMLNamespace.of(namespace));
-    }
-}
index c1694c90a11de1b1da62b246eb99dc2fa2926840..c04edcc879c72dedcb120a529db8a9933efdf692 100644 (file)
@@ -32,20 +32,20 @@ import org.opendaylight.yangtools.yang.model.repo.api.SourceIdentifier;
  * It is necessary in order to correct resolution of unknown statements used by linkage
  * phase (e.g. semantic version of yang modules).
  * </li>
- * <li>{@link #writeLinkage(StatementWriter, QNameToStatementDefinition, PrefixToModule, YangVersion)} -
+ * <li>{@link #writeLinkage(StatementWriter, QNameToStatementDefinition, PrefixResolver, YangVersion)} -
  * Source MUST emit only statements related in linkage, which are present in
  * supplied statement definition map. This step is used to build cross-source
  * linkage and visibility relationship, and to determine XMl namespaces and
  * prefixes.</li>
  * <li>
- * {@link #writeLinkageAndStatementDefinitions(StatementWriter, QNameToStatementDefinition, PrefixToModule,
+ * {@link #writeLinkageAndStatementDefinitions(StatementWriter, QNameToStatementDefinition, PrefixResolver,
  * YangVersion)}
  * - Source MUST emit only statements related to linkage and language extensions
  * definitions, which are present in supplied statement definition map. This
  * step is used to build statement definitions in order to fully processed
  * source.</li>
  * <li>
- * {@link #writeFull(StatementWriter, QNameToStatementDefinition, PrefixToModule, YangVersion)}
+ * {@link #writeFull(StatementWriter, QNameToStatementDefinition, PrefixResolver, YangVersion)}
  * - Source MUST emit all statements present in source. This step is used to
  * build full declared statement model of source.</li>
  * </ol>
@@ -88,8 +88,8 @@ public interface StatementStreamSource extends Identifiable<SourceIdentifier> {
      *             If source was is not valid, or provided statement writer
      *             failed to write statements.
      */
-    void writeLinkage(StatementWriter writer, QNameToStatementDefinition stmtDef, PrefixToModule preLinkagePrefixes,
-            YangVersion yangVersion);
+    void writeLinkage(StatementWriter writer, QNameToStatementDefinition stmtDef,
+        PrefixResolver preLinkagePrefixes, YangVersion yangVersion);
 
     /**
      * Emits only linkage and language extension statements to supplied
@@ -113,7 +113,7 @@ public interface StatementStreamSource extends Identifiable<SourceIdentifier> {
      *             failed to write statements.
      */
     void writeLinkageAndStatementDefinitions(StatementWriter writer, QNameToStatementDefinition stmtDef,
-            PrefixToModule prefixes, YangVersion yangVersion);
+        PrefixResolver prefixes, YangVersion yangVersion);
 
     /**
      * Emits every statements present in this statement source to supplied
@@ -133,6 +133,6 @@ public interface StatementStreamSource extends Identifiable<SourceIdentifier> {
      *             If source was is not valid, or provided statement writer
      *             failed to write statements.
      */
-    void writeFull(StatementWriter writer, QNameToStatementDefinition stmtDef, PrefixToModule prefixes,
-            YangVersion yangVersion);
+    void writeFull(StatementWriter writer, QNameToStatementDefinition stmtDef, PrefixResolver prefixes,
+        YangVersion yangVersion);
 }