You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@jena.apache.org by Rob Hall <an...@apache.org> on 2014/07/09 18:18:18 UTC

CMS diff: writing_propfuncs.mdtext

Clone URL (Committers only):
https://cms.apache.org/redirect?new=anonymous;action=diff;uri=http://jena.apache.org/documentation%2Fquery%2Fwriting_propfuncs.mdtext

Rob Hall

Index: trunk/content/documentation/query/writing_propfuncs.mdtext
===================================================================
--- trunk/content/documentation/query/writing_propfuncs.mdtext	(revision 0)
+++ trunk/content/documentation/query/writing_propfuncs.mdtext	(working copy)
@@ -0,0 +1,141 @@
+Title: ARQ - Writing Property Functions
+Notice:    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.
+
+**ARQ - Writing Property Functions**
+
+See also [Writing Filter Functions](writing_functions.html).
+
+Applications can add SPARQL property functions to the query engine. This is done by first implementing the
+ [`PropertyFunction`](http://jena.apache.org/documentation/javadoc/arq/com/hp/hpl/jena/sparql/pfunction/PropertyFunction.html)
+ interface, and then either registering that function or using the fake `java:` URI scheme to dynamically
+ load the function.
+
+**Writing SPARQL Property Functions**
+
+Similar to SPARQL Filter Functions, a SPARQL Property Function is an extension point of the SPARQL query language
+ that allows a URI to name a function in the query processor. A key difference is that Property Functions may
+ generate new bindings.
+
+Just like
+ [com.hp.hpl.jena.sparql.function.Function](http://jena.apache.org/documentation/javadoc/arq/com/hp/hpl/jena/sparql/function/Function.html)
+ there are various utility classes provided to simplify the creation of a Property Function. The selection of
+ one depends on the 'style' of the desired built-in. For example, `PFuncSimple` is expected to be the predicate
+ of triple patterns `?such ex:as ?this`, where neither argument is an `rdf:list`, and either may be a variable.
+ Alternatively, `PFuncAssignToObject` assumes that the subject will be bound, while the object will be a variable.
+
+    PropertyFunction
+        |
+        |--PropertyFunctionBase
+              |
+              |--PropertyFunctionEval
+                    |
+                    |--PFuncSimpleAndList
+                    |
+                    |--PFuncSimple
+                         |
+                         |--PFuncAssignToObject
+                         |
+                         |--PFuncAssignToSubject
+
+The choice of extension point determines the function signature that the developer will need to implement, and
+ primarily determines whether some of the arguments will be 
+ [`com.hp.hpl.jena.graph.Node`](https://jena.apache.org/documentation/javadoc/jena/com/hp/hpl/jena/graph/Node.html)s or 
+ [`com.hp.hpl.jena.sparql.pfunction.PropFuncArg`](http://jena.apache.org/documentation/javadoc/arq/com/hp/hpl/jena/sparql/pfunction/PropFuncArg.html)s.
+ In the latter case, the programmer can determine whether the argument is a list as well as how many
+ arguments it consists of.
+
+
+**Registration**
+
+Every property function is associated with a particular 
+ [`com.hp.hpl.jena.sparql.util.Context`](http://jena.apache.org/documentation/javadoc/arq/com/hp/hpl/jena/sparql/util/Context.html).
+ This allows you to limit the availability of the function to be global or associated with a particular dataset.
+ For example, a custom Property Function may expose an index which only has meaning with respect to some set
+ of data.
+
+Assuming you have an implementation of
+ [`com.hp.hpl.jena.sparql.pfunction.PropertyFunctionFactory`](http://jena.apache.org/documentation/javadoc/arq/com/hp/hpl/jena/sparql/pfunction/PropertyFunctionFactory.html) 
+ (shown later), you can register a function as follows:
+
+
+    final PropertyFunctionRegistry reg = PropertyFunctionRegistry.chooseRegistry(ARQ.getContext());
+    reg.put("urn:ex:fn#example", new ExamplePropertyFunctionFactory);
+    PropertyFunctionRegistry.set(ARQ.getContext(), reg);
+
+
+The only difference between global and dataset-specific registration is where the `Context` object comes from:
+
+    final Dataset ds = DatasetFactory.createMem();
+    final PropertyFunctionRegistry reg = PropertyFunctionRegistry.chooseRegistry(ds.getContext());
+    reg.put("urn:ex:fn#example", new ExamplePropertyFunctionFactory);
+    PropertyFunctionRegistry.set(ds.getContext(), reg);
+
+Note that 
+ [`com.hp.hpl.jena.sparql.pfunction.PropertyFunctionRegistry`](http://jena.apache.org/documentation/javadoc/arq/com/hp/hpl/jena/sparql/pfunction/PropertyFunctionRegistry.html)
+ has other `put` methods that allow registration by passing a `Class` object, as well.
+
+**Implementation**
+
+The implementation of a Property Function is actually quite straight forward once one is aware of the tools
+ at their disposal to do so. For example, if we wished to create a Property Function that returns no results
+ regardless of their arguments we could do so as follows:
+
+    public class ExamplePropertyFunctionFactory implements PropertyFunctionFactory {
+    	@Override
+    	public PropertyFunction create(final String uri)
+    	{	
+    		return new PFuncSimple()
+    		{
+    			@Override
+    			public QueryIterator execEvaluated(final Binding parent, final Node subject, final Node predicate, final Node object, final ExecutionContext execCxt) 
+    			{	
+                    return QueryIterNullIterator.create(execCtx);
+    			}
+    		};
+    	}
+    }
+
+`Node` and `PropFuncArg` objects allow the developer to reflect on the state of the arguments, and choose what
+ bindings to generate given the intended usage of the Property Function. For example, if the function expects a
+ list of three bound arguments for the object of the property, then it can throw a `ExprEvalException`
+ (or derivative) to indicate incorrect use. It is the responsability of the developer to identify what parts
+ of the argument are bound, and to respond appropriately.
+
+For example, if `?a ex:f ?b` were a triple pattern in a query, it could be called with `?a` bound, `?b` bound,
+ or neither. It may make sense to return new bindings that include `?b` if passed a concrete value for `?a`,
+ or conversely to generate new bindings for `?a` when passed a concrete `?b`. If both `?a` and `?b` are bound,
+ and the function wishes to confirm that the pairing is valid, it can return the existing binding. If there are
+ no valid solutions to return, then an empty solution may be presented.
+
+There are several extremely useful implementations of `QueryIterator` within the Jena library that make it
+easy to support typical use cases.
+
+Of particular note:
+
+  - [`QueryIterNullIterator`](https://jena.apache.org/documentation/javadoc/arq/com/hp/hpl/jena/sparql/engine/iterator/QueryIterNullIterator.html) - to indicate that there are no valid solutions/bindings for the given values
+  - [`QueryIterSingleton`](https://jena.apache.org/documentation/javadoc/arq/com/hp/hpl/jena/sparql/engine/iterator/QueryIterSingleton.html) - to provide a single solution/binding for the given values
+  - [`QueryIterPlainWrapper`](http://jena.apache.org/documentation/javadoc/arq/com/hp/hpl/jena/sparql/engine/iterator/QueryIterPlainWrapper.html) - to provide multiple solutions/bindings for the given values
+
+The second two cases require instances of `Binding` objects which can be obtained through static methods of
+ [`BindingFactory`](http://jena.apache.org/documentation/javadoc/arq/com/hp/hpl/jena/sparql/engine/binding/BindingFactory.html).
+ Creation of `Binding` objects will also require references to [`Var`](https://jena.apache.org/documentation/javadoc/arq/com/hp/hpl/jena/sparql/core/Var.html)
+ and [`NodeFactory`](https://jena.apache.org/documentation/javadoc/jena/com/hp/hpl/jena/graph/NodeFactory.html)
+
+Note that it can make a lot of sense to generate the `Iterator<Binding>` for `QueryIterPlainWrapper` by means of
+ Jena's `ExtendedIterator`. This can allow domain-specific value to be easily mapped to `Binding` objects in
+ a lazy fashion.
\ No newline at end of file

Property changes on: trunk/content/documentation/query/writing_propfuncs.mdtext
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property