package org.korsakow.ide; import java.sql.ResultSet; import java.util.List; import javax.xml.xpath.XPath; import javax.xml.xpath.XPathConstants; import javax.xml.xpath.XPathExpressionException; import javax.xml.xpath.XPathFactory; import org.korsakow.ide.util.Util; import org.korsakow.services.finder.NodeListAdapter; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; public class XPathHelper { private static String escapeArg(String arg) { if (arg.indexOf('"') != -1) { // avoid performance penalty // oh lordy, XPath 1.0 doesn't define an escaping mechanism // blogs.msdn.com/shjin/archive/2005/07/25/443077.aspx // this is undoubtedly terribly unperformant! String[] parts = arg.split("\""); if (arg.endsWith("\"")) // String.split doesn't include trailing empty strings parts = Util.arrayAdd(parts, ""); String esc = "concat('', \""+Util.join(parts, "\",'\"',\"") + "\")"; // FuncCocnat only allows > 1 arguments return esc; } else return '"' + arg + '"'; } public static String formatQuery(String format, Object... args) { String[] parts = format.split("[?]"); if (parts.length-1 != args.length) throw new IllegalArgumentException("Number of positions (" + (parts.length-1) + ") doesn't match argument count: " + format + "(" + args.length + ")"); StringBuilder sb = new StringBuilder(); for (int i = 0; i < args.length; ++i) { sb.append(parts[i]) .append(escapeArg(args[i].toString())); } sb.append(parts[parts.length-1]); return sb.toString(); } private static class ThreadLocalXPath extends ThreadLocal<XPath> { @Override protected XPath initialValue() { return XPathFactory.newInstance().newXPath(); } } private static ThreadLocal<XPath> xpathLocal = new ThreadLocalXPath(); private static XPath getXPath() { return xpathLocal.get(); } private final Node inputSource; public XPathHelper(Node inputSource) { if (inputSource == null) throw new NullPointerException(); this.inputSource = inputSource; } // ===================================================================================== // ===================================================================================== // nonstatic methods // ===================================================================================== // ===================================================================================== public Element xpathAsElement(String query) throws XPathExpressionException { return XPathHelper.xpathAsElement(inputSource, query); } public Element xpathAsElement(String query, Object... args) throws XPathExpressionException { return XPathHelper.xpathAsElement(inputSource, query, args); } public Node xpathAsNode(String query) throws XPathExpressionException { return XPathHelper.xpathAsNode(inputSource, query); } public Node xpathAsNode(String query, Object... args) throws XPathExpressionException { return XPathHelper.xpathAsNode(inputSource, query, args); } public NodeList xpathAsNodeList(String query) throws XPathExpressionException { return XPathHelper.xpathAsNodeList(inputSource, query); } public NodeList xpathAsNodeList(String query, Object... args) throws XPathExpressionException { return XPathHelper.xpathAsNodeList(inputSource, query, args); } public String xpathAsString(String query) throws XPathExpressionException { return XPathHelper.xpathAsString(inputSource, query); } public String xpathAsString(String query, Object... args) throws XPathExpressionException { return XPathHelper.xpathAsString(inputSource, query, args); } public int xpathAsInt(String query) throws XPathExpressionException { return XPathHelper.xpathAsInt(inputSource, query); } public int xpathAsInt(String query, Object... args) throws XPathExpressionException { return XPathHelper.xpathAsInt(inputSource, query, args); } public long xpathAsLong(String query) throws XPathExpressionException { return XPathHelper.xpathAsLong(inputSource, query); } public long xpathAsLong(String query, Object... args) throws XPathExpressionException { return XPathHelper.xpathAsLong(inputSource, query, args); } public boolean xpathAsBoolean(String query) throws XPathExpressionException { return XPathHelper.xpathAsBoolean(inputSource, query); } public boolean xpathAsBoolean(String query, Object... args) throws XPathExpressionException { return XPathHelper.xpathAsBoolean(inputSource, query, args); } public float xpathAsFloat(String query) throws XPathExpressionException { return XPathHelper.xpathAsFloat(inputSource, query); } public float xpathAsFloat(String query, Object... args) throws XPathExpressionException { return XPathHelper.xpathAsFloat(inputSource, query, args); } public double xpathAsDouble(String query) throws XPathExpressionException { return XPathHelper.xpathAsDouble(inputSource, query); } public ResultSet xpathAsResultSet(String query) throws XPathExpressionException { return XPathHelper.xpathAsResultSet(inputSource, query); } public ResultSet xpathAsResultSet(String query, Object... args) throws XPathExpressionException { return XPathHelper.xpathAsResultSet(inputSource, query, args); } public List<Node> xpathAsList(String query, Object... args) throws XPathExpressionException { return XPathHelper.xpathAsList(inputSource, query, args); } // ===================================================================================== // ===================================================================================== // static methods // ===================================================================================== // ===================================================================================== public static Element xpathAsElement(Node inputSource, String query) throws XPathExpressionException { return (Element)xpathAsNode(inputSource, query); } public static Element xpathAsElement(Node inputSource, String query, Object... args) throws XPathExpressionException { return xpathAsElement(inputSource, formatQuery(query, args)); } public static Node xpathAsNode(Node inputSource, String query) throws XPathExpressionException { // System.out.println(query); return (Node)getXPath().evaluate(query, inputSource, XPathConstants.NODE); } public static Node xpathAsNode(Node inputSource, String query, Object... args) throws XPathExpressionException { return xpathAsNode(inputSource, formatQuery(query, args)); } public static NodeList xpathAsNodeList(Node inputSource, String query) throws XPathExpressionException { return (NodeList)getXPath().evaluate(query, inputSource, XPathConstants.NODESET); } public static NodeList xpathAsNodeList(Node inputSource, String query, Object... args) throws XPathExpressionException { return xpathAsNodeList(inputSource, formatQuery(query, args)); } public static List<Node> xpathAsList(Node inputSource, String query) throws XPathExpressionException { return new NodeListAdapter(xpathAsNodeList(inputSource, query)); } public static List<Node> xpathAsList(Node inputSource, String query, Object... args) throws XPathExpressionException { return new NodeListAdapter(xpathAsNodeList(inputSource, query, args)); } public static String xpathAsString(Node inputSource, String query) throws XPathExpressionException { //System.out.println(query); return getXPath().evaluate(query, inputSource); } public static String xpathAsString(Node inputSource, String query, Object... args) throws XPathExpressionException { return xpathAsString(inputSource, formatQuery(query, args)); } public static int xpathAsInt(Node inputSource, String query) throws XPathExpressionException { return Integer.parseInt(xpathAsString(inputSource, query)); } public static int xpathAsInt(Node inputSource, String query, Object... args) throws XPathExpressionException { return xpathAsInt(inputSource, formatQuery(query, args)); } public static long xpathAsLong(Node inputSource, String query) throws XPathExpressionException { return Long.parseLong(xpathAsString(inputSource, query)); } public static long xpathAsLong(Node inputSource, String query, Object... args) throws XPathExpressionException { return xpathAsLong(inputSource, formatQuery(query, args)); } public static boolean xpathAsBoolean(Node inputSource, String query) throws XPathExpressionException { return Boolean.parseBoolean(xpathAsString(inputSource, query)); } public static boolean xpathAsBoolean(Node inputSource, String query, Object... args) throws XPathExpressionException { return xpathAsBoolean(inputSource, formatQuery(query, args)); } public static float xpathAsFloat(Node inputSource, String query) throws XPathExpressionException { return Float.parseFloat(xpathAsString(inputSource, query)); } public static float xpathAsFloat(Node inputSource, String query, Object... args) throws XPathExpressionException { return xpathAsFloat(inputSource, formatQuery(query, args)); } public static double xpathAsDouble(Node inputSource, String query) throws XPathExpressionException { return Double.parseDouble(xpathAsString(inputSource, query)); } public static ResultSet xpathAsResultSet(Node inputSource, String query) throws XPathExpressionException { return new NodeListResultSet(xpathAsNodeList(inputSource, query)); } public static ResultSet xpathAsResultSet(Node inputSource, String query, Object... args) throws XPathExpressionException { return new NodeListResultSet(xpathAsNodeList(inputSource, formatQuery(query, args))); } }