3 * Copyright © 2014 František Kučera (frantovo.cz)
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 package cz.frantovo.alt2xml.out.xpath;
20 import cz.frantovo.alt2xml.out.AbstractDOMAction;
21 import cz.frantovo.alt2xml.out.ActionContext;
22 import cz.frantovo.alt2xml.out.OutputActionException;
23 import java.io.PrintWriter;
24 import java.util.Arrays;
25 import java.util.HashMap;
26 import java.util.List;
28 import javax.xml.transform.dom.DOMResult;
29 import javax.xml.xpath.XPath;
30 import javax.xml.xpath.XPathExpression;
31 import javax.xml.xpath.XPathExpressionException;
32 import javax.xml.xpath.XPathFactory;
36 * @author Ing. František Kučera (frantovo.cz)
38 public class XPathAction extends AbstractDOMAction {
40 public static final String PARAMETER_TYPED_PARAMETERS = "typed-parameters";
41 private final XPathFactory xpathFactory;
42 private final XPath xpath;
43 private final String expressionString;
44 private final XPathExpression xpathExpression;
46 public XPathAction(ActionContext actionContext) throws OutputActionException {
48 xpathFactory = XPathFactory.newInstance();
49 xpath = xpathFactory.newXPath();
51 final List<String> actionData = getActionContext().getActionData();
53 if (actionData.size() < 1) {
54 throw new OutputActionException("Please specify the XPath expression as action data");
57 boolean typedParameters = Boolean.parseBoolean(actionContext.getActionProperties().getProperty(PARAMETER_TYPED_PARAMETERS));
59 Map<String, Object> xpathParameters = new HashMap<>();
61 for (int i = 1; i < actionData.size(); i++) {
62 String parameterName = actionData.get(i++);
63 String parameterType = typedParameters ? actionData.get(i++) : PARAMETER_TYPE.STRING.name();
64 Object parameterValue = parseParameterValue(parameterType, actionData.get(i));
65 xpathParameters.put(parameterName, parameterValue);
68 xpath.setXPathVariableResolver(new PropertiesVariableResolver(xpathParameters));
70 expressionString = actionData.get(0);
72 xpathExpression = xpath.compile(expressionString);
73 } catch (XPathExpressionException e) {
74 throw new OutputActionException("Unable to compile XPath: " + expressionString, e);
80 private enum PARAMETER_TYPE {
82 // TODO: wait for Java 8 widespread and rewrite with lambdas :-)
85 public Object parse(String value) {
91 public Object parse(String value) {
92 return Boolean.valueOf(value);
97 public Object parse(String value) {
98 return Integer.parseInt(value);
103 public Object parse(String value) {
104 return Long.parseLong(value);
109 public Object parse(String value) {
110 return Double.parseDouble(value);
114 public abstract Object parse(String value);
118 private static Object parseParameterValue(String type, String value) throws OutputActionException {
121 PARAMETER_TYPE parameterType = PARAMETER_TYPE.valueOf(type.toUpperCase());
124 return parameterType.parse(value);
125 } catch (IllegalArgumentException e) {
126 throw new OutputActionException("Unable to parse value: „" + value + "“ as " + parameterType.name());
128 } catch (IllegalArgumentException e) {
129 throw new OutputActionException(
130 "Invalid XPath parameter type: „" + type
131 + "“. Possible values are: " + Arrays.toString(PARAMETER_TYPE.values())
132 + " and are case insensitive.",
138 public void run(DOMResult domResult) throws OutputActionException {
140 String result = xpathExpression.evaluate(domResult.getNode());
141 try (PrintWriter out = new PrintWriter(getActionContext().getOutputStream())) {
144 } catch (XPathExpressionException e) {
145 throw new OutputActionException("Unable to evaluate XPath: " + xpathExpression, e);