# HG changeset patch # User Sascha L. Teichmann # Date 1386344098 -3600 # Node ID f1abd257f9336726e34ddd5a7fa3efcd7125c88b # Parent e0219f4079a810945a8e8aa0f6a0e101dec71099 Datacage: Added ... sorts the current dataset by Expression. Type is optional (default string). diff -r e0219f4079a8 -r f1abd257f933 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 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 macros; + private static final class KV implements Comparable { + + private Comparable key; + private Object [] data; + + public KV(Comparable 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 rows = orig.getRows(); + String [] columns = orig.getColumnLabels(); + + List sorted = new ArrayList(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)key, row)); + } + } + catch (XPathExpressionException xee) { + log.warn("unable to apply expression '" + + expr + "' to dataset. " + xee.getMessage(), xee); + } + finally { + frames.leave(); + } + } + Collections.sort(sorted); + List result = new ArrayList(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 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); }