You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jena.apache.org by an...@apache.org on 2014/12/28 20:05:40 UTC

[1/4] jena git commit: JENA-803 : Refactoring to generalize aggregates for custom aggregates.

Repository: jena
Updated Branches:
  refs/heads/master 7e5abeed5 -> 66efb4f65


JENA-803 : Refactoring to generalize aggregates for custom aggregates.

Project: http://git-wip-us.apache.org/repos/asf/jena/repo
Commit: http://git-wip-us.apache.org/repos/asf/jena/commit/a1ee6e18
Tree: http://git-wip-us.apache.org/repos/asf/jena/tree/a1ee6e18
Diff: http://git-wip-us.apache.org/repos/asf/jena/diff/a1ee6e18

Branch: refs/heads/master
Commit: a1ee6e18ae35ae2bd4349195dedff51f184bd233
Parents: 7e5abee
Author: Andy Seaborne <an...@apache.org>
Authored: Sun Dec 28 18:37:50 2014 +0000
Committer: Andy Seaborne <an...@apache.org>
Committed: Sun Dec 28 18:37:50 2014 +0000

----------------------------------------------------------------------
 .../hp/hpl/jena/sparql/algebra/Transformer.java |  4 +-
 .../hp/hpl/jena/sparql/expr/ExprAggregator.java |  7 +-
 .../com/hp/hpl/jena/sparql/expr/ExprList.java   | 20 ++++--
 .../hpl/jena/sparql/expr/aggregate/AggAvg.java  | 24 ++-----
 .../sparql/expr/aggregate/AggAvgDistinct.java   | 15 +----
 .../jena/sparql/expr/aggregate/AggCount.java    | 12 ++--
 .../sparql/expr/aggregate/AggCountDistinct.java |  8 ++-
 .../jena/sparql/expr/aggregate/AggCountVar.java | 20 ++----
 .../expr/aggregate/AggCountVarDistinct.java     | 20 ++----
 .../jena/sparql/expr/aggregate/AggCustom.java   | 66 +++++++++++++++---
 .../sparql/expr/aggregate/AggGroupConcat.java   | 17 ++---
 .../expr/aggregate/AggGroupConcatDistinct.java  | 17 ++---
 .../hpl/jena/sparql/expr/aggregate/AggMax.java  | 18 ++---
 .../jena/sparql/expr/aggregate/AggMaxBase.java  |  9 +--
 .../sparql/expr/aggregate/AggMaxDistinct.java   | 18 ++---
 .../hpl/jena/sparql/expr/aggregate/AggMin.java  | 18 ++---
 .../jena/sparql/expr/aggregate/AggMinBase.java  |  9 +--
 .../sparql/expr/aggregate/AggMinDistinct.java   | 19 ++----
 .../hpl/jena/sparql/expr/aggregate/AggNull.java | 14 +---
 .../jena/sparql/expr/aggregate/AggSample.java   | 26 +++----
 .../expr/aggregate/AggSampleDistinct.java       | 21 ++----
 .../hpl/jena/sparql/expr/aggregate/AggSum.java  | 20 ++----
 .../sparql/expr/aggregate/AggSumDistinct.java   | 22 ++----
 .../jena/sparql/expr/aggregate/Aggregator.java  | 14 ++--
 .../sparql/expr/aggregate/AggregatorBase.java   | 71 ++++++++++++++++++--
 .../expr/aggregate/AggregatorFactory.java       |  5 +-
 .../jena/sparql/serializer/FmtExprSPARQL.java   |  2 +-
 .../com/hp/hpl/jena/sparql/util/ExprUtils.java  |  8 +++
 28 files changed, 275 insertions(+), 249 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/jena/blob/a1ee6e18/jena-arq/src/main/java/com/hp/hpl/jena/sparql/algebra/Transformer.java
----------------------------------------------------------------------
diff --git a/jena-arq/src/main/java/com/hp/hpl/jena/sparql/algebra/Transformer.java b/jena-arq/src/main/java/com/hp/hpl/jena/sparql/algebra/Transformer.java
index 9ade24f..b4b1250 100644
--- a/jena-arq/src/main/java/com/hp/hpl/jena/sparql/algebra/Transformer.java
+++ b/jena-arq/src/main/java/com/hp/hpl/jena/sparql/algebra/Transformer.java
@@ -320,8 +320,8 @@ public class Transformer
                     changed = true ;
 
                 // The Aggregator expression
-                Expr e = aggregator.getExpr() ;
-                Expr e2 = e ;
+                ExprList e = aggregator.getExprList() ;
+                ExprList e2 = e ;
                 if ( e != null )    // Null means "no relevant expression" e.g. COUNT(*)
                     e2 = transform(e, exprTransform) ;
                 if ( e != e2 )

http://git-wip-us.apache.org/repos/asf/jena/blob/a1ee6e18/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/ExprAggregator.java
----------------------------------------------------------------------
diff --git a/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/ExprAggregator.java b/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/ExprAggregator.java
index 15dad36..0781477 100644
--- a/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/ExprAggregator.java
+++ b/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/ExprAggregator.java
@@ -28,6 +28,7 @@ import com.hp.hpl.jena.sparql.engine.binding.Binding ;
 import com.hp.hpl.jena.sparql.expr.aggregate.Aggregator ;
 import com.hp.hpl.jena.sparql.function.FunctionEnv ;
 import com.hp.hpl.jena.sparql.graph.NodeTransform ;
+import com.hp.hpl.jena.sparql.serializer.SerializationContext ;
 import com.hp.hpl.jena.sparql.util.Utils ;
 
 /** Group aggregation functions calculated a value during grouping and
@@ -95,8 +96,8 @@ public class ExprAggregator extends ExprNode
     public ExprVar getAggVar() { return exprVar ; }
     
     // As an expression suitable for outputting the calculation. 
-    public String asSparqlExpr()        
-    { return aggregator.toString() ; }
+    public String asSparqlExpr(SerializationContext sCxt)        
+    { return aggregator.asSparqlExpr(sCxt) ; }
     
     @Override
     public ExprAggregator copySubstitute(Binding binding)
@@ -129,7 +130,7 @@ public class ExprAggregator extends ExprNode
                 (var==null?"<>":"?"+var.getVarName())+
                 " "+aggregator.toString()+")"; }
     
-    public Expr copy(Var v)  { return new ExprAggregator(v, aggregator.copy(aggregator.getExpr())) ; }
+    public Expr copy(Var v)  { return new ExprAggregator(v, aggregator.copy(aggregator.getExprList())) ; }
     
     @Override
     public NodeValue eval(Binding binding, FunctionEnv env)

http://git-wip-us.apache.org/repos/asf/jena/blob/a1ee6e18/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/ExprList.java
----------------------------------------------------------------------
diff --git a/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/ExprList.java b/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/ExprList.java
index 2356d0d..51719f3 100644
--- a/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/ExprList.java
+++ b/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/ExprList.java
@@ -23,6 +23,7 @@ import java.util.* ;
 import com.hp.hpl.jena.sparql.core.Var ;
 import com.hp.hpl.jena.sparql.engine.ExecutionContext ;
 import com.hp.hpl.jena.sparql.engine.binding.Binding ;
+import com.hp.hpl.jena.sparql.graph.NodeTransform ;
 import com.hp.hpl.jena.sparql.util.Context ;
 
 public class ExprList implements Iterable<Expr>
@@ -55,9 +56,9 @@ public class ExprList implements Iterable<Expr>
         return true ;
     }
     
-    public Expr get(int idx)    { return expressions.get(idx) ; }
-    public int size()           { return expressions.size() ; }
-    public boolean isEmpty()    { return expressions.isEmpty() ; }
+    public Expr get(int idx)                            { return expressions.get(idx) ; }
+    public int size()                                   { return expressions.size() ; }
+    public boolean isEmpty()                            { return expressions.isEmpty() ; }
     public ExprList subList(int fromIdx, int toIdx)     { return new ExprList(expressions.subList(fromIdx, toIdx)) ; }
     public ExprList tail(int fromIdx)                   { return subList(fromIdx, expressions.size()) ; }
     
@@ -71,11 +72,20 @@ public class ExprList implements Iterable<Expr>
         for (Expr expr : expressions)
             expr.varsMentioned(acc) ;
     }
+    
+    /**
+     * Rewrite, applying a node->node transformation
+     */
+    public ExprList applyNodeTransform(NodeTransform transform) {
+        ExprList x = new ExprList() ;
+        for ( Expr e : expressions)
+            x.add(e.applyNodeTransform(transform));
+        return x ; 
+    }
 
     public ExprList copySubstitute(Binding binding) {
         ExprList x = new ExprList() ;
-        for (Iterator<Expr> iter = expressions.iterator(); iter.hasNext();) {
-            Expr expr = iter.next() ;
+        for (Expr expr : expressions ) {
             expr = expr.copySubstitute(binding) ;
             x.add(expr) ;
         }

http://git-wip-us.apache.org/repos/asf/jena/blob/a1ee6e18/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/aggregate/AggAvg.java
----------------------------------------------------------------------
diff --git a/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/aggregate/AggAvg.java b/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/aggregate/AggAvg.java
index 754e519..6ba91a1 100644
--- a/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/aggregate/AggAvg.java
+++ b/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/aggregate/AggAvg.java
@@ -22,44 +22,33 @@ import com.hp.hpl.jena.graph.Node ;
 import com.hp.hpl.jena.sparql.engine.binding.Binding ;
 import com.hp.hpl.jena.sparql.expr.Expr ;
 import com.hp.hpl.jena.sparql.expr.ExprEvalException ;
+import com.hp.hpl.jena.sparql.expr.ExprList ;
 import com.hp.hpl.jena.sparql.expr.NodeValue ;
 import com.hp.hpl.jena.sparql.expr.nodevalue.XSDFuncOp ;
 import com.hp.hpl.jena.sparql.function.FunctionEnv ;
-import com.hp.hpl.jena.sparql.sse.writers.WriterExpr ;
-import com.hp.hpl.jena.sparql.util.ExprUtils ;
 
 public class AggAvg extends AggregatorBase
 {
     // ---- AVG(?var)
-    private Expr expr ;
-
-    public AggAvg(Expr expr) { this.expr = expr ; } 
+    public AggAvg(Expr expr) { super("AVG", false, expr) ; } 
     @Override
-    public Aggregator copy(Expr expr) { return new AggAvg(expr) ; }
+    public Aggregator copy(ExprList expr) { return new AggAvg(expr.get(0)) ; }
 
     // XQuery/XPath Functions&Operators suggests zero
     // SQL suggests null.
     private static final NodeValue noValuesToAvg = NodeValue.nvZERO ; // null 
 
     @Override
-    public String toString() { return "avg("+ExprUtils.fmtSPARQL(expr)+")" ; }
-    @Override
-    public String toPrefixString() { return "(avg "+WriterExpr.asString(expr)+")" ; }
-
-    @Override
     public Accumulator createAccumulator()
     { 
-        return new AccAvg(expr) ;
+        return new AccAvg(getExpr()) ;
     }
 
     @Override
-    public final Expr getExpr() { return expr ; }
-
-    @Override
     public Node getValueEmpty()     { return NodeValue.toNode(noValuesToAvg) ; } 
     
     @Override
-    public int hashCode()   { return HC_AggAvg ^ expr.hashCode() ; }
+    public int hashCode()   { return HC_AggAvg ^ getExprList().hashCode() ; }
 
     @Override
     public boolean equals(Object other)
@@ -67,9 +56,8 @@ public class AggAvg extends AggregatorBase
         if ( this == other ) return true ;
         if ( ! ( other instanceof AggAvg ) ) return false ;
         AggAvg a = (AggAvg)other ;
-        return expr.equals(a.expr) ;
+        return exprList.equals(a.exprList) ;
     }
-
     
     // ---- Accumulator
     private static class AccAvg extends AccumulatorExpr

http://git-wip-us.apache.org/repos/asf/jena/blob/a1ee6e18/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/aggregate/AggAvgDistinct.java
----------------------------------------------------------------------
diff --git a/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/aggregate/AggAvgDistinct.java b/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/aggregate/AggAvgDistinct.java
index 6791cd3..deb2a48 100644
--- a/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/aggregate/AggAvgDistinct.java
+++ b/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/aggregate/AggAvgDistinct.java
@@ -22,38 +22,29 @@ import com.hp.hpl.jena.graph.Node ;
 import com.hp.hpl.jena.sparql.engine.binding.Binding ;
 import com.hp.hpl.jena.sparql.expr.Expr ;
 import com.hp.hpl.jena.sparql.expr.ExprEvalException ;
+import com.hp.hpl.jena.sparql.expr.ExprList ;
 import com.hp.hpl.jena.sparql.expr.NodeValue ;
 import com.hp.hpl.jena.sparql.expr.nodevalue.XSDFuncOp ;
 import com.hp.hpl.jena.sparql.function.FunctionEnv ;
-import com.hp.hpl.jena.sparql.sse.writers.WriterExpr ;
-import com.hp.hpl.jena.sparql.util.ExprUtils ;
 
 public class AggAvgDistinct extends AggregatorBase
 {
     // ---- AVG(DISTINCT expr)
     private Expr expr ;
 
-    public AggAvgDistinct(Expr expr) { this.expr = expr ; } 
+    public AggAvgDistinct(Expr expr) { super("AVG", true, expr) ; } 
     @Override
-    public Aggregator copy(Expr expr) { return new AggAvgDistinct(expr) ; }
+    public Aggregator copy(ExprList expr) { return new AggAvg(expr.get(0)) ; }
 
     private static final NodeValue noValuesToAvg = NodeValue.nvZERO ; 
 
     @Override
-    public String toString() { return "avg(distinct "+ExprUtils.fmtSPARQL(expr)+")" ; }
-    @Override
-    public String toPrefixString() { return "(avg distinct "+WriterExpr.asString(expr)+")" ; }
-
-    @Override
     public Accumulator createAccumulator()
     { 
         return new AccAvgDistinct(expr) ;
     }
 
     @Override
-    public final Expr getExpr() { return expr ; }
-
-    @Override
     public Node getValueEmpty()     { return NodeValue.toNode(noValuesToAvg) ; } 
 
     @Override

http://git-wip-us.apache.org/repos/asf/jena/blob/a1ee6e18/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/aggregate/AggCount.java
----------------------------------------------------------------------
diff --git a/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/aggregate/AggCount.java b/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/aggregate/AggCount.java
index 1e9c330..421535f 100644
--- a/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/aggregate/AggCount.java
+++ b/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/aggregate/AggCount.java
@@ -18,22 +18,24 @@
 
 package com.hp.hpl.jena.sparql.expr.aggregate;
 
+import org.apache.jena.atlas.logging.Log ;
+
 import com.hp.hpl.jena.graph.Node ;
 import com.hp.hpl.jena.sparql.engine.binding.Binding ;
 import com.hp.hpl.jena.sparql.expr.Expr ;
+import com.hp.hpl.jena.sparql.expr.ExprList ;
 import com.hp.hpl.jena.sparql.expr.NodeValue ;
 import com.hp.hpl.jena.sparql.function.FunctionEnv ;
 import com.hp.hpl.jena.sparql.graph.NodeConst ;
-
-import org.apache.jena.atlas.logging.Log ;
+import com.hp.hpl.jena.sparql.serializer.SerializationContext ;
 
 public class AggCount extends AggregatorBase
 {
     // ---- COUNT(*)
 
-    public AggCount() { }
+    public AggCount() { super("COUNT", false, (ExprList)null) ; }
     @Override
-    public Aggregator copy(Expr expr)
+    public Aggregator copy(ExprList expr)
     { 
         if ( expr != null )
             Log.warn(this, "Copying non-null expression for COUNT(*)") ;
@@ -49,6 +51,8 @@ public class AggCount extends AggregatorBase
     }
 
     @Override
+    public String asSparqlExpr(SerializationContext sCxt)       { return "count(*)" ; }
+    @Override
     public String toString()        { return "count(*)" ; }
     @Override
     public String toPrefixString()  { return "(count)" ; }

http://git-wip-us.apache.org/repos/asf/jena/blob/a1ee6e18/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/aggregate/AggCountDistinct.java
----------------------------------------------------------------------
diff --git a/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/aggregate/AggCountDistinct.java b/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/aggregate/AggCountDistinct.java
index ca96434..c2a3524 100644
--- a/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/aggregate/AggCountDistinct.java
+++ b/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/aggregate/AggCountDistinct.java
@@ -21,18 +21,20 @@ package com.hp.hpl.jena.sparql.expr.aggregate;
 import com.hp.hpl.jena.graph.Node ;
 import com.hp.hpl.jena.sparql.engine.binding.Binding ;
 import com.hp.hpl.jena.sparql.expr.Expr ;
+import com.hp.hpl.jena.sparql.expr.ExprList ;
 import com.hp.hpl.jena.sparql.expr.NodeValue ;
 import com.hp.hpl.jena.sparql.function.FunctionEnv ;
 import com.hp.hpl.jena.sparql.graph.NodeConst ;
+import com.hp.hpl.jena.sparql.serializer.SerializationContext ;
 
 import org.apache.jena.atlas.logging.Log ;
 
 public class AggCountDistinct extends AggregatorBase
 {
     // ---- COUNT(DISTINCT *)
-    public AggCountDistinct() { super() ; }
+    public AggCountDistinct() { super("COUNT", true, (ExprList)null) ; }
     @Override
-    public Aggregator copy(Expr expr)
+    public Aggregator copy(ExprList expr)
     { 
         if ( expr != null )
             Log.warn(this, "Copying non-null expression for COUNT(DISTINCT *)") ;
@@ -40,6 +42,8 @@ public class AggCountDistinct extends AggregatorBase
     }
     
     @Override
+    public String asSparqlExpr(SerializationContext sCxt)       { return "count(distinct *)" ; }
+    @Override
     public String toString()        { return "count(distinct *)" ; }
     @Override
     public String toPrefixString()  { return "(count distinct)" ; }

http://git-wip-us.apache.org/repos/asf/jena/blob/a1ee6e18/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/aggregate/AggCountVar.java
----------------------------------------------------------------------
diff --git a/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/aggregate/AggCountVar.java b/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/aggregate/AggCountVar.java
index 42e0e67..7163f6d 100644
--- a/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/aggregate/AggCountVar.java
+++ b/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/aggregate/AggCountVar.java
@@ -21,36 +21,26 @@ package com.hp.hpl.jena.sparql.expr.aggregate;
 import com.hp.hpl.jena.graph.Node ;
 import com.hp.hpl.jena.sparql.engine.binding.Binding ;
 import com.hp.hpl.jena.sparql.expr.Expr ;
+import com.hp.hpl.jena.sparql.expr.ExprList ;
 import com.hp.hpl.jena.sparql.expr.NodeValue ;
 import com.hp.hpl.jena.sparql.function.FunctionEnv ;
 import com.hp.hpl.jena.sparql.graph.NodeConst ;
-import com.hp.hpl.jena.sparql.sse.writers.WriterExpr ;
 
 public class AggCountVar extends AggregatorBase
 {
     // ---- COUNT(?var)
-    private Expr expr ;
-
-    public AggCountVar(Expr expr) { this.expr = expr ; }
-    @Override
-    public Aggregator copy(Expr expr) { return new AggCountVar(expr) ; }
-
+    public AggCountVar(Expr expr) { super("COUNT", false, expr) ; }
     @Override
-    public String toString() { return "count("+expr+")" ; }
-    @Override
-    public String toPrefixString() { return "(count "+WriterExpr.asString(expr)+")" ; }
+    public Aggregator copy(ExprList expr) { return new AggCountVar(expr.get(0)) ; }
 
     @Override
     public Accumulator createAccumulator()
     { 
-        return new AccCountVar(expr) ;
+        return new AccCountVar(getExpr()) ;
     }
 
     @Override
-    public Expr getExpr() { return expr ; }
-
-    @Override
-    public int hashCode()   { return HC_AggCountVar ^ expr.hashCode() ; }
+    public int hashCode()   { return HC_AggCountVar ^ exprList.hashCode() ; }
     
     @Override
     public boolean equals(Object other)

http://git-wip-us.apache.org/repos/asf/jena/blob/a1ee6e18/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/aggregate/AggCountVarDistinct.java
----------------------------------------------------------------------
diff --git a/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/aggregate/AggCountVarDistinct.java b/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/aggregate/AggCountVarDistinct.java
index d7ba879..1b171ee 100644
--- a/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/aggregate/AggCountVarDistinct.java
+++ b/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/aggregate/AggCountVarDistinct.java
@@ -21,24 +21,17 @@ package com.hp.hpl.jena.sparql.expr.aggregate;
 import com.hp.hpl.jena.graph.Node ;
 import com.hp.hpl.jena.sparql.engine.binding.Binding ;
 import com.hp.hpl.jena.sparql.expr.Expr ;
+import com.hp.hpl.jena.sparql.expr.ExprList ;
 import com.hp.hpl.jena.sparql.expr.NodeValue ;
 import com.hp.hpl.jena.sparql.function.FunctionEnv ;
 import com.hp.hpl.jena.sparql.graph.NodeConst ;
-import com.hp.hpl.jena.sparql.sse.writers.WriterExpr ;
 
 public class AggCountVarDistinct extends AggregatorBase
 {
     // ---- COUNT(DISTINCT ?var)
-    private Expr expr ;
-
-    public AggCountVarDistinct(Expr expr) { this.expr = expr ; } 
-    @Override
-    public Aggregator copy(Expr expr) { return new AggCountVarDistinct(expr) ; }
-
+    public AggCountVarDistinct(Expr expr) { super("COUNT", true, expr) ; }
     @Override
-    public String toString()        { return "count(distinct "+expr+")" ; }
-    @Override
-    public String toPrefixString()  { return "(count distinct "+WriterExpr.asString(expr)+")" ; }
+    public Aggregator copy(ExprList exprs) { return new AggCountVarDistinct(exprs.get(0)) ; }
 
     @Override
     public Accumulator createAccumulator()
@@ -47,13 +40,10 @@ public class AggCountVarDistinct extends AggregatorBase
     }
 
     @Override
-    public Expr getExpr() { return expr ; }
-
-    @Override
     public Node getValueEmpty()     { return NodeConst.nodeZero ; } 
 
     @Override
-    public int hashCode()   { return HC_AggCountVar ^ expr.hashCode() ; }
+    public int hashCode()   { return HC_AggCountVar ^ exprList.hashCode() ; }
     
     @Override
     public boolean equals(Object other)
@@ -69,7 +59,7 @@ public class AggCountVarDistinct extends AggregatorBase
     {
         private long count = 0 ;
 
-        public AccCountVarDistinct() { super(expr) ; } 
+        public AccCountVarDistinct() { super(getExpr()) ; } 
         // The group key part of binding will be the same for all elements of the group.
         @Override
         public void accumulateDistinct(NodeValue nv, Binding binding, FunctionEnv functionEnv)

http://git-wip-us.apache.org/repos/asf/jena/blob/a1ee6e18/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/aggregate/AggCustom.java
----------------------------------------------------------------------
diff --git a/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/aggregate/AggCustom.java b/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/aggregate/AggCustom.java
index 34e8212..cb7add4 100644
--- a/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/aggregate/AggCustom.java
+++ b/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/aggregate/AggCustom.java
@@ -18,12 +18,20 @@
 
 package com.hp.hpl.jena.sparql.expr.aggregate;
 
+import java.util.Locale ;
+
+import org.apache.jena.atlas.io.IndentedLineBuffer ;
+
 import com.hp.hpl.jena.graph.Node ;
+import com.hp.hpl.jena.query.QueryExecException ;
 import com.hp.hpl.jena.sparql.engine.binding.Binding ;
 import com.hp.hpl.jena.sparql.expr.Expr ;
 import com.hp.hpl.jena.sparql.expr.ExprList ;
 import com.hp.hpl.jena.sparql.expr.NodeValue ;
 import com.hp.hpl.jena.sparql.function.FunctionEnv ;
+import com.hp.hpl.jena.sparql.serializer.SerializationContext ;
+import com.hp.hpl.jena.sparql.sse.writers.WriterExpr ;
+import com.hp.hpl.jena.sparql.util.ExprUtils ;
 
 /** Syntax element and framework execution for custom aggregates.  
  */
@@ -32,33 +40,75 @@ public class AggCustom extends AggregatorBase
     // See also ExprAggregator
     
     private final String iri ;
-    private final ExprList exprs ;
 
-    public AggCustom(String iri, ExprList exprs) { this.iri = iri ; this.exprs = exprs ; } 
+    public AggCustom(String iri, ExprList exprs) { 
+        super("AGG", false, exprs) ;
+        this.iri = iri ; 
+    } 
     
     @Override
-    public Aggregator copy(Expr expr) { return this ; }
+    public Aggregator copy(ExprList exprs) { return new AggCustom(iri, exprs) ; }
     
     @Override
-    public String toString() {
-        return "AGG <>" ;
+    public String asSparqlExpr(SerializationContext sCxt) {
+        IndentedLineBuffer x = new IndentedLineBuffer() ;
+        x.append("(") ;
+        x.incIndent(); 
+        x.append(getName().toLowerCase(Locale.ROOT)) ;
+        x.append(" <") ;
+        x.append(iri);
+        x.append(">") ;
+        if ( isDistinct )
+            x.append("DISTINCT ") ;
+        ExprUtils.fmtSPARQL(x, getExprList(), sCxt) ;
+        x.append(")") ;
+        return x.asString() ;
     }
 
     @Override
-    public String toPrefixString() { return "(agg <"+iri+">)" ; }
+    public String toPrefixString() { 
+        IndentedLineBuffer x = new IndentedLineBuffer() ;
+        x.append("(") ;
+        x.append(getName()) ;
+        x.append(" <") ;
+        x.append(iri);
+        x.append(">") ;
+        x.incIndent(); 
+
+        x.append(getName().toLowerCase(Locale.ROOT)) ;
+        if ( isDistinct )
+            x.append("distinct ") ;
+        boolean first = true ;
+        for ( Expr e : getExprList() ) {
+            if ( ! first )
+                x.append(" ");
+            first = false ;
+            WriterExpr.output(x, e, null) ;
+            first = false ;
+
+        }
+        x.decIndent();
+        x.append(")") ;
+        return x.asString() ;
+    }
 
     @Override
     public Accumulator createAccumulator()
     { 
-        return createAccNull() ;
+        AccumulatorFactory f = AggregateRegistry.getAccumulatorFactory(iri) ;
+        if ( f == null )
+            throw new QueryExecException("Unregistered aggregate: "+iri) ;
+        return f.createAccumulator(this) ;
     }
 
     @Override
-    public Node getValueEmpty()     { return null ; } 
+    public Node getValueEmpty()     { return AggregateRegistry.getNoGroupValue(iri) ; } 
 
     @Override
     public Expr getExpr()           { return null ; }
     
+    public String getIRI()                  { return iri ; }
+
     @Override
     public int hashCode()   { return HC_AggNull ; }
     @Override

http://git-wip-us.apache.org/repos/asf/jena/blob/a1ee6e18/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/aggregate/AggGroupConcat.java
----------------------------------------------------------------------
diff --git a/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/aggregate/AggGroupConcat.java b/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/aggregate/AggGroupConcat.java
index 50a477c..046818c 100644
--- a/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/aggregate/AggGroupConcat.java
+++ b/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/aggregate/AggGroupConcat.java
@@ -24,6 +24,7 @@ import org.apache.jena.atlas.lib.StrUtils ;
 import com.hp.hpl.jena.graph.Node ;
 import com.hp.hpl.jena.sparql.engine.binding.Binding ;
 import com.hp.hpl.jena.sparql.expr.Expr ;
+import com.hp.hpl.jena.sparql.expr.ExprList ;
 import com.hp.hpl.jena.sparql.expr.NodeValue ;
 import com.hp.hpl.jena.sparql.function.FunctionEnv ;
 import com.hp.hpl.jena.sparql.graph.NodeConst ;
@@ -33,7 +34,6 @@ import com.hp.hpl.jena.sparql.util.ExprUtils ;
 public class AggGroupConcat extends AggregatorBase
 {
     static final String SeparatorDefault = " " ;
-    private final Expr expr ;
     private final String separator ;
     private final String effectiveSeparator ;
 
@@ -46,18 +46,18 @@ public class AggGroupConcat extends AggregatorBase
     
     private AggGroupConcat(Expr expr, String effectiveSeparator, String separatorSeen)
     {
-        this.expr = expr ; 
+        super("GROUP_CONCAT", false, expr) ;
         this.separator = separatorSeen ;
         this.effectiveSeparator = effectiveSeparator ; 
     }
     
     @Override
-    public Aggregator copy(Expr expr) { return new AggGroupConcat(expr, effectiveSeparator, separator) ; }
+    public Aggregator copy(ExprList expr) { return new AggGroupConcat(expr.get(0), effectiveSeparator, separator) ; }
 
     @Override
     public String toString()
     {
-        String x = "GROUP_CONCAT("+ExprUtils.fmtSPARQL(expr) ;
+        String x = "GROUP_CONCAT("+ExprUtils.fmtSPARQL(getExpr()) ;
         if ( separator != null )
         {
             String y = StrUtils.escapeString(separator) ;
@@ -77,26 +77,23 @@ public class AggGroupConcat extends AggregatorBase
             String y = StrUtils.escapeString(separator) ;
             x = x+"(separator '"+y+"') " ;
         }
-        x = x+WriterExpr.asString(expr)+")" ;
+        x = x+WriterExpr.asString(getExpr())+")" ;
         return x ; 
     }
 
     @Override
     public Accumulator createAccumulator()
     { 
-        return new AccGroupConcat(expr, effectiveSeparator) ;
+        return new AccGroupConcat(getExpr(), effectiveSeparator) ;
     }
 
-    @Override
-    public Expr getExpr() { return expr ; }
-    
     public String getSeparator() { return separator ; }
 
     @Override
     public Node getValueEmpty() { return NodeConst.emptyString ; } 
     
     @Override
-    public int hashCode()   { return HC_AggCountVar ^ expr.hashCode() ; }
+    public int hashCode()   { return HC_AggCountVar ^ exprList.hashCode() ; }
     
     @Override
     public boolean equals(Object other)

http://git-wip-us.apache.org/repos/asf/jena/blob/a1ee6e18/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/aggregate/AggGroupConcatDistinct.java
----------------------------------------------------------------------
diff --git a/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/aggregate/AggGroupConcatDistinct.java b/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/aggregate/AggGroupConcatDistinct.java
index a34f437..579f898 100644
--- a/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/aggregate/AggGroupConcatDistinct.java
+++ b/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/aggregate/AggGroupConcatDistinct.java
@@ -24,6 +24,7 @@ import org.apache.jena.atlas.lib.StrUtils ;
 import com.hp.hpl.jena.graph.Node ;
 import com.hp.hpl.jena.sparql.engine.binding.Binding ;
 import com.hp.hpl.jena.sparql.expr.Expr ;
+import com.hp.hpl.jena.sparql.expr.ExprList ;
 import com.hp.hpl.jena.sparql.expr.NodeValue ;
 import com.hp.hpl.jena.sparql.function.FunctionEnv ;
 import com.hp.hpl.jena.sparql.sse.writers.WriterExpr ;
@@ -31,7 +32,6 @@ import com.hp.hpl.jena.sparql.util.ExprUtils ;
 
 public class AggGroupConcatDistinct extends AggregatorBase
 {
-    private final Expr expr ;
     private final String separator ;
     private final String effectiveSeparator ;
 
@@ -44,18 +44,18 @@ public class AggGroupConcatDistinct extends AggregatorBase
 
     private AggGroupConcatDistinct(Expr expr, String effectiveSeparator, String separatorSeen)
     {
-        this.expr = expr ; 
+        super("GROUP_CONCAT", true, expr) ;
         this.separator = separatorSeen ;
         this.effectiveSeparator = effectiveSeparator ; 
     }
     
     @Override
-    public Aggregator copy(Expr expr) { return new AggGroupConcatDistinct(expr, effectiveSeparator, separator) ; }
+    public Aggregator copy(ExprList exprs) { return new AggGroupConcatDistinct(exprs.get(0), effectiveSeparator, separator) ; }
 
     @Override
     public String toString()
     {
-        String x = "GROUP_CONCAT(DISTINCT "+ExprUtils.fmtSPARQL(expr) ;
+        String x = "GROUP_CONCAT(DISTINCT "+ExprUtils.fmtSPARQL(getExpr()) ;
         if ( separator != null )
         {
             String y = StrUtils.escapeString(separator) ;
@@ -75,26 +75,23 @@ public class AggGroupConcatDistinct extends AggregatorBase
             String y = StrUtils.escapeString(separator) ;
             x = x+"(separator '"+y+"') " ;
         }
-        x = x+WriterExpr.asString(expr)+")" ;
+        x = x+WriterExpr.asString(getExpr())+")" ;
         return x ; 
     }
 
     @Override
     public Accumulator createAccumulator()
     { 
-        return new AccGroupConcatDistinct(expr, effectiveSeparator) ;
+        return new AccGroupConcatDistinct(getExpr(), effectiveSeparator) ;
     }
 
-    @Override
-    public Expr getExpr() { return expr ; }
-    
     public String getSeparator() { return separator ; }
 
     @Override
     public Node getValueEmpty()     { return null ; } 
 
     @Override
-    public int hashCode()   { return HC_AggCountVar ^ expr.hashCode() ; }
+    public int hashCode()   { return HC_AggCountVar ^ getExpr().hashCode() ; }
     
     @Override
     public boolean equals(Object other)

http://git-wip-us.apache.org/repos/asf/jena/blob/a1ee6e18/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/aggregate/AggMax.java
----------------------------------------------------------------------
diff --git a/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/aggregate/AggMax.java b/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/aggregate/AggMax.java
index cbb2790..11e7012 100644
--- a/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/aggregate/AggMax.java
+++ b/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/aggregate/AggMax.java
@@ -18,24 +18,20 @@
 
 package com.hp.hpl.jena.sparql.expr.aggregate;
 
+import org.apache.jena.atlas.lib.Lib ;
+
 import com.hp.hpl.jena.sparql.expr.Expr ;
-import com.hp.hpl.jena.sparql.sse.writers.WriterExpr ;
-import com.hp.hpl.jena.sparql.util.ExprUtils ;
+import com.hp.hpl.jena.sparql.expr.ExprList ;
 
 public class AggMax extends AggMaxBase
 {
     // ---- MAX(expr)
-    public AggMax(Expr expr) { super(expr) ; } 
-    @Override
-    public Aggregator copy(Expr expr) { return new AggMax(expr) ; }
-
-    @Override
-    public String toString() { return "max("+ExprUtils.fmtSPARQL(expr)+")" ; }
+    public AggMax(Expr expr) { super(expr, false) ; } 
     @Override
-    public String toPrefixString() { return "(max "+WriterExpr.asString(expr)+")" ; }
+    public Aggregator copy(ExprList expr) { return new AggMax(expr.get(0)) ; }
 
     @Override
-    public int hashCode()   { return HC_AggMax ^ expr.hashCode() ; }
+    public int hashCode()   { return HC_AggMax ^ getExpr().hashCode() ; }
     
     @Override
     public boolean equals(Object other)
@@ -44,6 +40,6 @@ public class AggMax extends AggMaxBase
         if ( ! ( other instanceof AggMax ) )
             return false ;
         AggMax agg = (AggMax)other ;
-        return expr.equals(agg.expr) ;
+        return Lib.equal(exprList, agg.exprList) ;
     }
 }

http://git-wip-us.apache.org/repos/asf/jena/blob/a1ee6e18/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/aggregate/AggMaxBase.java
----------------------------------------------------------------------
diff --git a/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/aggregate/AggMaxBase.java b/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/aggregate/AggMaxBase.java
index 6511e80..f3541e5 100644
--- a/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/aggregate/AggMaxBase.java
+++ b/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/aggregate/AggMaxBase.java
@@ -27,21 +27,16 @@ import com.hp.hpl.jena.sparql.function.FunctionEnv ;
 abstract class AggMaxBase extends AggregatorBase
 {
     // ---- MAX(expr) and MAX(DISTINCT expr)
-    protected final Expr expr ;
-
-    public AggMaxBase(Expr expr) { this.expr = expr ; } 
+    protected AggMaxBase(Expr expr, boolean isDistinct) { super("MAX", isDistinct, expr) ; } 
 
     @Override
     public
     final Accumulator createAccumulator()
     { 
-        return new AccMax(expr) ;
+        return new AccMax(getExpr()) ;
     }
 
     @Override
-    public final Expr getExpr() { return expr ; }
-
-    @Override
     public final Node getValueEmpty()     { return null ; } 
 
     // ---- Accumulator

http://git-wip-us.apache.org/repos/asf/jena/blob/a1ee6e18/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/aggregate/AggMaxDistinct.java
----------------------------------------------------------------------
diff --git a/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/aggregate/AggMaxDistinct.java b/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/aggregate/AggMaxDistinct.java
index e597420..9a5aeed 100644
--- a/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/aggregate/AggMaxDistinct.java
+++ b/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/aggregate/AggMaxDistinct.java
@@ -18,24 +18,20 @@
 
 package com.hp.hpl.jena.sparql.expr.aggregate;
 
+import org.apache.jena.atlas.lib.Lib ;
+
 import com.hp.hpl.jena.sparql.expr.Expr ;
-import com.hp.hpl.jena.sparql.sse.writers.WriterExpr ;
-import com.hp.hpl.jena.sparql.util.ExprUtils ;
+import com.hp.hpl.jena.sparql.expr.ExprList ;
 
 public class AggMaxDistinct extends AggMaxBase
 {
     // ---- MAX( DISTINCT expr)
-    public AggMaxDistinct(Expr expr) { super(expr) ; } 
-    @Override
-    public Aggregator copy(Expr expr) { return new AggMaxDistinct(expr) ; }
-
-    @Override
-    public String toString() { return "max(distinct "+ExprUtils.fmtSPARQL(getExpr())+")" ; }
+    public AggMaxDistinct(Expr expr) { super(expr, true) ; } 
     @Override
-    public String toPrefixString() { return "(max distinct "+WriterExpr.asString(getExpr())+")" ; }
+    public Aggregator copy(ExprList expr) { return new AggMaxDistinct(expr.get(0)) ; }
 
     @Override
-    public int hashCode()   { return HC_AggMaxDistinct ^ expr.hashCode() ; }
+    public int hashCode()   { return HC_AggMaxDistinct ^ getExpr().hashCode() ; }
     
     @Override
     public boolean equals(Object other)
@@ -44,7 +40,7 @@ public class AggMaxDistinct extends AggMaxBase
         if ( ! ( other instanceof AggMaxDistinct ) )
             return false ;
         AggMaxDistinct agg = (AggMaxDistinct)other ;
-        return expr.equals(agg.expr) ;
+        return Lib.equal(exprList, agg.exprList) ;
     }
 
 }

http://git-wip-us.apache.org/repos/asf/jena/blob/a1ee6e18/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/aggregate/AggMin.java
----------------------------------------------------------------------
diff --git a/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/aggregate/AggMin.java b/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/aggregate/AggMin.java
index 4255585..b24e8f4 100644
--- a/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/aggregate/AggMin.java
+++ b/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/aggregate/AggMin.java
@@ -18,24 +18,20 @@
 
 package com.hp.hpl.jena.sparql.expr.aggregate;
 
+import org.apache.jena.atlas.lib.Lib ;
+
 import com.hp.hpl.jena.sparql.expr.Expr ;
-import com.hp.hpl.jena.sparql.sse.writers.WriterExpr ;
-import com.hp.hpl.jena.sparql.util.ExprUtils ;
+import com.hp.hpl.jena.sparql.expr.ExprList ;
 
 public class AggMin extends AggMinBase
 {
     // ---- MIN(?var)
-    public AggMin(Expr expr) { super(expr) ; } 
-    @Override
-    public Aggregator copy(Expr expr) { return new AggMin(expr) ; }
-
-    @Override
-    public String toString() { return "min("+ExprUtils.fmtSPARQL(expr)+")" ; }
+    public AggMin(Expr expr) { super(expr, false) ; } 
     @Override
-    public String toPrefixString() { return "(min "+WriterExpr.asString(expr)+")" ; }
+    public Aggregator copy(ExprList exprs) { return new AggMin(exprs.get(0)) ; }
 
     @Override
-    public int hashCode()   { return HC_AggMin ^ expr.hashCode() ; }
+    public int hashCode()   { return HC_AggMin ^ getExpr().hashCode() ; }
     
     @Override
     public boolean equals(Object other)
@@ -44,6 +40,6 @@ public class AggMin extends AggMinBase
         if ( ! ( other instanceof AggMin ) )
             return false ;
         AggMin agg = (AggMin)other ;
-        return expr.equals(agg.expr) ;
+        return Lib.equal(exprList, agg.exprList) ;
     }
 }

http://git-wip-us.apache.org/repos/asf/jena/blob/a1ee6e18/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/aggregate/AggMinBase.java
----------------------------------------------------------------------
diff --git a/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/aggregate/AggMinBase.java b/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/aggregate/AggMinBase.java
index 7895f7e..c8df0f3 100644
--- a/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/aggregate/AggMinBase.java
+++ b/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/aggregate/AggMinBase.java
@@ -27,21 +27,16 @@ import com.hp.hpl.jena.sparql.function.FunctionEnv ;
 abstract class AggMinBase extends AggregatorBase
 {
     // ---- MIN(expr) and MIN(DISTINCT expr)
-    protected final Expr expr ;
-
-    public AggMinBase(Expr expr) { this.expr = expr ; } 
+    protected AggMinBase(Expr expr, boolean isDistinct) { super("MIN", isDistinct, expr) ; } 
 
     @Override
     public
     final Accumulator createAccumulator()
     { 
-        return new AccMin(expr) ;
+        return new AccMin(getExpr()) ;
     }
 
     @Override
-    public final Expr getExpr() { return expr ; }
-
-    @Override
     public final Node getValueEmpty()     { return null ; } 
 
     // ---- Accumulator

http://git-wip-us.apache.org/repos/asf/jena/blob/a1ee6e18/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/aggregate/AggMinDistinct.java
----------------------------------------------------------------------
diff --git a/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/aggregate/AggMinDistinct.java b/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/aggregate/AggMinDistinct.java
index 3bded0d..6d4990b 100644
--- a/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/aggregate/AggMinDistinct.java
+++ b/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/aggregate/AggMinDistinct.java
@@ -18,24 +18,19 @@
 
 package com.hp.hpl.jena.sparql.expr.aggregate;
 
+import org.apache.jena.atlas.lib.Lib ;
+
 import com.hp.hpl.jena.sparql.expr.Expr ;
-import com.hp.hpl.jena.sparql.sse.writers.WriterExpr ;
-import com.hp.hpl.jena.sparql.util.ExprUtils ;
+import com.hp.hpl.jena.sparql.expr.ExprList ;
 
 public class AggMinDistinct extends AggMinBase
 {
     // ---- MIN(DISTINCT expr)
-    public AggMinDistinct(Expr expr) { super(expr) ; }
-    @Override
-    public Aggregator copy(Expr expr) { return new AggMinDistinct(expr) ; }
-
+    public AggMinDistinct(Expr expr) { super(expr, false) ; } 
     @Override
-    public String toString() { return "min(distinct "+ExprUtils.fmtSPARQL(getExpr())+")" ; }
-    @Override
-    public String toPrefixString() { return "(min distinct "+WriterExpr.asString(getExpr())+")" ; }
-
+    public Aggregator copy(ExprList exprs) { return new AggMinDistinct(exprs.get(0)) ; }
     @Override
-    public int hashCode()   { return HC_AggMinDistinct ^ expr.hashCode() ; }
+    public int hashCode()   { return HC_AggMinDistinct ^ getExpr().hashCode() ; }
     
    @Override
     public boolean equals(Object other)
@@ -44,6 +39,6 @@ public class AggMinDistinct extends AggMinBase
         if ( ! ( other instanceof AggMinDistinct ) )
             return false ;
         AggMinDistinct agg = (AggMinDistinct)other ;
-        return expr.equals(agg.expr) ;
+        return Lib.equal(exprList, agg.exprList) ;
     } 
 }

http://git-wip-us.apache.org/repos/asf/jena/blob/a1ee6e18/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/aggregate/AggNull.java
----------------------------------------------------------------------
diff --git a/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/aggregate/AggNull.java b/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/aggregate/AggNull.java
index 10283b7..1272176 100644
--- a/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/aggregate/AggNull.java
+++ b/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/aggregate/AggNull.java
@@ -20,7 +20,7 @@ package com.hp.hpl.jena.sparql.expr.aggregate;
 
 import com.hp.hpl.jena.graph.Node ;
 import com.hp.hpl.jena.sparql.engine.binding.Binding ;
-import com.hp.hpl.jena.sparql.expr.Expr ;
+import com.hp.hpl.jena.sparql.expr.ExprList ;
 import com.hp.hpl.jena.sparql.expr.NodeValue ;
 import com.hp.hpl.jena.sparql.function.FunctionEnv ;
 
@@ -29,16 +29,11 @@ import com.hp.hpl.jena.sparql.function.FunctionEnv ;
  */
 public class AggNull extends AggregatorBase
 {
-    public AggNull() { } 
+    public AggNull() { super("AGGNULL", false, (ExprList)null) ; } 
     @Override
-    public Aggregator copy(Expr expr) { return this ; }
+    public Aggregator copy(ExprList exprs) { return this ; }
     
     @Override
-    public String toString() { return "aggnull()" ; }
-    @Override
-    public String toPrefixString() { return "(aggnull)" ; }
-
-    @Override
     public Accumulator createAccumulator()
     { 
         return createAccNull() ;
@@ -48,9 +43,6 @@ public class AggNull extends AggregatorBase
     public Node getValueEmpty()     { return null ; } 
 
     @Override
-    public Expr getExpr()           { return null ; }
-    
-    @Override
     public int hashCode()   { return HC_AggNull ; }
     @Override
     public boolean equals(Object other)

http://git-wip-us.apache.org/repos/asf/jena/blob/a1ee6e18/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/aggregate/AggSample.java
----------------------------------------------------------------------
diff --git a/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/aggregate/AggSample.java b/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/aggregate/AggSample.java
index ed9460e..5177ece 100644
--- a/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/aggregate/AggSample.java
+++ b/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/aggregate/AggSample.java
@@ -18,42 +18,34 @@
 
 package com.hp.hpl.jena.sparql.expr.aggregate;
 
+import org.apache.jena.atlas.lib.Lib ;
+
 import com.hp.hpl.jena.graph.Node ;
 import com.hp.hpl.jena.sparql.engine.binding.Binding ;
 import com.hp.hpl.jena.sparql.expr.Expr ;
+import com.hp.hpl.jena.sparql.expr.ExprList ;
 import com.hp.hpl.jena.sparql.expr.NodeValue ;
 import com.hp.hpl.jena.sparql.function.FunctionEnv ;
-import com.hp.hpl.jena.sparql.sse.writers.WriterExpr ;
-import com.hp.hpl.jena.sparql.util.ExprUtils ;
 
 public class AggSample extends AggregatorBase
 {
     // ---- Sample(expr)
-    private final Expr expr ;
-
-    public AggSample(Expr expr) { this.expr = expr ; } 
-    @Override
-    public Aggregator copy(Expr expr) { return new AggSample(expr) ; }
+    public AggSample(Expr expr) { super("SAMPLE", false, expr) ; } 
     
     @Override
-    public String toString() { return "sample("+ExprUtils.fmtSPARQL(expr)+")" ; }
-    @Override
-    public String toPrefixString() { return "(sample "+WriterExpr.asString(expr)+")" ; }
-
+    public Aggregator copy(ExprList exprs) { return new AggSample(exprs.get(0)) ; }
+    
     @Override
     public Accumulator createAccumulator()
     { 
-        return new AccSample(expr) ;
+        return new AccSample(getExpr()) ;
     }
 
     @Override
-    public Expr getExpr() { return expr ; }
-
-    @Override
     public Node getValueEmpty()     { return null ; } 
 
     @Override
-    public int hashCode()   { return HC_AggSample ^ expr.hashCode() ; }
+    public int hashCode()   { return HC_AggSample ^ getExpr().hashCode() ; }
     @Override
     public boolean equals(Object other)
     {
@@ -61,7 +53,7 @@ public class AggSample extends AggregatorBase
         if ( ! ( other instanceof AggSample ) )
             return false ;
         AggSample agg = (AggSample)other ;
-        return agg.getExpr().equals(getExpr()) ;
+        return Lib.equal(this.exprList, agg.exprList) ;
     } 
 
     // ---- Accumulator

http://git-wip-us.apache.org/repos/asf/jena/blob/a1ee6e18/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/aggregate/AggSampleDistinct.java
----------------------------------------------------------------------
diff --git a/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/aggregate/AggSampleDistinct.java b/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/aggregate/AggSampleDistinct.java
index 64a0f27..dad6e2b 100644
--- a/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/aggregate/AggSampleDistinct.java
+++ b/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/aggregate/AggSampleDistinct.java
@@ -21,36 +21,25 @@ package com.hp.hpl.jena.sparql.expr.aggregate;
 import com.hp.hpl.jena.graph.Node ;
 import com.hp.hpl.jena.sparql.engine.binding.Binding ;
 import com.hp.hpl.jena.sparql.expr.Expr ;
+import com.hp.hpl.jena.sparql.expr.ExprList ;
 import com.hp.hpl.jena.sparql.expr.NodeValue ;
 import com.hp.hpl.jena.sparql.function.FunctionEnv ;
-import com.hp.hpl.jena.sparql.sse.writers.WriterExpr ;
-import com.hp.hpl.jena.sparql.util.ExprUtils ;
 
 public class AggSampleDistinct extends AggregatorBase
 {
     // ---- Sample(DISTINCT expr)
-    private final Expr expr ;
-
-    public AggSampleDistinct(Expr expr) { this.expr = expr ; } 
-    @Override
-    public Aggregator copy(Expr expr) { return new AggSampleDistinct(expr) ; }
-
+    public AggSampleDistinct(Expr expr) { super("SAMPLE", true, expr) ; } 
     @Override
-    public String toString() { return "SAMPLE(DISTINCT "+ExprUtils.fmtSPARQL(expr)+")" ; }
-    @Override
-    public String toPrefixString() { return "(sample distinct"+WriterExpr.asString(expr)+")" ; }
+    public Aggregator copy(ExprList exprs) { return new AggSampleDistinct(exprs.get(0)) ; }
 
     @Override
     public Accumulator createAccumulator()
     { 
-        return new AccSampleDistict(expr) ;
+        return new AccSampleDistict(getExpr()) ;
     }
 
     @Override
-    public Expr getExpr() { return expr ; }
-
-    @Override
-    public int hashCode()   { return HC_AggSample ^ expr.hashCode() ; }
+    public int hashCode()   { return HC_AggSample ^ getExpr().hashCode() ; }
     @Override
     public boolean equals(Object other)
     {

http://git-wip-us.apache.org/repos/asf/jena/blob/a1ee6e18/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/aggregate/AggSum.java
----------------------------------------------------------------------
diff --git a/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/aggregate/AggSum.java b/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/aggregate/AggSum.java
index e9eb6e6..bbc1d38 100644
--- a/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/aggregate/AggSum.java
+++ b/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/aggregate/AggSum.java
@@ -22,41 +22,31 @@ import com.hp.hpl.jena.graph.Node ;
 import com.hp.hpl.jena.sparql.engine.binding.Binding ;
 import com.hp.hpl.jena.sparql.expr.Expr ;
 import com.hp.hpl.jena.sparql.expr.ExprEvalException ;
+import com.hp.hpl.jena.sparql.expr.ExprList ;
 import com.hp.hpl.jena.sparql.expr.NodeValue ;
 import com.hp.hpl.jena.sparql.expr.nodevalue.XSDFuncOp ;
 import com.hp.hpl.jena.sparql.function.FunctionEnv ;
-import com.hp.hpl.jena.sparql.sse.writers.WriterExpr ;
-import com.hp.hpl.jena.sparql.util.ExprUtils ;
 
 public class AggSum  extends AggregatorBase
 {
     // ---- SUM(expr)
     private static final NodeValue noValuesToSum = NodeValue.nvZERO ; 
-    private Expr expr ;
 
-    public AggSum(Expr expr) { this.expr = expr ; } 
+    public AggSum(Expr expr) { super("SUM", false, expr) ; } 
     @Override
-    public Aggregator copy(Expr expr) { return new AggSum(expr) ; }
-
-    @Override
-    public String toString() { return "sum("+ExprUtils.fmtSPARQL(expr)+")" ; }
-    @Override
-    public String toPrefixString() { return "(sum "+WriterExpr.asString(expr)+")" ; }
+    public Aggregator copy(ExprList exprs) { return new AggSum(exprs.get(0)) ; }
 
     @Override
     public Accumulator createAccumulator()
     { 
-        return new AccSum(expr) ;
+        return new AccSum(getExpr()) ;
     }
 
     @Override
-    public Expr getExpr() { return expr ; }
-
-    @Override
     public Node getValueEmpty() { return NodeValue.toNode(noValuesToSum) ; } 
 
     @Override
-    public int hashCode()   { return HC_AggSum ^ expr.hashCode() ; }
+    public int hashCode()   { return HC_AggSum ^ getExpr().hashCode() ; }
     
     @Override
     public boolean equals(Object other)

http://git-wip-us.apache.org/repos/asf/jena/blob/a1ee6e18/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/aggregate/AggSumDistinct.java
----------------------------------------------------------------------
diff --git a/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/aggregate/AggSumDistinct.java b/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/aggregate/AggSumDistinct.java
index 3b62f06..197b088 100644
--- a/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/aggregate/AggSumDistinct.java
+++ b/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/aggregate/AggSumDistinct.java
@@ -22,39 +22,29 @@ import com.hp.hpl.jena.graph.Node ;
 import com.hp.hpl.jena.sparql.engine.binding.Binding ;
 import com.hp.hpl.jena.sparql.expr.Expr ;
 import com.hp.hpl.jena.sparql.expr.ExprEvalException ;
+import com.hp.hpl.jena.sparql.expr.ExprList ;
 import com.hp.hpl.jena.sparql.expr.NodeValue ;
 import com.hp.hpl.jena.sparql.expr.nodevalue.XSDFuncOp ;
 import com.hp.hpl.jena.sparql.function.FunctionEnv ;
-import com.hp.hpl.jena.sparql.sse.writers.WriterExpr ;
-import com.hp.hpl.jena.sparql.util.ExprUtils ;
 
 public class AggSumDistinct  extends AggregatorBase
 {
     // ---- SUM(DISTINCT expr)
-    private Expr expr ;
-
-    public AggSumDistinct(Expr expr) { this.expr = expr ; } 
+    public AggSumDistinct(Expr expr) { super("SUM", true, expr) ; } 
     @Override
-    public Aggregator copy(Expr expr) { return new AggSumDistinct(expr) ; }
+    public Aggregator copy(ExprList exprs) { return new AggSumDistinct(exprs.get(0)) ; }
 
     private static final NodeValue noValuesToSum = NodeValue.nvZERO ; 
     
     @Override
-    public String toString() { return "sum(distinct "+ExprUtils.fmtSPARQL(expr)+")" ; }
-    @Override
-    public String toPrefixString() { return "(sum distinct "+WriterExpr.asString(expr)+")" ; }
-
-    @Override
     public Accumulator createAccumulator()
     { 
-        return new AccSumDistinct(expr) ;
+        return new AccSumDistinct(getExpr()) ;
     }
 
     @Override
-    public Expr getExpr() { return expr ; }
-
-    @Override
-    public int hashCode()   { return HC_AggSumDistinct ^ expr.hashCode() ; }
+    public int hashCode()   { return HC_AggSumDistinct ^ getExpr().hashCode() ; }
+    
     @Override
     public boolean equals(Object other)
     {

http://git-wip-us.apache.org/repos/asf/jena/blob/a1ee6e18/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/aggregate/Aggregator.java
----------------------------------------------------------------------
diff --git a/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/aggregate/Aggregator.java b/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/aggregate/Aggregator.java
index 9ece99f..04129af 100644
--- a/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/aggregate/Aggregator.java
+++ b/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/aggregate/Aggregator.java
@@ -19,8 +19,9 @@
 package com.hp.hpl.jena.sparql.expr.aggregate;
 
 import com.hp.hpl.jena.graph.Node ;
-import com.hp.hpl.jena.sparql.expr.Expr ;
+import com.hp.hpl.jena.sparql.expr.ExprList ;
 import com.hp.hpl.jena.sparql.graph.NodeTransform ;
+import com.hp.hpl.jena.sparql.serializer.SerializationContext ;
 
 /** An Aggregator is the processor for the whole result stream.
  *  BindingKeys identify which section of a group we're in. */ 
@@ -40,13 +41,18 @@ public interface Aggregator
     // Key to identify an aggregator as syntax for duplicate use in a query.
     public String key() ;           
     
-    /** Get the expression - may be null (e.g COUNT(*)) ; */ 
-    public Expr getExpr() ;
-    public Aggregator copy(Expr expr) ;
+    /** Get the SPARQL name (COUNT, AVG etc) */
+    public String getName() ;
+    
+    public ExprList getExprList() ;
+    public Aggregator copy(ExprList exprs) ;
     public Aggregator copyTransform(NodeTransform transform) ;
     
     @Override
     public int hashCode() ;
     @Override
     public boolean equals(Object other) ;
+
+    /** Format as an (extended) SPARQL expression */
+    public String asSparqlExpr(SerializationContext sCxt) ;
 }

http://git-wip-us.apache.org/repos/asf/jena/blob/a1ee6e18/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/aggregate/AggregatorBase.java
----------------------------------------------------------------------
diff --git a/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/aggregate/AggregatorBase.java b/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/aggregate/AggregatorBase.java
index 9f1db45..65355f3 100644
--- a/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/aggregate/AggregatorBase.java
+++ b/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/aggregate/AggregatorBase.java
@@ -19,14 +19,21 @@
 package com.hp.hpl.jena.sparql.expr.aggregate;
 
 import java.util.HashMap ;
+import java.util.Locale ;
 import java.util.Map ;
 
+import org.apache.jena.atlas.io.IndentedLineBuffer ;
+
 import com.hp.hpl.jena.graph.Node ;
 import com.hp.hpl.jena.sparql.ARQInternalErrorException ;
 import com.hp.hpl.jena.sparql.engine.binding.Binding ;
 import com.hp.hpl.jena.sparql.expr.Expr ;
+import com.hp.hpl.jena.sparql.expr.ExprList ;
 import com.hp.hpl.jena.sparql.expr.NodeValue ;
 import com.hp.hpl.jena.sparql.graph.NodeTransform ;
+import com.hp.hpl.jena.sparql.serializer.SerializationContext ;
+import com.hp.hpl.jena.sparql.sse.writers.WriterExpr ;
+import com.hp.hpl.jena.sparql.util.ExprUtils ;
 
 /** Aggregate that does everything except the per-group aggregation that is needed for each operation */  
 public abstract class AggregatorBase implements Aggregator 
@@ -43,7 +50,19 @@ public abstract class AggregatorBase implements Aggregator
     // but COUNT(*) and COUNT(Expr) are different beasts
     // each in DISTINCT and non-DISTINCT versions 
     
-    protected AggregatorBase() {}
+    protected final String name ; 
+    protected final boolean isDistinct ;
+    protected final ExprList exprList ;
+    
+    protected AggregatorBase(String name, boolean isDistinct, Expr expr) {
+        this(name, isDistinct, new ExprList(expr)) ;
+    }
+    
+    protected AggregatorBase(String name, boolean isDistinct, ExprList exprList) {
+        this.name = name ;
+        this.isDistinct = isDistinct ;  
+        this.exprList = exprList ;
+    }
     
     private Map<Binding, Accumulator> buckets = new HashMap<>() ;   // Bindingkey => Accumulator
 
@@ -70,17 +89,61 @@ public abstract class AggregatorBase implements Aggregator
     @Override
     public final Aggregator copyTransform(NodeTransform transform)
     {
-        Expr e = getExpr() ;
+        ExprList e = getExprList() ;
         if ( e != null )
             e = e.applyNodeTransform(transform) ;
         return copy(e) ;
     }
     
     @Override
-    public abstract String toString() ;
+    public String asSparqlExpr(SerializationContext sCxt) {
+        IndentedLineBuffer x = new IndentedLineBuffer() ;
+        x.append(getName()) ;
+        x.append("(") ;
+        if ( isDistinct )
+            x.append("DISTINCT") ;
+        if ( getExprList() != null ) {
+            x.append(" ");
+            ExprUtils.fmtSPARQL(x, getExprList(), sCxt) ;
+        }
+        x.append(")") ;
+        return x.asString() ;
+    }
+    
+    /** Many aggergate use a single expression.
+     *  This convebnience operation gets the expression if there is exactly one.
+     */
+    protected Expr getExpr() {
+        if ( exprList != null && exprList.size() == 1 )
+            return getExprList().get(0) ;
+        return null ;
+    }
+    
+    @Override
+    public ExprList getExprList()           { return exprList ; }
+
+    @Override
+    public String getName()                 { return name ; } 
 
     @Override
-    public abstract String toPrefixString() ;
+    public String toString()                { return asSparqlExpr(null) ; }
+
+    @Override
+    public String toPrefixString() {
+        IndentedLineBuffer x = new IndentedLineBuffer() ;
+        x.append("(") ;
+        x.append(getName().toLowerCase(Locale.ROOT)) ;
+        x.incIndent(); 
+        if ( isDistinct )
+            x.append(" distinct") ;
+        for ( Expr e : getExprList() ) {
+            x.append(" ");
+            WriterExpr.output(x, e, null) ;
+        }
+        x.decIndent();
+        x.append(")") ;
+        return x.asString() ;
+    }
     
     @Override
     public abstract int hashCode() ;

http://git-wip-us.apache.org/repos/asf/jena/blob/a1ee6e18/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/aggregate/AggregatorFactory.java
----------------------------------------------------------------------
diff --git a/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/aggregate/AggregatorFactory.java b/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/aggregate/AggregatorFactory.java
index 2204b71..a0a565e 100644
--- a/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/aggregate/AggregatorFactory.java
+++ b/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/aggregate/AggregatorFactory.java
@@ -64,8 +64,9 @@ public class AggregatorFactory {
         return new AggNull() ;
     }
 
-    public static Aggregator create(java.lang.String iri, ExprList a) {
-        Log.fatal(AggregatorFactory.class, "Not implemented: custom aggregates (extedned syntax)") ;
+    public static Aggregator create(String iri, ExprList a) {
+        if ( ! AggregateRegistry.isRegistered(iri) )
+            Log.fatal(AggregatorFactory.class, "Not registered: custom aggregate <"+iri+">") ;
         return new AggCustom(iri, a) ;
     }
 }

http://git-wip-us.apache.org/repos/asf/jena/blob/a1ee6e18/jena-arq/src/main/java/com/hp/hpl/jena/sparql/serializer/FmtExprSPARQL.java
----------------------------------------------------------------------
diff --git a/jena-arq/src/main/java/com/hp/hpl/jena/sparql/serializer/FmtExprSPARQL.java b/jena-arq/src/main/java/com/hp/hpl/jena/sparql/serializer/FmtExprSPARQL.java
index 3d9a9e8..2a6f7e3 100644
--- a/jena-arq/src/main/java/com/hp/hpl/jena/sparql/serializer/FmtExprSPARQL.java
+++ b/jena-arq/src/main/java/com/hp/hpl/jena/sparql/serializer/FmtExprSPARQL.java
@@ -222,7 +222,7 @@ public class FmtExprSPARQL
         @Override
         public void visit(ExprAggregator eAgg)
         {
-            out.print(eAgg.asSparqlExpr()) ;
+            out.print(eAgg.asSparqlExpr(context)) ;
         }
         
         

http://git-wip-us.apache.org/repos/asf/jena/blob/a1ee6e18/jena-arq/src/main/java/com/hp/hpl/jena/sparql/util/ExprUtils.java
----------------------------------------------------------------------
diff --git a/jena-arq/src/main/java/com/hp/hpl/jena/sparql/util/ExprUtils.java b/jena-arq/src/main/java/com/hp/hpl/jena/sparql/util/ExprUtils.java
index c60fc72..8009b66 100644
--- a/jena-arq/src/main/java/com/hp/hpl/jena/sparql/util/ExprUtils.java
+++ b/jena-arq/src/main/java/com/hp/hpl/jena/sparql/util/ExprUtils.java
@@ -192,6 +192,14 @@ public class ExprUtils
         return buff.toString() ; 
     }
 
+    public static String fmtSPARQL(ExprList exprs, SerializationContext sCxt)
+    {
+        IndentedLineBuffer buff = new IndentedLineBuffer() ;
+        fmtSPARQL(buff, exprs, sCxt) ;
+        return buff.toString() ; 
+    }
+
+
     public static String strComparison(int cmp)
     {
         switch (cmp)


[2/4] jena git commit: JENA-803 : Bare framework for custom aggregates

Posted by an...@apache.org.
JENA-803 : Bare framework for custom aggregates

Project: http://git-wip-us.apache.org/repos/asf/jena/repo
Commit: http://git-wip-us.apache.org/repos/asf/jena/commit/addc1987
Tree: http://git-wip-us.apache.org/repos/asf/jena/tree/addc1987
Diff: http://git-wip-us.apache.org/repos/asf/jena/diff/addc1987

Branch: refs/heads/master
Commit: addc1987ee41505053686eb76c62e9045806fa5e
Parents: a1ee6e1
Author: Andy Seaborne <an...@apache.org>
Authored: Sun Dec 28 18:38:28 2014 +0000
Committer: Andy Seaborne <an...@apache.org>
Committed: Sun Dec 28 18:38:28 2014 +0000

----------------------------------------------------------------------
 .../expr/aggregate/AccumulatorFactory.java      | 31 +++++++++
 .../expr/aggregate/AggregateRegistry.java       | 70 ++++++++++++++++++++
 2 files changed, 101 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/jena/blob/addc1987/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/aggregate/AccumulatorFactory.java
----------------------------------------------------------------------
diff --git a/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/aggregate/AccumulatorFactory.java b/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/aggregate/AccumulatorFactory.java
new file mode 100644
index 0000000..e5ba9cc
--- /dev/null
+++ b/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/aggregate/AccumulatorFactory.java
@@ -0,0 +1,31 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.hp.hpl.jena.sparql.expr.aggregate;
+
+/** Fatory to create accumulators. An Accumulator is
+ * processor for one group key for one execution.
+ */
+public interface AccumulatorFactory {
+    /**
+     * 
+     * @return Accumulator
+     */
+    public Accumulator createAccumulator(AggCustom agg) ;
+}
+

http://git-wip-us.apache.org/repos/asf/jena/blob/addc1987/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/aggregate/AggregateRegistry.java
----------------------------------------------------------------------
diff --git a/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/aggregate/AggregateRegistry.java b/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/aggregate/AggregateRegistry.java
new file mode 100644
index 0000000..b47ff81
--- /dev/null
+++ b/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/aggregate/AggregateRegistry.java
@@ -0,0 +1,70 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.hp.hpl.jena.sparql.expr.aggregate;
+
+import java.util.HashMap ;
+import java.util.Map ;
+
+import com.hp.hpl.jena.graph.Node ;
+
+/** Registry of custom aggregates
+ * There is only a single global registry of aggregates - it affects parsing
+ * and parsing happens before Context or Execution makes sense.   
+ */
+public class AggregateRegistry {
+    
+    private static Map<String, AccumulatorFactory> registry = new HashMap<>() ;
+    private static Map<String, Node>               noGroupValues = new HashMap<>() ;
+    
+    /**
+     * Register a custom aggregate, with its associated factory for accumulators.
+     */
+    public static void register(String uri, AccumulatorFactory accFactory) {
+        register(uri, accFactory, null) ;
+    }
+
+    public static void register(String uri, AccumulatorFactory accFactory, Node noGroupValue) {
+        registry.put(uri, accFactory) ;
+        noGroupValues.put(uri, noGroupValue) ;
+    }
+
+    /**
+     * Remove a registration.
+     */
+    public static void unregister(String uri) {
+        registry.remove(uri) ;
+        noGroupValues.remove(uri) ;
+    }
+    
+    /** Return the AccumulatorFactory for a registered custom aggregate. */
+    public static AccumulatorFactory getAccumulatorFactory(String uri) {
+        return registry.get(uri) ;
+    }
+    
+    /** Return the AccumulatorFactory for a registered custom aggregate. */
+    public static Node getNoGroupValue(String uri) {
+        return noGroupValues.get(uri) ;
+    }
+
+    /** Return the AccumulatorFactory for a registered custom aggregate. */
+    public static boolean isRegistered(String uri) {
+        return registry.containsKey(uri) ;
+    }
+}
+


[3/4] jena git commit: Fix output formatting.

Posted by an...@apache.org.
Fix output formatting.

Project: http://git-wip-us.apache.org/repos/asf/jena/repo
Commit: http://git-wip-us.apache.org/repos/asf/jena/commit/748180ae
Tree: http://git-wip-us.apache.org/repos/asf/jena/tree/748180ae
Diff: http://git-wip-us.apache.org/repos/asf/jena/diff/748180ae

Branch: refs/heads/master
Commit: 748180ae89724a0c82fa56f36b02a9d6ff18f53a
Parents: addc198
Author: Andy Seaborne <an...@apache.org>
Authored: Sun Dec 28 18:55:31 2014 +0000
Committer: Andy Seaborne <an...@apache.org>
Committed: Sun Dec 28 18:55:31 2014 +0000

----------------------------------------------------------------------
 .../sparql/expr/aggregate/AggGroupConcat.java   | 64 ++++++++++++++------
 .../expr/aggregate/AggGroupConcatDistinct.java  | 31 ++--------
 .../sparql/expr/aggregate/AggregatorBase.java   | 28 ++++-----
 3 files changed, 65 insertions(+), 58 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/jena/blob/748180ae/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/aggregate/AggGroupConcat.java
----------------------------------------------------------------------
diff --git a/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/aggregate/AggGroupConcat.java b/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/aggregate/AggGroupConcat.java
index 046818c..0a3c3d5 100644
--- a/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/aggregate/AggGroupConcat.java
+++ b/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/aggregate/AggGroupConcat.java
@@ -18,6 +18,7 @@
 
 package com.hp.hpl.jena.sparql.expr.aggregate;
 
+import org.apache.jena.atlas.io.IndentedLineBuffer ;
 import org.apache.jena.atlas.lib.Lib ;
 import org.apache.jena.atlas.lib.StrUtils ;
 
@@ -28,6 +29,7 @@ import com.hp.hpl.jena.sparql.expr.ExprList ;
 import com.hp.hpl.jena.sparql.expr.NodeValue ;
 import com.hp.hpl.jena.sparql.function.FunctionEnv ;
 import com.hp.hpl.jena.sparql.graph.NodeConst ;
+import com.hp.hpl.jena.sparql.serializer.SerializationContext ;
 import com.hp.hpl.jena.sparql.sse.writers.WriterExpr ;
 import com.hp.hpl.jena.sparql.util.ExprUtils ;
 
@@ -55,32 +57,58 @@ public class AggGroupConcat extends AggregatorBase
     public Aggregator copy(ExprList expr) { return new AggGroupConcat(expr.get(0), effectiveSeparator, separator) ; }
 
     @Override
-    public String toString()
-    {
-        String x = "GROUP_CONCAT("+ExprUtils.fmtSPARQL(getExpr()) ;
-        if ( separator != null )
-        {
-            String y = StrUtils.escapeString(separator) ;
-            x = x+"; SEPARATOR='"+y+"'" ;
-        }
-        x = x+")" ;
-        return x ; 
-    }    
+    public String toPrefixString() {
+        return prefixGroupConcatString(super.isDistinct,  separator, getExprList()) ;
+    }
     
     @Override
-    public String toPrefixString()
-    {
-        String x = "(group_concat " ;
+    public String asSparqlExpr(SerializationContext sCxt) {
+        return asSparqlExpr(isDistinct, separator, exprList, sCxt) ;
+    }
+    
+    protected static String asSparqlExpr(boolean isDistinct, String separator, ExprList exprs, SerializationContext sCxt) {
+        IndentedLineBuffer x = new IndentedLineBuffer() ;
+        x.append("GROUP_CONCAT") ;
+        if ( isDistinct )
+            x.append(" DISTINCT") ;
+        x.append(" (") ;
+        ExprUtils.fmtSPARQL(x, exprs, sCxt) ;
+        if ( separator != null ) {
+            x.append(" ; separator=") ;
+            String y = StrUtils.escapeString(separator) ;
+            x.append("'") ;
+            x.append(y) ;
+            x.append("'") ;
+        }
+            
+        x.append(")") ;
         
+        return x.asString() ;
+    }
+    
+    protected static String prefixGroupConcatString(boolean isDistinct, String separator, ExprList exprs) { 
+        IndentedLineBuffer x = new IndentedLineBuffer() ;
+        x.append("(") ;
+        x.append("group_concat") ;
+        if ( isDistinct )
+            x.append(" distinct") ;
         if ( separator != null )
         {
             String y = StrUtils.escapeString(separator) ;
-            x = x+"(separator '"+y+"') " ;
+            x.append("(separator '") ;
+            x.append(y) ;
+            x.append("')") ;
+        }
+        x.incIndent(); 
+        for ( Expr e : exprs ) {
+            x.append(" ");
+            WriterExpr.output(x, e, null) ;
         }
-        x = x+WriterExpr.asString(getExpr())+")" ;
-        return x ; 
+        x.decIndent();
+        x.append(")") ;
+        return x.asString() ;
     }
-
+    
     @Override
     public Accumulator createAccumulator()
     { 

http://git-wip-us.apache.org/repos/asf/jena/blob/748180ae/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/aggregate/AggGroupConcatDistinct.java
----------------------------------------------------------------------
diff --git a/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/aggregate/AggGroupConcatDistinct.java b/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/aggregate/AggGroupConcatDistinct.java
index 579f898..ebef4b6 100644
--- a/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/aggregate/AggGroupConcatDistinct.java
+++ b/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/aggregate/AggGroupConcatDistinct.java
@@ -19,7 +19,6 @@
 package com.hp.hpl.jena.sparql.expr.aggregate;
 
 import org.apache.jena.atlas.lib.Lib ;
-import org.apache.jena.atlas.lib.StrUtils ;
 
 import com.hp.hpl.jena.graph.Node ;
 import com.hp.hpl.jena.sparql.engine.binding.Binding ;
@@ -27,8 +26,7 @@ import com.hp.hpl.jena.sparql.expr.Expr ;
 import com.hp.hpl.jena.sparql.expr.ExprList ;
 import com.hp.hpl.jena.sparql.expr.NodeValue ;
 import com.hp.hpl.jena.sparql.function.FunctionEnv ;
-import com.hp.hpl.jena.sparql.sse.writers.WriterExpr ;
-import com.hp.hpl.jena.sparql.util.ExprUtils ;
+import com.hp.hpl.jena.sparql.serializer.SerializationContext ;
 
 public class AggGroupConcatDistinct extends AggregatorBase
 {
@@ -53,30 +51,13 @@ public class AggGroupConcatDistinct extends AggregatorBase
     public Aggregator copy(ExprList exprs) { return new AggGroupConcatDistinct(exprs.get(0), effectiveSeparator, separator) ; }
 
     @Override
-    public String toString()
-    {
-        String x = "GROUP_CONCAT(DISTINCT "+ExprUtils.fmtSPARQL(getExpr()) ;
-        if ( separator != null )
-        {
-            String y = StrUtils.escapeString(separator) ;
-            x = x+"; SEPARATOR='"+y+"'" ;
-        }
-        x = x+")" ;
-        return x ; 
-    }    
+    public String toPrefixString() {
+        return AggGroupConcat.prefixGroupConcatString(super.isDistinct,  separator, getExprList()) ;
+    }
     
     @Override
-    public String toPrefixString()
-    {
-        String x = "(group_concat distinct " ;
-        
-        if ( separator != null )
-        {
-            String y = StrUtils.escapeString(separator) ;
-            x = x+"(separator '"+y+"') " ;
-        }
-        x = x+WriterExpr.asString(getExpr())+")" ;
-        return x ; 
+    public String asSparqlExpr(SerializationContext sCxt) {
+        return AggGroupConcat.asSparqlExpr(isDistinct, separator, exprList, sCxt) ;
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/jena/blob/748180ae/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/aggregate/AggregatorBase.java
----------------------------------------------------------------------
diff --git a/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/aggregate/AggregatorBase.java b/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/aggregate/AggregatorBase.java
index 65355f3..919746d 100644
--- a/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/aggregate/AggregatorBase.java
+++ b/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/aggregate/AggregatorBase.java
@@ -95,21 +95,6 @@ public abstract class AggregatorBase implements Aggregator
         return copy(e) ;
     }
     
-    @Override
-    public String asSparqlExpr(SerializationContext sCxt) {
-        IndentedLineBuffer x = new IndentedLineBuffer() ;
-        x.append(getName()) ;
-        x.append("(") ;
-        if ( isDistinct )
-            x.append("DISTINCT") ;
-        if ( getExprList() != null ) {
-            x.append(" ");
-            ExprUtils.fmtSPARQL(x, getExprList(), sCxt) ;
-        }
-        x.append(")") ;
-        return x.asString() ;
-    }
-    
     /** Many aggergate use a single expression.
      *  This convebnience operation gets the expression if there is exactly one.
      */
@@ -129,6 +114,19 @@ public abstract class AggregatorBase implements Aggregator
     public String toString()                { return asSparqlExpr(null) ; }
 
     @Override
+    public String asSparqlExpr(SerializationContext sCxt) {
+        IndentedLineBuffer x = new IndentedLineBuffer() ;
+        x.append(getName()) ;
+        x.append("(") ;
+        if ( isDistinct )
+            x.append("DISTINCT ") ;
+        if ( getExprList() != null )
+            ExprUtils.fmtSPARQL(x, getExprList(), sCxt) ;
+        x.append(")") ;
+        return x.asString() ;
+    }
+
+    @Override
     public String toPrefixString() {
         IndentedLineBuffer x = new IndentedLineBuffer() ;
         x.append("(") ;


[4/4] jena git commit: Bug fix for repeated use of transformation in ExprLists

Posted by an...@apache.org.
Bug fix for repeated use of transformation in ExprLists

Project: http://git-wip-us.apache.org/repos/asf/jena/repo
Commit: http://git-wip-us.apache.org/repos/asf/jena/commit/66efb4f6
Tree: http://git-wip-us.apache.org/repos/asf/jena/tree/66efb4f6
Diff: http://git-wip-us.apache.org/repos/asf/jena/diff/66efb4f6

Branch: refs/heads/master
Commit: 66efb4f658e5c227c29cba0f3f8d1b186a28bd10
Parents: 748180a
Author: Andy Seaborne <an...@apache.org>
Authored: Sun Dec 28 19:04:29 2014 +0000
Committer: Andy Seaborne <an...@apache.org>
Committed: Sun Dec 28 19:04:29 2014 +0000

----------------------------------------------------------------------
 .../java/com/hp/hpl/jena/sparql/expr/ExprTransformer.java   | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/jena/blob/66efb4f6/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/ExprTransformer.java
----------------------------------------------------------------------
diff --git a/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/ExprTransformer.java b/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/ExprTransformer.java
index b6c4271..ac1db00 100644
--- a/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/ExprTransformer.java
+++ b/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/ExprTransformer.java
@@ -72,9 +72,12 @@ public class ExprTransformer
         
         final Expr result()
         { 
-            if ( stack.size() != 1 )
-                Log.warn(this, "Stack is not aligned") ;
-            return stack.peek() ; 
+            if ( stack.size() != 1 ) {
+                Log.warn(this, "Stack is not aligned (size = "+stack.size()+")") ;
+                if ( stack.isEmpty() )
+                    return null ;
+            }
+            return stack.pop() ; 
         }
 
         ApplyExprTransformVisitor(ExprTransform transform)