From 70fccf194fb80d172602950752d3259c58f5bcfc Mon Sep 17 00:00:00 2001 From: Robert Varga Date: Sat, 28 Apr 2018 12:37:52 +0200 Subject: [PATCH] Do not use jaxen XPath We are really interested only in Expr and its evaluation, hence we can skip the BaseXPath class, which is hiding things from us. This also lowers the memory overhead of compiled expression very slightly and improves performance, as the result is not needlessly obfuscated via a singleton list. Furthermore we no longer go through XPathReaderFactory, which incurs reflection overhead, but rather instantiate org.jaxen.saxpath.base.XPathReader directly. Change-Id: I7fd315c17f4013f927e724226408ba12f8445606 Signed-off-by: Robert Varga --- .../yangtools/yang/data/jaxen/JaxenXPath.java | 68 ++++++++++++------- 1 file changed, 44 insertions(+), 24 deletions(-) diff --git a/yang/yang-data-jaxen/src/main/java/org/opendaylight/yangtools/yang/data/jaxen/JaxenXPath.java b/yang/yang-data-jaxen/src/main/java/org/opendaylight/yangtools/yang/data/jaxen/JaxenXPath.java index df2c4f49b5..0eb03a1e05 100644 --- a/yang/yang-data-jaxen/src/main/java/org/opendaylight/yangtools/yang/data/jaxen/JaxenXPath.java +++ b/yang/yang-data-jaxen/src/main/java/org/opendaylight/yangtools/yang/data/jaxen/JaxenXPath.java @@ -18,11 +18,12 @@ import java.util.List; import java.util.Optional; import javax.annotation.Nonnull; import javax.xml.xpath.XPathExpressionException; -import org.jaxen.BaseXPath; -import org.jaxen.ContextSupport; import org.jaxen.JaxenException; -import org.jaxen.XPath; +import org.jaxen.JaxenHandler; +import org.jaxen.XPathSyntaxException; import org.jaxen.expr.Expr; +import org.jaxen.saxpath.SAXPathException; +import org.jaxen.saxpath.XPathReader; import org.opendaylight.yangtools.yang.common.QNameModule; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier; import org.opendaylight.yangtools.yang.data.api.schema.xpath.XPathBooleanResult; @@ -41,34 +42,38 @@ final class JaxenXPath implements XPathExpression { private final Converter converter; private final SchemaPath schemaPath; - private final XPath xpath; + private final Expr expr; private JaxenXPath(final Converter converter, final SchemaPath schemaPath, - final XPath xpath) { + final Expr expr) { this.converter = requireNonNull(converter); this.schemaPath = requireNonNull(schemaPath); - this.xpath = requireNonNull(xpath); + this.expr = requireNonNull(expr); } static JaxenXPath create(final Converter converter, final SchemaPath schemaPath, final String xpath) throws JaxenException { - final BaseXPath compiled = new BaseXPath(xpath) { - private static final long serialVersionUID = 1L; - @Override - protected ContextSupport getContextSupport() { - throw new UnsupportedOperationException(xpath); - } - }; + final Expr parsed; + try { + final XPathReader reader = new org.jaxen.saxpath.base.XPathReader(); + final JaxenHandler handler = new JaxenHandler(); + reader.setXPathHandler(handler); + reader.parse(xpath); + parsed = handler.getXPathExpr().getRootExpr(); + } catch (org.jaxen.saxpath.XPathSyntaxException e) { + throw new XPathSyntaxException(e); + } catch (SAXPathException e) { + throw new JaxenException(e); + } - final Expr expr = compiled.getRootExpr(); - LOG.debug("Compiled {} to expression {}", xpath, expr); + LOG.debug("Compiled {} to expression {}", xpath, parsed); new ExprWalker(new ExprListener() { // FIXME: perform expression introspection to understand things like apex, etc. - }).walk(expr); + }).walk(parsed); - return new JaxenXPath(converter, schemaPath, compiled); + return new JaxenXPath(converter, schemaPath, parsed); } @Override @@ -79,13 +84,7 @@ final class JaxenXPath implements XPathExpression { final NormalizedNodeContextSupport contextSupport = NormalizedNodeContextSupport.create( (JaxenDocument)document, converter); - final Object result; - try { - result = xpath.evaluate(contextSupport.createContext(path)); - } catch (JaxenException e) { - throw new XPathExpressionException(e); - } - + final Object result = evaluate(contextSupport.createContext(path)); if (result instanceof String) { return Optional.of((XPathStringResult) () -> (String) result); } else if (result instanceof Number) { @@ -106,6 +105,27 @@ final class JaxenXPath implements XPathExpression { }); } + private Object evaluate(final NormalizedNodeContext context) throws XPathExpressionException { + final Object result; + try { + result = expr.evaluate(context); + } catch (JaxenException e) { + throw new XPathExpressionException(e); + } + + if (result instanceof List) { + final List list = (List) result; + if (list.size() == 1) { + final Object first = list.get(0); + if (first instanceof String || first instanceof Number || first instanceof Boolean) { + return first; + } + } + } + + return result; + } + @Nonnull @Override public SchemaPath getEvaluationPath() { -- 2.36.6