Mercurial > dive4elements > river
changeset 6087:47775e3a8cf6
Datacage: Introduced <dc:virtual-column name="colname" type="type" expr="XPath">
dc:virtual-column can be used to virtual add or replace a column named 'colname' to
the current result set. The value is determined by evaluating "XPath", the type is
determined by "type" (possible values: number, bool, node, nodeset, string. defaults to string).
Usage:
<dc:virtual-column name="c" type="number" expr="$a+$b">
<dc:for-each>
<dc:message>{$a} + {$b} = {$c}</dc:message>
</dc:for-each>
</dc:virtual-column>
table
a | b
--+--
1 | 2
3 | 4
will result in:
1 + 2 = 3
3 + 4 = 7
author | Sascha L. Teichmann <teichmann@intevation.de> |
---|---|
date | Fri, 24 May 2013 12:19:25 +0200 |
parents | 46c18b687fdc |
children | 127cc609c12b |
files | artifacts/src/main/java/org/dive4elements/river/artifacts/datacage/templating/Builder.java artifacts/src/main/java/org/dive4elements/river/artifacts/datacage/templating/ResultData.java |
diffstat | 2 files changed, 123 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/datacage/templating/Builder.java Fri May 24 10:06:58 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/datacage/templating/Builder.java Fri May 24 12:19:25 2013 +0200 @@ -453,6 +453,117 @@ : groupExprStack.peek(); } + protected void virtualColumn(Node parent, Element current) + throws SQLException + { + log.debug("dc:virtual-column"); + + if (connectionsStack.isEmpty()) { + log.debug("dc:virtual-column without having results"); + return; + } + + NodeList subs = current.getChildNodes(); + int S = subs.getLength(); + + if (S == 0) { + log.debug("dc:virtual-column has no children"); + return; + } + + String name = expand(current.getAttribute("name")); + String expr = current.getAttribute("expr").trim(); + String type = current.getAttribute("type").trim(); + + QName returnType = typeToQName(type); + + XPathExpression x; + try { + x = getXPathExpression(expr); + } + catch (XPathExpressionException xee) { + log.warn("Invalid expression '" + expr + "'."); + return; + } + + Pair<Builder.NamedConnection, ResultData> pair = + connectionsStack.peek(); + + ResultData orig = connectionsStack.peek().getB(); + + int index = orig.indexOfColumn(name); + + ResultData rd = index >= 0 // Already has column with this name? + ? replaceColumn(orig, index, x, returnType) + : addColumn(orig, name, x, returnType); + + pair.setB(rd); + try { + for (int i = 0; i < S; ++i) { + build(parent, subs.item(i)); + } + } + finally { + pair.setB(orig); + } + } + + protected ResultData addColumn( + ResultData rd, + String name, + XPathExpression expr, + QName returnType + ) { + String [] origColumns = rd.getColumnLabels(); + int index = origColumns.length; + String [] newColumns = Arrays.copyOf(origColumns, index+1); + ResultData result = new ResultData(newColumns); + fillResult(result, rd, index, index+1, expr, returnType); + return result; + } + + protected ResultData replaceColumn( + ResultData rd, + int index, + XPathExpression expr, + QName returnType + ) { + String [] columns = rd.getColumnLabels(); + ResultData result = new ResultData(columns); + fillResult(result, rd, index, columns.length, expr, returnType); + return result; + } + + protected void fillResult( + ResultData result, + ResultData rd, + int index, + int size, + XPathExpression expr, + QName returnType + ) { + List<Object []> rows = rd.getRows(); + String [] origColumns = rd.getColumnLabels(); + for (int i = 0, R = rows.size(); i < R; ++i) { + Object [] row = rows.get(i); + frames.enter(); + try { + frames.put(origColumns, row); + Object value = expr.evaluate(EVAL_DOCUMENT, returnType); + Object [] copy = Arrays.copyOf(row, size); + copy[index] = value; + result.add(copy); + } + catch (XPathExpressionException xxe) { + log.warn("unable to apply expression '" + + expr + "' to dataset.", xxe); + } + finally { + frames.leave(); + } + } + } + protected void iterate(Node parent, Element current) throws SQLException { @@ -907,6 +1018,9 @@ else if ("group".equals(localName)) { group(parent, curr); } + else if ("virtual-column".equals(localName)) { + virtualColumn(parent, curr); + } else if ("text".equals(localName)) { text(parent, curr); }
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/datacage/templating/ResultData.java Fri May 24 10:06:58 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/datacage/templating/ResultData.java Fri May 24 12:19:25 2013 +0200 @@ -77,6 +77,15 @@ return this; } + public int indexOfColumn(String column) { + for (int i = 0; i < columns.length; ++i) { + if (columns[i].equalsIgnoreCase(column)) { + return i; + } + } + return -1; + } + public void add(Object [] result) { rows.add(result); }