From 472b26748ad2f34aa2a99494f1826f2df6d0dc3b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Euzenat?= <Jerome.Euzenat@inria.fr>
Date: Wed, 31 Mar 2010 08:43:56 +0000
Subject: [PATCH] - moved tutorial2 to tutorial4

---
 html/tutorial/index.html              |  17 +-
 html/tutorial/tutorial4/MyApp.java    | 408 +++++++++++++++++++++++++
 html/tutorial/tutorial4/Skeleton.java | 220 ++++++++++++++
 html/tutorial/tutorial4/index.html    | 413 ++++++++++++++++++++++++++
 html/tutorial/tutorial4/ontology1.owl | 309 +++++++++++++++++++
 html/tutorial/tutorial4/ontology2.owl | 311 +++++++++++++++++++
 6 files changed, 1669 insertions(+), 9 deletions(-)
 create mode 100644 html/tutorial/tutorial4/MyApp.java
 create mode 100644 html/tutorial/tutorial4/Skeleton.java
 create mode 100644 html/tutorial/tutorial4/index.html
 create mode 100644 html/tutorial/tutorial4/ontology1.owl
 create mode 100644 html/tutorial/tutorial4/ontology2.owl

diff --git a/html/tutorial/index.html b/html/tutorial/index.html
index 3ea793a4..ae15ccdc 100644
--- a/html/tutorial/index.html
+++ b/html/tutorial/index.html
@@ -54,7 +54,10 @@ take advatage of that API:
 <dt><a href="tutorial1/server.html">Manipulating alignments through a Web client</a></dt>
 <dd>Does most of what is done in the former tutorial but through an
   Web (HTTP) client using the Alignment server only.</dd>
-<dt><a href="tutorial2/index.html">Manipulating alignments in Java programs</a></dt>
+<dt><a href="tutorial3/embed.html">Manipulating alignments in Java programs (and embedding the Alignment API within an application</a></dt>
+<dd>Explains how an aplication
+  developer can embed the Alignment API within an application.</dd>
+<dt><a href="tutorial4/index.html">Exploiting alignments and reasoning</a></dt>
 <dd>This tutorial will learn you to:
 <ul>
 <li>communicate the alignment server
@@ -66,10 +69,6 @@ through its REST web service API,</li>
 </ul>
 It is based on Java programming and using various
 related APIs.</dd>
-<dt><a href="tutorial3/embed.html">Embedding the Alignment API
-  within an application</a></dt>
-<dd>Explains how an aplication
-  developer can embed the Alignment API within an application.</dd>
 <dt><a href="tutorial3/index.html">Extending the Alignment API with a new matcher</a></dt>
 <dd>Explains how an ontology matching developer can easily integrate
   its matcher within the Alignment API.</dd>
@@ -120,6 +119,7 @@ output" onclick="hide('qu3')"/></form></div-->
 	<input type="button" onclick="hide('qu3')" value="Hide output"/>
 </div>
 <div class="explain" id="qu3"><pre>
+Alignment API implementation 4.0
 usage: Procalign [options] URI1 URI2
 options are:
 	--impl=className -i classname		Use the given alignment implementation.
@@ -132,8 +132,6 @@ options are:
 	--debug[=n] -d [n]		Report debug info at level n
 	-Dparam=value			Set parameter
 	--help -h			Print this message
-
-Alignment API implementation 3.2 ($Id$)
 </pre></div>
 
 <p>The above command outputs the command line usage of the Procalign class. We do not detail it here, this tutorial will present it entirelly.</p>
@@ -160,8 +158,9 @@ Now you can go back to any of the tutorials:
 <ul>
 <li><a href="tutorial1/index.html">Using the Alignment API</a></li>
 <li><a href="tutorial1/server.html">Manipulating Alignments through a Web client</a></li>
-<li><a href="tutorial2/index.html">Manipulating alignments in Java programs</a></li>
-<li><a href="tutorial3/embed.html">Embedding the Alignment API within an application</a></li>
+<li><a href="tutorial3/embed.html">Manipulating alignments in Java
+    programs (and embedding the Alignment API within an application)</a></li>
+<li><a href="tutorial4/index.html">Exploiting alignments and reasoning</a></li>
 <li><a href="tutorial3/index.html">Extending the Alignment API with a new matcher</a></li>
 </ul>
 </p>
diff --git a/html/tutorial/tutorial4/MyApp.java b/html/tutorial/tutorial4/MyApp.java
new file mode 100644
index 00000000..df0a739e
--- /dev/null
+++ b/html/tutorial/tutorial4/MyApp.java
@@ -0,0 +1,408 @@
+/*
+ * $Id$
+ *
+ * Copyright (C) INRIA, 2009-2010
+ *
+ * Modifications to the initial code base are copyright of their
+ * respective authors, or their employers as appropriate.  Authorship
+ * of the modifications may be determined from the ChangeLog placed at
+ * the end of this file.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA.
+ */
+
+// Alignment API classes
+import org.semanticweb.owl.align.Alignment;
+import org.semanticweb.owl.align.AlignmentException;
+import org.semanticweb.owl.align.AlignmentProcess;
+import org.semanticweb.owl.align.AlignmentVisitor;
+
+// Alignment API implementation classes
+import fr.inrialpes.exmo.align.impl.BasicParameters;
+import fr.inrialpes.exmo.align.impl.ObjectAlignment;
+import fr.inrialpes.exmo.align.impl.URIAlignment;
+import fr.inrialpes.exmo.align.impl.BasicAlignment;
+import fr.inrialpes.exmo.align.impl.method.StringDistAlignment;
+import fr.inrialpes.exmo.align.impl.renderer.OWLAxiomsRendererVisitor;
+import fr.inrialpes.exmo.align.util.NullStream;
+import fr.inrialpes.exmo.align.parser.AlignmentParser;
+
+// Jena
+import com.hp.hpl.jena.rdf.model.ModelFactory;
+import com.hp.hpl.jena.rdf.model.Model;
+import com.hp.hpl.jena.ontology.OntModelSpec;
+import com.hp.hpl.jena.query.QueryFactory;
+import com.hp.hpl.jena.query.Query;
+import com.hp.hpl.jena.query.ResultSet;
+import com.hp.hpl.jena.query.ResultSetFormatter;
+import com.hp.hpl.jena.query.QueryExecution;
+import com.hp.hpl.jena.query.QueryExecutionFactory;
+
+// OWL API
+import org.semanticweb.owlapi.model.IRI;
+import org.semanticweb.owlapi.model.OWLOntologyManager;
+import org.semanticweb.owlapi.model.OWLOntology;
+import org.semanticweb.owlapi.model.OWLOntologyCreationException;
+import org.semanticweb.owlapi.model.OWLClass;
+import org.semanticweb.owlapi.model.OWLAxiom;
+import org.semanticweb.owlapi.model.OWLClassExpression;
+import org.semanticweb.owlapi.model.OWLNamedIndividual;
+import org.semanticweb.owlapi.apibinding.OWLManager;
+import org.semanticweb.owlapi.reasoner.OWLReasoner;
+
+// Pellet
+import com.clarkparsia.pellet.owlapiv3.PelletReasoner;
+
+// IDDL
+import fr.inrialpes.exmo.iddl.IDDLReasoner;
+import fr.inrialpes.exmo.iddl.conf.Semantics;
+
+// SAX standard classes
+import org.xml.sax.SAXException;
+
+// DOM Standard classes
+import org.w3c.dom.Document;
+import org.w3c.dom.NodeList;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.OutputKeys;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.xpath.XPathFactory;
+import javax.xml.xpath.XPath;
+import javax.xml.xpath.XPathExpression;
+import javax.xml.xpath.XPathExpressionException;
+import javax.xml.xpath.XPathConstants;
+
+// Java standard classes
+import java.util.Set;
+import java.util.Properties;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.io.BufferedWriter;
+import java.io.OutputStreamWriter;
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
+import java.io.InputStream;
+import java.io.FileInputStream;
+import java.io.PrintStream;
+import java.io.FileNotFoundException;
+import java.io.ByteArrayInputStream;
+import java.io.StringReader;
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.io.File;
+import java.io.FileWriter;
+import java.net.URI;
+import java.net.URL;
+import java.net.MalformedURLException;
+import java.net.URISyntaxException;
+
+/**
+ * MyApp
+ *
+ * Reconcile two ontologies in various ways
+ */
+
+public class MyApp {
+
+    String RESTServ = "http://aserv.inrialpes.fr/rest/";
+
+    public static void main( String[] args ) {
+	new MyApp().run( args );
+    }
+
+    public void run( String[] args ) {
+	String myId = "JETest";
+	Alignment al = null;
+	URI uri1 = null;
+	URI uri2 = null;
+	//String u1 = "http://alignapi.gforge.inria.fr/tutorial/tutorial2/ontology1.owl";
+	//String u2 = "http://alignapi.gforge.inria.fr/tutorial/tutorial2/ontology2.owl";
+	String u1 = "file:ontology1.owl";
+	String u2 = "file:ontology2.owl";
+	String method = "fr.inrialpes.exmo.align.impl.method.StringDistAlignment";
+	String tempOntoFileName = "/tmp/myresult.owl";
+	Properties params = new BasicParameters();
+	try {
+	    uri1 = new URI( u1 );
+	    uri2 = new URI( u2 );
+	} catch (URISyntaxException use) { use.printStackTrace(); }
+
+	// ***** First exercise: matching *****
+	// (Sol1) Try to find an alignment between two ontologies from the server
+	// ask for it
+	String found = getFromURLString( RESTServ+"find?onto1="+u1+"&onto2="+u2, false );
+	// retrieve it
+	// If there exists alignments, ask for the first one
+	NodeList alset = extractFromResult( found, "//findResponse/alignmentList/alid[1]/text()", false );
+
+	// (Sol3) Match the ontologies on the server
+	if ( alset.getLength() == 0 ) {
+	    // call for matching
+	    // * tested (must add force = true)
+	    //String match = getFromURLString( RESTServ+"match?onto1="+u1+"&onto2="+u2+"&method="+method+"&pretty="+myId+"&action=Match", true );
+	    // This returns a URI
+	}
+
+	if ( alset.getLength() > 0 ) {
+	    // Ask it
+	    String alid = alset.item(0).getNodeValue();
+	    found = getFromURLString( RESTServ+"retrieve?method=fr.inrialpes.exmo.align.impl.renderer.RDFRendererVisitor&id="+alid, false );
+	    alset = extractFromResult( found, "//retrieveResponse/result/*[1]",true );
+
+	    // This code is heavy as hell
+	    String xmlString = null;
+	    try {
+		// Set up the output transformer
+		TransformerFactory transfac = TransformerFactory.newInstance();
+		Transformer trans = transfac.newTransformer();
+		trans.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
+		trans.setOutputProperty(OutputKeys.INDENT, "yes");
+
+		// Print the DOM node
+		StringWriter sw = new StringWriter();
+		DOMSource source = new DOMSource( alset.item(0) );
+		trans.transform(source, new StreamResult(sw));
+		xmlString = sw.toString();
+		//System.out.println(xmlString);
+	    } catch (TransformerException e) {
+		e.printStackTrace();
+	    }
+
+	    // parse it as an alignment
+	    // (better passing to the SAXHandler)
+	    try {
+		AlignmentParser aparser = new AlignmentParser(0);
+		Alignment alu = aparser.parseString( xmlString );
+		al = ObjectAlignment.toObjectAlignment((URIAlignment)alu);
+	    } catch (SAXException saxe) { 
+		saxe.printStackTrace(); 
+	    } catch (AlignmentException ae) { 
+		ae.printStackTrace();
+	    }
+	}
+
+	// (Sol2) Match the ontologies with a local algorithm
+	if ( al == null ){ // Unfortunatelly no alignment was available
+	    AlignmentProcess ap = new StringDistAlignment();
+	    try {
+		ap.init( uri1, uri2 );
+		params.setProperty("stringFunction","smoaDistance");
+		params.setProperty("noinst","1");
+		ap.align( (Alignment)null, params );
+		al = ap;
+		// Supplementary:
+		// upload the result on the server
+		// store it
+	    } catch (AlignmentException ae) { ae.printStackTrace(); }
+	}
+
+	// Alternative: find an intermediate ontology between which there are alignments
+	// find (basically a graph traversal operation)
+	// retrieve them
+	// parse them
+	// compose them
+
+	// ***** Second exercise: merging/transforming *****
+
+	// (Sol1) generate a merged ontology between the ontologies (OWLAxioms)
+	PrintWriter writer = null;
+	File merged = new File( tempOntoFileName );
+	try {
+	    writer = new PrintWriter ( new FileWriter( merged, false ), true );
+	    AlignmentVisitor renderer = new OWLAxiomsRendererVisitor(writer);
+	    al.render(renderer);
+	} catch (UnsupportedEncodingException uee) {
+	    uee.printStackTrace();
+	} catch (AlignmentException ae) {
+	    ae.printStackTrace();
+	} catch (IOException ioe) { 
+	    ioe.printStackTrace();
+	} finally {
+	    if ( writer != null ) {
+		writer.flush();
+		writer.close();
+	    }
+	}
+
+	// (Sol2) import the data from one ontology into the other
+
+	// ***** Third exercise: querying/reasoning *****
+
+	// (Sol1) Use SPARQL to answer queries (at the data level)
+	InputStream in = null;
+	QueryExecution qe = null;
+	try {
+	        in = new FileInputStream( merged );
+		//in = new URL("http://alignapi.gforge.inria.fr/tutorial/tutorial2/ontology1.owl").openStream();
+		//OntModelSpec.OWL_MEM_RDFS_INF or no arguments to see the difference...
+		Model model = ModelFactory.createOntologyModel(OntModelSpec.OWL_DL_MEM_RULE_INF,null);
+	    model.read(in,"file:///tmp/myresult.owl"); 
+	    in.close();
+	
+	    // Create a new query
+	    // Could also be selected by supervisor ???
+	    String queryString = 
+		"PREFIX foaf: <http://xmlns.com/foaf/0.1/> " +
+		"PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> " +
+		"PREFIX aa: <http://alignapi.gforge.inria.fr/tutorial/tutorial2/ontology1.owl#> " +
+		"SELECT ?fn ?ln ?t ?s " +
+		//"SELECT ?fn ?ln " +
+		"WHERE {" +
+                "      ?student rdf:type aa:Estudiante . " +
+		"      ?student aa:firstname  ?fn. " +
+		"      ?student aa:lastname  ?ln. " +
+		"OPTIONAL   {   ?student aa:affiliation ?t . } " +
+		"OPTIONAL   {   ?student aa:supervisor ?s . } " +
+		"      }";
+
+	    Query query = QueryFactory.create(queryString);
+
+	    // Execute the query and obtain results
+	    qe = QueryExecutionFactory.create(query, model);
+	    ResultSet results = qe.execSelect();
+
+	    // Output query results	
+	    ResultSetFormatter.out(System.out, results, query);
+	} catch (FileNotFoundException fnfe) {
+	    fnfe.printStackTrace();
+	} catch (IOException ioe) {
+	    ioe.printStackTrace();
+	} finally {
+	    // Important - free up resources used running the query
+	    if ( qe != null ) qe.close();
+	}
+
+	// Alternative: Use Pellet to answer queries
+
+	// ***** Fourth exercise: reasoning *****
+
+	// Variant 1: reasoning with merged ontologies
+	OWLOntologyManager manager = OWLManager.createOWLOntologyManager();
+	//Pellet
+	OWLReasoner reasoner = null;
+
+	//System.setErr( new PrintStream( new NullStream() ) );
+	// Load the ontology 
+	try {
+	    OWLOntology ontology = manager.loadOntology( IRI.create( "file://"+tempOntoFileName ) );
+	    reasoner = new PelletReasoner( ontology, org.semanticweb.owlapi.reasoner.BufferingMode.NON_BUFFERING );
+	    reasoner.prepareReasoner();
+	} catch (OWLOntologyCreationException ooce) { 
+	    ooce.printStackTrace(); 
+	}
+
+	// get the instances of a class
+	OWLClass estud = manager.getOWLDataFactory().getOWLClass( IRI.create( "http://alignapi.gforge.inria.fr/tutorial/tutorial2/ontology1.owl#Estudiante" ) );   
+	OWLClass person = manager.getOWLDataFactory().getOWLClass( IRI.create( "http://alignapi.gforge.inria.fr/tutorial/tutorial2/ontology2.owl#Person" ) );   
+	OWLClass student = manager.getOWLDataFactory().getOWLClass( IRI.create( "http://alignapi.gforge.inria.fr/tutorial/tutorial2/ontology2.owl#Student" ) );   
+	Set<OWLNamedIndividual> instances  = reasoner.getInstances( estud, false ).getFlattened();
+	System.err.println("Pellet(Merged): There are "+instances.size()+" students "+estud.getIRI());
+
+	testPelletSubClass( manager, reasoner, estud, person );
+	testPelletSubClass( manager, reasoner, estud, student );
+
+	// Variant 2: reasoning with distributed semantics (IDDL)
+	// test consistency of aligned ontologies
+	IDDLReasoner dreasoner = new IDDLReasoner( Semantics.DL );
+	dreasoner.addOntology( uri1 );
+	dreasoner.addOntology( uri2 );
+	dreasoner.addAlignment( al );
+	if ( dreasoner.isConsistent() ) {
+	    System.out.println( "IDDL: the alignment network is consistent");
+	    testIDDLSubClass( dreasoner, uri1, uri2, estud, person );
+	    testIDDLSubClass( dreasoner, uri1, uri2, estud, student );
+         } else {
+	    System.out.println( "IDDL: the alignment network is inconsistent");
+	}
+    }
+
+    public void testPelletSubClass( OWLOntologyManager manager, OWLReasoner reasoner, OWLClassExpression d1, OWLClassExpression d2 ) {
+	OWLAxiom axiom = manager.getOWLDataFactory().getOWLSubClassOfAxiom( d1, d2 );
+	boolean isit = reasoner.isEntailed( axiom );
+	if ( isit ) {
+	    System.out.println( "Pellet(Merged): "+d1+" is subclass of "+d2 );
+	} else {
+	    System.out.println( "Pellet(Merged): "+d1+" is not necessarily subclass of "+d2 );
+	}
+    }
+
+    public void testIDDLSubClass( IDDLReasoner dreasoner, URI onto1, URI onto2, OWLClassExpression d1, OWLClassExpression d2 ) {
+	Alignment al2 = new ObjectAlignment();
+	try {
+	    al2.init( onto1, onto2 );
+	    // add the cell
+	    al2.addAlignCell( d1, d2, "&lt;", 1. );
+	} catch (AlignmentException ae) { ae.printStackTrace(); }
+	if ( dreasoner.isEntailed( al2 ) ) {
+	    System.out.println( "IDDL: "+d1+" <= "+d2+" is entailed" );
+	} else {
+	    System.out.println( "IDDL: "+d1+" <= "+d2+" is not entailed" );
+	}
+    }
+
+    public String getFromURLString( String u, boolean print ){
+	URL url = null;
+	String result = "<?xml version='1.0'?>";
+	try {
+	    url = new URL( u );
+	    BufferedReader in = new BufferedReader(
+    				new InputStreamReader(
+    				  url.openStream()));
+	    String inputLine;
+	    while ((inputLine = in.readLine()) != null) {
+		if (print) System.out.println(inputLine);
+		result += inputLine;
+	    }
+	    in.close();
+	}
+	catch ( MalformedURLException mue ) { mue.printStackTrace(); }
+	catch ( IOException mue ) { mue.printStackTrace(); }
+	return result;
+    }
+
+    public NodeList extractFromResult( String found, String path, boolean print ){
+	Document document = null;
+	NodeList nodes = null;
+	try { // Parse the returned stringAS XML
+	    DocumentBuilder parser =
+		DocumentBuilderFactory.newInstance().newDocumentBuilder();
+	    document = parser.parse(new ByteArrayInputStream( found.getBytes() ));
+	} catch ( ParserConfigurationException pce ) { pce.printStackTrace(); }
+	catch ( SAXException se ) { se.printStackTrace(); }
+	catch ( IOException ioe ) { ioe.printStackTrace(); }
+
+	try { // Apply the Xpath expression
+	    XPathFactory factory = XPathFactory.newInstance();
+	    XPath xpath = factory.newXPath();
+	    //XPathExpression expr = xpath.compile("//book[author='Neal Stephenson']/title/text()");
+	    XPathExpression expr = xpath.compile( path );
+	    Object result = expr.evaluate( document, XPathConstants.NODESET );
+	    nodes = (NodeList)result;
+	    if ( print ) {
+		for ( int i = 0; i < nodes.getLength(); i++) {
+		    System.out.println(nodes.item(i).getNodeValue()); 
+		}
+	    }
+	} catch (XPathExpressionException xpee) { xpee.printStackTrace(); }
+	return nodes;
+    }
+}
diff --git a/html/tutorial/tutorial4/Skeleton.java b/html/tutorial/tutorial4/Skeleton.java
new file mode 100644
index 00000000..415f0c95
--- /dev/null
+++ b/html/tutorial/tutorial4/Skeleton.java
@@ -0,0 +1,220 @@
+/*
+ * $Id$
+ *
+ * Copyright (C) INRIA, 2009
+ *
+ * Modifications to the initial code base are copyright of their
+ * respective authors, or their employers as appropriate.  Authorship
+ * of the modifications may be determined from the ChangeLog placed at
+ * the end of this file.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA.
+ */
+
+// Alignment API classes
+import org.semanticweb.owl.align.Alignment;
+import org.semanticweb.owl.align.AlignmentException;
+import org.semanticweb.owl.align.AlignmentProcess;
+import org.semanticweb.owl.align.AlignmentVisitor;
+import org.semanticweb.owl.align.Parameters;
+
+// Alignment API implementation classes
+import fr.inrialpes.exmo.align.impl.BasicParameters;
+import fr.inrialpes.exmo.align.impl.ObjectAlignment;
+import fr.inrialpes.exmo.align.impl.URIAlignment;
+import fr.inrialpes.exmo.align.impl.BasicAlignment;
+import fr.inrialpes.exmo.align.impl.method.StringDistAlignment;
+import fr.inrialpes.exmo.align.impl.renderer.OWLAxiomsRendererVisitor;
+import fr.inrialpes.exmo.align.parser.AlignmentParser;
+
+// Jena
+import com.hp.hpl.jena.rdf.model.ModelFactory;
+import com.hp.hpl.jena.rdf.model.Model;
+import com.hp.hpl.jena.ontology.OntModelSpec;
+import com.hp.hpl.jena.query.QueryFactory;
+import com.hp.hpl.jena.query.Query;
+import com.hp.hpl.jena.query.ResultSet;
+import com.hp.hpl.jena.query.ResultSetFormatter;
+import com.hp.hpl.jena.query.QueryExecution;
+import com.hp.hpl.jena.query.QueryExecutionFactory;
+
+// Pellet
+
+// IDDL
+import fr.inrialpes.exmo.iddl.IDDLReasoner;
+import fr.inrialpes.exmo.iddl.conf.Semantics;
+
+// SAX standard classes
+import org.xml.sax.SAXException;
+
+// DOM Standard classes
+import org.w3c.dom.Document;
+import org.w3c.dom.NodeList;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.OutputKeys;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.xpath.XPathFactory;
+import javax.xml.xpath.XPath;
+import javax.xml.xpath.XPathExpression;
+import javax.xml.xpath.XPathExpressionException;
+import javax.xml.xpath.XPathConstants;
+
+// Java standard classes
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.io.BufferedWriter;
+import java.io.OutputStreamWriter;
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
+import java.io.InputStream;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.ByteArrayInputStream;
+import java.io.StringReader;
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.io.File;
+import java.io.FileWriter;
+import java.net.URI;
+import java.net.URL;
+import java.net.MalformedURLException;
+import java.net.URISyntaxException;
+
+/**
+ * MyApp
+ *
+ * Reconcile two ontologies in various ways
+ */
+
+public class MyApp {
+
+    String RESTServ = "http://aserv.inrialpes.fr/rest/";
+
+    public static void main( String[] args ) {
+	new MyApp().run( args );
+    }
+
+    public void run( String[] args ) {
+
+	// Setting variables
+	String myId = "JETest";
+	Alignment al = null;
+	URI uri1 = null;
+	URI uri2 = null;
+	//String u1 = "http://alignapi.gforge.inria.fr/tutorial2/ontology1.owl";
+	//String u2 = "http://alignapi.gforge.inria.fr/tutorial2/ontology2.owl";
+	String u1 = "file:ontology1.owl";
+	String u2 = "file:ontology2.owl";
+	String method = "fr.inrialpes.exmo.align.impl.method.StringDistAlignment";
+	Parameters params = new BasicParameters();
+	try {
+	    uri1 = new URI( u1 );
+	    uri2 = new URI( u2 );
+	} catch (URISyntaxException use) { use.printStackTrace(); exit(); }
+
+	try {
+
+	    // ***** First exercise: matching *****
+	    // (Sol1) Try to find an alignment between two ontologies from the server
+	    // ask for it
+	    // retrieve it
+	    // parse it as an alignment
+
+	    // (Sol2) Match the ontologies with a local algorithm
+	    // match
+
+	    // (Sol3) Match the ontologies on the server
+	    // call for matching
+	    // retrieve it
+	    // parse it as an alignment
+
+	    // Alternative: find an intermediate ontology between which there are alignments
+	    // find (basically a graph traversal operation)
+	    // retrieve them
+	    // parse them
+	    // compose them
+
+	    // Supplementary:
+	    // upload the result on the server
+	    // store it
+
+	    // ***** Second exercise: merging/transforming *****
+
+	    // (Sol1) generate a merged ontology between the ontologies (OWLAxioms)
+
+	    // (Sol2) import the data from one ontology into the other
+
+	    // ***** Third exercise: querying and reasoning *****
+
+	    // (Sol1) Use SPARQL to answer queries (at the data level)
+
+	    // (Sol2) Use Pellet to answer queries (at the ontology level)
+
+	} catch (Exception e) { e.printStackTrace(); exit();  }
+    }
+
+    public String getFromURLString( String u, boolean print ){
+	URL url = null;
+	String result = "<?xml version='1.0'?>";
+	try {
+	    url = new URL( u );
+	    BufferedReader in = new BufferedReader(
+    				new InputStreamReader(
+    				  url.openStream()));
+	    String inputLine;
+	    while ((inputLine = in.readLine()) != null) {
+		if (print) System.out.println(inputLine);
+		result += inputLine;
+	    }
+	    in.close();
+	}
+	catch ( MalformedURLException mue ) { mue.printStackTrace(); }
+	catch ( IOException mue ) { mue.printStackTrace(); }
+	return result;
+    }
+
+    public NodeList extractFromResult( String found, String path, boolean print ){
+	Document document = null;
+	NodeList nodes = null;
+	try { // Parse the returned string as XML
+	    DocumentBuilder parser =
+		DocumentBuilderFactory.newInstance().newDocumentBuilder();
+	    document = parser.parse(new ByteArrayInputStream( found.getBytes() ));
+	} catch ( ParserConfigurationException pce ) { pce.printStackTrace(); }
+	catch ( SAXException se ) { se.printStackTrace(); }
+	catch ( IOException ioe ) { ioe.printStackTrace(); }
+
+	try { // Apply the Xpath expression
+	    XPathFactory factory = XPathFactory.newInstance();
+	    XPath xpath = factory.newXPath();
+	    XPathExpression expr = xpath.compile( path );
+	    Object result = expr.evaluate( document, XPathConstants.NODESET );
+	    nodes = (NodeList)result;
+	    if ( print ) {
+		for ( int i = 0; i < nodes.getLength(); i++) {
+		    System.out.println(nodes.item(i).getNodeValue()); 
+		}
+	    }
+	} catch (XPathExpressionException xpee) { xpee.printStackTrace(); }
+	return nodes;
+    }
+}
diff --git a/html/tutorial/tutorial4/index.html b/html/tutorial/tutorial4/index.html
new file mode 100644
index 00000000..6db7a7a8
--- /dev/null
+++ b/html/tutorial/tutorial4/index.html
@@ -0,0 +1,413 @@
+<?xml version="1.0"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+<title>Exploiting alignments and reasoning</title>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
+<link rel="stylesheet" type="text/css" href="../../base.css" />
+<link rel="stylesheet" type="text/css" href="../../style.css" />
+<script type="text/javascript">
+<!--
+function show(id) {
+	var element = document.getElementById(id);
+	element.style.display = "block";
+}
+function hide(id) {
+	var element = document.getElementById(id);
+	element.style.display = "none";
+}
+-->
+</script>
+<style type="text/css">
+<!--
+div.logic {
+	padding-left: 5px;
+	padding-right: 5px;
+	margin-top: 10px;
+	margin-bottom: 10px;
+}
+-->
+</style>
+</head>
+<body style="background-color: #FFFFFF;">
+
+<h1>Exploiting alignments and reasoning: advanced tutorial on the Alignment <abbr title="Application Programming Interface">API</abbr> and server</h1>
+
+<p>
+<dl>
+<dt>This version:</dt>
+<dd>http://alignapi.gforge.inria.fr/tutorial/tutorial2/</dd>
+<dt>Author:</dt>
+<dd><a href="http://exmo.inrialpes.fr/people/euzenat">J&eacute;r&ocirc;me Euzenat</a>, INRIA  &amp; LIG
+</dd>
+</dl>
+</p>
+
+<p style="border-top: 2px solid
+	  #AAAAAA; padding-top: 15px; padding-bottom: 15px;">
+Here is a more advanced tutorial for the
+alignment <abbr>API</abbr> which explains how to interface the API
+with other components.
+This tutorial will show how to:
+<ul>
+<li>communicate the alignment server
+through its REST web service API,</li>
+<li>manipulate alignments with the Alignment API in Java,</li>
+<li>perform OWL reasoning on aligned ontologies and compose
+  alignments.</li>
+</ul>
+This time, the tutorial is based on Java programming and using various
+related APIs.
+</p>
+<p>
+Other tutorials are <a href="../index.html">available</a>.</p>
+<p  style="border-top: 2px solid #AAAAAA;"><small>This tutorial has
+    been designed for the Alignment API version 4.0. It is currently
+    incomplete due to the upgrade of Pellet to version 2.0.2 and IDDL.</small></p>
+	
+<h2>Preparation</h2>
+	
+<p>Just:
+<div class="fragment">
+$ cd tutorial2
+</div>
+</p>
+	
+<h2>Data</h2>
+	
+<p>
+We have two ontologies, <a href="ontology1.owl">ontology1.owl</a>
+and <a href="ontology2.owl">ontology2.owl</a>, under which two sets of
+students are described. Unfortunately, the
+administration started to record participants with their own ontology
+before finding that using <a href="http://foaf-project.org">FOAF</a>
+would be a better idea. We now end up with two incomplete lists of
+participants.
+</p>
+<p>
+The goal is to have a unified view of these participants. For that
+purpose, we will match the two ontologies and reason with the result
+in order to view participants from boths ontologies under the other
+ontology. This is not a difficult task, the goal here is only to show
+how this could be achieved.
+</p>
+	
+<p>For that purpose, you have to develop a program in Java. 
+We first define the CLASSPATH because a lot of external software is required
+<div class="fragment">
+$ setenv CLASSPATH ../../../lib/align.jar:../../../lib/procalign.jar:../../../lib/jena/jena.jar:../../../lib/jena/arq.jar:../../../lib/iddl/iddl.jar:../../../lib/pellet/pellet-core.jar:../../../lib/pellet/pellet-owlapiv3.jar:../../../lib/pellet/pellet-rules.jar:../../../lib/pellet/pellet-datatypes.jar:../../../lib/pellet/aterm-java-1.6.jar:../../../lib/pellet/pellet-query.jar:../../../lib/ontosim/ontosim.jar:../../../lib/pellet/pellet-el.jar:../../../lib/log4j/commons-logging.jar:../../../lib/log4j/log4j.jar:../../../lib/xerces/xercesImpl.jar:../../../lib/jena/iri.jar:../../../lib/jena/icu4j_3_4.jar:../../../lib/jena/concurrent.jar:../../../lib/xsdlib/relaxngDatatype.jar:../../../lib/xsdlib/xsdlib.jar:results
+</div>
+The list of jars is long, but at least it is explicit and you
+should be safe with this one.
+This programme can be compiled by:
+<div class="fragment">
+$ javac -d results MyApp.java
+</div>
+</p>
+<p>This
+  programme can be run by:
+<div class="fragment">
+$ java MyApp
+</div></p>
+You can start with the empty template <a href="Skeleton.java">Skeleton.java</a>.
+</p>
+
+<h2>Matching ontologies</h2>
+
+<p>
+This can be achieved:
+<ul>
+<li>by finding an alignment from the web/server</li>
+<li>by running a matcher locally</li>
+<li>by running a matcher on the alignment server</li>
+<li>by finding a chain of alignments from the web/server</li>
+</ul>
+</p>
+
+<p>
+Write a program that does try to find an alignment on the alignment
+server <a href="http://aserv.inrialpes.fr">http://aserv.inrialpes.fr</a>
+and, if none is found, computes one.
+</p>
+<div class="button">
+  <input type="button" onclick="show('qu0')" value="Various variables"/>
+  <input type="button" onclick="show('qu1')" value="Show solution 1"/>
+  <input type="button" onclick="show('qu2')" value="Show solution 2"/>
+  <input type="button" onclick="show('qu3')" value="Show solution 3"/>
+  <input type="button" onclick="hide('qu1');hide('qu2');hide('qu3');" value="Hide solutions"/>
+</div>
+<div class="explain" id="qu0">
+<p>After introducing the main variables:</p>
+<pre>
+	String myId = "JETest";
+	Alignment al = null;
+	URI uri1 = null;
+	URI uri2 = null;
+	//String u1 = "http://alignapi.gforge.inria.fr/tutorial/tutorial2/ontology1.owl";
+	//String u2 = "http://alignapi.gforge.inria.fr/tutorial/tutorial2/ontology2.owl";
+	String u1 = "file:ontology1.owl";
+	String u2 = "file:ontology2.owl";
+	String method = "fr.inrialpes.exmo.align.impl.method.StringDistAlignment";
+	String tempOntoFileName = "/tmp/myresult.owl";
+	Parameters params = new BasicParameters();
+	try {
+	    uri1 = new URI( u1 );
+	    uri2 = new URI( u2 );
+	} catch (URISyntaxException use) { use.printStackTrace(); }
+</pre>
+</div>
+<div class="explain" id="qu1">
+<p>The programme will invoke the alignment server:</p>
+<pre>
+	// (Sol1) Try to find an alignment between two ontologies from the server
+	// ask for it
+	String found = getFromURLString( RESTServ+"find?onto1="+u1+"&onto2="+u2, false );
+</pre>
+<p>Retrieve the alignment itself:</p>
+<pre>
+	// retrieve it
+	// If there exists alignments, ask for the first one
+	NodeList alset = extractFromResult( found, "//findResponse/alignmentList/alid[1]/text()", false );
+</pre>
+<p>And parse it:</p>
+<pre>
+	// parse it as an alignment
+	// (better passing to the SAXHandler)
+	AlignmentParser aparser = new AlignmentParser(0);
+	Alignment alu = aparser.parseString( xmlString );
+	al = ObjectAlignment.toObjectAlignment((URIAlignment)alu);
+</pre>
+</div>
+<div class="explain" id="qu2"><p>Just create an instance of
+    AlignmentProcess and call it:</p>
+<pre>
+	// (Sol2) Match the ontologies with a local algorithm
+	if ( al == null ){ // Unfortunatelly no alignment was available
+	    AlignmentProcess ap = new StringDistAlignment();
+	    ap.init( uri1, uri2 );
+	    params.setParameter("stringFunction","smoaDistance");
+	    ap.align( (Alignment)null, params );
+	    al = ap;
+	}
+</pre>
+</div>
+<div class="explain" id="qu3"><p>Match on the server:</p>
+<pre>
+	// (Sol3) Match the ontologies on the server
+	if ( alset.getLength() == 0 ) {
+	    // call for matching
+	    String match = getFromURLString( RESTServ+"match?onto1="+u1+"&onto2="+u2+"&method="+method+"&pretty="+myId+"&action=Match&force=true", true );
+	}
+</pre>
+<p>The remainder is the same as in the first solution.</p>
+</div>
+<div class="logic">
+<p><b>More work:</b> You can also store localy computed alignments on
+  the alignment server.</p>
+</div>
+<div class="button">
+  <input type="button" onclick="show('qu4')" value="Show solution"/>
+  <input type="button" onclick="hide('qu4');" value="Hide solution"/>
+</div>
+<div class="explain" id="qu4"><p>Not ready yet (but not difficult)</p>
+<pre>
+</pre>
+</div>
+
+<h2>Manipulate the data</h2>
+
+<p>
+Again, this is either:
+<ul>
+<li>generating OWL axioms from the alignments and merge the ontologies</li>
+<li>transforming data from one ontology to another</li>
+</ul>
+</p>
+<p>
+This can be done with the alignment API support.
+</p>
+
+<div class="button">
+  <input type="button" onclick="show('qu5')" value="Show solution 1"/>
+  <!--input type="button" onclick="show('qu6')" value="Show solution 2"/-->
+  <input type="button" onclick="hide('qu5');hide('qu6');" value="Hide solutions"/>
+</div>
+<div class="explain" id="qu5">
+<p>In fact everything is done in one step:</p>
+<pre>
+	// (Sol1) generate a merged ontology between the ontologies (OWLAxioms)
+	File merged = new File( tempOntoFileName );
+	PrintWriter writer = new PrintWriter ( new FileWriter( merged, false ), true );
+	AlignmentVisitor renderer = new OWLAxiomsRendererVisitor(writer);
+	al.render(renderer);
+	writer.flush();
+	writer.close();
+</pre>
+<p>You can look at the result in myresult.owl</p>
+</div>
+<div class="explain" id="qu6"><p>Not ready yet</p>
+<pre>
+</pre>
+</div>
+
+<h2>Generate the answers</h2>
+
+<p>
+This can be done in three ways:
+<ul>
+<li>using SPARQL</li>
+<li>using a reasonner such as Pellet to answer these queries against
+  the merged ontologies.</li>
+<li>using a "distributed" reasoner, in our case IDDL, to answer these
+  queries against non merged aligned ontologies.</li>
+</ul>
+</p>
+<p>
+In case you go for SPARQL please, take care of the inference regime
+and observe what are the differences in this case. You can of course
+run various queries and start by runing them in one of the initial
+ontologies instead of the merged one.
+</p>
+</p>
+<div class="button">
+  <input type="button" onclick="show('qu7')" value="Show solution 1"/>
+  <!--input type="button" onclick="show('qu8')" value="Show solution 2"/>
+  <input type="button" onclick="show('qu9')" value="Show solution 3"/-->
+  <input type="button" onclick="hide('qu7');hide('qu8');hide('qu9');" value="Hide solutions"/>
+</div>
+<div class="explain" id="qu7">
+<p>Prepare the system:</p>
+<pre>
+	// (Sol1) Use SPARQL to answer queries (at the data level)
+	InputStream in = new FileInputStream( merged );
+	//OntModelSpec.OWL_MEM_RDFS_INF or no arguments to see the difference...
+	Model model = ModelFactory.createOntologyModel(OntModelSpec.OWL_DL_MEM_RULE_INF,null);
+	model.read(in,"file:///tmp/myresult.owl"); 
+	in.close();
+</pre>	
+<p>Query (please play by changing the query)</p>
+<pre>
+        // Create a new query
+	String queryString = 
+		"PREFIX foaf: <http://xmlns.com/foaf/0.1/> " +
+		"PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> " +
+		"PREFIX aa: <http://alignapi.gforge.inria.fr/tutorial/tutorial2/ontology1.owl#> " +
+		"SELECT ?fn ?ln ?t " +
+		"WHERE {" +
+                "      ?student rdf:type aa:Person . " +
+		"      ?student aa:firstname  ?fn. " +
+		"      ?student aa:lastname  ?ln. " +
+		"      ?student aa:topic ?t . " +
+		"      }";
+</pre>	
+<p>Evaluation:</p>
+<pre>
+	Query query = QueryFactory.create(queryString);
+
+	// Execute the query and obtain results
+	QueryExecution qe = QueryExecutionFactory.create(query, model);
+	ResultSet results = qe.execSelect();
+	
+	// Output query results	
+	ResultSetFormatter.out(System.out, results, query);
+</pre>
+</div>
+<div class="explain" id="qu8">
+<p>Create Reasoner instance and load the merged ontologies:</p>
+<pre>
+	OWLOntologyManager manager = OWLManager.createOWLOntologyManager();
+	Reasoner reasoner = new Reasoner( manager );
+	try {
+	    OWLOntology ontology = manager.loadOntology( URI.create( "file://"+tempOntoFileName ) );
+	    reasoner.loadOntology( ontology );
+	} catch (OWLOntologyCreationException ooce) { ooce.printStackTrace(); }
+</pre>
+<p>Get the instances of "Estudiantes":</p>
+<pre>
+	OWLClass estud = manager.getOWLDataFactory().getOWLClass( URI.create( "http://alignapi.gforge.inria.fr/tutorial/tutorial2/ontology1.owl#Estudiante" ) );   
+	OWLClass person = manager.getOWLDataFactory().getOWLClass( URI.create( "http://alignapi.gforge.inria.fr/tutorial/tutorial2/ontology2.owl#Person" ) );   
+	OWLClass student = manager.getOWLDataFactory().getOWLClass( URI.create( "http://alignapi.gforge.inria.fr/tutorial/tutorial2/ontology2.owl#Student" ) );   
+	Set instances  = reasoner.getIndividuals( estud, false );
+	System.err.println("Pellet(Merged): There are "+instances.size()+" students "+estud.getURI());
+</pre>
+<p>Some subsumption tests:</p>
+<pre>
+	testPelletSubClass( manager, reasoner, estud, person );
+	testPelletSubClass( manager, reasoner, estud, student );
+</pre>
+<p>Such that:</p>
+<pre>
+    public void testPelletSubClass( OWLOntologyManager manager, Reasoner reasoner, OWLDescription d1, OWLDescription d2 ) {
+	OWLAxiom axiom = manager.getOWLDataFactory().getOWLSubClassAxiom( d1, d2 );
+	boolean isit = reasoner.isEntailed( axiom );
+	if ( isit ) {
+	    System.out.println( "Pellet(Merged): "+d1+" is subclass of "+d2 );
+	} else {
+	    System.out.println( "Pellet(Merged): "+d1+" is not necessarily subclass of "+d2 );
+	}
+    }
+</pre>
+</div>
+<div class="explain" id="qu9">
+<p>Load the two ontologies and the alignment in the IDDL reasoner:</p>
+<pre>
+	IDDLReasoner dreasoner = new IDDLReasoner( Semantics.DL );
+	dreasoner.addOntology( uri1 );
+	dreasoner.addOntology( uri2 );
+	dreasoner.addAlignment( al );
+</pre>
+<p>Test consistency and check if a particular correspondence is a consequence:</p>
+<pre>
+	if ( dreasoner.isConsistent() ) {
+	    System.out.println( "IDDL: the alignment network is consistent");
+	    testIDDLSubClass( dreasoner, uri1, uri2, estud, person );
+	    testIDDLSubClass( dreasoner, uri1, uri2, estud, student );
+         } else {
+	    System.out.println( "IDDL: the alignment network is inconsistent");
+	}
+</pre>
+<p>Such that:</p>
+<pre>
+    public void testIDDLSubClass( IDDLReasoner dreasoner, URI onto1, URI onto2, OWLDescription d1, OWLDescription d2 ) {
+	Alignment al2 = new ObjectAlignment();
+	try {
+	    al2.init( onto1, onto2 );
+	    // add the cell
+	    al2.addAlignCell( d1, d2, "&lt;", 1. );
+	} catch (AlignmentException ae) { ae.printStackTrace(); }
+	if ( dreasoner.isEntailed( al2 ) ) {
+	    System.out.println( "IDDL: "+d1+" <= "+d2+" is entailed" );
+	} else {
+	    System.out.println( "IDDL: "+d1+" <= "+d2+" is not entailed" );
+	}
+    }
+</pre>
+</div>
+
+The results for these execution are (for Pellet):
+<pre>
+Pellet(Merged): There are 47 students http://alignapi.gforge.inria.fr/tutorial/tutorial2/ontology1.owl#Estudiante
+Pellet(Merged): Estudiante is not necessarily subclass of Person
+Pellet(Merged): Estudiante is subclass of Student
+</pre>
+and for IDDL:
+<pre>
+IDDL: the alignment network is consistent
+IDDL: Estudiante <= Person is not entailed
+IDDL: Estudiante <= Student is entailed
+</pre>
+	
+<!--h2>Full solution</h2>
+	
+<p>Do you want to see a possible solution?</p>
+<p>A full working solution is <a href="MyApp.java">MyApp.java</a>.</p-->
+
+<hr />
+<small>
+<p style="text-align: center;">http://alignapi.gforge.inria.fr/tutorial/tutorial2/</p>
+</small>
+<hr />
+<p>$Id$</p>
+</body>
+</html>
diff --git a/html/tutorial/tutorial4/ontology1.owl b/html/tutorial/tutorial4/ontology1.owl
new file mode 100644
index 00000000..0f025f5b
--- /dev/null
+++ b/html/tutorial/tutorial4/ontology1.owl
@@ -0,0 +1,309 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!DOCTYPE rdf:RDF [
+          <!ENTITY xsd		"http://www.w3.org/2001/XMLSchema#" >
+	  <!ENTITY rdf		"http://www.w3.org/1999/02/22-rdf-syntax-ns#" >
+	  <!ENTITY rdfs		"http://www.w3.org/2000/01/rdf-schema#" >
+	  <!ENTITY dc		"http://purl.org/dc/elements/1.1/" > 
+	  <!ENTITY owl		"http://www.w3.org/2002/07/owl#" >
+	  <!ENTITY units	"http://visus.mit.edu/fontomri/0.01/units.owl#" >
+	  <!ENTITY bibtex	"http://purl.org/net/nknouf/ns/bibtex#">
+	  <!ENTITY dcterms 	"http://purl.org/dc/terms/">
+	  <!ENTITY dctype 	"http://purl.org/dc/dcmitype/"> ]>
+
+<rdf:RDF
+ xmlns="http://alignapi.gforge.inria.fr/tutorial/tutorial2/ontology1.owl#"
+ xml:base="http://alignapi.gforge.inria.fr/tutorial/tutorial2/ontology1.owl#"
+ xmlns:units	="&units;"
+ xmlns:foaf	="http://xmlns.com/foaf/0.1/"
+ xmlns:rdf	="&rdf;"
+ xmlns:xsd	="&xsd;"
+ xmlns:rdfs	="&rdfs;"
+ xmlns:owl	="http://www.w3.org/2002/07/owl#"
+ xmlns:wot	="http://xmlns.com/wot/0.1/"
+ xmlns:dc	="&dc;"
+ xmlns:dcterms	="&dcterms;"
+ xmlns:dctype	="&dctype;"
+ xmlns:bibtex	="&bibtex;">
+  
+  <owl:Ontology rdf:about="http://alignapi.gforge.inria.fr/tutorial/tutorial2/ontology1.owl">
+    <dc:creator>Jérôme Euzenat</dc:creator>
+    <dc:description>Example for Alignment API advanced turorial</dc:description>
+    <dc:date>2009-07-06</dc:date>
+    <rdfs:label>First ontology</rdfs:label>
+    <dc:title>ontology1.owl: an fake list of students</dc:title>
+    <dc:identifier rdf:datatype="&xsd;anyURI">http://alignapi.gforge.inria.fr/tutorial/tutorial2/ontology1.owl</dc:identifier>
+  </owl:Ontology>
+
+  <owl:Class rdf:ID="Estudiante">
+    <rdfs:label xml:lang="en">Estudiante</rdfs:label>
+  </owl:Class>
+
+<Estudiante>
+  <lastname>Fitzgerald</lastname>
+  <firstname>Ella</firstname>
+  <gender>Female</gender>
+  <affiliation>Vanilla University of Technology</affiliation>
+  <city>Vanilla</city>
+  <country>AT</country>
+  <year>1</year>
+  <topic>Semantic Process Mining</topic>
+  <supervisor>Prof. Giancarlo Cetriolo</supervisor>
+</Estudiante>
+
+<Estudiante>
+  <lastname>Blackey</lastname>
+  <firstname>Art</firstname>
+  <gender>Male</gender>
+  <affiliation>University of Albatra</affiliation>
+  <city>Albatra</city>
+  <country>ES</country>
+  <year>1</year>
+  <topic>Semantic Web applications</topic>
+  <supervisor>Paola Pomodoro</supervisor>
+  <supervisor>Pierluiggi Pomodoro</supervisor>
+</Estudiante>
+
+<Estudiante>
+  <lastname>Coleman</lastname>
+  <firstname>Ornette</firstname>
+  <gender>Male</gender>
+  <affiliation>Trinidad College Dubrovnik</affiliation>
+  <city>Dubrovnik</city>
+  <country>IE</country>
+  <year>1</year>
+  <topic>Conceptualization and Implementation of a ontology based Meta-Layer for the Management of Ontology Mapping Representations in Order to Support Sharing and Reuse of Ontology Mappings</topic>
+  <supervisor>Carla Cipolla</supervisor>
+</Estudiante>
+
+<Estudiante>
+  <lastname>Davis</lastname>
+  <firstname>Miles</firstname>
+  <gender>Male</gender>
+  <affiliation>JOHANNISBEER RESEARCH</affiliation>
+  <city>Guacamole</city>
+  <country>AT</country>
+  <year>1</year>
+  <topic>Automatic Metadata-Based Video Editing Systems</topic>
+  <supervisor>Univ.-Prof. Dr. Paolo Carciofo</supervisor>
+</Estudiante>
+
+<Estudiante>
+  <lastname>Coltrane</lastname>
+  <firstname>John</firstname>
+  <gender>Male</gender>
+  <affiliation>Estrellas</affiliation>
+  <city>Aroma</city>
+  <country>IT</country>
+  <topic>Semantic web applications, ontology management systems</topic>
+</Estudiante>
+
+<Estudiante>
+  <lastname>Holliday</lastname>
+  <firstname>Billie</firstname>
+  <gender>Female</gender>
+  <affiliation>University of Soupaloignon</affiliation>
+  <city>Soupaloignon</city>
+  <country>GB</country>
+  <year>1</year>
+  <topic>Adaptive Hypermedia and Competency Model</topic>
+  <supervisor>Dr.Federico diGuava</supervisor>
+  <supervisor>Mr. Laurenzo Girafiore</supervisor>
+</Estudiante>
+
+<Estudiante>
+  <lastname>Monk</lastname>
+  <firstname>Thelonious</firstname>
+  <gender>Male</gender>
+  <affiliation>Madeira Instutute of Technology</affiliation>
+  <city>Madeira</city>
+  <country>PT</country>
+  <year>1</year>
+  <topic>Semantic Web Annotation and Distributed Resource Authorization</topic>
+  <supervisor>Stefano Zucchini</supervisor>
+</Estudiante>
+
+<Estudiante>
+  <lastname>McRae</lastname>
+  <firstname>Carmen</firstname>
+  <gender>Female</gender>
+  <affiliation>University of the Rainforest</affiliation>
+  <city>Lluvianda</city>
+  <country>SI</country>
+  <year>3</year>
+  <supervisor>Mario Staggioni</supervisor>
+</Estudiante>
+
+<Estudiante>
+  <lastname>Bley</lastname>
+  <firstname>Carla</firstname>
+  <gender>Female</gender>
+  <affiliation>none</affiliation>
+  <city>Yves sur Gifette</city>
+  <country>FR</country>
+  <year>1</year>
+  <supervisor>Christina Melocoton</supervisor>
+</Estudiante>
+
+<Estudiante>
+  <lastname>Simone</lastname>
+  <firstname>Nina</firstname>
+  <gender>Female</gender>
+  <affiliation>Research Center of the Americas</affiliation>
+  <city>Florida</city>
+  <country>IT</country>
+  <year>3</year>
+  <topic>Legal ontologies and legal theory</topic>
+  <supervisor>Domenica Melanzana</supervisor>
+</Estudiante>
+
+<Estudiante>
+  <lastname>Joplin</lastname>
+  <firstname>Janis</firstname>
+  <gender>Female</gender>
+  <affiliation>University of Zoulouland</affiliation>
+  <city>Zouloucity</city>
+  <country>ES</country>
+  <year>1</year>
+  <topic>Semantic Web</topic>
+  <supervisor>Medusa Pesto</supervisor>
+  <supervisor>Fiorenta Pescadore</supervisor>
+</Estudiante>
+
+<Estudiante>
+  <lastname>Powell</lastname>
+  <firstname>Bud</firstname>
+  <gender>Male</gender>
+  <affiliation>SPAM</affiliation>
+  <affiliation>Cogebom</affiliation>
+  <city>Porto Bello</city>
+  <country>FR</country>
+  <year>1</year>
+  <topic>The design and the implementation of an Information resources meta-model and its services : application to the medical field</topic>
+  <supervisor>Giovanni Dolomitti</supervisor>
+</Estudiante>
+
+<Estudiante>
+  <lastname>De Wilde</lastname>
+  <firstname>Laurent</firstname>
+  <gender>Male</gender>
+  <affiliation>University of Sussex</affiliation>
+  <city>Glouchester</city>
+  <country>GB</country>
+  <year>1</year>
+  <supervisor>Ugo Calamari</supervisor>
+  <supervisor>Simona Riccota</supervisor>
+</Estudiante>
+
+<Estudiante>
+  <lastname>Calloway</lastname>
+  <firstname>Cab</firstname>
+  <gender>Male</gender>
+  <affiliation>University of Shepperington</affiliation>
+  <city>Shepperington</city>
+  <country>GB</country>
+</Estudiante>
+
+<Estudiante>
+  <lastname>Goodman</lastname>
+  <firstname>Benny</firstname>
+  <gender>Male</gender>
+  <affiliation>The Univesity of the true way</affiliation>
+  <city>Dehli</city>
+  <country>BR</country>
+  <year>1</year>
+  <topic>Semantic Integration of Information</topic>
+  <supervisor>Prof. Dr. Riccardo Peperoni</supervisor>
+</Estudiante>
+
+<Estudiante>
+  <lastname>Parker</lastname>
+  <firstname>Charlie</firstname>
+  <gender>Male</gender>
+  <affiliation>Institut Von Humboldt</affiliation>
+  <city>Any</city>
+  <country>FR</country>
+  <year>1</year>
+  <topic>semantic Web services discovery</topic>
+  <supervisor>Cecilia Parmiggiano</supervisor>
+</Estudiante>
+
+<Estudiante>
+  <lastname>Peterson</lastname>
+  <firstname>Oscar</firstname>
+  <gender>Male</gender>
+  <affiliation>Institute for Applied Boxology</affiliation>
+  <city>Pariggi</city>
+  <country>IT</country>
+  <year>1</year>
+  <topic>Collaborative building of knowledge resources for the Semantic Web</topic>
+  <supervisor>Dott. Antolio Bresaola</supervisor>
+</Estudiante>
+
+<Estudiante>
+  <lastname>Getz</lastname>
+  <firstname>Stan</firstname>
+  <gender>Male</gender>
+  <affiliation>Altacola research centre</affiliation>
+  <city>Cloppenburg</city>
+  <country>DE</country>
+  <year>1</year>
+  <topic>health informatics</topic>
+  <supervisor>Prof. Pierpaolo Polenta</supervisor>
+</Estudiante>
+
+<Estudiante>
+  <lastname>Zorn</lastname>
+  <firstname>John</firstname>
+  <gender>Male</gender>
+  <affiliation>Altacola research centre</affiliation>
+  <city>Cloppenburg</city>
+  <country>DE</country>
+  <year>1</year>
+  <topic>Complex Event Processing</topic>
+  <supervisor>Prof. Pierpaolo Polenta</supervisor>
+</Estudiante>
+
+<Estudiante>
+  <lastname>Tyner</lastname>
+  <firstname>McCoy</firstname>
+  <gender>Male</gender>
+  <affiliation>University of Soupaloignon</affiliation>
+  <city>Soupaloignon</city>
+  <country>GB</country>
+  <year>1</year>
+  <topic>Trust and the Semantic Web</topic>
+  <supervisor>Dr Nanni Girasole</supervisor>
+</Estudiante>
+
+<Estudiante>
+  <lastname>Hawkins</lastname>
+  <firstname>Coleman</firstname>
+  <gender>Male</gender>
+  <affiliation>University of South Poland</affiliation>
+  <city>Krakow</city>
+  <country>IT</country>
+  <year>1</year>
+  <topic>Markup Languages and Semantic Web</topic>
+  <supervisor>Pepe Frutti di Mare</supervisor>
+</Estudiante>
+
+<Estudiante>
+  <lastname>Franklin</lastname>
+  <firstname>Aretha</firstname>
+  <gender>Female</gender>
+  <affiliation>University of Huelva</affiliation>
+  <city>Huelva</city>
+  <country>ES</country>
+</Estudiante>
+
+<Estudiante>
+  <lastname>Baker</lastname>
+  <firstname>Chet</firstname>
+  <gender>Male</gender>
+  <affiliation>University Pie XXIII</affiliation>
+  <city>Orssini</city>
+  <country>FR</country>
+</Estudiante>
+
+</rdf:RDF>
diff --git a/html/tutorial/tutorial4/ontology2.owl b/html/tutorial/tutorial4/ontology2.owl
new file mode 100644
index 00000000..62f9262c
--- /dev/null
+++ b/html/tutorial/tutorial4/ontology2.owl
@@ -0,0 +1,311 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!DOCTYPE rdf:RDF [
+          <!ENTITY xsd		"http://www.w3.org/2001/XMLSchema#" >
+	  <!ENTITY rdf		"http://www.w3.org/1999/02/22-rdf-syntax-ns#" >
+	  <!ENTITY rdfs		"http://www.w3.org/2000/01/rdf-schema#" >
+	  <!ENTITY dc		"http://purl.org/dc/elements/1.1/" > 
+	  <!ENTITY owl		"http://www.w3.org/2002/07/owl#" >
+	  <!ENTITY units	"http://visus.mit.edu/fontomri/0.01/units.owl#" >
+	  <!ENTITY bibtex	"http://purl.org/net/nknouf/ns/bibtex#">
+	  <!ENTITY dcterms 	"http://purl.org/dc/terms/">
+	  <!ENTITY dctype 	"http://purl.org/dc/dcmitype/"> ]>
+
+<!--
+   xmlns="http://xmlns.com/foaf/0.1/#"
+   xml:base="http://xmlns.com/foaf/0.1/#"
+-->
+<rdf:RDF
+ xmlns="http://alignapi.gforge.inria.fr/tutorial/tutorial2/ontology2.owl#"
+ xml:base="http://alignapi.gforge.inria.fr/tutorial/tutorial2/ontology2.owl#"
+ xmlns:units	="&units;"
+ xmlns:foaf	="http://xmlns.com/foaf/0.1/"
+ xmlns:rdf	="&rdf;"
+ xmlns:xsd	="&xsd;"
+ xmlns:rdfs	="&rdfs;"
+ xmlns:owl	="http://www.w3.org/2002/07/owl#"
+ xmlns:wot	="http://xmlns.com/wot/0.1/"
+ xmlns:dc	="&dc;"
+ xmlns:dcterms	="&dcterms;"
+ xmlns:dctype	="&dctype;"
+ xmlns:bibtex	="&bibtex;">
+  
+  <owl:Ontology rdf:about="http://alignapi.gforge.inria.fr/tutorial/tutorial2/ontology2.owl">
+    <dc:creator>Jérôme Euzenat</dc:creator>
+    <dc:description>Example for Alignment API advanced turorial</dc:description>
+    <dc:date>2009-07-06</dc:date>
+    <rdfs:label>Second ontology</rdfs:label>
+    <dc:title>ontology2.owl: another fake list of students</dc:title>
+    <dc:identifier rdf:datatype="&xsd;anyURI">http://alignapi.gforge.inria.fr/tutorial/tutorial2/ontology2.owl</dc:identifier>
+  </owl:Ontology>
+
+  <owl:Class rdf:ID="Student">
+    <rdfs:label xml:lang="en">Student</rdfs:label>
+  </owl:Class>
+
+<Student>
+  <name>Krall</name>
+  <first-name>Diana</first-name>
+  <gender>Female</gender>
+  <institution>Royal University of Worchester sauce</institution>
+  <city-of-study>Worchester sauce</city-of-study>
+  <country-of-study>GB</country-of-study>
+  <year-in-phd>1</year-in-phd>
+  <topics-of-interest>OWL and SKOS: Exploring the relationship between formal and informal knowledge representation</topics-of-interest>
+  <phd-advisor>Dr. A. Verdura</phd-advisor>
+  <phd-advisor>C. Fragola</phd-advisor>
+</Student>
+
+<Student>
+  <name>Gordon</name>
+  <first-name>Dexter</first-name>
+  <gender>Male</gender>
+  <institution>Eelberg University</institution>
+  <city-of-study>Eelberg</city-of-study>
+  <country-of-study>DK</country-of-study>
+  <year-in-phd>1</year-in-phd>
+  <topics-of-interest>Social Web Applications, Personalization, Semantic Web</topics-of-interest>
+  <phd-advisor>C. Pannacotta</phd-advisor>
+</Student>
+
+<Student>
+  <name>Reinhardt</name>
+  <first-name>Django</first-name>
+  <gender>Male</gender>
+  <institution>University Pie XXIII</institution>
+  <institution>IRIA Saskatchevan</institution>
+  <city-of-study>Orssini</city-of-study>
+  <country-of-study>FR</country-of-study>
+  <year-in-phd>1</year-in-phd>
+  <topics-of-interest>Ontology Matching and Alignment</topics-of-interest>
+  <phd-advisor>Prof. Chr. Melocoton</phd-advisor>
+</Student>
+
+<Student>
+  <name>Miller</name>
+  <first-name>Glenn</first-name>
+  <gender>Male</gender>
+  <institution>University of Shepperington</institution>
+  <city-of-study>Shepperington</city-of-study>
+  <country-of-study>GB</country-of-study>
+  <year-in-phd>1</year-in-phd>
+  <topics-of-interest>Digital Identities and Contextual Knowledge</topics-of-interest>
+  <phd-advisor>Professor G. Limone</phd-advisor>
+</Student>
+
+<Student>
+  <name>McLean</name>
+  <first-name>Jackie</first-name>
+  <gender>Male</gender>
+  <institution>Polytechnic of Madeira</institution>
+  <city-of-study>Madeira</city-of-study>
+  <country-of-study>PT</country-of-study>
+  <year-in-phd>3</year-in-phd>
+  <topics-of-interest>Ontology Alignment</topics-of-interest>
+  <phd-advisor>S. Zucchini</phd-advisor>
+</Student>
+
+<Student>
+  <name>Merchant</name>
+  <first-name>Natalie</first-name>
+  <gender>Female</gender>
+  <institution>JOHANNISBEER RESEARCH</institution>
+  <city-of-study>Guacamole</city-of-study>
+  <country-of-study>AT</country-of-study>
+  <topics-of-interest>Social Semantic Web</topics-of-interest>
+</Student>
+
+<Student>
+  <name>Hampton</name>
+  <first-name>Lionel</first-name>
+  <gender>Male</gender>
+  <institution>Politecnico di Madalena</institution>
+  <city-of-study>Madalena</city-of-study>
+  <country-of-study>ES</country-of-study>
+  <topics-of-interest>ODEMapster</topics-of-interest>
+  <phd-advisor>A. Gorgonzola</phd-advisor>
+  <phd-advisor>O. Mascarponne</phd-advisor>
+</Student>
+
+<Student>
+  <name>Jones</name>
+  <first-name>Rickie Lee</first-name>
+  <gender>Female</gender>
+  <institution>Philip Vanderbilt Universiteit</institution>
+  <institution>Velo Research</institution>
+  <city-of-study>Amsteelkoog</city-of-study>
+  <country-of-study>NL</country-of-study>
+  <year-in-phd>1</year-in-phd>
+  <topics-of-interest>A combined approach to alignment of patient record data with a clinical context using computerized guidelines and semantic reasoning.</topics-of-interest>
+  <phd-advisor>A. Lambretta</phd-advisor>
+</Student>
+
+<Student>
+  <name>Rollins</name>
+  <first-name>Sonny</first-name>
+  <gender>Male</gender>
+  <institution>Universita di Miggliore</institution>
+  <city-of-study>Miggliore</city-of-study>
+  <country-of-study>IT</country-of-study>
+  <year-in-phd>1</year-in-phd>
+  <topics-of-interest>social construction of semantic models</topics-of-interest>
+  <phd-advisor>M. Pecorino</phd-advisor>
+</Student>
+
+<Student>
+  <name>Burrell</name>
+  <first-name>Kenny</first-name>
+  <gender>Male</gender>
+  <institution>Politecnico di Belladona</institution>
+  <city-of-study>Belladona</city-of-study>
+  <country-of-study>IT</country-of-study>
+  <year-in-phd>1</year-in-phd>
+  <topics-of-interest>Semantic Web</topics-of-interest>
+  <phd-advisor>S. Proscuitto</phd-advisor>
+</Student>
+
+<Student>
+  <name>Brubeck</name>
+  <first-name>Dave</first-name>
+  <gender>Male</gender>
+  <institution>University of Namibia</institution>
+  <city-of-study>Nürnberg am See</city-of-study>
+  <country-of-study>BE</country-of-study>
+  <year-in-phd>3</year-in-phd>
+  <topics-of-interest>Semantic Web Application: Enhancing Web Usability by Handling the Local Contexts of Web Users</topics-of-interest>
+  <phd-advisor>G. Belladonna</phd-advisor>
+  <phd-advisor>P. Tiramissu</phd-advisor>
+</Student>
+
+<Student>
+  <name>Ellington</name>
+  <first-name>Duke</first-name>
+  <gender>Male</gender>
+  <institution>Vanilla University of Technology</institution>
+  <city-of-study>Vanilla</city-of-study>
+  <country-of-study>AT</country-of-study>
+  <year-in-phd>3</year-in-phd>
+  <topics-of-interest>Context-aware Trip Planning</topics-of-interest>
+  <phd-advisor>Prof. G. Cetriolo</phd-advisor>
+</Student>
+
+<Student>
+  <name>Jackson</name>
+  <first-name>Milt</first-name>
+  <gender>Male</gender>
+  <institution>Escena</institution>
+  <city-of-study>Aroma</city-of-study>
+  <country-of-study>IT</country-of-study>
+</Student>
+
+<Student>
+  <name>Lee</name>
+  <first-name>Peggy</first-name>
+  <gender>Female</gender>
+  <institution>University des Mitteleuropa</institution>
+  <city-of-study>Linden</city-of-study>
+  <country-of-study>AT</country-of-study>
+  <year-in-phd>1</year-in-phd>
+  <topics-of-interest>Ontology-driven Information Extraction</topics-of-interest>
+  <phd-advisor>a.Univ.Prof.DI.Dr. Z. Melone</phd-advisor>
+</Student>
+
+<Student>
+  <name>Gilberto</name>
+  <first-name>Astrud</first-name>
+  <gender>Female</gender>
+  <institution>Universität der Gemütlichkeit</institution>
+  <city-of-study>Monte Bianco</city-of-study>
+  <country-of-study>DE</country-of-study>
+  <year-in-phd>1</year-in-phd>
+  <topics-of-interest>Emergent semantics</topics-of-interest>
+  <phd-advisor>Pr. Dr. M. Coppa</phd-advisor>
+</Student>
+
+<Student>
+  <name>Rigby</name>
+  <first-name>Eleonore</first-name>
+  <gender>Female</gender>
+  <institution>Politecnico di Bermudas</institution>
+  <city-of-study>Brest Litovsk</city-of-study>
+  <country-of-study>MX</country-of-study>
+</Student>
+
+<Student>
+  <name>Black</name>
+  <first-name>Cilla</first-name>
+  <gender>Female</gender>
+  <institution>University of Shepperington</institution>
+  <city-of-study>Shepperington</city-of-study>
+  <country-of-study>GB</country-of-study>
+  <year-in-phd>1</year-in-phd>
+  <phd-advisor>Prof. G. Limone</phd-advisor>
+</Student>
+
+<Student>
+  <name>Shepp</name>
+  <first-name>Archie</first-name>
+  <gender>Male</gender>
+  <institution>Occarina University</institution>
+  <city-of-study>Paretto Yeats</city-of-study>
+  <country-of-study>GB</country-of-study>
+  <topics-of-interest>Personal Information Management</topics-of-interest>
+</Student>
+
+<Student>
+  <name>Tatum</name>
+  <first-name>Art</first-name>
+  <gender>Male</gender>
+  <institution>National Kapodistrian University of Athens</institution>
+  <city-of-study>Athens</city-of-study>
+  <country-of-study>GR</country-of-study>
+  <year-in-phd>1</year-in-phd>
+  <topics-of-interest>Query evaluation on spatial and temporal RDF databases in Semantic Web</topics-of-interest>
+  <phd-advisor>B. Tiramisu</phd-advisor>
+</Student>
+
+<Student>
+  <name>Corea</name>
+  <first-name>Chick</first-name>
+  <gender>Male</gender>
+  <institution>University of Ausblick</institution>
+  <city-of-study>Ausblick</city-of-study>
+  <country-of-study>DE</country-of-study>
+  <year-in-phd>1</year-in-phd>
+  <topics-of-interest>Semantic technologies in business processes and rules</topics-of-interest>
+  <phd-advisor>Prof. Dr. A. Belladonna</phd-advisor>
+</Student>
+
+<Student>
+  <name>Bryant</name>
+  <first-name>Ray</first-name>
+  <institution>Handshuh University</institution>
+  <city-of-study>Handshuh</city-of-study>
+  <country-of-study>BE</country-of-study>
+</Student>
+
+<Student>
+  <name>Zawinul</name>
+  <first-name>Joe</first-name>
+  <institution>Institute for Social Coworkers</institution>
+  <city-of-study>Madalena</city-of-study>
+  <country-of-study>ES</country-of-study>
+</Student>
+
+<Student>
+  <name>Sinclair</name>
+  <first-name>Betty</first-name>
+  <institution>Institute for Social Coworkers</institution>
+  <city-of-study>Madalena</city-of-study>
+  <country-of-study>ES</country-of-study>
+</Student>
+
+<Student>
+  <name>Aldderley</name>
+  <first-name>Julian</first-name>
+  <institution>Politecnico di Madalena</institution>
+  <city-of-study>Botella de Mantequilla</city-of-study>
+  <country-of-study>ES</country-of-study>
+</Student>
+
+</rdf:RDF>
-- 
GitLab