changeset 7669:f1abd257f933

Datacage: Added <dc:sort> <dc:sort expr="Expression" type="Type"> ... </dc:sort> sorts the current dataset by Expression. Type is optional (default string).
author Sascha L. Teichmann <teichmann@intevation.de>
date Fri, 06 Dec 2013 16:34:58 +0100
parents e0219f4079a8
children 03dc5cc22e26
files artifacts/src/main/java/org/dive4elements/river/artifacts/datacage/templating/Builder.java
diffstat 1 files changed, 111 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/datacage/templating/Builder.java	Fri Dec 06 15:36:47 2013 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/datacage/templating/Builder.java	Fri Dec 06 16:34:58 2013 +0100
@@ -75,6 +75,26 @@
 
     protected Map<String, Element> macros;
 
+    private static final class KV implements Comparable<KV> {
+
+        private Comparable<Object> key;
+        private Object [] data;
+
+        public KV(Comparable<Object> key, Object [] data) {
+            this.key = key;
+            this.data = data;
+        }
+
+        @Override
+        public int compareTo(KV other) {
+            return key.compareTo(other.key);
+        }
+
+        public Object [] getData() {
+            return data;
+        }
+    }
+
     /** Connection to either of the databases. */
     public static class NamedConnection {
 
@@ -581,6 +601,94 @@
             }
         }
 
+
+        protected ResultData createSortedResultData(
+            ResultData orig,
+            String expr,
+            String type
+        ) {
+            XPathExpression x;
+            try {
+                x = getXPathExpression(expr);
+            }
+            catch (XPathExpressionException xee) {
+                log.warn("Invalid sort expression '" + expr + "'.");
+                return orig;
+            }
+
+            QName returnType = typeToQName(type);
+
+            List<Object []> rows = orig.getRows();
+            String [] columns = orig.getColumnLabels();
+
+            List<KV> sorted = new ArrayList<KV>(rows.size());
+
+            for (Object [] row: rows) {
+                frames.enter();
+                try {
+                    frames.put(columns, row);
+                    Object key = x.evaluate(EVAL_DOCUMENT, returnType);
+
+                    if (key instanceof Comparable) {
+                        sorted.add(new KV((Comparable<Object>)key, row));
+                    }
+                }
+                catch (XPathExpressionException xee) {
+                    log.warn("unable to apply expression '" +
+                        expr + "' to dataset. " + xee.getMessage(), xee);
+                }
+                finally {
+                    frames.leave();
+                }
+            }
+            Collections.sort(sorted);
+            List<Object []> result = new ArrayList<Object []>(sorted.size());
+            for (KV kv: sorted) {
+                result.add(kv.getData());
+            }
+            return new ResultData(columns, result);
+        }
+
+        protected void sort(Node parent, Element current)
+        throws SQLException
+        {
+            log.debug("dc:sort");
+
+            if (connectionsStack.isEmpty()) {
+                log.debug("dc:sort without having results");
+                return;
+            }
+
+            String expr = current.getAttribute("expr").trim();
+            String type = current.getAttribute("type").trim();
+
+            if (expr.isEmpty()) {
+                log.warn("missing 'expr' in dc:sort");
+                return;
+            }
+
+            Pair<Builder.NamedConnection, ResultData> pair =
+                connectionsStack.peek();
+
+            ResultData orig = connectionsStack.peek().getB();
+
+            ResultData sorted = createSortedResultData(orig, expr, type);
+
+            NodeList subs = current.getChildNodes();
+
+            pair.setB(sorted);
+            try {
+                for (int i = 0, S = subs.getLength(); i < S; ++i) {
+                    build(parent, subs.item(i));
+                }
+            }
+            finally {
+                if (orig != null) {
+                    pair.setB(orig);
+                }
+            }
+        }
+
         public Object getGroupKey() {
             return groupExprStack.isEmpty()
                 ? null
@@ -1145,6 +1253,9 @@
                     else if ("group".equals(localName)) {
                         group(parent, curr);
                     }
+                    else if ("sort".equals(localName)) {
+                        sort(parent, curr);
+                    }
                     else if ("virtual-column".equals(localName)) {
                         virtualColumn(parent, curr);
                     }

http://dive4elements.wald.intevation.org