When a Jena-based reasoner is selected, methods of any class on the Java classpath can be wrapped in a SADL External equation and thereby be made available for use as built-ins in Jena rules. The arguments of the method and its return type must be XML datatypes that are compatible with Java data types. The XSD datatypes and their Java types currently supported are
The SADL implicit model (SadlImplicitModel.sadl) contains the definition of the External class, which is in the domain of the property externalUri. This property identifies the Java package, class, and method being wrapped. The SADL argument types and the return type are used to check for compatibility with the Java method at evaluation time. The actual Jena Literals passed in to the method on evaluation are translated to the appropriate Java instances for a Java reflection invocation of the method. The Java package referenced must be on the Java classpath in order to be found by the reflection invocation. Java classes not on the SADL IDE classpath can be wrapped in an Eclipse plug-in and made available, as described below.
Here are a number of examples of External declarations that use common Java classes and methods.
External indexOf(string str, string match) returns int : "java.lang.String.indexOf".
External substring(string str, int start) returns string : "java.lang.String.substring".
Rule R1: if x is a URI and y is ^uri of x then ln of x is substring(y, indexOf(y, "#") + 1).
External formatString(string fmt, ...) returns string : "java.lang.String.format".
The SADL Expr statement can be used to test an External that wraps a Java class method. Note that the reasoner is not invoked and the arguments in the Expr statement must be simple primitive data values, not more complex expressions such as triple patterns. The External with the provided arguments is evaluated and the result displayed as an Info marker on that line in the editor window. For each of the methods in the examples above, shown are an Expr statement that tests the External along with the evaluation results.
Expr: random(). // Evaluates to: 0.673450890873411
Expr: booleanToString(false). // Evaluates to: "false"
Expr: doubleCompare(3.14159, 3.141591). // Evaluates to: -1
Expr: formatString("name is %s", "sonoo"). // Evaluates to: "name is sonoo"
Expr: formatString("value is %f",32.33434). // Evaluates to: "value is 32.334340"
Expr: formatString("value is %32.12f",32.33434). // Evaluates to: "value is 32.334340000000"
Expr: formatString("value is %32.12f
is not null is %b", 32.33434, 23.456).
// Evaluates to:
"value
32.334339141846 is not null is true"
Expr:
formatString("value is %32.12f != %f", 32.33434, 23.456).
//
Evaluates
to: "value is 32.334340000000 != 23.456000"
All of the examples above use Java classes that are normally on the Java classpath. In order to wrap Java classes not already on the classpath, it is necessary to make them available to the Eclipse class loader of the plug-in invoking the external Java class method, the Jena reasoner plug-in. This is accomplished by placing the new class(es) in a separate Eclipse plug-in and making that plug-in's class(es) visible to the reasoner's class loader. Either existing jar files or custom Java classes can be placed in an Eclipse plug-in project. Once properly placed in an Eclipse plug-in, the plug-in can be added to the Eclipse SADL environment and the classes and methods can be referenced in SADL External equations. Note that this is an alternative to developing custom Jena built-ins that extend the Jena BaseBuiltin class, see Creating and Deploying Custom Jena Built-ins.
As an example of how to create an Eclipse plug-in providing the code for a SADL External equation, we will walk through developing and deploying a class and method to increment an input integer by 2. The SADL External equation definition, the test Expr[ession], and a rule using the equation are as follows.
Expr: increment(3).
Rule R1: if x is a ^Rule then print(x, increment(3)).
Ask: select r where r is a ^Rule. // this is just to allow testing of the model
The result of the Expr statement will be displayed as an Info marker:
We start the development by creating a plug-in project. The Java class and method to be executed are shown below.
package com.naturalsemantics.sadl.builtin.increment;
public class Increment {
public int increment(int i) {
return i+2;
}
}
The content of the plug-in project's META_INF/MANIFEST.MF file are essential to its function. It must contain the following lines, which allow the SADL's reasoner classloader to find the new class.
Require-Bundle:
com.ge.research.sadl.jena-wrapper-for-sadl
Eclipse-RegisteredBuddy: com.ge.research.sadl.jena-wrapper-for-sadl
The first line indicates that this plug-in is not valid unless the plug-in identified in Require-Bundle is installed.
The second line indicates that this plug-in has the reasoner plug-in as an Eclipse buddy, meaning that the reasoner plug-in's class loader will look in this bundle.
The third line exports the
package containing our class and method so that they will be visible to
the reasoner's class loader.
In order to be able to install the plug-in into an Eclipse SADL IDE, it is also necessary to create an Eclipse feature project that references our plug-in project. Finally, the feature must be added to an Eclipse update project. Once this is completed, the update site can be built and the update used to install the new plug-in into the Eclipse SADL IDE.
The three projects that implement this example are available for download in this ZIP file.