Fabien GANDON,
Fabien.Gandon@sophia.inria.fr
Priscille Durville,
Priscille.Durville@sophia.inria.fr
Our team uses and maintains a SPARQL search engine named "Corese"
Sewese is a Java 5 application and hasto be embedded in webapps deployed on a servlet container
It can be deployed under Tomcat 5.5.x and uses Servlet API 2.4, JSP 2.0 and the standard JSP Tag library 1.1.2.
It uses the following opensource libraries:
XML technologies for every non-java files (e.g JSPX, XSL, XML).
Relying as much as possible
Sewese provides a set of filters, servlets, JSP tags and libraries as well as some templates to build new applications ; it is organized around four main types of components:
Toolkits:
Filters: provide mechanisms to implement transversal processing on requests and response
e.g. maintain context variable about the user's profile using parameterized SPARQL queries
JSP Lib: (Semtags)
Servlets: implement responses requiring important processing
e.g. a servlet implements the update of a class in an existing ontology
The first thing to do is to initialize at least one Corese instance to load annotations and ontologies.
00 01 02 03 04 05 | <c:if test="${empty applicationScope['defaultEngineWrapper']}"> <stl:init ontoDir="WEB-INF/data/schemas" annotDir="WEB-INF/data/annotations" ruleDir="WEB-INF/data/rules" humans="http://www.inria.fr/2007/04/17/humans.rdfs#" /> </c:if> |
Several tags to run SPARQL queries but most useful one is a JSP loop tag to directly iterate over the results
01 02 03 04 05 | <ul> <stl:for-each-result query="SELECT ?name WHERE { ?x humans:name ?name }"> <li>${name}</li> </stl:for-each-result> </ul> |
There is also a function to quickly send a query and obtain the first value of the first result:
01 02 03 | <c:set var="myQuery" value="SELECT ?age WHERE { ?x humans:name 'John' . ?x humans:age ?age }" /> John is ${stl:quickQuery(pageContext,myQuery)}-year old. |
Equivalents of the classical if and choose tags but using SPARQL queries as test.
01 02 03 04 05 06 07 08 09 10 11 12 | <stl:for-each-result query="SELECT ?x ?name ?age WHERE { ?x humans:name ?name . OPTIONAL { ?x humans:age ?age } }"> <li> <stl:choose> <stl:when test="ASK { <${x}> rdf:type humans:Female }"> <span style="color: red">${name}</span></stl:when> <stl:when test="ASK { <${x}> rdf:type humans:Male }"> <span style="color: blue">${name}</span></stl:when> <stl:otherwise>${name}</stl:otherwise> </stl:choose> <c:if test="${!empty age}"> (${age})</c:if> </li> </stl:for-each-result> |
There are functions to access the schemas.
01 02 03 04 05 06 07 | <ul> <stl:for-each-child root="http://www.inria.fr/2007/04/17/humans.rdfs#Animal" var="current"> <li>${stl:label(pageContext, current, 'en', true)} (${stl:allInstanceNb(pageContext, current)})</li> </stl:for-each-child> </ul> |
Identify the roots.
01 02 03 04 05 | <ul> <stl:for-each-root-concept var="current"> <li>${stl:label(pageContext, current, 'en', true)}</li> </stl:for-each-root-concept> </ul> |
Tags to modify RDF/XML files.
01 02 03 04 05 06 07 08 09 10 | <stl:modify-annot kind="replace" xpath="/rdf:RDF/humans:Person/humans:name[text()='${param['name_before']}']" forceUpdate="true" file="human_2007_04_17.rdf" humans="http://www.inria.fr/2007/04/17/humans.rdfs#" rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"> <humans:name xmlns:humans="http://www.inria.fr/2007/04/17/humans.rdfs#"> ${param['name_after']} </humans:name> </stl:modify-annot> |
Many other tags ; see online API doc.
Including also Corese goodies such as...
My watch has one hand... but it's not a bug... it's a feature!
In IR precision and logical truth are not always the main criteria.
Corese allows us to relax typing constraints (e.g. "handout" vs. "tutorial") using the length of the paths between types to evaluate the "cost" of the approximation.
Query with approximation.
01 02 03 | <stl:for-each-result query="SELECT MORE ?name WHERE { ... }"> <li>${name} was found with a similarity of ${similarity}</li> </stl:for-each-result> |
NB: Corese and Sewese will both become open source with a free licence next month