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/29 17:46:44 UTC

[3/3] jena git commit: JENA-803 : Example custom aggregate

JENA-803 : Example custom aggregate

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

Branch: refs/heads/master
Commit: 6537629d8a1c6f03810612321327e4dbc96f0dfa
Parents: a01534e
Author: Andy Seaborne <an...@apache.org>
Authored: Mon Dec 29 16:42:43 2014 +0000
Committer: Andy Seaborne <an...@apache.org>
Committed: Mon Dec 29 16:42:43 2014 +0000

----------------------------------------------------------------------
 .../examples/aggregates/CustomAggregate.java    | 113 +++++++++++++++++++
 1 file changed, 113 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/jena/blob/6537629d/jena-arq/src-examples/arq/examples/aggregates/CustomAggregate.java
----------------------------------------------------------------------
diff --git a/jena-arq/src-examples/arq/examples/aggregates/CustomAggregate.java b/jena-arq/src-examples/arq/examples/aggregates/CustomAggregate.java
new file mode 100644
index 0000000..2650508
--- /dev/null
+++ b/jena-arq/src-examples/arq/examples/aggregates/CustomAggregate.java
@@ -0,0 +1,113 @@
+/**
+ * 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 arq.examples.aggregates;
+
+import org.apache.jena.atlas.logging.LogCtl ;
+
+import com.hp.hpl.jena.graph.Graph ;
+import com.hp.hpl.jena.query.* ;
+import com.hp.hpl.jena.rdf.model.ModelFactory ;
+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.aggregate.Accumulator ;
+import com.hp.hpl.jena.sparql.expr.aggregate.AccumulatorFactory ;
+import com.hp.hpl.jena.sparql.expr.aggregate.AggCustom ;
+import com.hp.hpl.jena.sparql.expr.aggregate.AggregateRegistry ;
+import com.hp.hpl.jena.sparql.function.FunctionEnv ;
+import com.hp.hpl.jena.sparql.graph.NodeConst ;
+import com.hp.hpl.jena.sparql.sse.SSE ;
+
+/**
+ * Custom aggregate example.
+ * <p>
+ * Custom aggregates must be registered before parsing the query; custom
+ * aggregates and custom functions have the same syntax so the to tell the
+ * differenc, the parser needs to know which IRIs are custom aggregates.
+ * <p>
+ * The aggregate is registered as a URI, AccumulatorFactory and default value
+ * for the "no groups" case.
+ */
+public class CustomAggregate {
+    static { LogCtl.setCmdLogging(); }
+    /**
+     * Execution of a custom aggregate is with accumulators. One accumulator is
+     * created for the factory for each group in a query execution.
+     */
+    static AccumulatorFactory myAccumulatorFactory = new AccumulatorFactory() {
+        @Override
+        public Accumulator createAccumulator(AggCustom agg) { return new MyAccumulator(agg) ; }
+    } ;
+    
+    /**
+     * Example accumulators - counts the number of valid literals
+     * of an expression over a group. 
+     */
+    static class MyAccumulator implements Accumulator {
+        int count = 0 ;
+        private AggCustom agg ;
+        MyAccumulator(AggCustom agg) { this.agg = agg ; }
+
+        /** Function called on each row in a group */
+        @Override
+        public void accumulate(Binding binding, FunctionEnv functionEnv) {
+            ExprList exprList = agg.getExprList() ;
+            for(Expr expr: exprList) {
+                try {
+                    NodeValue nv = expr.eval(binding, functionEnv) ;
+                    // Evaluation succeeded.
+                    if ( nv.isLiteral())
+                        count ++ ;
+                } catch (ExprEvalException ex) {}
+            }
+        }
+
+        /** Function called to retrieve the value for a single group */
+        @Override
+        public NodeValue getValue() {
+            return NodeValue.makeInteger(count) ;
+        }
+    }
+    
+    public static void main(String[] args) {
+        
+        // Example aggregate that counts literals.
+        // Returns unbound for no rows. 
+        String aggUri = "http://example/countLiterals" ;
+        
+        
+        /* Registration */
+        AggregateRegistry.register(aggUri, myAccumulatorFactory, NodeConst.nodeMinusOne);
+        
+        
+        // Some data.
+        Graph g = SSE.parseGraph("(graph (:s :p :o) (:s :p 1))") ;
+        String qs = "SELECT (<http://example/countLiterals>(?o) AS ?x) {?s ?p ?o}" ;
+        
+        // Execution as normal.
+        Query q = QueryFactory.create(qs) ;
+        try ( QueryExecution qexec = QueryExecutionFactory.create(q, ModelFactory.createModelForGraph(g)) ) {
+            ResultSet rs = qexec.execSelect() ;
+            ResultSetFormatter.out(rs);
+        }
+    }
+    
+}