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 com.google.common.base.Converter;
11 import com.google.common.base.Function;
12 import com.google.common.base.Optional;
13 import com.google.common.base.Preconditions;
14 import com.google.common.collect.Lists;
15 import java.util.Collection;
16 import java.util.List;
17 import javax.xml.xpath.XPathExpressionException;
18 import org.jaxen.BaseXPath;
19 import org.jaxen.ContextSupport;
20 import org.jaxen.JaxenException;
21 import org.jaxen.expr.Expr;
22 import org.opendaylight.yangtools.yang.common.QNameModule;
23 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
24 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
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);
38 protected static final Function<NormalizedNodeContext, NormalizedNode<?, ?>> EXTRACT_NODE =
39 new Function<NormalizedNodeContext, NormalizedNode<?, ?>>() {
41 public NormalizedNode<?, ?> apply(final NormalizedNodeContext input) {
42 return input.getNode();
45 private final Converter<String, QNameModule> converter;
46 private final SchemaPath schemaPath;
47 private final BaseXPath xpath;
49 private JaxenXPath(final Converter<String, QNameModule> converter, final SchemaPath schemaPath,
50 final BaseXPath xpath) {
51 this.converter = Preconditions.checkNotNull(converter);
52 this.schemaPath = Preconditions.checkNotNull(schemaPath);
53 this.xpath = Preconditions.checkNotNull(xpath);
56 static JaxenXPath create(final Converter<String, QNameModule> converter, final SchemaPath schemaPath,
57 final String xpath) throws JaxenException {
58 final BaseXPath compiled = new BaseXPath(xpath) {
59 private static final long serialVersionUID = 1L;
62 protected ContextSupport getContextSupport() {
63 throw new UnsupportedOperationException(xpath);
67 final Expr expr = compiled.getRootExpr();
68 LOG.debug("Compiled {} to expression {}", xpath, expr);
70 // FIXME: perform expression introspection to understand things like apex, etc.
72 return new JaxenXPath(converter, schemaPath, compiled);
76 public Optional<? extends XPathResult<?>> evaluate(final XPathDocument document, final YangInstanceIdentifier path)
77 throws XPathExpressionException {
78 Preconditions.checkArgument(document instanceof JaxenDocument);
80 final NormalizedNodeContextSupport contextSupport = NormalizedNodeContextSupport.create(
81 (JaxenDocument)document, converter);
85 result = xpath.evaluate(contextSupport.createContext(path));
86 } catch (JaxenException e) {
87 throw new XPathExpressionException(e);
90 if (result instanceof String) {
91 return Optional.of(new XPathStringResult() {
93 public String getValue() {
94 return (String)result;
97 } else if (result instanceof Number) {
98 return Optional.of(new XPathNumberResult() {
100 public Number getValue() {
101 return (Number) result;
104 } else if (result instanceof Boolean) {
105 return Optional.of(new XPathBooleanResult() {
107 public Boolean getValue() {
108 return (Boolean) result;
111 } else if (result != null){
112 return Optional.of(new XPathNodesetResult() {
113 @SuppressWarnings("unchecked")
115 public Collection<NormalizedNode<?, ?>> getValue() {
116 // XXX: Will this really work, or do we need to perform deep transformation?
117 return Lists.transform((List<NormalizedNodeContext>) result, EXTRACT_NODE);
121 return Optional.absent();
126 public SchemaPath getEvaluationPath() {
131 public SchemaPath getApexPath() {
132 // TODO: improve this
133 return SchemaPath.ROOT;