SPARQL to SPIN Converter

In this tutorial we create a SPARQL to SPIN converter using the Topraid SPIN API. Furthermore we use Apache Jena and Maven to setup a simple FileChooser UI to convert a selected SPARQL Query.

SPIN is a de-facto industry standard to represent SPARQL, rules and constraints on Semantic Web models. Among others, SPIN is used to:

  1. Calculate the value of a property based on other properties:
    • Caluclate the area of a geometric figure as a product of its height and width
    • Caluclate the age of a person as a difference between today’s date and person’s birthday date
  2. Isolate a set of rules to be executed under certain conditions:
    • Support incremental reasoning, to initialize certain values when a resource is first created
  3. Constraint checking
  4. Definition of new SPARQL functions

1. Prerequisites

  1. SPIN API:  Download SPIN 1.4
  2. Apache Jena: Download Jena
  3. Optional: Install Maven

2. Project Setup

  1. Without Maven:
    • Create a standard Java project
    • Include the SPIN and Jena JAR files in your classpath
  2. Create a Maven project and adapt the POM file with the following code
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    	<modelVersion>4.0.0</modelVersion>
    
    	<groupId>com.tutorialacademy.rdf</groupId>
    	<artifactId>spin</artifactId>
    	<version>0.0.1-SNAPSHOT</version>
    	<packaging>jar</packaging>
    
    	<name>spin</name>
    	<url>http://maven.apache.org</url>
    
    	<properties>
    		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    	</properties>
    
    	<dependencies>
    	
    		<dependency>
    			<groupId>org.topbraid</groupId>
    			<artifactId>spin</artifactId>
    			<version>1.4.0</version>
    		</dependency>
    
    		<dependency>
    			<groupId>org.apache.jena</groupId>
    			<artifactId>apache-jena-libs</artifactId>
    			<type>pom</type>
    			<version>2.11.0</version>
    		</dependency>
    		
    	</dependencies>
    
    	<repositories>
    	
    		<repository>
    			<id>org.topbraid</id>
    			<url>http://topquadrant.com/repository/spin</url>
    		</repository>
    		
    	</repositories>
    	
    </project>
    

    Update or rebuild your project to download the required libraries. Afterwards create a package and create a Java class called SPARQL2SPINConverter. The necessary code is provided in the next chapter.

3. Code Example

The following example will open a FileChooser UI to select a SPARQL rule that should be converted to the SPIN syntax. We use the following SPARQL query stored in sparqlQuery.txt:

PREFIX ta:      <https://tutorial-academy.com/2015/spin#>
PREFIX sp:      <http://spinrdf.org/sp#> 
PREFIX rdf:     <http://www.w3.org/1999/02/22-rdf-syntax-ns#> 

SELECT ( ( AVG ( ?value ) ) AS ?average ) ?sensor
WHERE
{
	?measurement 	rdf:type 		ta:Measurement .
    ?measurement 	ta:timestamp 	?timestamp .
    ?measurement 	ta:value 		?value .
    ?measurement 	ta:sensor 		?sensor .
}
GROUP BY ( ?sensor )
ORDER BY DESC ( ?average )

The necessary Java code is shown below:

package com.tutorialacademy.rdf.spin;

import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Paths;

import javax.swing.JFileChooser;
import javax.swing.JFrame;

import org.topbraid.spin.arq.ARQ2SPIN;
import org.topbraid.spin.arq.ARQFactory;
import org.topbraid.spin.model.Select;
import org.topbraid.spin.system.SPINModuleRegistry;

import com.hp.hpl.jena.query.Query;
import com.hp.hpl.jena.rdf.model.Model;
import com.hp.hpl.jena.rdf.model.ModelFactory;
import com.hp.hpl.jena.util.FileUtils;

/**
 * Converts between textual SPARQL representation and SPIN RDF model.
 */
public class SPARQL2SPINConverter 
{
	public static String readFile( String path, Charset encoding )  
	{
		byte[] encoded = null;
		try
		{
			encoded = Files.readAllBytes( Paths.get( path ) );
		} catch (IOException e)
		{
			e.printStackTrace();
		}
		return new String( encoded, encoding );
	}
	
	public static void main(String[] args) 
	{
		// Register system functions
		SPINModuleRegistry.get().init();
		
		// Create an empty OntModel
		final Model model = ModelFactory.createDefaultModel();
		
		// FileChooser UI
		JFrame frame = new JFrame( "SPARQL2SPIN Converter" );
		frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
		Container contentPane = frame.getContentPane();

		JFileChooser fileChooser = new JFileChooser(".");
		fileChooser.setControlButtonsAreShown( false );
		contentPane.add( fileChooser, BorderLayout.CENTER );

		ActionListener actionListener = new ActionListener() 
		{
			public void actionPerformed( ActionEvent actionEvent ) 
			{
				model.removeAll();
				JFileChooser theFileChooser = (JFileChooser) actionEvent.getSource();
				String command = actionEvent.getActionCommand();
				if ( command.equals( JFileChooser.APPROVE_SELECTION ) ) 
				{
					File selectedFile = theFileChooser.getSelectedFile();
					
					// read rule
					String query = readFile( selectedFile.getAbsolutePath(), Charset.defaultCharset() );
					
					Query arqQuery = ARQFactory.get().createQuery( model, query );
					ARQ2SPIN arq2SPIN = new ARQ2SPIN( model );
					Select sparqlQuery = (Select) arq2SPIN.createQuery( arqQuery, null );
					
					System.out.println( "SPARQL Query:\n" + sparqlQuery );
					System.out.println( "\nSPIN Representation:" );
					model.write( System.out, FileUtils.langTurtle );
				} 
			}
		};
		
		fileChooser.addActionListener( actionListener );

		frame.pack();
		frame.setVisible(true);
	}
}

Now you can execute the Java code and select the sparqlQuery.txt file.

SPARQL2SPIN Converter
SPARQL2SPIN Converter

Doubleclick the specified SPARQL query and check the console output of your Java programm. You should see something like:

SPARQL Query:
SELECT ((AVG(?value)) AS ?average) ?sensor
WHERE {
    ?measurement a <https://tutorial-academy.com/2015/spin#Measurement> .
    ?measurement <https://tutorial-academy.com/2015/spin#timestamp> ?timestamp .
    ?measurement <https://tutorial-academy.com/2015/spin#value> ?value .
    ?measurement <https://tutorial-academy.com/2015/spin#sensor> ?sensor .
}
GROUP BY ?sensor
ORDER BY DESC (?average)

SPIN Representation:
[ a                              <http://spinrdf.org/sp#Select> ;
  <http://spinrdf.org/sp#groupBy>
          ( [ <http://spinrdf.org/sp#varName>
                    "sensor"^^<http://www.w3.org/2001/XMLSchema#string> ] ) ;
  <http://spinrdf.org/sp#orderBy>
          ( [ a       <http://spinrdf.org/sp#Desc> ;
              <http://spinrdf.org/sp#expression>
                      [ <http://spinrdf.org/sp#varName>
                                "average"^^<http://www.w3.org/2001/XMLSchema#string> ]
            ] ) ;
  <http://spinrdf.org/sp#resultVariables>
          ( [ <http://spinrdf.org/sp#expression>
                      [ a       <http://spinrdf.org/sp#Avg> ;
                        <http://spinrdf.org/sp#expression>
                                [ <http://spinrdf.org/sp#varName>
                                          "value"^^<http://www.w3.org/2001/XMLSchema#string> ]
                      ] ;
              <http://spinrdf.org/sp#varName>
                      "average"^^<http://www.w3.org/2001/XMLSchema#string>
            ] [ <http://spinrdf.org/sp#varName>
                    "sensor"^^<http://www.w3.org/2001/XMLSchema#string> ] ) ;
  <http://spinrdf.org/sp#where>  ( [ <http://spinrdf.org/sp#object>  <https://tutorial-academy.com/2015/spin#Measurement> ;
                                     <http://spinrdf.org/sp#predicate>
                                             <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> ;
                                     <http://spinrdf.org/sp#subject>
                                             [ <http://spinrdf.org/sp#varName>
                                                       "measurement"^^<http://www.w3.org/2001/XMLSchema#string> ]
                                   ] [ <http://spinrdf.org/sp#object>  [ <http://spinrdf.org/sp#varName>
                                                         "timestamp"^^<http://www.w3.org/2001/XMLSchema#string> ] ;
                                       <http://spinrdf.org/sp#predicate>
                                               <https://tutorial-academy.com/2015/spin#timestamp> ;
                                       <http://spinrdf.org/sp#subject>
                                               [ <http://spinrdf.org/sp#varName>
                                                         "measurement"^^<http://www.w3.org/2001/XMLSchema#string> ]
                                     ] [ <http://spinrdf.org/sp#object>  [ <http://spinrdf.org/sp#varName>
                                                           "value"^^<http://www.w3.org/2001/XMLSchema#string> ] ;
                                         <http://spinrdf.org/sp#predicate>
                                                 <https://tutorial-academy.com/2015/spin#value> ;
                                         <http://spinrdf.org/sp#subject>
                                                 [ <http://spinrdf.org/sp#varName>
                                                           "measurement"^^<http://www.w3.org/2001/XMLSchema#string> ]
                                       ] [ <http://spinrdf.org/sp#object>  [ <http://spinrdf.org/sp#varName>
                                                             "sensor"^^<http://www.w3.org/2001/XMLSchema#string> ] ;
                                           <http://spinrdf.org/sp#predicate>
                                                   <https://tutorial-academy.com/2015/spin#sensor> ;
                                           <http://spinrdf.org/sp#subject>
                                                   [ <http://spinrdf.org/sp#varName>
                                                             "measurement"^^<http://www.w3.org/2001/XMLSchema#string> ]
                                         ] )
] .

Now you converted an existing SPARQL query into the SPIN syntax representation.

If you have problems or questions, feel free to comment.

Facebooktwitterredditpinterestlinkedinmail

Related posts

Leave a Comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.