2 * Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.yangtools.yang.data.jaxen;
10 import static com.google.common.base.Preconditions.checkArgument;
11 import static java.util.Objects.requireNonNull;
13 import com.google.common.base.Converter;
14 import com.google.common.collect.Lists;
15 import java.util.List;
16 import java.util.Optional;
17 import javax.annotation.Nonnull;
18 import javax.xml.xpath.XPathExpressionException;
19 import org.jaxen.BaseXPath;
20 import org.jaxen.ContextSupport;
21 import org.jaxen.JaxenException;
22 import org.jaxen.expr.Expr;
23 import org.opendaylight.yangtools.yang.common.QNameModule;
24 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
25 import org.opendaylight.yangtools.yang.data.api.schema.xpath.XPathBooleanResult;
26 import org.opendaylight.yangtools.yang.data.api.schema.xpath.XPathDocument;
27 import org.opendaylight.yangtools.yang.data.api.schema.xpath.XPathExpression;
28 import org.opendaylight.yangtools.yang.data.api.schema.xpath.XPathNodesetResult;
29 import org.opendaylight.yangtools.yang.data.api.schema.xpath.XPathNumberResult;
30 import org.opendaylight.yangtools.yang.data.api.schema.xpath.XPathResult;
31 import org.opendaylight.yangtools.yang.data.api.schema.xpath.XPathStringResult;
32 import org.opendaylight.yangtools.yang.model.api.SchemaPath;
33 import org.slf4j.Logger;
34 import org.slf4j.LoggerFactory;
36 final class JaxenXPath implements XPathExpression {
37 private static final Logger LOG = LoggerFactory.getLogger(JaxenXPath.class);
39 private final Converter<String, QNameModule> converter;
40 private final SchemaPath schemaPath;
41 private final BaseXPath xpath;
43 private JaxenXPath(final Converter<String, QNameModule> converter, final SchemaPath schemaPath,
44 final BaseXPath xpath) {
45 this.converter = requireNonNull(converter);
46 this.schemaPath = requireNonNull(schemaPath);
47 this.xpath = requireNonNull(xpath);
50 static JaxenXPath create(final Converter<String, QNameModule> converter, final SchemaPath schemaPath,
51 final String xpath) throws JaxenException {
52 final BaseXPath compiled = new BaseXPath(xpath) {
53 private static final long serialVersionUID = 1L;
56 protected ContextSupport getContextSupport() {
57 throw new UnsupportedOperationException(xpath);
61 final Expr expr = compiled.getRootExpr();
62 LOG.debug("Compiled {} to expression {}", xpath, expr);
64 new ExprWalker(new ExprListener() {
65 // FIXME: perform expression introspection to understand things like apex, etc.
68 return new JaxenXPath(converter, schemaPath, compiled);
72 public Optional<? extends XPathResult<?>> evaluate(@Nonnull final XPathDocument document,
73 @Nonnull final YangInstanceIdentifier path) throws XPathExpressionException {
74 checkArgument(document instanceof JaxenDocument);
76 final NormalizedNodeContextSupport contextSupport = NormalizedNodeContextSupport.create(
77 (JaxenDocument)document, converter);
81 result = xpath.evaluate(contextSupport.createContext(path));
82 } catch (JaxenException e) {
83 throw new XPathExpressionException(e);
86 if (result instanceof String) {
87 return Optional.of((XPathStringResult) () -> (String)result);
88 } else if (result instanceof Number) {
89 return Optional.of((XPathNumberResult) () -> (Number) result);
90 } else if (result instanceof Boolean) {
91 return Optional.of((XPathBooleanResult) () -> (Boolean) result);
92 } else if (result != null) {
93 return Optional.of((XPathNodesetResult) () -> {
94 // XXX: Will this really work, or do we need to perform deep transformation?
95 return Lists.transform((List<NormalizedNodeContext>) result, NormalizedNodeContext::getNode);
98 return Optional.empty();
104 public SchemaPath getEvaluationPath() {
110 public SchemaPath getApexPath() {
111 // TODO: improve this
112 return SchemaPath.ROOT;