Refactor yang-xpath-impl error handling 30/80630/3
authorRobert Varga <robert.varga@pantheon.tech>
Wed, 27 Feb 2019 14:38:10 +0000 (15:38 +0100)
committerRobert Varga <robert.varga@pantheon.tech>
Wed, 27 Feb 2019 15:30:45 +0000 (16:30 +0100)
Separate out CapturingErrorListener and make sure we install it
in InstanceIdentifierParser.

Change-Id: I9313161708daa122854b423015bdbcffef369bda
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
yang/yang-xpath-impl/src/main/java/org/opendaylight/yangtools/yang/xpath/impl/AntlrXPathParser.java
yang/yang-xpath-impl/src/main/java/org/opendaylight/yangtools/yang/xpath/impl/AntlrYangXPathExpression.java
yang/yang-xpath-impl/src/main/java/org/opendaylight/yangtools/yang/xpath/impl/CapturingErrorListener.java [new file with mode: 0644]
yang/yang-xpath-impl/src/main/java/org/opendaylight/yangtools/yang/xpath/impl/InstanceIdentifierParser.java
yang/yang-xpath-impl/src/main/java/org/opendaylight/yangtools/yang/xpath/impl/Utils.java [moved from yang/yang-xpath-impl/src/main/java/org/opendaylight/yangtools/yang/xpath/impl/LiteralExprUtils.java with 71% similarity]

index d8cc076fbb9255dce8d75b9e77f0f68ceb24783b..e49f8c437a6b38533925cb19441ab365cb3158aa 100644 (file)
@@ -34,15 +34,11 @@ import java.util.Map;
 import java.util.Optional;
 import java.util.Set;
 import javax.xml.xpath.XPathExpressionException;
-import org.antlr.v4.runtime.BaseErrorListener;
 import org.antlr.v4.runtime.CharStreams;
 import org.antlr.v4.runtime.CommonTokenStream;
 import org.antlr.v4.runtime.ParserRuleContext;
-import org.antlr.v4.runtime.RecognitionException;
-import org.antlr.v4.runtime.Recognizer;
 import org.antlr.v4.runtime.tree.ParseTree;
 import org.antlr.v4.runtime.tree.TerminalNode;
-import org.eclipse.jdt.annotation.Nullable;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.common.YangConstants;
 import org.opendaylight.yangtools.yang.common.YangNamespaceContext;
@@ -133,32 +129,14 @@ final class AntlrXPathParser implements YangXPathParser {
         final xpathLexer lexer = new xpathLexer(CharStreams.fromString(xpath));
         final xpathParser parser = new xpathParser(new CommonTokenStream(lexer));
 
-        final List<XPathExpressionException> errors = new ArrayList<>();
-        final BaseErrorListener listener = new BaseErrorListener() {
-            @Override
-            public void syntaxError(final @Nullable Recognizer<?, ?> recognizer, final @Nullable Object offendingSymbol,
-                    final int line, final int charPositionInLine, final @Nullable String msg,
-                    final @Nullable RecognitionException cause) {
-                final XPathExpressionException ex = new XPathExpressionException(msg);
-                ex.initCause(cause);
-                if (errors.isEmpty()) {
-                    errors.add(ex);
-                } else {
-                    errors.get(0).addSuppressed(ex);
-                }
-            }
-        };
-
+        final CapturingErrorListener listener = new CapturingErrorListener();
         lexer.removeErrorListeners();
         lexer.addErrorListener(listener);
         parser.removeErrorListeners();
         parser.addErrorListener(listener);
 
         final YangExpr expr = parseExpr(parser.main().expr());
-        if (!errors.isEmpty()) {
-            throw errors.get(0);
-        }
-
+        listener.reportError();
         return new AntlrYangXPathExpression(namespaceContext, mathMode, expr, xpath);
     }
 
index 5d14aeaf7d83eab8c466b2f9b79687ee3c37a91b..d46e13f56c52c5f5894df0fa7fe9bd79c8eacd9c 100644 (file)
@@ -44,7 +44,7 @@ final class AntlrYangXPathExpression implements YangXPathExpression {
 
     @Override
     public YangQNameExpr interpretAsQName(final YangLiteralExpr expr) throws XPathExpressionException {
-        return LiteralExprUtils.interpretAsQName(namespaceContext, expr);
+        return Utils.interpretAsQName(namespaceContext, expr);
     }
 
     @Override
diff --git a/yang/yang-xpath-impl/src/main/java/org/opendaylight/yangtools/yang/xpath/impl/CapturingErrorListener.java b/yang/yang-xpath-impl/src/main/java/org/opendaylight/yangtools/yang/xpath/impl/CapturingErrorListener.java
new file mode 100644 (file)
index 0000000..d6a5d31
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2019 Pantheon Technologies, s.r.o.  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.xpath.impl;
+
+import javax.xml.xpath.XPathExpressionException;
+import org.antlr.v4.runtime.BaseErrorListener;
+import org.antlr.v4.runtime.RecognitionException;
+import org.antlr.v4.runtime.Recognizer;
+import org.eclipse.jdt.annotation.Nullable;
+
+final class CapturingErrorListener extends BaseErrorListener {
+    private @Nullable XPathExpressionException error;
+
+    @Override
+    public void syntaxError(final @Nullable Recognizer<?, ?> recognizer, final @Nullable Object offendingSymbol,
+            final int line, final int charPositionInLine, final @Nullable String msg,
+            final @Nullable RecognitionException cause) {
+        final XPathExpressionException ex = Utils.wrapException(cause, "%s", msg);
+        if (error == null) {
+            error = ex;
+        } else {
+            error.addSuppressed(ex);
+        }
+    }
+
+    void reportError() throws XPathExpressionException {
+        if (error != null) {
+            throw error;
+        }
+    }
+}
index 63bd5004bbbf58c7e71d0e10427097efa55bbc4a..e03b2471b2262ae4724f91ecc4539f894f04d1f2 100644 (file)
@@ -55,12 +55,15 @@ final class InstanceIdentifierParser {
     YangLocationPath interpretAsInstanceIdentifier(final YangLiteralExpr expr) throws XPathExpressionException {
         final xpathLexer lexer = new xpathLexer(CharStreams.fromString(expr.getLiteral()));
         final instanceIdentifierParser parser = new instanceIdentifierParser(new CommonTokenStream(lexer));
+        final CapturingErrorListener listener = new CapturingErrorListener();
         lexer.removeErrorListeners();
+        lexer.addErrorListener(listener);
         parser.removeErrorListeners();
-
-        // FIXME: add listeners
+        parser.addErrorListener(listener);
 
         final InstanceIdentifierContext id = parser.instanceIdentifier();
+        listener.reportError();
+
         final int length = id.getChildCount();
         final List<Step> steps = new ArrayList<>(length / 2);
         for (int i = 1; i < length; i += 2) {
similarity index 71%
rename from yang/yang-xpath-impl/src/main/java/org/opendaylight/yangtools/yang/xpath/impl/LiteralExprUtils.java
rename to yang/yang-xpath-impl/src/main/java/org/opendaylight/yangtools/yang/xpath/impl/Utils.java
index 2d0ed0c906edc19f49e83ea10a8f037f7c7e3473..2c2c1198e37cd2b16e88d9e887e98381e5f3ab5c 100644 (file)
@@ -8,17 +8,17 @@
 package org.opendaylight.yangtools.yang.xpath.impl;
 
 import javax.xml.xpath.XPathExpressionException;
+import org.eclipse.jdt.annotation.Nullable;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.common.YangNamespaceContext;
 import org.opendaylight.yangtools.yang.xpath.api.YangLiteralExpr;
-import org.opendaylight.yangtools.yang.xpath.api.YangLocationPath;
 import org.opendaylight.yangtools.yang.xpath.api.YangQNameExpr;
 
 /**
- * Utilities for interpreting {@link YangLiteralExpr}s as {@link YangQNameExpr}s and {@link YangLocationPath}s.
+ * Various simplistic utilities shared across classes.
  */
-final class LiteralExprUtils {
-    private LiteralExprUtils() {
+final class Utils {
+    private Utils() {
 
     }
 
@@ -31,17 +31,24 @@ final class LiteralExprUtils {
             try {
                 qname = namespaceContext.createQName(text.substring(0, colon), text.substring(colon + 1));
             } catch (IllegalArgumentException e) {
-                throw new XPathExpressionException(e);
+                throw wrapException(e, "Cannot interpret %s as a QName", expr);
             }
         } else {
             try {
                 // Deal with UnprefixedNames by interpreting them in implicit namespace
                 qname = namespaceContext.createQName(expr.getLiteral());
             } catch (IllegalArgumentException | IllegalStateException e) {
-                throw new XPathExpressionException(e);
+                throw wrapException(e, "Cannot interpret %s as a QName", expr);
             }
         }
 
         return YangQNameExpr.of(qname);
     }
+
+    static XPathExpressionException wrapException(final @Nullable Throwable cause, final String format,
+            final Object... args) {
+        final XPathExpressionException ret = new XPathExpressionException(String.format(format, args));
+        ret.initCause(cause);
+        return ret;
+    }
 }