Rework LeafRefValidation 66/86566/17
authorRobert Varga <robert.varga@pantheon.tech>
Wed, 25 Dec 2019 11:12:54 +0000 (12:12 +0100)
committerRobert Varga <robert.varga@pantheon.tech>
Thu, 26 Dec 2019 12:03:23 +0000 (13:03 +0100)
This reworks LeafRefValidation in terms of interpreting XPathExpression
via exposed parsed steps. This allows us to eliminate a chunk of parsing
code, speeding the initialization process up.

QNamePredicateImpl/AbstractQNameWithPredicate are losing their Serializable
trait, as it is not really useful and tickles SpotBugs unnecessarily.

JIRA: YANGTOOLS-1051
Change-Id: I502f54052ca8bb10e6595f41ba7aca6cef9550ce
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
13 files changed:
yang/yang-data-impl/pom.xml
yang/yang-data-impl/src/main/antlr4/org/opendaylight/yangtools/yang/data/impl/leafref/LeafRefPathLexer.g4 [deleted file]
yang/yang-data-impl/src/main/antlr4/org/opendaylight/yangtools/yang/data/impl/leafref/LeafRefPathParser.g4 [deleted file]
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/leafref/AbstractQNameWithPredicate.java
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/leafref/LeafRefContextBuilder.java
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/leafref/LeafRefContextTreeBuilder.java
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/leafref/LeafRefPathErrorListener.java [deleted file]
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/leafref/LeafRefPathParserImpl.java
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/leafref/LeafRefPathParserListenerImpl.java [deleted file]
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/leafref/LeafRefPathSyntaxErrorException.java [deleted file]
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/leafref/QNamePredicateImpl.java
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/leafref/QNameWithPredicateImpl.java
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/leafref/SimpleQNameWithPredicate.java

index 2c094a4531f6cbd0413cb46f6ca32bb6290fc001..1b0856bc7f94d47c0c2ba8a020bb561c64166a86 100644 (file)
     <description>${project.artifactId}</description>
 
     <properties>
-        <!-- FIXME: antlr-generated code does not pass SB -->
+        <!-- FIXME: fixup/suppress remaining bugs and remove this -->
         <odlparent.spotbugs.enforce>false</odlparent.spotbugs.enforce>
     </properties>
 
     <build>
         <plugins>
-            <plugin>
-                <groupId>org.antlr</groupId>
-                <artifactId>antlr4-maven-plugin</artifactId>
-                <executions>
-                    <execution>
-                        <goals>
-                            <goal>antlr4</goal>
-                        </goals>
-                    </execution>
-                </executions>
-                <configuration>
-                    <visitor>true</visitor>
-                    <listener>true</listener>
-                </configuration>
-            </plugin>
             <plugin>
                 <groupId>org.apache.felix</groupId>
                 <artifactId>maven-bundle-plugin</artifactId>
             <groupId>com.google.guava</groupId>
             <artifactId>guava</artifactId>
         </dependency>
-        <dependency>
-            <groupId>org.antlr</groupId>
-            <artifactId>antlr4-runtime</artifactId>
-        </dependency>
         <dependency>
             <groupId>javax.xml.bind</groupId>
             <artifactId>jaxb-api</artifactId>
diff --git a/yang/yang-data-impl/src/main/antlr4/org/opendaylight/yangtools/yang/data/impl/leafref/LeafRefPathLexer.g4 b/yang/yang-data-impl/src/main/antlr4/org/opendaylight/yangtools/yang/data/impl/leafref/LeafRefPathLexer.g4
deleted file mode 100644 (file)
index 3d63ee9..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-lexer grammar LeafRefPathLexer;
-
-COLON : ':' ;
-SLASH : '/' ;
-DOTS : '..' ;
-EQUAL : '=' ;
-LEFT_SQUARE_BRACKET : '[' ;
-RIGHT_SQUARE_BRACKET : ']' ;
-LEFT_PARENTHESIS : '(' ;
-RIGHT_PARENTHESIS : ')' ;
-
-CURRENT_KEYWORD : 'current';
-
-SEP: [ \n\r\t]+ ;
-IDENTIFIER : [a-zA-Z_][a-zA-Z0-9_\-.]*;
-
diff --git a/yang/yang-data-impl/src/main/antlr4/org/opendaylight/yangtools/yang/data/impl/leafref/LeafRefPathParser.g4 b/yang/yang-data-impl/src/main/antlr4/org/opendaylight/yangtools/yang/data/impl/leafref/LeafRefPathParser.g4
deleted file mode 100644 (file)
index 1ae7f9e..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-parser grammar LeafRefPathParser;
-
-options {
-    tokenVocab = LeafRefPathLexer;
-}
-
-path_arg : (absolute_path | relative_path) EOF;
-
-absolute_path : (SLASH node_identifier (path_predicate)*)+;
-
-relative_path : (DOTS SLASH)* descendant_path;
-
-descendant_path : node_identifier ((path_predicate)* absolute_path)?;
-
-path_predicate : LEFT_SQUARE_BRACKET SEP? path_equality_expr SEP? RIGHT_SQUARE_BRACKET;
-
-path_equality_expr : node_identifier SEP? EQUAL SEP? path_key_expr;
-
-path_key_expr : current_function_invocation SEP? SLASH SEP? rel_path_keyexpr;
-
-rel_path_keyexpr : (DOTS SEP? SLASH SEP?)* (node_identifier SEP? SLASH SEP?)* node_identifier;
-
-node_identifier : (prefix COLON)? identifier;
-
-current_function_invocation : CURRENT_KEYWORD SEP? LEFT_PARENTHESIS SEP? RIGHT_PARENTHESIS;
-
-prefix : identifier;
-
-identifier: IDENTIFIER | CURRENT_KEYWORD;
-
index 3c76548deeadf95b7b2550aee0101c28e40ec756..0228cf71c94c00de0005ed3084e8b329235d4f19 100644 (file)
@@ -7,16 +7,13 @@
  */
 package org.opendaylight.yangtools.yang.data.impl.leafref;
 
-import java.io.Serializable;
 import java.util.Objects;
 import java.util.Optional;
 import org.opendaylight.yangtools.concepts.Immutable;
 import org.opendaylight.yangtools.yang.common.QNameModule;
 import org.opendaylight.yangtools.yang.common.Revision;
 
-abstract class AbstractQNameWithPredicate implements Immutable, Serializable, QNameWithPredicate {
-    private static final long serialVersionUID = 1L;
-
+abstract class AbstractQNameWithPredicate implements Immutable, QNameWithPredicate {
     @Override
     public final boolean equals(final Object obj) {
         if (this == obj) {
index 47e9a6152adc7b4acc37a2577c01fb4ae7fb9d00..b8036a474c8b157dea26901f18164f3ab1843296 100644 (file)
@@ -97,7 +97,7 @@ final class LeafRefContextBuilder implements Builder<LeafRefContext> {
     }
 
     void setLeafRefTargetPath(final LeafRefPath leafRefPath) {
-        this.leafRefTargetPath = leafRefPath;
+        this.leafRefTargetPath = requireNonNull(leafRefPath);
     }
 
     String getLeafRefTargetPathString() {
@@ -105,7 +105,7 @@ final class LeafRefContextBuilder implements Builder<LeafRefContext> {
     }
 
     void setLeafRefTargetPathString(final String leafRefPathString) {
-        this.leafRefTargetPathString = leafRefPathString;
+        this.leafRefTargetPathString = requireNonNull(leafRefPathString);
     }
 
     QName getCurrentNodeQName() {
index 19271b98411a76766a5c9583bb9f57e096caaec8..08fb284f6fd3738565d2a4d5f26042b5e8670d76 100644 (file)
@@ -7,8 +7,6 @@
  */
 package org.opendaylight.yangtools.yang.data.impl.leafref;
 
-import static com.google.common.base.Preconditions.checkNotNull;
-
 import java.util.Collection;
 import java.util.LinkedList;
 import java.util.List;
@@ -20,6 +18,7 @@ import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.Module;
+import org.opendaylight.yangtools.yang.model.api.PathExpression;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
 import org.opendaylight.yangtools.yang.model.api.TypedDataSchemaNode;
@@ -64,8 +63,7 @@ final class LeafRefContextTreeBuilder {
         return rootBuilder.build();
     }
 
-    private LeafRefContext buildLeafRefContextReferencingTree(final DataSchemaNode node, final Module currentModule)
-            throws LeafRefYangSyntaxErrorException {
+    private LeafRefContext buildLeafRefContextReferencingTree(final DataSchemaNode node, final Module currentModule) {
         final LeafRefContextBuilder currentLeafRefContextBuilder = new LeafRefContextBuilder(node.getQName(),
             node.getPath(), schemaContext);
 
@@ -88,18 +86,17 @@ final class LeafRefContextTreeBuilder {
             }
 
         } else if (node instanceof TypedDataSchemaNode) {
-            final TypeDefinition<?> type = ((TypedDataSchemaNode) node).getType();
+            final TypedDataSchemaNode typedNode = (TypedDataSchemaNode) node;
+            final TypeDefinition<?> type = typedNode.getType();
 
             // FIXME: fix case when type is e.g. typedef -> typedef -> leafref
             if (type instanceof LeafrefTypeDefinition) {
                 final LeafrefTypeDefinition leafrefType = (LeafrefTypeDefinition) type;
-                final String leafRefPathString = leafrefType.getPathStatement().getOriginalString();
-                final LeafRefPathParserImpl leafRefPathParser = new LeafRefPathParserImpl(schemaContext,
-                        checkNotNull(getBaseTypeModule(leafrefType), "Unable to find base module for leafref %s", node),
-                        node);
-                final LeafRefPath leafRefPath = leafRefPathParser.parseLeafRefPath(leafRefPathString);
+                final PathExpression path = leafrefType.getPathStatement();
+                final LeafRefPathParserImpl leafRefPathParser = new LeafRefPathParserImpl(leafrefType, typedNode);
+                final LeafRefPath leafRefPath = leafRefPathParser.parseLeafRefPath(path);
 
-                currentLeafRefContextBuilder.setLeafRefTargetPathString(leafRefPathString);
+                currentLeafRefContextBuilder.setLeafRefTargetPathString(path.getOriginalString());
                 currentLeafRefContextBuilder.setReferencing(true);
                 currentLeafRefContextBuilder.setLeafRefTargetPath(leafRefPath);
 
@@ -112,18 +109,6 @@ final class LeafRefContextTreeBuilder {
         return currentLeafRefContextBuilder.build();
     }
 
-    private Module getBaseTypeModule(final LeafrefTypeDefinition leafrefType) {
-        /*
-         * Find the first definition of supplied leafref type and return the
-         * module which contains this definition.
-         */
-        LeafrefTypeDefinition baseLeafRefType = leafrefType;
-        while (baseLeafRefType.getBaseType() != null) {
-            baseLeafRefType = baseLeafRefType.getBaseType();
-        }
-        return schemaContext.findModule(baseLeafRefType.getQName().getModule()).orElse(null);
-    }
-
     private LeafRefContext buildLeafRefContextReferencedByTree(final DataSchemaNode node, final Module currentModule)
             throws LeafRefYangSyntaxErrorException {
         final LeafRefContextBuilder currentLeafRefContextBuilder = new LeafRefContextBuilder(node.getQName(),
diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/leafref/LeafRefPathErrorListener.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/leafref/LeafRefPathErrorListener.java
deleted file mode 100644 (file)
index 5947649..0000000
+++ /dev/null
@@ -1,67 +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.data.impl.leafref;
-
-import java.util.ArrayList;
-import java.util.List;
-import org.antlr.v4.runtime.BaseErrorListener;
-import org.antlr.v4.runtime.RecognitionException;
-import org.antlr.v4.runtime.Recognizer;
-import org.opendaylight.yangtools.yang.model.api.Module;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-class LeafRefPathErrorListener extends BaseErrorListener {
-    private static final Logger LOG = LoggerFactory.getLogger(LeafRefPathErrorListener.class);
-
-    private final List<LeafRefPathSyntaxErrorException> exceptions = new ArrayList<>(1);
-    private final Module module;
-
-    LeafRefPathErrorListener(final Module module) {
-        this.module = module;
-    }
-
-    @Override
-    @SuppressWarnings("checkstyle:parameterName")
-    public void syntaxError(final Recognizer<?, ?> recognizer, final Object offendingSymbol, final int line,
-            final int charPositionInLine, final String msg, final RecognitionException e) {
-        LOG.debug("Syntax error in module {} at {}:{}: {}", module.getName(), line, charPositionInLine, msg, e);
-
-        exceptions.add(new LeafRefPathSyntaxErrorException(module.getName(), line, charPositionInLine, msg, e));
-    }
-
-    public void validate() throws LeafRefPathSyntaxErrorException {
-        if (exceptions.isEmpty()) {
-            return;
-        }
-
-        // Single exception: just throw it
-        if (exceptions.size() == 1) {
-            throw exceptions.get(0);
-        }
-
-        final StringBuilder sb = new StringBuilder();
-        String exceptionModule = null;
-        boolean first = true;
-        for (final LeafRefPathSyntaxErrorException e : exceptions) {
-            if (exceptionModule == null) {
-                exceptionModule = e.getModule();
-            }
-            if (first) {
-                first = false;
-            } else {
-                sb.append('\n');
-            }
-
-            sb.append(e.getFormattedMessage());
-        }
-
-        throw new LeafRefPathSyntaxErrorException(exceptionModule, 0, 0, sb.toString());
-    }
-
-}
index d781984325f67faf48116dcd6278dc95441dd796..2e763958b74c047a170f2d84e8fb668ec8e8f790 100644 (file)
  */
 package org.opendaylight.yangtools.yang.data.impl.leafref;
 
-import org.antlr.v4.runtime.CharStreams;
-import org.antlr.v4.runtime.CommonTokenStream;
-import org.antlr.v4.runtime.tree.ParseTreeWalker;
-import org.opendaylight.yangtools.yang.data.impl.leafref.LeafRefPathParser.Path_argContext;
-import org.opendaylight.yangtools.yang.model.api.Module;
-import org.opendaylight.yangtools.yang.model.api.SchemaContext;
-import org.opendaylight.yangtools.yang.model.api.SchemaNode;
+import static com.google.common.base.Preconditions.checkState;
+
+import com.google.common.collect.ImmutableList;
+import java.util.ArrayDeque;
+import java.util.Deque;
+import java.util.Set;
+import org.opendaylight.yangtools.yang.common.AbstractQName;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.common.QNameModule;
+import org.opendaylight.yangtools.yang.common.UnqualifiedQName;
+import org.opendaylight.yangtools.yang.model.api.PathExpression;
+import org.opendaylight.yangtools.yang.model.api.PathExpression.DerefSteps;
+import org.opendaylight.yangtools.yang.model.api.PathExpression.LocationPathSteps;
+import org.opendaylight.yangtools.yang.model.api.PathExpression.Steps;
+import org.opendaylight.yangtools.yang.model.api.TypedDataSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.type.LeafrefTypeDefinition;
+import org.opendaylight.yangtools.yang.xpath.api.YangBinaryExpr;
+import org.opendaylight.yangtools.yang.xpath.api.YangBinaryOperator;
+import org.opendaylight.yangtools.yang.xpath.api.YangExpr;
+import org.opendaylight.yangtools.yang.xpath.api.YangFunction;
+import org.opendaylight.yangtools.yang.xpath.api.YangFunctionCallExpr;
+import org.opendaylight.yangtools.yang.xpath.api.YangLocationPath;
+import org.opendaylight.yangtools.yang.xpath.api.YangLocationPath.QNameStep;
+import org.opendaylight.yangtools.yang.xpath.api.YangLocationPath.Relative;
+import org.opendaylight.yangtools.yang.xpath.api.YangLocationPath.Step;
+import org.opendaylight.yangtools.yang.xpath.api.YangPathExpr;
+import org.opendaylight.yangtools.yang.xpath.api.YangQNameExpr;
 
 final class LeafRefPathParserImpl {
-    private final SchemaContext schemaContext;
-    private final Module module;
-    private final SchemaNode node;
-
-    LeafRefPathParserImpl(final SchemaContext schemaContext, final Module currentModule, final SchemaNode currentNode) {
-        this.schemaContext = schemaContext;
-        this.module = currentModule;
-        this.node = currentNode;
+    private final QNameModule leafrefModule;
+    private final QNameModule nodeModule;
+
+    LeafRefPathParserImpl(final LeafrefTypeDefinition leafrefType, final TypedDataSchemaNode currentNode) {
+        // FIXME: these two namespaces look not quite right:
+        //        - leafrefModule is used for absolute paths, irrespective of where they occur
+        //        - nodeModule is used for relative paths, irrespective of where they occur
+        //
+        // There is little in RFC7950 which would hint at such a distinction and if even if it were true, it would be
+        // the job of YANG parser to ensure that absolute paths are bound during parsing.
+        //
+        // The only distinction is relative to where the leafref is defined, namely:
+        //
+        // 1) as per section 9.9.2:
+        //     o  If the "path" statement is defined within a typedef, the context
+        //        node is the leaf or leaf-list node in the data tree that
+        //        references the typedef.
+        //
+        //     o  Otherwise, the context node is the node in the data tree for which
+        //        the "path" statement is defined.
+        //
+        // 2) as per section 6.4.1:
+        //     o  Names without a namespace prefix belong to the same namespace as
+        //        the identifier of the current node.  Inside a grouping, that
+        //        namespace is affected by where the grouping is used (see
+        //        Section 7.13).  Inside a typedef, that namespace is affected by
+        //        where the typedef is referenced.  If a typedef is defined and
+        //        referenced within a grouping, the namespace is affected by where
+        //        the grouping is used (see Section 7.13).
+        this.leafrefModule = getBaseModule(leafrefType);
+        this.nodeModule = currentNode.getQName().getModule();
     }
 
-    LeafRefPath parseLeafRefPath(final String path) throws LeafRefYangSyntaxErrorException {
-        final Path_argContext pathCtx = parseLeafRefPathSource(path);
+    LeafRefPath parseLeafRefPath(final PathExpression path) {
+        final Steps steps = path.getSteps();
+        if (steps instanceof LocationPathSteps) {
+            return parseLocationPath(((LocationPathSteps) steps).getLocationPath());
+        } else if (steps instanceof DerefSteps) {
+            throw new UnsupportedOperationException("deref() leafrefs are not implemented yet");
+        } else {
+            throw new IllegalStateException("Unsupported steps " + steps);
+        }
+    }
 
-        final ParseTreeWalker walker = new ParseTreeWalker();
-        final LeafRefPathParserListenerImpl leafRefPathParserListenerImpl = new LeafRefPathParserListenerImpl(
-            schemaContext, module, node);
-        walker.walk(leafRefPathParserListenerImpl, pathCtx);
+    private LeafRefPath parseLocationPath(final YangLocationPath locationPath) {
+        return LeafRefPath.create(
+            createPathSteps(locationPath.isAbsolute() ? leafrefModule : nodeModule, locationPath.getSteps()),
+            locationPath.isAbsolute());
+    }
 
-        return leafRefPathParserListenerImpl.getLeafRefPath();
+    private static Deque<QNameWithPredicate> createPathSteps(final QNameModule localModule,
+            final ImmutableList<Step> steps) {
+        final Deque<QNameWithPredicate> path = new ArrayDeque<>(steps.size());
+        for (Step step : steps) {
+            switch (step.getAxis()) {
+                case CHILD:
+                    checkState(step instanceof QNameStep, "Unsupported step %s", step);
+                    path.add(adaptChildStep((QNameStep) step, localModule));
+                    break;
+                case PARENT:
+                    path.add(QNameWithPredicate.UP_PARENT);
+                    break;
+                default:
+                    throw new IllegalStateException("Unsupported axis in step " + step);
+            }
+        }
+        return path;
     }
 
-    private Path_argContext parseLeafRefPathSource(final String path) throws LeafRefYangSyntaxErrorException {
-        final LeafRefPathLexer lexer = new LeafRefPathLexer(CharStreams.fromString(path));
-        final LeafRefPathParser parser = new LeafRefPathParser(new CommonTokenStream(lexer));
+    private static QNameWithPredicate adaptChildStep(final QNameStep step, final QNameModule localModule) {
+        final QName qname = resolve(step.getQName(), localModule);
+        final Set<YangExpr> predicates = step.getPredicates();
+        if (predicates.isEmpty()) {
+            return new SimpleQNameWithPredicate(qname);
+        }
+
+        final QNameWithPredicateBuilder builder = new QNameWithPredicateBuilder(qname.getModule(),
+            qname.getLocalName());
+
+        for (YangExpr pred : predicates) {
+            final QNamePredicateBuilder predBuilder = new QNamePredicateBuilder();
+
+            if (pred instanceof YangBinaryExpr) {
+                final YangBinaryExpr eqPred = (YangBinaryExpr) pred;
+                checkState(eqPred.getOperator() == YangBinaryOperator.EQUALS);
 
-        final LeafRefPathErrorListener errorListener = new LeafRefPathErrorListener(module);
-        lexer.removeErrorListeners();
-        lexer.addErrorListener(errorListener);
-        parser.removeErrorListeners();
-        parser.addErrorListener(errorListener);
+                final YangExpr left = eqPred.getLeftExpr();
+                checkState(left instanceof YangQNameExpr, "Unsupported left expression %s", left);
+                predBuilder.setIdentifier(resolve(((YangQNameExpr) left).getQName(), localModule));
+
+                final YangExpr right = eqPred.getRightExpr();
+                if (right instanceof YangPathExpr) {
+                    final YangPathExpr rightPath = (YangPathExpr) right;
+                    final YangExpr filter = rightPath.getFilterExpr();
+                    if (filter instanceof YangFunctionCallExpr) {
+                        checkState(YangFunction.CURRENT.getIdentifier().equals(
+                            ((YangFunctionCallExpr) filter).getName()));
+                    } else {
+                        throw new IllegalStateException("Unhandled filter " + filter);
+                    }
+
+                    final Relative location = rightPath.getLocationPath()
+                            .orElseThrow(() -> new IllegalStateException("Missing locationPath in " + rightPath));
+                    predBuilder.setPathKeyExpression(LeafRefPath.create(
+                        createPathSteps(localModule, location.getSteps()), false));
+                } else {
+                    throw new UnsupportedOperationException("Not implemented for " + right);
+                }
+            }
+
+            builder.addQNamePredicate(predBuilder.build());
+        }
+
+        return builder.build();
+    }
+
+    private static QName resolve(final AbstractQName qname, final QNameModule localModule) {
+        if (qname instanceof QName) {
+            return (QName) qname;
+        } else if (qname instanceof UnqualifiedQName) {
+            // Bind to namespace. Note we expect to perform frequent matching, hence we are interning the result
+            return ((UnqualifiedQName) qname).bindTo(localModule).intern();
+        } else {
+            throw new IllegalStateException("Unhandled unresolved QName " + qname);
+        }
+    }
 
-        final Path_argContext result = parser.path_arg();
-        errorListener.validate();
-        return result;
+    /**
+     * Find the first definition of supplied leafref type and return the module which contains this definition.
+     */
+    private static QNameModule getBaseModule(final LeafrefTypeDefinition leafrefType) {
+        LeafrefTypeDefinition current = leafrefType;
+        while (true) {
+            final LeafrefTypeDefinition base = current.getBaseType();
+            if (base == null) {
+                return current.getQName().getModule();
+            }
+            current = base;
+        }
     }
 }
diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/leafref/LeafRefPathParserListenerImpl.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/leafref/LeafRefPathParserListenerImpl.java
deleted file mode 100644 (file)
index 078abd2..0000000
+++ /dev/null
@@ -1,186 +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.data.impl.leafref;
-
-import static com.google.common.base.Preconditions.checkArgument;
-
-import com.google.common.collect.Lists;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Optional;
-import org.antlr.v4.runtime.tree.TerminalNode;
-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.data.impl.leafref.LeafRefPathParser.IdentifierContext;
-import org.opendaylight.yangtools.yang.data.impl.leafref.LeafRefPathParser.Node_identifierContext;
-import org.opendaylight.yangtools.yang.data.impl.leafref.LeafRefPathParser.Path_argContext;
-import org.opendaylight.yangtools.yang.data.impl.leafref.LeafRefPathParser.Path_equality_exprContext;
-import org.opendaylight.yangtools.yang.data.impl.leafref.LeafRefPathParser.Path_predicateContext;
-import org.opendaylight.yangtools.yang.data.impl.leafref.LeafRefPathParser.PrefixContext;
-import org.opendaylight.yangtools.yang.data.impl.leafref.LeafRefPathParser.Rel_path_keyexprContext;
-import org.opendaylight.yangtools.yang.data.impl.leafref.LeafRefPathParser.Relative_pathContext;
-import org.opendaylight.yangtools.yang.model.api.Module;
-import org.opendaylight.yangtools.yang.model.api.ModuleImport;
-import org.opendaylight.yangtools.yang.model.api.SchemaContext;
-import org.opendaylight.yangtools.yang.model.api.SchemaNode;
-
-final class LeafRefPathParserListenerImpl extends LeafRefPathParserBaseListener {
-
-    private final List<QNameWithPredicateBuilder> leafRefPathQnameList = new ArrayList<>();
-    private final SchemaContext schemaContext;
-    private final Module module;
-    private final Module leafrefModule;
-    // FIXME: use for identifier path completion
-    private final SchemaNode node;
-
-    private ParsingState currentParsingState = ParsingState.LEAF_REF_PATH;
-    private List<QNameWithPredicateBuilder> predicatePathKeyQnameList;
-    private QNameWithPredicateBuilder currentLeafRefPathQName;
-    private QNamePredicateBuilder currentPredicate;
-    private QNameModule currentQnameModule;
-    private String currentQNameLocalName;
-    private LeafRefPath leafRefPath;
-    private boolean relativePath = false;
-
-    private enum ParsingState {
-        LEAF_REF_PATH, PATH_PREDICATE, PREDICATE_PATH_EQUALITY_EXPR, PATH_KEY_EXPR
-    }
-
-    LeafRefPathParserListenerImpl(final SchemaContext schemaContext, final Module leafrefModule,
-            final SchemaNode currentNode) {
-        this.schemaContext = schemaContext;
-        this.module = schemaContext.findModule(currentNode.getQName().getModule()).get();
-        this.leafrefModule = leafrefModule;
-        this.node = currentNode;
-    }
-
-    @Override
-    public void enterPath_predicate(final Path_predicateContext ctx) {
-        currentParsingState = ParsingState.PATH_PREDICATE;
-        currentPredicate = new QNamePredicateBuilder();
-    }
-
-    @Override
-    public void exitPath_predicate(final Path_predicateContext ctx) {
-        currentLeafRefPathQName.addQNamePredicate(currentPredicate.build());
-        currentPredicate = null;
-        currentParsingState = ParsingState.LEAF_REF_PATH;
-    }
-
-
-    @Override
-    public void enterRel_path_keyexpr(final Rel_path_keyexprContext ctx) {
-        currentParsingState = ParsingState.PATH_KEY_EXPR;
-
-        final List<TerminalNode> dots = ctx.DOTS();
-        predicatePathKeyQnameList = new ArrayList<>(dots.size());
-        for (int i = 0; i < dots.size(); ++i) {
-            predicatePathKeyQnameList.add(QNameWithPredicateBuilder.UP_PARENT_BUILDER);
-        }
-    }
-
-    @Override
-    public void exitRel_path_keyexpr(final Rel_path_keyexprContext ctx) {
-        final LeafRefPath pathKeyExpression = LeafRefPath.create(Lists.transform(predicatePathKeyQnameList,
-            QNameWithPredicateBuilder::build), false);
-        currentPredicate.setPathKeyExpression(pathKeyExpression);
-
-        currentParsingState = ParsingState.PREDICATE_PATH_EQUALITY_EXPR;
-    }
-
-    @Override
-    public void enterRelative_path(final Relative_pathContext ctx) {
-        relativePath = true;
-        final List<TerminalNode> dots = ctx.DOTS();
-        for (int i = 0; i < dots.size(); ++i) {
-            leafRefPathQnameList.add(QNameWithPredicateBuilder.UP_PARENT_BUILDER);
-        }
-    }
-
-    @Override
-    public void enterPath_equality_expr(final Path_equality_exprContext ctx) {
-        currentParsingState = ParsingState.PREDICATE_PATH_EQUALITY_EXPR;
-    }
-
-    @Override
-    public void exitPath_equality_expr(final Path_equality_exprContext ctx) {
-        currentParsingState = ParsingState.PATH_PREDICATE;
-    }
-
-    @Override
-    public void enterPrefix(final PrefixContext ctx) {
-        final String prefix = ctx.getText();
-        if (!leafrefModule.getPrefix().equals(prefix)) {
-            final Optional<QNameModule> qnameModuleOpt = getQNameModuleForImportPrefix(leafrefModule, prefix);
-            checkArgument(qnameModuleOpt.isPresent(), "No module import for prefix: %s in module: %s", prefix,
-                leafrefModule.getName());
-            currentQnameModule = qnameModuleOpt.get();
-        } else {
-            currentQnameModule = leafrefModule.getQNameModule();
-        }
-    }
-
-    @Override
-    public void exitPath_arg(final Path_argContext ctx) {
-        leafRefPath = LeafRefPath.create(Lists.transform(leafRefPathQnameList, QNameWithPredicateBuilder::build),
-            !relativePath);
-    }
-
-    @Override
-    public void enterIdentifier(final IdentifierContext ctx) {
-        currentQNameLocalName = ctx.getText();
-    }
-
-    @Override
-    public void exitNode_identifier(final Node_identifierContext ctx) {
-        if (currentQnameModule == null) {
-            if (relativePath) {
-                currentQnameModule = module.getQNameModule();
-            } else {
-                currentQnameModule = leafrefModule.getQNameModule();
-            }
-        }
-
-        if (currentParsingState == ParsingState.PREDICATE_PATH_EQUALITY_EXPR) {
-            currentPredicate.setIdentifier(QName.create(currentQnameModule, currentQNameLocalName));
-        } else {
-            final QNameWithPredicateBuilder qnameBuilder = new QNameWithPredicateBuilder(currentQnameModule,
-                currentQNameLocalName);
-
-            if (currentParsingState == ParsingState.PATH_KEY_EXPR) {
-                predicatePathKeyQnameList.add(qnameBuilder);
-            } else if (currentParsingState == ParsingState.LEAF_REF_PATH) {
-                currentLeafRefPathQName = qnameBuilder;
-                leafRefPathQnameList.add(qnameBuilder);
-            }
-        }
-        currentQnameModule = null;
-        currentQNameLocalName = null;
-    }
-
-    public LeafRefPath getLeafRefPath() {
-        return leafRefPath;
-    }
-
-    private Optional<QNameModule> getQNameModuleForImportPrefix(final Module targetModule, final String prefix) {
-        final ModuleImport moduleImport = getModuleImport(targetModule, prefix);
-        if (moduleImport == null) {
-            return Optional.empty();
-        }
-
-        final String moduleName = moduleImport.getModuleName();
-        final Optional<Revision> revision = moduleImport.getRevision();
-        return schemaContext.findModule(moduleName, revision).map(Module::getQNameModule);
-    }
-
-    private static ModuleImport getModuleImport(final Module targetModule, final String prefix) {
-        return targetModule.getImports().stream()
-            .filter(imp -> prefix.equals(imp.getPrefix())).findFirst().orElse(null);
-    }
-}
diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/leafref/LeafRefPathSyntaxErrorException.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/leafref/LeafRefPathSyntaxErrorException.java
deleted file mode 100644 (file)
index 6f2450a..0000000
+++ /dev/null
@@ -1,23 +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.data.impl.leafref;
-
-public class LeafRefPathSyntaxErrorException extends LeafRefYangSyntaxErrorException {
-
-    private static final long serialVersionUID = 1L;
-
-    public LeafRefPathSyntaxErrorException(final String module, final int line, final int charPositionInLine,
-            final String message) {
-        super(module, line, charPositionInLine, message, null);
-    }
-
-    public LeafRefPathSyntaxErrorException(final String module, final int line, final int charPositionInLine,
-            final String message, final Throwable cause) {
-        super(module,line,charPositionInLine,message,cause);
-    }
-}
index 73e7bcd123b96b11b1d6b318fed622fe8a0bd188..43d8baf19c6693c86b5a7b82c0936614ad9e871a 100644 (file)
@@ -9,13 +9,10 @@ package org.opendaylight.yangtools.yang.data.impl.leafref;
 
 import static java.util.Objects.requireNonNull;
 
-import java.io.Serializable;
 import org.opendaylight.yangtools.concepts.Immutable;
 import org.opendaylight.yangtools.yang.common.QName;
 
-class QNamePredicateImpl implements Immutable, Serializable, QNamePredicate {
-    private static final long serialVersionUID = 1L;
-
+class QNamePredicateImpl implements Immutable, QNamePredicate {
     private final QName identifier;
     private final LeafRefPath pathKeyExpression;
 
index 390fe345d7b045f9dabfe86df7495064219cac1c..b1bed027545f4b2b984c0908603e1a6dc5923b11 100644 (file)
@@ -13,9 +13,6 @@ import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.common.QNameModule;
 
 final class QNameWithPredicateImpl extends AbstractQNameWithPredicate {
-
-    private static final long serialVersionUID = 1L;
-
     private final ImmutableList<QNamePredicate> qnamePredicates;
     private final QNameModule moduleQname;
     private final String localName;
index 1e414df14aed5013bb15ed0fef2ef2c57084f981..e811ed211603826c9b6263242a7aa3938bd62de1 100644 (file)
@@ -15,8 +15,6 @@ import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.common.QNameModule;
 
 public class SimpleQNameWithPredicate extends AbstractQNameWithPredicate {
-    private static final long serialVersionUID = 1L;
-
     private final QName qname;
 
     SimpleQNameWithPredicate(final QName qname) {