java/alt2xml-out-xpath/src/cz/frantovo/alt2xml/out/xpath/XPathAction.java
author František Kučera <franta-hg@frantovo.cz>
Sat, 06 Sep 2014 18:37:24 +0200
changeset 79 3581fe8cd4fe
parent 72 4ba54a632eb8
child 97 a72d55ff30c9
permissions -rw-r--r--
out-xpath: trailing line-break is optional
     1 /**
     2  * Alt2XML
     3  * Copyright © 2014 František Kučera (frantovo.cz)
     4  *
     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.
     9  *
    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.
    14  *
    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/>.
    17  */
    18 package cz.frantovo.alt2xml.out.xpath;
    19 
    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;
    27 import java.util.Map;
    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;
    33 
    34 /**
    35  *
    36  * @author Ing. František Kučera (frantovo.cz)
    37  */
    38 public class XPathAction extends AbstractDOMAction {
    39 
    40 	public static final String PARAMETER_TYPED_PARAMETERS = "typed-parameters";
    41 	public static final String PARAMETER_LINE_BREAK = "line-break";
    42 	private final boolean typedParameters;
    43 	private final boolean lineBreak;
    44 	private final XPathFactory xpathFactory;
    45 	private final XPath xpath;
    46 	private final String expressionString;
    47 	private final XPathExpression xpathExpression;
    48 
    49 	public XPathAction(ActionContext actionContext) throws OutputActionException {
    50 		super(actionContext);
    51 		xpathFactory = XPathFactory.newInstance();
    52 		xpath = xpathFactory.newXPath();
    53 
    54 		final List<String> actionData = getActionContext().getActionData();
    55 
    56 		if (actionData.size() < 1) {
    57 			throw new OutputActionException("Please specify the XPath expression as action data");
    58 		} else {
    59 
    60 			typedParameters = Boolean.parseBoolean(actionContext.getActionProperties().getProperty(PARAMETER_TYPED_PARAMETERS));
    61 			lineBreak = Boolean.parseBoolean(actionContext.getActionProperties().getProperty(PARAMETER_LINE_BREAK, Boolean.TRUE.toString()));
    62 
    63 			Map<String, Object> xpathParameters = new HashMap<>();
    64 
    65 			for (int i = 1; i < actionData.size(); i++) {
    66 				String parameterName = actionData.get(i++);
    67 				String parameterType = typedParameters ? actionData.get(i++) : PARAMETER_TYPE.STRING.name();
    68 				Object parameterValue = parseParameterValue(parameterType, actionData.get(i));
    69 				xpathParameters.put(parameterName, parameterValue);
    70 			}
    71 
    72 			xpath.setXPathVariableResolver(new PropertiesVariableResolver(xpathParameters));
    73 
    74 			expressionString = actionData.get(0);
    75 			try {
    76 				xpathExpression = xpath.compile(expressionString);
    77 			} catch (XPathExpressionException e) {
    78 				throw new OutputActionException("Unable to compile XPath: " + expressionString, e);
    79 			}
    80 
    81 		}
    82 	}
    83 
    84 	private enum PARAMETER_TYPE {
    85 
    86 		// TODO: wait for Java 8 widespread and rewrite with lambdas :-)
    87 		STRING {
    88 					@Override
    89 					public Object parse(String value) {
    90 						return value;
    91 					}
    92 				},
    93 		BOOLEAN {
    94 					@Override
    95 					public Object parse(String value) {
    96 						return Boolean.valueOf(value);
    97 					}
    98 				},
    99 		INTEGER {
   100 					@Override
   101 					public Object parse(String value) {
   102 						return Integer.parseInt(value);
   103 					}
   104 				},
   105 		LONG {
   106 					@Override
   107 					public Object parse(String value) {
   108 						return Long.parseLong(value);
   109 					}
   110 				},
   111 		DOUBLE {
   112 					@Override
   113 					public Object parse(String value) {
   114 						return Double.parseDouble(value);
   115 					}
   116 				};
   117 
   118 		public abstract Object parse(String value);
   119 
   120 	}
   121 
   122 	private static Object parseParameterValue(String type, String value) throws OutputActionException {
   123 
   124 		try {
   125 			PARAMETER_TYPE parameterType = PARAMETER_TYPE.valueOf(type.toUpperCase());
   126 
   127 			try {
   128 				return parameterType.parse(value);
   129 			} catch (IllegalArgumentException e) {
   130 				throw new OutputActionException("Unable to parse value: „" + value + "“ as " + parameterType.name());
   131 			}
   132 		} catch (IllegalArgumentException e) {
   133 			throw new OutputActionException(
   134 					"Invalid XPath parameter type: „" + type
   135 					+ "“. Possible values are: " + Arrays.toString(PARAMETER_TYPE.values())
   136 					+ " and are case insensitive.",
   137 					e);
   138 		}
   139 	}
   140 
   141 	@Override
   142 	public void run(DOMResult domResult) throws OutputActionException {
   143 		try {
   144 			String result = xpathExpression.evaluate(domResult.getNode());
   145 			try (PrintWriter out = new PrintWriter(getActionContext().getOutputStream())) {
   146 				out.print(result);
   147 				if (lineBreak) {
   148 					out.println();
   149 				}
   150 			}
   151 		} catch (XPathExpressionException e) {
   152 			throw new OutputActionException("Unable to evaluate XPath: " + xpathExpression, e);
   153 		}
   154 	}
   155 }