Tuesday, September 14, 2010

Registering Custom SPARQL Functions

The Semantics Platform allows custom SPARQL functions to be registered with a client model. Once a function has been registered it can be used in a SPARQL query using the URI it was registered with. A custom SPARQL function can be implemented as a static method on a .NET class that has the proper delegate type. The Semantics Platform enables all the custom SPARQL functions in an assembly to be loaded provided they are declared with the proper attributes.

The example below shows a custom SPARQL function implemented in C# that supports the delegate type (ClientFunctionCall). The function calculates the area of a circle based on a single argument that represents the radius. The function checks that the proper number of arguments are provided. It calculates the area and returns it as the result argument. If the function is called with a result argument set to a value then it must be compared to the calculated area to see if the expression evaluates to true. The function should return false if the function fails to generate a value or the comparison fails.

[ClientFunctionAttribute(
    "http://example.org/fn/areaOfCircle", 
    "[bf]b", 
    Deterministic=true)]
public static bool AreaOfCircleFunction(
    FunctionCallParams funcParams)
{
    TableRow funcArgValues = funcParams.ArgRow;

    // Make sure we have exactly 2 arguments in 
    // our arguments collection.
    //
    // index 0: The result value
    // index 1: The radius
    if (funcArgValues.Count == 2 && 
        funcArgValues[1] != null && 
        funcArgValues[1] is RdfLiteral && 
        ((RdfLiteral)funcArgValues[1]).IsNumeric)
    {
        // A = PI * R^2
        double area = Math.PI * Math.Pow(
            (double)(RdfLiteral)funcArgValues[1], 2);

        RdfLiteral resultValue = area;

        // If a result value was provided (index 0) 
        // then test for equality.
        if (RdfValue.IsNull(funcArgValues[0]) || 
            funcArgValues[0] == resultValue)
        {
            funcArgValues[0] = resultValue;
            return true;
        }
    }

    return false; //evaluated as false
}

Notice, the method is declared with an attribute called ClientFunctionAttribute. This attribute requires a URI to identify the SPARQL function and a binding pattern. A binding pattern is a form of a regular express where ‘b’ represents a bound argument and ‘f’ represents an unbound argument (aka free). In the example above the binding pattern ‘[bf]b’ indicates the result argument can be bound or free and the first argument must be bound. The method attribute is also sets the property Deterministic to true to indicate it is a deterministic function.

One way to register the custom SPARQL function is using the Model Manager. Open a model, new or existing, and right click on the Functions folder to display the menu and select ‘Load Assembly…’.

image

This will display the dialog box shown above. Simply browse and select the assembly file that contains the custom SPARQL function(s). The dialog will display all the methods found in the assembly that are declared with the proper attribute and delegate type. You may select specific SPARQL functions to load or just load them all.

Once loaded they may be used in a SPARQL query using the Model Manager query window as shown below. The function is called using the URI it was registered with.

image

The custom functions assembly can also be loaded via the Semantics Platform .NET API using the helper class ClientFunctionLoader. This class will create the required class for registering a SPARQL function with an instance of a ClientModel. The C# code below provides and example of its use.

ClientModel model = new ClientModel();

ClientFunctionLoader loader = new ClientFunctionLoader(
    "c:\\SPARQL\\CustomFunctions.dll");

foreach (RdfUri uri in loader.FunctionUris)
{
    model.RegisterFunction(uri, loader.CreateFunction(uri));
}

This is the easiest way to register a custom SPARQL function.

0 comments:

Post a Comment