# HG changeset patch # User Sascha L. Teichmann # Date 1369390765 -7200 # Node ID 47775e3a8cf678b1adc0ba814a665da1c271d0e6 # Parent 46c18b687fdc2882afc7b4e35ba705f72b1af98d Datacage: Introduced 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: {$a} + {$b} = {$c} table a | b --+-- 1 | 2 3 | 4 will result in: 1 + 2 = 3 3 + 4 = 7 diff -r 46c18b687fdc -r 47775e3a8cf6 artifacts/src/main/java/org/dive4elements/river/artifacts/datacage/templating/Builder.java --- 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 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 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); } diff -r 46c18b687fdc -r 47775e3a8cf6 artifacts/src/main/java/org/dive4elements/river/artifacts/datacage/templating/ResultData.java --- 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); }