[Dive4elements-commits] [PATCH 1 of 2] Datacage: Introduced <dc:virtual-column name="colname" type="type" expr="XPath">

Wald Commits scm-commit at wald.intevation.org
Fri May 24 12:22:08 CEST 2013


# HG changeset patch
# User Sascha L. Teichmann <teichmann at intevation.de>
# Date 1369390765 -7200
# Node ID 47775e3a8cf678b1adc0ba814a665da1c271d0e6
# Parent  46c18b687fdc2882afc7b4e35ba705f72b1af98d
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

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<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);
                     }
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);
     }


More information about the Dive4elements-commits mailing list