Home
Categories
Dictionary
Glossary
Download
Project Details
Changes Log
What Links Here
FAQ
License

Jena custom functions



Two services of the Jena module allow to ask a SPARQL request:
  • The owlRequest service allow to ask a query and get the results as text or in the XML format
  • The http://dassault-aviation.com/jena:owlObjectRequest service allow to ask a query and get the results as objects
The list of functions allowed in the BIND or FILTER expressions is limited to the list specified in the SPARQL standard. However Jena allows to specify our own functions.

Use case

The SPARQL standard has a specified list of functions which can be used in the BIND or FILTER expressions. For example, it is possible to define a variable as the sume of two others such as:
      SELECT ?a ?length1 ?length2 ?sum
      WHERE {
         ?a rdf:type my:MyClass .
         ?a my:Length1 ?length1 .
         ?a my:Length2 ?length2 .
         BIND (?length1 + ?length2 as ?sum)
      }
However the list of these functions is limited. For example the sine and cosine functions are not handled out of the box. And of course complex custom functions are not.

For example, suppose that we have an ontology with the following class:
  • "Triangle": the concept of a circle This class has the following data properties:
    • "Hypothenuse": the length of the hypothenuse of the triangle (and xsd:decimal property)
    • "Angle": the angle of the hypothenuse (and xsd:decimal property)
Suppose that we want to get all the Triangles in our ontology and return the opposite side length. The properformula is of course: opposite = Hypothenuse * sine(Angle).

We can't use this in SPARQL because the sine function is not handled by SPARQL. But we will be able to define an opposite function with two arguments and then specify the following SPARQL query:
      SELECT ?triangle ?hypothenuse ?opposite
      WHERE {
         ?triangle rdf:type my:Triangle .
         ?triangle my:Hypothenuse ?hypothenuse .
         ?triangle my:Angle ?angle .
         BIND (my:opposite(?hypothenuse, ?angle) as ?opposite)
      }
Or we can rather the sine function with one argument and perform:
      SELECT ?triangle ?hypothenuse ?opposite
      WHERE {
         ?triangle rdf:type my:Triangle .
         ?triangle my:Hypothenuse ?hypothenuse .
         ?triangle my:Angle ?angle .
         BIND (?hypothenuse * my:sine(?angle) as ?opposite)
      }
Note that in this example I used the same prefix for the function as for my ontology but it is not mandatory, for example I could use a specific math prefix instead if I wanted to.

Defining custom functions

To define custom functions to use in queries, you need to specify the customFunctions property in the Jena module. The value of the property will be an XML file specifying the function factories to use in queries.

CustomFunctions grammar

See the grammar for the custom functions schema.

CustomFunctions structure

The customFunctions XML file defines one or more factory or factoryPath elements. The factories must implement the FunctionFactory interface and define one or several functions which will be available in SPARQL queries.

Note that the Jar files containing the factories must be provided in the Jena application library or in the shared libraries.

Factory element

A factory element has the following attributes:
  • name: the name of the factory
  • path: the path of the factory class. This class must implement the Jena FunctionFactory interface
  • namespace: the namespace to use for the functions defined in the factory
  • prefix: the prefix to use for the factory functions
It also has function or uaFunction children for each function define by the factory. A function or uaFunction element has the following attributes:
  • name: the name of the function (this is the name which must be used in the SPARQL query)
  • countArguments: the expected number of arguments when calling the function. If this attribute is absent or is -1, the function will be able to handle any number of arguments


For example:
      <customFunctions>
         <factory name="mathFactory" path="org.da.protoframework.jena.testfunctions.MathFactory" prefix="math" namespace="http://www.dassault.aviation.com/math">
            <function name="opposite" countArguments="2" />
         </factory>
      </customFunctions>
Note that a limitation of function elements is that (as you can see), you can only use arguments from data properties passed to the function in the query. For example in our example the function can only use the hypothenuse and angle because there are two arguments in the function. By constrast uaFunction elements can invoke and subscribe to services.

FactoryPath element

A factoryPath element has the following attributes:
  • path: the path of Jar file containing the factory class
Contrary to factory elements, the name, namespace, and prefix elements, and the class to use for the factory will be specified in the Jar file manifest.

The manifest property called JenaFactoryConf must specify the path of an XML file in the Jar file using the customFunctions grammar, with only one factory.

For example, for the manifest file:
      JenaFactoryConf: org/da/protoframework/jena/testfunctions/customFunction.xml
      <customFunctions>
         <factory name="mathFactory" path="org.da.protoframework.jena.testfunctions.MathFactory" prefix="math" namespace="http://www.dassault.aviation.com/math">
            <function name="opposite" countArguments="2" />
         </factory>
      </customFunctions>

Function element


A function element must implement Jena Function interface. This function will be created by the factory by the FunctionFactory.create(String) method.

For example, suppose that we have a factory which manage our opposite function. We will have the following code for this factory:
      public class MyFactory implements FunctionFactory {
        public MyFactory() {
        }

        public Function create(String fctName) {
          if (fctName.equals("opposite") {
            return new oppositeFunction();
          } else {
            return null;
          }
        }
      }
We can have the following code for the opposite function:
      public class oppositeFunction extends FunctionBase2 {

        public oppositeFunction() {
          super();
        }

        public NodeValue exec(NodeValue hypothenusenv, NodeValue anglenv) {
          float hypothenuse = hypothenusenv.getFloat();
          float angle = anglenv.getFloat();
          float opposite = (float)(hypothenuse * Math.sin(angle));
          return NodeValue.makeFloat(opposite);
        }
      }
Note that a limitation of these functions is that (as you can see), you can only use arguments from data properties passed to the function in the query. For example in our example the function can only use the hypothenuse and angle because there are two arguments in the function. By constrast uaFunction elements can invoke and subscribe to services.

UaFunction element

Main Article: Jena uaFunctions

A uaFunction element is a function which will be able to invoke and subscribe to services in the framework to get results.

See also


Categories: builtin-applis

Copyright 2017-2020 Dassault Aviation. All Rights Reserved. Documentation and source under the LGPL v3 licence