sascha@998: package de.intevation.flys.artifacts.datacage.templating; sascha@998: sascha@998: import de.intevation.artifacts.common.utils.XMLUtils; sascha@998: sascha@1818: import de.intevation.flys.utils.Pair; sascha@1818: teichmann@4740: import java.sql.Connection; teichmann@4740: import java.sql.SQLException; teichmann@4740: teichmann@4740: import java.util.ArrayDeque; teichmann@4740: import java.util.ArrayList; teichmann@4740: import java.util.Deque; teichmann@4740: import java.util.HashMap; teichmann@4740: import java.util.List; teichmann@4740: import java.util.Map; teichmann@4740: teichmann@4740: import java.util.regex.Matcher; teichmann@4740: import java.util.regex.Pattern; teichmann@4740: teichmann@4740: import javax.xml.namespace.QName; teichmann@4740: teichmann@4740: import javax.xml.xpath.XPath; teichmann@4740: import javax.xml.xpath.XPathConstants; teichmann@4740: import javax.xml.xpath.XPathExpressionException; teichmann@4740: import javax.xml.xpath.XPathFactory; teichmann@4740: sascha@998: import org.apache.log4j.Logger; sascha@998: teichmann@4740: import org.w3c.dom.Document; teichmann@4740: import org.w3c.dom.Element; teichmann@4740: import org.w3c.dom.Node; teichmann@4740: import org.w3c.dom.NodeList; teichmann@4740: felix@4526: felix@4897: /** Handles and evaluate meta-data template against dbs. */ sascha@998: public class Builder sascha@998: { sascha@998: private static Logger log = Logger.getLogger(Builder.class); sascha@998: sascha@1015: public static final String CONNECTION_USER = "user"; sascha@1015: public static final String CONNECTION_SYSTEM = "system"; sascha@1015: public static final String DEFAULT_CONNECTION_NAME = CONNECTION_SYSTEM; sascha@1015: sascha@998: public static final Pattern STRIP_LINE_INDENT = sascha@998: Pattern.compile("\\s*\\r?\\n\\s*"); sascha@998: sascha@998: public static final String DC_NAMESPACE_URI = sascha@998: "http://www.intevation.org/2011/Datacage"; sascha@998: sascha@998: private static final Document EVAL_DOCUMENT = sascha@998: XMLUtils.newDocument(); sascha@998: sascha@998: private static final XPathFactory XPATH_FACTORY = sascha@998: XPathFactory.newInstance(); sascha@998: sascha@998: protected Document template; sascha@998: sascha@998: protected Map compiledStatements; sascha@998: felix@4526: /** Connection to either of the databases. */ sascha@1011: public static class NamedConnection { sascha@1011: sascha@1011: protected String name; sascha@1011: protected Connection connection; sascha@1011: protected boolean cached; sascha@1011: sascha@1011: public NamedConnection() { sascha@1011: } sascha@1011: sascha@1011: public NamedConnection( sascha@3076: String name, sascha@1011: Connection connection sascha@1011: ) { sascha@1011: this(name, connection, true); sascha@1011: } sascha@1011: sascha@1011: public NamedConnection( sascha@3076: String name, sascha@1011: Connection connection, sascha@1011: boolean cached sascha@1011: ) { sascha@1011: this.name = name; sascha@1011: this.connection = connection; sascha@1011: this.cached = cached; sascha@1011: } sascha@1011: } // class NamedConnection sascha@1011: sascha@998: public class BuildHelper sascha@998: { sascha@1818: protected Node output; sascha@1818: protected Document owner; sascha@1818: protected StackFrames frames; sascha@1818: protected List connections; sascha@1818: protected Map statements; sascha@1818: protected Deque> connectionsStack; teichmann@4890: protected Deque macroBodies; sascha@998: sascha@998: public BuildHelper( sascha@1011: Node output, sascha@1011: List connections, sascha@1011: Map parameters sascha@998: ) { sascha@1011: if (connections.isEmpty()) { sascha@1011: throw new IllegalArgumentException("no connections given."); sascha@1011: } sascha@1011: sascha@1011: this.connections = connections; sascha@1818: connectionsStack = sascha@1818: new ArrayDeque>(); sascha@1011: this.output = output; sascha@1011: frames = new StackFrames(parameters); sascha@1011: owner = getOwnerDocument(output); sascha@1011: statements = sascha@1011: new HashMap(); teichmann@4890: macroBodies = new ArrayDeque(); sascha@998: } sascha@998: sascha@998: public void build() throws SQLException { sascha@998: try { sascha@998: synchronized (template) { sascha@998: for (Node current: rootsToList()) { sascha@998: build(output, current); sascha@998: } sascha@998: } sascha@998: } sascha@998: finally { sascha@998: closeStatements(); sascha@998: } sascha@998: } sascha@998: sascha@998: protected void closeStatements() { sascha@998: for (CompiledStatement.Instance csi: statements.values()) { sascha@998: csi.close(); sascha@998: } sascha@998: statements.clear(); sascha@998: } sascha@998: felix@1890: /** felix@4896: * Return first statement node in NodeList, respecting felix@4897: * macros but not doing evaluation (e.g. of s). felix@4896: */ felix@4896: private Node findStatementNode(NodeList nodes) { felix@4896: int S = nodes.getLength(); felix@4896: felix@4896: // Check direct children and take special care of macros. felix@4896: for (int i = 0; i < S; ++i) { felix@4896: Node node = nodes.item(i); felix@4896: String ns; felix@4896: // Regular statement node. felix@4896: if (node.getNodeType() == Node.ELEMENT_NODE felix@4896: && node.getLocalName().equals("statement") felix@4896: && (ns = node.getNamespaceURI()) != null felix@4896: && ns.equals(DC_NAMESPACE_URI)) { felix@4896: return node; felix@4896: } felix@4896: // Macro node. Descend. felix@4896: else if (node.getNodeType() == Node.ELEMENT_NODE felix@4896: && node.getLocalName().equals("call-macro") felix@4896: && (ns = node.getNamespaceURI()) != null felix@4896: && ns.equals(DC_NAMESPACE_URI)) { felix@4896: felix@4896: String macroName = ((Element)node).getAttribute("name"); felix@4896: Node inMacroNode = felix@4896: findStatementNode(getMacroChildren(macroName)); felix@4896: if (inMacroNode != null) { felix@4896: return inMacroNode; felix@4896: } felix@4896: } felix@4896: felix@4896: } felix@4896: felix@4896: return null; felix@4896: } felix@4896: felix@4896: /** felix@1890: * Handle a \ node. felix@1890: */ sascha@998: protected void context(Node parent, Element current) sascha@998: throws SQLException sascha@998: { sascha@1023: log.debug("dc:context"); sascha@998: sascha@1023: NodeList subs = current.getChildNodes(); felix@4896: Node stmntNode = findStatementNode(subs); sascha@1023: int S = subs.getLength(); sascha@1023: sascha@1023: if (stmntNode == null) { sascha@1023: log.warn("dc:context: cannot find statement"); sascha@998: return; sascha@998: } sascha@998: felix@1890: String stmntText = stmntNode.getTextContent(); felix@1890: sascha@1011: String con = current.getAttribute("connection"); sascha@1011: sascha@1011: String key = con + "-" + stmntText; sascha@1011: sascha@1011: CompiledStatement.Instance csi = statements.get(key); sascha@998: sascha@998: if (csi == null) { sascha@998: CompiledStatement cs = compiledStatements.get(stmntText); sascha@998: csi = cs.new Instance(); sascha@1011: statements.put(key, csi); sascha@998: } sascha@998: sascha@1011: NamedConnection connection = connectionsStack.isEmpty() sascha@1011: ? connections.get(0) sascha@1818: : connectionsStack.peek().getA(); sascha@998: sascha@1011: if (con.length() > 0) { sascha@1011: for (NamedConnection nc: connections) { sascha@1011: if (con.equals(nc.name)) { sascha@1011: connection = nc; sascha@1011: break; sascha@998: } sascha@998: } sascha@1011: } sascha@1011: sascha@1023: ResultData rd = csi.execute( sascha@1023: connection.connection, sascha@1023: frames, sascha@1023: connection.cached); sascha@1011: sascha@1023: // only descent if there are results sascha@1023: if (!rd.isEmpty()) { teichmann@4051: connectionsStack.push( teichmann@4051: new Pair(connection, rd)); sascha@1023: try { sascha@1023: for (int i = 0; i < S; ++i) { sascha@1023: build(parent, subs.item(i)); sascha@1011: } sascha@998: } sascha@1023: finally { sascha@1023: connectionsStack.pop(); sascha@1023: } sascha@998: } sascha@1023: } sascha@1023: felix@1890: /** felix@1890: * Kind of foreach over results of a statement within a context. felix@1890: */ sascha@3076: protected void elements(Node parent, Element current) sascha@1023: throws SQLException sascha@1023: { sascha@1023: log.debug("dc:elements"); sascha@1023: sascha@1818: if (connectionsStack.isEmpty()) { sascha@1023: log.warn("dc:elements without having results"); sascha@1023: return; sascha@1023: } sascha@1023: sascha@1023: NodeList subs = current.getChildNodes(); sascha@1023: int S = subs.getLength(); sascha@1023: sascha@1023: if (S == 0) { sascha@1023: log.debug("dc:elements has no children"); sascha@1023: return; sascha@1023: } sascha@1023: sascha@1818: ResultData rd = connectionsStack.peek().getB(); sascha@1023: sascha@1023: String [] columns = rd.getColumnLabels(); sascha@1023: sascha@1023: //if (log.isDebugEnabled()) { sascha@1023: // log.debug("pushing vars: " sascha@1023: // + java.util.Arrays.toString(columns)); sascha@1023: //} sascha@1023: sascha@1023: for (Object [] row: rd.getRows()) { sascha@1023: frames.enter(); sascha@1023: try { sascha@1023: frames.put(columns, row); sascha@1023: //if (log.isDebugEnabled()) { sascha@1023: // log.debug("current vars: " + frames.dump()); sascha@1023: //} sascha@1023: for (int i = 0; i < S; ++i) { sascha@1023: build(parent, subs.item(i)); sascha@1023: } sascha@1023: } sascha@1023: finally { sascha@1023: frames.leave(); sascha@1023: } sascha@1011: } sascha@998: } sascha@998: felix@1890: /** felix@1890: * Create element. felix@1890: */ sascha@998: protected void element(Node parent, Element current) sascha@998: throws SQLException sascha@998: { sascha@998: String attr = expand(current.getAttribute("name")); sascha@998: sascha@998: if (log.isDebugEnabled()) { sascha@998: log.debug("dc:element -> '" + attr + "'"); sascha@998: } sascha@998: sascha@998: if (attr.length() == 0) { sascha@998: log.warn("no name attribute found"); sascha@998: return; sascha@998: } sascha@998: sascha@998: Element element = owner.createElement(attr); sascha@998: sascha@998: NodeList children = current.getChildNodes(); sascha@998: for (int i = 0, N = children.getLength(); i < N; ++i) { sascha@998: build(element, children.item(i)); sascha@998: } sascha@998: sascha@998: parent.appendChild(element); sascha@998: } sascha@998: sascha@998: protected void text(Node parent, Element current) sascha@998: throws SQLException sascha@998: { sascha@998: log.debug("dc:text"); sascha@998: String value = expand(current.getTextContent()); sascha@998: parent.appendChild(owner.createTextNode(value)); sascha@998: } sascha@998: felix@1890: /** felix@1890: * Add attribute to an element felix@3571: * @see Element felix@1890: */ sascha@998: protected void attribute(Node parent, Element current) { sascha@998: sascha@998: if (parent.getNodeType() != Node.ELEMENT_NODE) { sascha@998: log.warn("need element here"); sascha@998: return; sascha@998: } sascha@998: sascha@998: String name = expand(current.getAttribute("name")); sascha@998: String value = expand(current.getAttribute("value")); sascha@998: sascha@998: Element element = (Element)parent; sascha@998: sascha@998: element.setAttribute(name, value); sascha@998: } sascha@998: felix@4893: /** felix@4893: * Call-Macro node. felix@4893: * Evaluate child-nodes of the given macro element (not its text). felix@4893: */ sascha@998: protected void callMacro(Node parent, Element current) sascha@998: throws SQLException sascha@998: { sascha@998: String name = current.getAttribute("name"); sascha@998: sascha@998: if (name.length() == 0) { sascha@998: log.warn("missing 'name' attribute in 'call-macro'"); sascha@998: return; sascha@998: } sascha@998: sascha@998: NodeList macros = template.getElementsByTagNameNS( sascha@998: DC_NAMESPACE_URI, "macro"); sascha@998: teichmann@4890: Element macro = null; teichmann@4890: sascha@998: for (int i = 0, N = macros.getLength(); i < N; ++i) { teichmann@4890: Element m = (Element) macros.item(i); teichmann@4890: if (name.equals(m.getAttribute("name"))) { teichmann@4890: macro = m; teichmann@4890: break; teichmann@4890: } teichmann@4890: } teichmann@4890: teichmann@4890: if (macro != null) { teichmann@4890: macroBodies.push(current.getChildNodes()); teichmann@4890: try { sascha@998: NodeList subs = macro.getChildNodes(); sascha@998: for (int j = 0, M = subs.getLength(); j < M; ++j) { sascha@998: build(parent, subs.item(j)); sascha@998: } teichmann@4890: } teichmann@4890: finally { teichmann@4890: macroBodies.pop(); sascha@998: } sascha@998: } teichmann@4890: else { teichmann@4890: log.warn("no macro '" + name + "' found."); teichmann@4890: } teichmann@4890: } sascha@998: teichmann@4890: protected void macroBody(Node parent, Element current) teichmann@4890: throws SQLException teichmann@4890: { teichmann@4890: if (!macroBodies.isEmpty()) { teichmann@4890: NodeList children = macroBodies.peek(); teichmann@4890: for (int i = 0, N = children.getLength(); i < N; ++i) { teichmann@4890: build(parent, children.item(i)); teichmann@4890: } teichmann@4890: } teichmann@4890: else { teichmann@4890: log.warn("no current macro"); teichmann@4890: } sascha@998: } sascha@998: felix@4896: /** Get macro node children, not resolving bodies. */ felix@4896: protected NodeList getMacroChildren(String name) { felix@4896: NodeList macros = template.getElementsByTagNameNS( felix@4896: DC_NAMESPACE_URI, "macro"); felix@4896: felix@4896: Element macro = null; felix@4896: felix@4896: for (int i = 0, N = macros.getLength(); i < N; ++i) { felix@4896: Element m = (Element) macros.item(i); felix@4896: if (name.equals(m.getAttribute("name"))) { felix@4896: macro = m; felix@4896: break; felix@4896: } felix@4896: } felix@4896: felix@4896: if (macro != null) { felix@4896: return macro.getChildNodes(); felix@4896: } felix@4896: return null; felix@4896: } felix@4896: sascha@998: protected void ifClause(Node parent, Element current) sascha@998: throws SQLException sascha@998: { sascha@998: String test = current.getAttribute("test"); sascha@998: sascha@998: if (test.length() == 0) { sascha@998: log.warn("missing 'test' attribute in 'if'"); sascha@998: return; sascha@998: } sascha@998: teichmann@4737: Boolean result = evaluateXPathToBoolean(test); sascha@998: sascha@998: if (result != null && result.booleanValue()) { sascha@998: NodeList subs = current.getChildNodes(); sascha@998: for (int i = 0, N = subs.getLength(); i < N; ++i) { sascha@998: build(parent, subs.item(i)); sascha@998: } sascha@998: } sascha@998: } sascha@998: sascha@998: protected void choose(Node parent, Element current) sascha@998: throws SQLException sascha@998: { sascha@998: Node branch = null; sascha@998: sascha@998: NodeList children = current.getChildNodes(); sascha@998: for (int i = 0, N = children.getLength(); i < N; ++i) { sascha@998: Node child = children.item(i); sascha@998: String ns = child.getNamespaceURI(); sascha@998: if (ns == null sascha@998: || !ns.equals(DC_NAMESPACE_URI) sascha@998: || child.getNodeType() != Node.ELEMENT_NODE sascha@998: ) { sascha@998: continue; sascha@998: } sascha@998: String name = child.getLocalName(); sascha@998: if ("when".equals(name)) { sascha@998: Element when = (Element)child; sascha@998: String test = when.getAttribute("test"); sascha@998: if (test.length() == 0) { sascha@998: log.warn("no 'test' attribute found for when"); sascha@998: continue; sascha@998: } sascha@998: teichmann@4737: Boolean result = evaluateXPathToBoolean(test); sascha@998: if (result != null && result.booleanValue()) { sascha@998: branch = child; sascha@998: break; sascha@998: } sascha@998: sascha@998: continue; sascha@998: } sascha@998: else if ("otherwise".equals(name)) { sascha@998: branch = child; sascha@998: // No break here. sascha@998: } sascha@998: } sascha@998: sascha@998: if (branch != null) { sascha@998: NodeList subs = branch.getChildNodes(); sascha@998: for (int i = 0, N = subs.getLength(); i < N; ++i) { sascha@998: build(parent, subs.item(i)); sascha@998: } sascha@998: } sascha@998: } sascha@998: teichmann@4740: protected Object evaluateXPath(String expr, QName returnType) { sascha@998: sascha@998: if (log.isDebugEnabled()) { sascha@998: log.debug("evaluate: '" + expr + "'"); sascha@998: } sascha@998: sascha@998: try { sascha@998: XPath xpath = XPATH_FACTORY.newXPath(); sascha@998: xpath.setXPathVariableResolver(frames); sascha@998: xpath.setXPathFunctionResolver(FunctionResolver.FUNCTIONS); teichmann@4740: return xpath.evaluate(expr, EVAL_DOCUMENT, returnType); sascha@998: } teichmann@4740: catch (XPathExpressionException xpee) { teichmann@4740: log.error("expression: " + expr, xpee); sascha@998: } sascha@998: return null; sascha@998: } sascha@998: teichmann@4737: protected Boolean evaluateXPathToBoolean(String expr) { teichmann@4737: teichmann@4740: Object result = evaluateXPath(expr, XPathConstants.BOOLEAN); teichmann@4737: teichmann@4737: return result instanceof Boolean teichmann@4737: ? (Boolean)result teichmann@4737: : null; teichmann@4737: } teichmann@4737: teichmann@4737: protected void convert(Element current) { sascha@998: sascha@998: String variable = expand(current.getAttribute("var")); sascha@998: String type = expand(current.getAttribute("type")); sascha@998: sascha@1716: Object [] result = new Object[1]; sascha@1716: sascha@1716: if (frames.getStore(variable, result)) { sascha@1716: Object object = TypeConverter.convert(result[0], type); sascha@1716: frames.put(variable.toUpperCase(), object); sascha@998: } sascha@998: } sascha@998: teichmann@4740: felix@4891: /** Put content as variable on stackframes. */ teichmann@4737: protected void variable(Element current) { teichmann@4737: teichmann@4737: String varName = expand(current.getAttribute("name")); teichmann@4737: String expr = current.getAttribute("expr"); teichmann@4740: String type = current.getAttribute("type"); teichmann@4737: teichmann@4737: if (varName.length() == 0 || expr.length() == 0) { teichmann@4737: log.error("dc:variable 'name' or 'expr' empty."); teichmann@4737: } teichmann@4737: else { teichmann@4740: frames.put( teichmann@4740: varName.toUpperCase(), teichmann@4740: evaluateXPath(expr, typeToQName(type))); teichmann@4737: } teichmann@4737: } teichmann@4737: sascha@998: protected String expand(String s) { sascha@998: Matcher m = CompiledStatement.VAR.matcher(s); sascha@998: sascha@1716: Object [] result = new Object[1]; sascha@1716: sascha@998: StringBuffer sb = new StringBuffer(); sascha@998: while (m.find()) { sascha@998: String key = m.group(1); sascha@1716: result[0] = null; sascha@1716: if (frames.getStore(key, result)) { sascha@1716: m.appendReplacement( sascha@1716: sb, result[0] != null ? result[0].toString() : ""); sascha@1716: } sascha@1716: else { sascha@1716: m.appendReplacement(sb, "\\${" + key + "}"); sascha@1716: } sascha@998: } sascha@998: m.appendTail(sb); sascha@998: return sb.toString(); sascha@998: } sascha@998: sascha@998: protected void build(Node parent, Node current) sascha@998: throws SQLException sascha@998: { sascha@998: String ns = current.getNamespaceURI(); sascha@998: if (ns != null && ns.equals(DC_NAMESPACE_URI)) { sascha@998: if (current.getNodeType() != Node.ELEMENT_NODE) { sascha@998: log.warn("need elements here"); sascha@998: } sascha@998: else { sascha@998: String localName = current.getLocalName(); sascha@998: if ("attribute".equals(localName)) { sascha@998: attribute(parent, (Element)current); sascha@998: } sascha@998: else if ("context".equals(localName)) { sascha@998: context(parent, (Element)current); sascha@998: } sascha@998: else if ("if".equals(localName)) { sascha@998: ifClause(parent, (Element)current); sascha@998: } sascha@998: else if ("choose".equals(localName)) { sascha@998: choose(parent, (Element)current); sascha@998: } sascha@998: else if ("call-macro".equals(localName)) { sascha@998: callMacro(parent, (Element)current); sascha@998: } teichmann@4890: else if ("macro-body".equals(localName)) { teichmann@4890: macroBody(parent, (Element)current); teichmann@4890: } sascha@998: else if ("macro".equals(localName)) { felix@1029: // Simply ignore the definition. sascha@998: } sascha@998: else if ("element".equals(localName)) { sascha@998: element(parent, (Element)current); sascha@998: } sascha@1023: else if ("elements".equals(localName)) { sascha@1023: elements(parent, (Element)current); sascha@1023: } sascha@998: else if ("text".equals(localName)) { sascha@998: text(parent, (Element)current); sascha@998: } teichmann@4737: else if ("variable".equals(localName)) { teichmann@4737: variable((Element)current); teichmann@4737: } sascha@1023: else if ("comment".equals(localName) sascha@1023: || "statement".equals(localName)) { sascha@1023: // ignore comments and statements in output sascha@1017: } sascha@998: else if ("convert".equals(localName)) { teichmann@4737: convert((Element)current); sascha@998: } sascha@998: else { sascha@998: log.warn("unknown '" + localName + "' -> ignore"); sascha@998: } sascha@998: } sascha@998: return; sascha@998: } sascha@998: sascha@998: if (current.getNodeType() == Node.TEXT_NODE) { sascha@998: String txt = current.getNodeValue(); sascha@998: if (txt != null && txt.trim().length() == 0) { sascha@998: return; sascha@998: } sascha@998: } sascha@998: bjoern@4353: if (current.getNodeType() == Node.COMMENT_NODE) { bjoern@4353: // Ignore XML comments bjoern@4353: return; bjoern@4353: } bjoern@4353: sascha@998: Node copy = owner.importNode(current, false); sascha@998: sascha@998: NodeList children = current.getChildNodes(); sascha@998: for (int i = 0, N = children.getLength(); i < N; ++i) { sascha@998: build(copy, children.item(i)); sascha@998: } sascha@998: parent.appendChild(copy); sascha@998: } sascha@998: } // class BuildHelper sascha@998: sascha@998: sascha@998: public Builder() { sascha@998: compiledStatements = new HashMap(); sascha@998: } sascha@998: sascha@998: public Builder(Document template) { sascha@998: this(); sascha@998: this.template = template; sascha@998: compileStatements(); sascha@998: } sascha@998: teichmann@4740: protected static QName typeToQName(String type) { teichmann@4740: if ("number" .equals(type)) return XPathConstants.NUMBER; teichmann@4740: if ("bool" .equals(type)) return XPathConstants.BOOLEAN; teichmann@4740: if ("node" .equals(type)) return XPathConstants.NODE; teichmann@4740: if ("nodeset".equals(type)) return XPathConstants.NODESET; teichmann@4740: return XPathConstants.STRING; teichmann@4740: } teichmann@4740: felix@4614: /** Handle elements. */ sascha@998: protected void compileStatements() { sascha@998: sascha@998: NodeList nodes = template.getElementsByTagNameNS( sascha@998: DC_NAMESPACE_URI, "statement"); sascha@998: sascha@998: for (int i = 0, N = nodes.getLength(); i < N; ++i) { sascha@998: Element stmntElement = (Element)nodes.item(i); sascha@998: String stmnt = trimStatement(stmntElement.getTextContent()); sascha@998: if (stmnt == null || stmnt.length() == 0) { sascha@998: throw new IllegalArgumentException("found empty statement"); sascha@998: } sascha@998: CompiledStatement cs = new CompiledStatement(stmnt); felix@1029: // For faster lookup store a shortend string into the template. sascha@998: stmnt = "s" + i; sascha@998: stmntElement.setTextContent(stmnt); sascha@998: compiledStatements.put(stmnt, cs); sascha@998: } sascha@998: } sascha@998: sascha@998: protected List rootsToList() { sascha@998: sascha@998: NodeList roots = template.getElementsByTagNameNS( sascha@998: DC_NAMESPACE_URI, "template"); sascha@998: sascha@998: List elements = new ArrayList(); sascha@998: sascha@998: for (int i = 0, N = roots.getLength(); i < N; ++i) { sascha@998: NodeList rootChildren = roots.item(i).getChildNodes(); sascha@998: for (int j = 0, M = rootChildren.getLength(); j < M; ++j) { sascha@998: Node child = rootChildren.item(j); sascha@998: if (child.getNodeType() == Node.ELEMENT_NODE) { sascha@998: elements.add(child); sascha@998: } sascha@998: } sascha@998: } sascha@998: sascha@998: return elements; sascha@998: } sascha@998: sascha@998: protected static final String trimStatement(String stmnt) { sascha@998: if (stmnt == null) return null; sascha@998: //XXX: Maybe a bit to radical for multiline strings? sascha@998: return STRIP_LINE_INDENT.matcher(stmnt.trim()).replaceAll(" "); sascha@998: } sascha@998: sascha@998: protected static Document getOwnerDocument(Node node) { sascha@998: Document document = node.getOwnerDocument(); sascha@998: return document != null ? document : (Document)node; sascha@998: } sascha@998: sascha@1011: private static final List wrap(Connection connection) { sascha@1011: List list = new ArrayList(1); sascha@1015: list.add(new NamedConnection(DEFAULT_CONNECTION_NAME, connection)); sascha@1011: return list; sascha@1011: } sascha@1011: sascha@998: public void build( sascha@998: Connection connection, sascha@998: Node output, sascha@998: Map parameters sascha@998: ) sascha@998: throws SQLException sascha@998: { sascha@1011: build(wrap(connection), output, parameters); sascha@1011: } sascha@1011: sascha@1011: public void build( sascha@1011: List connections, sascha@1011: Node output, sascha@1011: Map parameters sascha@1011: ) sascha@1011: throws SQLException sascha@1011: { sascha@1011: BuildHelper helper = new BuildHelper(output, connections, parameters); sascha@998: sascha@998: helper.build(); sascha@998: } sascha@998: } sascha@998: // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :