BUG-4599: do not attempt to construct invalid QNames 19/29519/17
authorRobert Varga <robert.varga@pantheon.sk>
Mon, 9 Nov 2015 08:27:39 +0000 (09:27 +0100)
committerRobert Varga <nite@hq.sk>
Fri, 16 Dec 2016 17:05:38 +0000 (17:05 +0000)
QName should not allow for localname to contain ':', so do
not construct it just for lookups. Also move the code to its
only user, so we can evolve it.

Change-Id: Ib6c2b9aa0ea3fa14c1d843162a4b232a12e10cc4
Signed-off-by: Robert Varga <robert.varga@pantheon.sk>
yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/impl/YangStatementParserListenerImpl.java
yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/Utils.java

index 45bde58754e4ea9bf0f332a92bfff67f1a702711..c20c2d1e179de4ea6ebe41caefa5ac1037e35ccb 100644 (file)
@@ -18,7 +18,9 @@ import org.opendaylight.yangtools.antlrv4.code.gen.YangStatementParser.KeywordCo
 import org.opendaylight.yangtools.antlrv4.code.gen.YangStatementParser.StatementContext;
 import org.opendaylight.yangtools.antlrv4.code.gen.YangStatementParserBaseListener;
 import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.common.QNameModule;
 import org.opendaylight.yangtools.yang.common.YangConstants;
+import org.opendaylight.yangtools.yang.model.api.meta.StatementDefinition;
 import org.opendaylight.yangtools.yang.parser.spi.meta.ModelProcessingPhase;
 import org.opendaylight.yangtools.yang.parser.spi.source.DeclarationInTextSource;
 import org.opendaylight.yangtools.yang.parser.spi.source.PrefixToModule;
@@ -73,8 +75,7 @@ public class YangStatementParserListenerImpl extends YangStatementParserBaseList
         final StatementSourceReference ref = DeclarationInTextSource.atPosition(sourceName, ctx
             .getStart().getLine(), ctx.getStart().getCharPositionInLine());
         final String keywordTxt = Verify.verifyNotNull(ctx.getChild(KeywordContext.class, 0)).getText();
-        final QName identifier = QName.create(YangConstants.RFC6020_YIN_MODULE, keywordTxt);
-        final QName validStatementDefinition = Utils.getValidStatementDefinition(prefixes, stmtDef, identifier);
+        final QName validStatementDefinition = getValidStatementDefinition(prefixes, stmtDef, keywordTxt);
 
         final int childId = counters.peek().getAndIncrement();
         counters.push(new Counter());
@@ -97,8 +98,7 @@ public class YangStatementParserListenerImpl extends YangStatementParserBaseList
 
         KeywordContext keyword = ctx.getChild(KeywordContext.class, 0);
         String statementName = keyword.getText();
-        QName identifier = QName.create(YangConstants.RFC6020_YIN_MODULE, statementName);
-        if (stmtDef != null && Utils.getValidStatementDefinition(prefixes, stmtDef, identifier) != null
+        if (stmtDef != null && getValidStatementDefinition(prefixes, stmtDef, statementName) != null
                 && toBeSkipped.isEmpty()) {
             writer.endStatement(ref);
         }
@@ -107,4 +107,51 @@ public class YangStatementParserListenerImpl extends YangStatementParserBaseList
         toBeSkipped.remove(statementName);
         counters.pop();
     }
+
+    /**
+     * Based on identifier read from source and collections of relevant prefixes and statement definitions mappings
+     * provided for actual phase, method resolves and returns valid QName for declared statement to be written.
+     * This applies to any declared statement, including unknown statements.
+     *
+     * @param prefixes collection of all relevant prefix mappings supplied for actual parsing phase
+     * @param stmtDef collection of all relevant statement definition mappings provided for actual parsing phase
+     * @param keywordText statement keyword text to parse from source
+     * @return valid QName for declared statement to be written, or null
+     */
+    private static QName getValidStatementDefinition(final PrefixToModule prefixes,
+            final QNameToStatementDefinition stmtDef, final String keywordText) {
+        final int firstColon = keywordText.indexOf(':');
+        if (firstColon == -1) {
+            final StatementDefinition statementDefinition = stmtDef.get(
+                new QName(YangConstants.RFC6020_YIN_NAMESPACE, keywordText));
+            return statementDefinition != null ? statementDefinition.getStatementName() : null;
+        }
+
+        final int secondColon = keywordText.indexOf(':', firstColon + 1);
+        if (secondColon != -1) {
+            // Malformed string
+            return null;
+        }
+        if (prefixes == null) {
+            // No prefixes to look up from
+            return null;
+        }
+
+        final String prefix = keywordText.substring(0, firstColon);
+        final QNameModule qNameModule = prefixes.get(prefix);
+        if (qNameModule == null) {
+            // Failed to look the namespace
+            return null;
+        }
+
+        final String localName = keywordText.substring(firstColon + 1);
+        final StatementDefinition foundStmtDef;
+        if (prefixes.isPreLinkageMap()) {
+            foundStmtDef = stmtDef.getByNamespaceAndLocalName(qNameModule.getNamespace(), localName);
+        } else {
+            foundStmtDef = stmtDef.get(QName.create(qNameModule, localName));
+        }
+
+        return foundStmtDef != null ? foundStmtDef.getStatementName() : null;
+    }
 }
index 0a5bfbc8c02262373e7b10a9cf6ba41e4aea12dd..86ffd0ae09fd5ac0cbb20d9579745acb37632a09 100644 (file)
@@ -41,7 +41,6 @@ import org.opendaylight.yangtools.yang.model.api.DeviateKind;
 import org.opendaylight.yangtools.yang.model.api.ModuleIdentifier;
 import org.opendaylight.yangtools.yang.model.api.RevisionAwareXPath;
 import org.opendaylight.yangtools.yang.model.api.Status;
-import org.opendaylight.yangtools.yang.model.api.meta.StatementDefinition;
 import org.opendaylight.yangtools.yang.model.api.stmt.BelongsToStatement;
 import org.opendaylight.yangtools.yang.model.api.stmt.ModuleStatement;
 import org.opendaylight.yangtools.yang.model.api.stmt.RevisionStatement;
@@ -61,8 +60,6 @@ import org.opendaylight.yangtools.yang.parser.spi.source.ImpPrefixToModuleIdenti
 import org.opendaylight.yangtools.yang.parser.spi.source.ModuleCtxToModuleQName;
 import org.opendaylight.yangtools.yang.parser.spi.source.ModuleIdentifierToModuleQName;
 import org.opendaylight.yangtools.yang.parser.spi.source.ModuleNameToModuleQName;
-import org.opendaylight.yangtools.yang.parser.spi.source.PrefixToModule;
-import org.opendaylight.yangtools.yang.parser.spi.source.QNameToStatementDefinition;
 import org.opendaylight.yangtools.yang.parser.spi.source.SourceException;
 import org.opendaylight.yangtools.yang.parser.stmt.reactor.RootStatementContext;
 import org.opendaylight.yangtools.yang.parser.stmt.reactor.StatementContextBase;
@@ -394,51 +391,6 @@ public final class Utils {
         return identifier;
     }
 
-    /**
-     *
-     * Based on identifier read from source and collections of relevant prefixes and statement definitions mappings
-     * provided for actual phase, method resolves and returns valid QName for declared statement to be written.
-     * This applies to any declared statement, including unknown statements.
-     *
-     * @param prefixes - collection of all relevant prefix mappings supplied for actual parsing phase
-     * @param stmtDef - collection of all relevant statement definition mappings provided for actual parsing phase
-     * @param identifier - statement to parse from source
-     * @return valid QName for declared statement to be written
-     *
-     */
-    public static QName getValidStatementDefinition(final PrefixToModule prefixes,
-            final QNameToStatementDefinition stmtDef, final QName identifier) {
-        final StatementDefinition def = stmtDef.get(identifier);
-        if (def != null) {
-            return def.getStatementName();
-        }
-        if (prefixes == null) {
-            return null;
-        }
-
-        final String prefixedLocalName = identifier.getLocalName();
-        final String[] namesParts = prefixedLocalName.split(":");
-        if (namesParts.length != 2) {
-            return null;
-        }
-
-        final String prefix = namesParts[0];
-        final String localName = namesParts[1];
-        final QNameModule qNameModule = prefixes.get(prefix);
-        if (qNameModule == null) {
-            return null;
-        }
-
-        if (prefixes.isPreLinkageMap()) {
-            final StatementDefinition foundStmtDef = stmtDef.getByNamespaceAndLocalName(qNameModule.getNamespace(),
-                localName);
-            return foundStmtDef != null ? foundStmtDef.getStatementName() : null;
-        }
-
-        final QName qName = QName.create(qNameModule, localName);
-        return stmtDef.get(qName) != null ? qName : null;
-    }
-
     static SchemaNodeIdentifier nodeIdentifierFromPath(final StmtContext<?, ?, ?> ctx, final String path) {
         // FIXME: is the path trimming really necessary??
         final List<QName> qNames = new ArrayList<>();