[tracker] Add ontology utilities



commit 28fba5177d13d6d2a800370dfa2d7aadb9c4b9ac
Author: Ivan Frade <ifrade src gnome org>
Date:   Thu Apr 9 09:46:19 2009 +0200

    Add ontology utilities
---
 configure.ac                                     |    1 +
 utils/Makefile.am                                |    1 +
 utils/services/Makefile.am                       |   32 ++
 utils/services/README.example                    |   27 ++
 utils/services/gen-doc.sh                        |   31 ++
 utils/services/ontology-validator.c              |  221 +++++++++++++
 utils/services/rdfxml2metadatasample.xsl         |   22 +-
 utils/services/rdfxml2servicesample.xsl          |   61 ++++
 utils/services/resources/logo-maemo-ontology.png |  Bin 0 -> 3948 bytes
 utils/services/resources/nie-maemo.css           |  198 ++++++++++++
 utils/services/service2rdf-xml.py                |    2 +-
 utils/services/ttl2html.c                        |   89 ++++++
 utils/services/ttl_html.c                        |  293 ++++++++++++++++++
 utils/services/ttl_html.h                        |   18 ++
 utils/services/ttl_loader.c                      |  357 ++++++++++++++++++++++
 utils/services/ttl_loader.h                      |   21 ++
 utils/services/ttl_model.c                       |  118 +++++++
 utils/services/ttl_model.h                       |   54 ++++
 18 files changed, 1539 insertions(+), 7 deletions(-)

diff --git a/configure.ac b/configure.ac
index f75f37c..dc80edd 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1441,6 +1441,7 @@ AC_CONFIG_FILES([
 	utils/Makefile
 	utils/qdbm/Makefile
 	utils/tracker-fts/Makefile
+	utils/services/Makefile
 ])
 
 AC_OUTPUT
diff --git a/utils/Makefile.am b/utils/Makefile.am
index 641f2e7..bfe190c 100644
--- a/utils/Makefile.am
+++ b/utils/Makefile.am
@@ -5,5 +5,6 @@ build_sqlite_fts = tracker-fts
 endif
 
 SUBDIRS = 			\
+	services		\
 	$(build_sqlite_fts)	\
 	qdbm
diff --git a/utils/services/Makefile.am b/utils/services/Makefile.am
new file mode 100644
index 0000000..ca92326
--- /dev/null
+++ b/utils/services/Makefile.am
@@ -0,0 +1,32 @@
+include $(top_srcdir)/Makefile.decl
+
+noinst_PROGRAMS = ontology-validator ttl2html
+
+INCLUDES = 				\
+	-DG_LOG_DOMAIN=\"Tracker\"	\
+	$(WARN_CFLAGS)			\
+	$(GLIB2_CFLAGS)			\
+	$(RAPTOR_CFLAGS)		\
+	$(GIO_CFLAGS)
+
+ontology_validator_SOURCES =		\
+	ontology-validator.c
+
+ontology_validator_LDADD =		\
+	$(RAPTOR_LIBS) 			\
+	$(GLIB2_LIBS)			\
+	$(GIO_LIBS)							
+
+ttl2html_SOURCES =			\
+	ttl2html.c			\
+	ttl_loader.h			\
+	ttl_loader.c			\
+	ttl_model.h 			\
+	ttl_model.c			\
+	ttl_html.h			\
+	ttl_html.c
+
+ttl2html_LDADD = 			\
+	$(RAPTOR_LIBS) 			\
+	$(GLIB2_LIBS)			\
+	$(GIO_LIBS)	
diff --git a/utils/services/README.example b/utils/services/README.example
index 34bfdcd..42edbc5 100644
--- a/utils/services/README.example
+++ b/utils/services/README.example
@@ -1 +1,28 @@
+== ttl2html ==
+
+   This programs outputs in stdout a HTML representation of the TTL ontology file.
+
+   It receives as parameter an ontology TTL file, and
+   optionally the base URI for the classes in that ontology. This base
+   URI is used to turn the internal references in the ontology into
+   HTML anchors.
+
+   E.g.
+
+ ./ttl2html -f ../../data/ontologies/39-mto.ontology -u http://www.tracker-project.org/temp/mto#
+
+
+== ontology-validator ==
+
+   This program check that all files in the ontology are TTL
+   syntactically correct, and all referenced classes are defined
+   somewhere in the ontology.
+
+   It receives as parameter the ontology files directory. Usually:
+
+ ./ontology-validator -o ../../data/ontologies
+
+
+== Deprecated ==
+
 python ./service2xml.py < ../../data/services/email.metadata > t.xml ; xsltproc sample.xsl t.xml
diff --git a/utils/services/gen-doc.sh b/utils/services/gen-doc.sh
new file mode 100755
index 0000000..f4c4f69
--- /dev/null
+++ b/utils/services/gen-doc.sh
@@ -0,0 +1,31 @@
+#!/bin/bash
+
+#
+# This script generates the HTML documentation from TTL description 
+# for the tracker specific ontologies
+#
+BUILD_DIR="./build/ontologies"
+
+if [ -e $BUILD_DIR ]; then
+    echo "Removing old " $BUILD_DIR "directory"
+    rm -rf $BUILD_DIR
+fi
+
+echo "Creating new directory"
+mkdir -p $BUILD_DIR
+
+echo "Compiling the tools"
+make
+
+
+for f in `find ../../data/ontologies -name "*.description"` ; do 
+      # ../../data/ontologies/XX-aaa.description -> PREFIX=aaa
+      TMPNAME=${f%.description} 
+      PREFIX=${TMPNAME#*-}
+      echo "Generating $PREFIX"
+      mkdir -p $BUILD_DIR/$PREFIX
+      ./ttl2html -d $f -o $BUILD_DIR/$PREFIX/index.html
+done
+
+echo "Copying resources"
+cp -R resources/ $BUILD_DIR
\ No newline at end of file
diff --git a/utils/services/ontology-validator.c b/utils/services/ontology-validator.c
new file mode 100644
index 0000000..7ebcb9e
--- /dev/null
+++ b/utils/services/ontology-validator.c
@@ -0,0 +1,221 @@
+#include <raptor.h>
+#include <glib.h>
+#include <glib/gstdio.h>
+#include <gio/gio.h>
+#include <string.h>
+
+static gchar	     *ontology_dir = NULL;
+
+static GOptionEntry   entries[] = {
+	{ "ontology-dir", 'o', 0, G_OPTION_ARG_FILENAME, &ontology_dir,
+	  "Directory containing the ontology description files (TTL FORMAT)",
+	  NULL
+	},
+	{ NULL }
+};
+
+typedef void (* TurtleTripleCallback) (void *user_data, const raptor_statement *triple);
+
+#define RDFS_CLASS "http://www.w3.org/2000/01/rdf-schema#Class";
+#define RDF_PROPERTY "http://www.w3.org/1999/02/22-rdf-syntax-ns#Property";
+#define RDFS_SUBCLASSOF  "http://www.w3.org/2000/01/rdf-schema#subClassOf";
+#define RDFS_TYPE "http://www.w3.org/1999/02/22-rdf-syntax-ns#type";
+#define TRACKER_NAMESPACE "http://www.tracker-project.org/ontologies/tracker#Namespace";
+#define RDFS_RANGE "http://www.w3.org/2000/01/rdf-schema#range";
+#define RDFS_DOMAIN "http://www.w3.org/2000/01/rdf-schema#domain";
+
+static void 
+raptor_error (void *user_data, raptor_locator* locator, const char *message)
+{
+	g_message ("RAPTOR parse error: %s:%d:%d: %s\n", 
+		   (gchar *) user_data,
+		   locator->line,
+		   locator->column,
+		   message);
+}
+
+static GList *unknown_items = NULL;
+static GList *known_items = NULL;
+
+static gboolean
+exists_or_already_reported (const gchar *item)
+{
+        if (!g_list_find_custom (known_items, 
+                                 item, 
+                                 (GCompareFunc) g_strcmp0)){
+                if (!g_list_find_custom (unknown_items,
+                                         item,
+                                         (GCompareFunc) g_strcmp0)) {
+                        return FALSE;
+                }
+        }
+        return TRUE;
+}
+
+static void
+turtle_load_ontology (void                   *user_data,
+                      const raptor_statement *triple) 
+{
+
+        gchar *turtle_subject;
+        gchar *turtle_predicate;
+        char  *turtle_object;
+
+	/* set new statement */
+	turtle_subject = g_strdup ((const gchar *) raptor_uri_as_string ((raptor_uri *) triple->subject));
+	turtle_predicate = g_strdup ((const gchar *) raptor_uri_as_string ((raptor_uri *) triple->predicate));
+	turtle_object = g_strdup ((const gchar *) triple->object);
+
+        /* nmo:Email a rdfs:Class 
+         *  If rdfs:Class exists, add nmo:Email to the known_items 
+         **/
+        if (!g_strcmp0 (turtle_predicate, RDFS_TYPE)) {
+
+                if (!g_strcmp0 (turtle_object, TRACKER_NAMESPACE)) {
+                        /* Ignore the internal tracker namespace definitions */
+                        return;
+                }
+
+                /* Check the class is already defined */
+                if (!exists_or_already_reported (turtle_object)) {
+                        g_error ("Class %s is subclass of %s but %s is not defined",
+                                 turtle_subject, turtle_object, turtle_object);
+                } else {
+                        known_items = g_list_prepend (known_items, turtle_subject);
+                }
+        }
+
+        /*
+         * nmo:Message rdfs:subClassOf nie:InformationElement
+         *  Check nie:InformationElement is defined
+         */
+        if (!g_strcmp0 (turtle_predicate, RDFS_SUBCLASSOF)
+            || !g_strcmp0 (turtle_predicate, RDFS_RANGE)
+            || !g_strcmp0 (turtle_predicate, RDFS_DOMAIN)) {
+                /* Check the class is already defined */
+                if (!exists_or_already_reported (turtle_object)) {
+                        g_error ("Class %s refears to %s but it is not defined",
+                                 turtle_subject, turtle_object);
+                }
+        }
+
+
+}
+
+static void 
+process_file (const gchar *ttl_file, TurtleTripleCallback handler)
+{
+        FILE *file;
+        raptor_parser *parser;
+        raptor_uri *uri, *buri, *base_uri;
+	unsigned char  *uri_string;
+
+        g_print ("Processing %s\n", ttl_file);
+        file = g_fopen (ttl_file, "r");
+
+	parser = raptor_new_parser ("turtle");
+	base_uri = raptor_new_uri ((unsigned char *) "/");
+
+	raptor_set_statement_handler (parser, NULL, 
+                                      handler);
+	raptor_set_fatal_error_handler (parser, (void *)file, raptor_error);
+	raptor_set_error_handler (parser, (void *)file, raptor_error);
+	raptor_set_warning_handler (parser, (void *)file, raptor_error);
+
+	uri_string = raptor_uri_filename_to_uri_string (ttl_file);
+	uri = raptor_new_uri (uri_string);
+	buri = raptor_new_uri ((unsigned char *) base_uri);
+
+	raptor_parse_file (parser, uri, buri);
+
+	raptor_free_uri (uri);
+	raptor_free_parser (parser);
+	fclose (file);
+}
+
+static void
+load_ontology_files (const gchar *services_dir)
+{
+        GList       *files = NULL;
+        GDir        *services;
+        const gchar *conf_file;
+        GFile       *f;
+        gchar       *dir_uri, *fullpath;
+        
+        f = g_file_new_for_path (services_dir);
+        dir_uri = g_file_get_path (f);
+
+        g_print ("dir_uri %s\n", dir_uri);
+        services = g_dir_open (dir_uri, 0, NULL);
+        
+        conf_file = g_dir_read_name (services);
+                        
+        while (conf_file) {
+
+                if (!g_str_has_suffix (conf_file, "ontology")) {
+                        conf_file = g_dir_read_name (services);
+                        continue;
+                }
+                
+                fullpath = g_build_filename (dir_uri, conf_file, NULL);
+                files = g_list_insert_sorted (files, fullpath, (GCompareFunc) g_strcmp0);
+                conf_file = g_dir_read_name (services);
+        }
+
+        g_dir_close (services);
+
+        //process_file (fullpath, turtle_load_ontology, NULL);
+        g_list_foreach (files, (GFunc) process_file, turtle_load_ontology);
+
+        g_list_foreach (files, (GFunc) g_free, NULL);
+        g_object_unref (f);
+        g_free (dir_uri);
+}
+
+static void
+load_basic_classes ()
+{
+        known_items = g_list_prepend (known_items, RDFS_CLASS);
+        known_items = g_list_prepend (known_items, RDF_PROPERTY);
+}
+
+gint
+main (gint argc, gchar **argv) 
+{
+        GOptionContext *context;
+
+        g_type_init ();
+        raptor_init ();
+
+
+	/* Translators: this messagge will apper immediately after the	*/
+	/* usage string - Usage: COMMAND [OPTION]... <THIS_MESSAGE>	*/
+	context = g_option_context_new ("- Validate the ontology consistency");
+
+	/* Translators: this message will appear after the usage string */
+	/* and before the list of options.				*/
+	g_option_context_add_main_entries (context, entries, NULL);
+	g_option_context_parse (context, &argc, &argv, NULL);
+
+        if (!ontology_dir) {
+		gchar *help;
+
+		g_printerr ("%s\n\n",
+			    "Ontology directory is mandatory");
+
+		help = g_option_context_get_help (context, TRUE, NULL);
+		g_option_context_free (context);
+		g_printerr ("%s", help);
+		g_free (help);
+
+		return -1;
+        }
+
+        load_basic_classes ();
+        //"/home/ivan/devel/codethink/tracker-ssh/data/services"
+        load_ontology_files (ontology_dir);
+
+        raptor_finish ();
+
+        return 0;
+}
diff --git a/utils/services/rdfxml2metadatasample.xsl b/utils/services/rdfxml2metadatasample.xsl
index 0a5c758..af9d9a6 100644
--- a/utils/services/rdfxml2metadatasample.xsl
+++ b/utils/services/rdfxml2metadatasample.xsl
@@ -35,19 +35,29 @@
        <xsl:when test="substring-after($about, '#')">
          <xsl:if test="substring-before($about, '#') != 'XMLSchema'"><xsl:value-of select="substring-before($about, '#')"/>:</xsl:if><xsl:value-of select="substring-after($about, '#')"/>
        </xsl:when>
-       <xsl:otherwise>DC:<xsl:value-of select="$about"/></xsl:otherwise>
+       <xsl:otherwise>dc:<xsl:value-of select="$about"/></xsl:otherwise>
     </xsl:choose>
   </xsl:otherwise>
  </xsl:choose>
 </xsl:template>
 
+<xsl:template name="convert-datatype-of">
+ <xsl:param name="datatype"/>
+ <xsl:choose>
+  <xsl:when test="substring-after($datatype, ':')">resource</xsl:when>
+  <xsl:when test="$datatype = 'float'">double</xsl:when>
+  <xsl:when test="$datatype = 'dateTime'">date</xsl:when>
+  <xsl:otherwise><xsl:value-of select="$datatype"/></xsl:otherwise>
+ </xsl:choose>
+</xsl:template>
+
 <xsl:template match="rdf:RDF">
 <xsl:for-each select="rdf:Property">
 
-[<xsl:call-template name="predicate-of"><xsl:with-param name="about"><xsl:value-of select="@rdf:about"/></xsl:with-param></xsl:call-template>]
-<xsl:choose>
+[<xsl:call-template name="predicate-of"><xsl:with-param name="about"><xsl:value-of select="@rdf:about"/></xsl:with-param></xsl:call-template>]<xsl:choose>
 <xsl:when test="rdfs:range">
-DataType=<xsl:call-template name="predicate-of"><xsl:with-param name="about"><xsl:value-of select="rdfs:range/@rdf:resource"/></xsl:with-param></xsl:call-template>
+DataType=<xsl:call-template name="convert-datatype-of"><xsl:with-param name="datatype">
+<xsl:call-template name="predicate-of"><xsl:with-param name="about"><xsl:value-of select="rdfs:range/@rdf:resource"/></xsl:with-param></xsl:call-template></xsl:with-param></xsl:call-template>
 </xsl:when>
 <xsl:otherwise>Abstract=true
 DataType=string</xsl:otherwise>
@@ -60,8 +70,8 @@ DisplayName=<xsl:value-of select="rdfs:label"/>
 Domain=<xsl:call-template name="predicate-of"><xsl:with-param name="about"><xsl:value-of select="rdfs:domain/@rdf:resource"/></xsl:with-param></xsl:call-template></xsl:if>
 
 <xsl:if test="rdfs:subPropertyOf">
-SuperProperties=<xsl:for-each select="rdfs:subPropertyOf"><xsl:if test="@rdf:resource"><xsl:call-template name="predicate-of"><xsl:with-param name="about"><xsl:value-of select="@rdf:resource"/></xsl:with-param></xsl:call-template>;</xsl:if><xsl:for-each select="rdfs:subPropertyOf/rdf:Property"><xsl:call-template name="predicate-of"><xsl:with-param name="about"><xsl:value-of select="@rdf:about"/></xsl:with-param></xsl:call-template>;</xsl:for-each></xsl:for-each></xsl:if>
-
+SuperProperties=<xsl:for-each select="rdfs:subPropertyOf">
+<xsl:if test="@rdf:resource"><xsl:call-template name="predicate-of"><xsl:with-param name="about"><xsl:value-of select="@rdf:resource"/></xsl:with-param></xsl:call-template>;</xsl:if><xsl:for-each select="rdf:Property"><xsl:call-template name="predicate-of"><xsl:with-param name="about"><xsl:value-of select="@rdf:about"/></xsl:with-param></xsl:call-template>;</xsl:for-each></xsl:for-each></xsl:if>
 <xsl:if test="rdfs:comment">
 Description=<xsl:value-of select="rdfs:comment"/></xsl:if>
 </xsl:for-each>
diff --git a/utils/services/rdfxml2servicesample.xsl b/utils/services/rdfxml2servicesample.xsl
new file mode 100644
index 0000000..43d28cd
--- /dev/null
+++ b/utils/services/rdfxml2servicesample.xsl
@@ -0,0 +1,61 @@
+<xsl:stylesheet version = '1.0'
+     xmlns:xsl='http://www.w3.org/1999/XSL/Transform'
+  xmlns:nid3="http://www.semanticdesktop.org/ontologies/2007/05/10/nid3#";
+  xmlns:nfo="http://www.semanticdesktop.org/ontologies/2007/03/22/nfo#";
+  xmlns:nmo="http://www.semanticdesktop.org/ontologies/2007/03/22/nmo#";
+  xmlns:nie="http://www.semanticdesktop.org/ontologies/2007/01/19/nie#";
+  xmlns:exif="http://www.kanzaki.com/ns/exif#";
+  xmlns:nao="http://www.semanticdesktop.org/ontologies/2007/08/15/nao#";
+  xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#";
+  xmlns:protege="http://protege.stanford.edu/system#";
+  xmlns:dcterms="http://purl.org/dc/terms/";
+  xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#";
+  xmlns:ncal="http://www.semanticdesktop.org/ontologies/2007/04/02/ncal#";
+  xmlns:xsd="http://www.w3.org/2001/XMLSchema#";
+  xmlns:nrl="http://www.semanticdesktop.org/ontologies/2007/08/15/nrl#";
+  xmlns:pimo="http://www.semanticdesktop.org/ontologies/2007/11/01/pimo#";
+  xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#";
+  xmlns:tmo="http://www.semanticdesktop.org/ontologies/2008/05/20/tmo#";
+  xmlns:dc="http://purl.org/dc/elements/1.1/";
+  xmlns:nco="http://www.semanticdesktop.org/ontologies/2007/03/22/nco#";
+  xmlns:nexif="http://www.semanticdesktop.org/ontologies/2007/05/10/nexif#";>
+
+<xsl:output method="text" />
+
+<xsl:template name="predicate-of">
+ <xsl:param name="about"/>
+ <xsl:choose>
+  <xsl:when test="substring-after($about, '/')">
+   <xsl:call-template name="predicate-of">
+     <xsl:with-param name="about" select="substring-after($about, '/')"/>
+   </xsl:call-template>
+  </xsl:when>
+  <xsl:otherwise>
+     <xsl:choose>
+       <xsl:when test="substring-after($about, '#')">
+         <xsl:if test="substring-before($about, '#') != 'XMLSchema'"><xsl:value-of select="substring-before($about, '#')"/>:</xsl:if><xsl:value-of select="substring-after($about, '#')"/>
+       </xsl:when>
+       <xsl:otherwise>dc:<xsl:value-of select="$about"/></xsl:otherwise>
+    </xsl:choose>
+  </xsl:otherwise>
+ </xsl:choose>
+</xsl:template>
+
+<xsl:template match="rdf:RDF">
+<xsl:for-each select="rdfs:Class">
+
+[<xsl:call-template name="predicate-of"><xsl:with-param name="about"><xsl:value-of select="@rdf:about"/></xsl:with-param></xsl:call-template>]<xsl:if test="rdfs:label">
+DisplayName=<xsl:value-of select="rdfs:label"/>
+</xsl:if>
+<xsl:if test="rdfs:subClassOf">
+SuperClasses=<xsl:for-each select="rdfs:subClassOf">
+<xsl:if test="@rdf:resource">
+<!-- xsl:if test="substring-after(@rdf:resource, '#') != 'Resource'" //-->
+<xsl:call-template name="predicate-of"><xsl:with-param name="about"><xsl:value-of select="@rdf:resource"/></xsl:with-param></xsl:call-template>;</xsl:if><!-- /xsl:if //-->
+<xsl:for-each select="rdfs:Class"><xsl:call-template name="predicate-of"><xsl:with-param name="about"><xsl:value-of select="@rdf:about"/></xsl:with-param></xsl:call-template>;</xsl:for-each></xsl:for-each></xsl:if>
+<xsl:if test="rdfs:comment">
+Description=<xsl:value-of select="rdfs:comment"/></xsl:if>
+</xsl:for-each>
+</xsl:template>
+</xsl:stylesheet> 
+
diff --git a/utils/services/resources/logo-maemo-ontology.png b/utils/services/resources/logo-maemo-ontology.png
new file mode 100644
index 0000000..3e8f43e
Binary files /dev/null and b/utils/services/resources/logo-maemo-ontology.png differ
diff --git a/utils/services/resources/nie-maemo.css b/utils/services/resources/nie-maemo.css
new file mode 100644
index 0000000..6ac96a4
--- /dev/null
+++ b/utils/services/resources/nie-maemo.css
@@ -0,0 +1,198 @@
+/* Adapted from a "Style for an "Interest Group Note" */ /*
+   Copyright 1997-2003 W3C (MIT, ERCIM, Keio). All Rights Reserved.
+   The following software licensing rules apply:
+   http://www.w3.org/Consortium/Legal/copyright-software */
+
+body {
+	padding: 2em 1em 2em 70px;
+	margin: 0;
+	font-family: sans-serif;
+	color: black;
+	background: white;
+	background-position: top left;
+	background-attachment: fixed;
+	background-repeat: no-repeat;
+}
+
+blockquote { margin-top: 0pt; margin-bottom: 0pt; text-align: justify }
+
+pre { border: 1.00pt solid #000000; padding: 0.02in; width:85%; }
+    
+blockquote pre { border: none; width: 100% }
+    
+p {text-indent: 15pt}
+    
+.footnotes { font-size: smaller; background-color:#fef; width: 70% }
+    
+address {text-align: right; text-indent: 15pt}
+
+:link {
+	color: #856347;
+	background: transparent
+}
+
+table {
+	border: solid;
+	width: 100%;
+	border-collapse: collapse;
+}
+
+td {
+	border: 1px solid black;
+}
+
+TD.rowheader {
+	width: 20%;	
+}
+
+:visited {
+	color: #609;
+	background: transparent
+}
+
+a:active {
+	color: #C00;
+	background: transparent
+}
+
+a:link img,a:visited img {
+	border-style: none
+}
+
+/* no border on img links */
+a img {
+	color: white;
+}
+
+/* trick to hide the border in Netscape 4 */
+ media all { 
+	/* hide the next rule from Netscape 4 */
+	a img {
+		color: inherit;
+	} 
+	/* undo the color change above */
+}
+
+th,td { 
+	/* ns 4 */
+	font-family: sans-serif;
+}
+
+h1,h2,h3,h4,h5,h6 {
+	text-align: left
+}
+
+/* background should be transparent, but WebTV has a bug */
+h1,h2,h3 {
+	color: #CE5C00;
+	background: white
+}
+
+h1 {
+	font: 170% sans-serif
+}
+
+h2 {
+	font: 140% sans-serif
+}
+
+h3 {
+	font: 120% sans-serif
+}
+
+h4 {
+	font: bold 100% sans-serif
+}
+
+h5 {
+	font: italic 100% sans-serif
+}
+
+h6 {
+	font: small-caps 100% sans-serif
+}
+
+.hide {
+	display: none
+}
+
+div.head {
+	margin-bottom: 1em
+}
+
+div.head h1 {
+	margin-top: 2em;
+	clear: both
+}
+
+div.head table {
+	margin-left: 2em;
+	margin-top: 2em
+}
+
+p.copyright {
+	font-size: small
+}
+
+p.copyright small {
+	font-size: small
+}
+
+ media screen { /* hide from IE3 */
+	a [href]:hover {
+		background: #ffa
+	}
+}
+
+pre {
+	margin-left: 2em
+}
+
+/*
+p {
+  margin-top: 0.6em;
+  margin-bottom: 0.6em;
+}
+*/
+dt,dd {
+	margin-top: 0;
+	margin-bottom: 0
+}  /* opera 3.50 */
+dt {
+	font-weight: bold
+}
+
+pre,code {
+	font-family: monospace
+}  /* navigator 4 requires this */
+ul.toc,ol.toc {
+	list-style: disc; /* Mac NS has problem with 'none' */
+	list-style: none;
+}
+
+ media aural {
+	h1,h2,h3 {
+		stress: 20;
+		richness: 90
+	}
+	.hide {
+		speak: none
+	}
+	p.copyright {
+		volume: x-soft;
+		speech-rate: x-fast
+	}
+	dt {
+		pause-before: 20%
+	}
+	pre {
+		speak-punctuation: code
+	}
+}
+
+/* Copyright 1997-2003 W3C (MIT, ERCIM, Keio). All Rights Reserved.
+   The following software licensing rules apply:
+   http://www.w3.org/Consortium/Legal/copyright-software */
+body {
+	background-image: url(logo-maemo-ontology.png);
+}
\ No newline at end of file
diff --git a/utils/services/service2rdf-xml.py b/utils/services/service2rdf-xml.py
index 8b6f2ff..a309c55 100644
--- a/utils/services/service2rdf-xml.py
+++ b/utils/services/service2rdf-xml.py
@@ -94,7 +94,7 @@ def main():
            if name == "weight":
             print "\t\t<rdfs:comment>Weight is " + value + "</rdfs:comment>"
 
-        print "\t</rdfs:Property>"
+        print "\t</rdf:Property>"
 
      print "</rdf:RDF>"
   except getopt.GetoptError, err:
diff --git a/utils/services/ttl2html.c b/utils/services/ttl2html.c
new file mode 100644
index 0000000..c3bbe05
--- /dev/null
+++ b/utils/services/ttl2html.c
@@ -0,0 +1,89 @@
+#include <glib.h>
+#include <gio/gio.h>
+#include <string.h>
+#include <stdio.h>
+#include "ttl_loader.h"
+#include "ttl_model.h"
+#include "ttl_html.h"
+
+static gchar *desc_file = NULL;
+static gchar *output_file = NULL;
+
+static GOptionEntry   entries[] = {
+	{ "desc", 'd', 0, G_OPTION_ARG_FILENAME, &desc_file,
+	  "TTL file with the ontology description and documentation",
+	  NULL
+	},
+	{ "output", 'o', 0, G_OPTION_ARG_FILENAME, &output_file,
+	  "File to write the output (default stdout)",
+	  NULL
+	},
+	{ NULL }
+};
+
+gint
+main (gint argc, gchar **argv) 
+{
+        GOptionContext *context;
+        Ontology *ontology = NULL;
+        OntologyDescription *description = NULL;
+        gchar *ttl_file = NULL;
+        gchar *dirname = NULL;
+        FILE *f = NULL;
+
+        g_type_init ();
+
+	/* Translators: this messagge will apper immediately after the	*/
+	/* usage string - Usage: COMMAND [OPTION]... <THIS_MESSAGE>	*/
+	context = g_option_context_new ("- Generates HTML doc for a TTL file");
+
+	/* Translators: this message will appear after the usage string */
+	/* and before the list of options.				*/
+	g_option_context_add_main_entries (context, entries, NULL);
+	g_option_context_parse (context, &argc, &argv, NULL);
+
+        if (!desc_file) {
+		gchar *help;
+
+		g_printerr ("%s\n\n",
+			    "Description file is mandatory");
+
+		help = g_option_context_get_help (context, TRUE, NULL);
+		g_option_context_free (context);
+		g_printerr ("%s", help);
+		g_free (help);
+
+		return -1;
+        }
+
+        if (output_file) {
+                f = fopen (output_file, "w");
+        } else {
+                f = stdout;
+        }
+        g_assert (f != NULL);
+
+        ttl_loader_init ();
+        description = ttl_loader_load_description (desc_file);
+
+        dirname = g_path_get_dirname (desc_file);
+        ttl_file = g_build_filename (dirname,
+                                     description->relativePath, 
+                                     NULL);
+
+        ontology = ttl_loader_load_ontology (ttl_file);
+        g_free (ttl_file);
+        g_free (dirname);
+
+        ttl_html_print (description, ontology, f);
+
+        ttl_loader_free_ontology (ontology);
+        ttl_loader_free_description (description);
+
+        ttl_loader_shutdown ();
+        g_option_context_free (context);
+        
+        fclose (f);
+
+        return 0;
+}
diff --git a/utils/services/ttl_html.c b/utils/services/ttl_html.c
new file mode 100644
index 0000000..c9ab7bc
--- /dev/null
+++ b/utils/services/ttl_html.c
@@ -0,0 +1,293 @@
+#include "ttl_html.h"
+#include <glib/gprintf.h>
+
+static gchar *local_uri = NULL;
+
+typedef struct {
+        gchar *namespace;
+        gchar *uri;
+} Namespace;
+
+Namespace NAMESPACES [] = {
+        {"dc", "http://purl.org/dc/elements/1.1/"},
+        {"fts", "http://www.tracker-project.org/ontologies/fts#"},
+        {"mto", "http://www.tracker-project.org/temp/mto#"},
+        {"nao", "http://www.semanticdesktop.org/ontologies/2007/08/15/nao#"},
+        {"ncal", "http://www.semanticdesktop.org/ontologies/2007/04/02/ncal#"},
+        {"nco", "http://www.semanticdesktop.org/ontologies/2007/03/22/nco#"},
+        {"nfo", "http://www.semanticdesktop.org/ontologies/2007/03/22/nfo#"},
+        {"nid3", "http://www.semanticdesktop.org/ontologies/2007/05/10/nid3#"},
+        {"nie", "http://www.semanticdesktop.org/ontologies/2007/01/19/nie#"},
+        {"nmm", "http://www.tracker-project.org/temp/nmm#"},
+        {"nmo", "http://www.semanticdesktop.org/ontologies/2007/03/22/nmo#"},
+        {"nrl", "http://www.semanticdesktop.org/ontologies/2007/08/15/nrl#"},
+        {"rdf", "http://www.w3.org/1999/02/22-rdf-syntax-ns#"},
+        {"rdfs", "http://www.w3.org/2000/01/rdf-schema#"},
+        {"tracker", "http://www.tracker-project.org/ontologies/tracker#"},
+        {"xsd", "http://www.w3.org/2001/XMLSchema#"},
+        {NULL, NULL}
+};
+
+typedef struct {
+        Ontology *ontology;
+        OntologyDescription *description;
+        FILE *output;
+} CallbackInfo;
+
+static gchar *
+qname_to_link (const gchar *qname)
+{
+        gchar **pieces;
+        gchar *name;
+
+        if (local_uri) {
+                /* There is a local URI! */
+                if (g_str_has_prefix (qname, local_uri)) {
+                        pieces = g_strsplit (qname, "#", 2);
+                        g_assert (g_strv_length (pieces) == 2);
+                        name = g_strdup_printf ("#%s", pieces[1]);
+                        g_strfreev (pieces);
+                        return name;
+                }
+        }
+        
+        return g_strdup (qname);
+}
+
+static gchar *
+qname_to_shortname (const gchar *qname)
+{
+        gchar **pieces;
+        gchar  *name = NULL;
+        gint    i;
+
+        for (i = 0; NAMESPACES[i].namespace != NULL; i++) {
+                if (g_str_has_prefix (qname, NAMESPACES[i].uri)) {
+                        pieces = g_strsplit (qname, "#", 2);
+                        g_assert (g_strv_length (pieces) == 2);
+
+                        name = g_strdup_printf ("%s:%s", 
+                                                NAMESPACES[i].namespace, 
+                                                pieces[1]);
+                        g_strfreev (pieces);
+                        break;
+                }
+        }
+
+        if (!name) {
+                return g_strdup (qname);
+        } else {
+                return name;
+        }
+}
+
+static void
+print_author (gpointer item, gpointer user_data) {
+        FILE *f = (FILE *)user_data;
+        g_fprintf (f,"<dd>%s</dd>", (gchar *)item);
+}
+
+static void
+print_reference (gpointer item, gpointer user_data)
+{
+        gchar *shortname;
+        gchar *link;
+        FILE *f = (FILE *)user_data;
+
+        shortname = qname_to_shortname ((gchar *)item);
+        link = qname_to_link ((gchar *)item);
+
+        g_fprintf (f,"<a href=\"%s\">%s</a>, ", link , shortname);
+
+        g_free (shortname);
+        g_free (link);
+}
+
+
+
+static void
+print_references_list (FILE *f, GList *list)
+{
+        g_fprintf (f,"<td>");
+        if (list == NULL) {
+                g_fprintf (f,"--");
+        } else {
+                g_list_foreach (list, print_reference, f);
+        }
+        g_fprintf (f,"</td>");
+}
+
+
+static void
+print_html_header (FILE *f, OntologyDescription *desc)
+{
+        g_fprintf (f,"<html>\n");
+        g_fprintf (f,"<head>\n");
+        g_fprintf (f,"\t<link rel=\"stylesheet\" type=\"text/css\"");
+        g_fprintf (f," href=\"../resources/nie-maemo.css\" />\n");
+        g_fprintf (f,"<title>%s</title>\n", desc->title);
+        g_fprintf (f,"</head>\n");
+        g_fprintf (f,"<body>\n");
+        g_fprintf (f,"<div class=\"head\">\n");
+        g_fprintf (f," <div class=\"nav\">\n");
+        g_fprintf (f," <a href=\"http://www.maemo.org\";> <img alt=\"MAEMO logo\" ");
+        g_fprintf (f," src=\"http://static.maemo.org/style_maemo2007/maemo-logo.gif\"; /></a>\n");
+        g_fprintf (f,"</div>\n");
+// style="border: 0px solid ; width: 180px; height: 88px;"  /> </a> </div>
+
+        g_fprintf (f,"<h1>%s</h1>\n", desc->title);
+        g_fprintf (f," <dl>\n");
+        g_fprintf (f,"  <dt>Latest Version</dt><dd>FIXME</dd>\n");
+        g_fprintf (f,"  <dt></dt>\n");
+        g_fprintf (f,"  <dt>This Version</dt><dd>FIXME</dd>\n");
+        g_fprintf (f,"  <dt></dt>\n");
+        g_fprintf (f,"  <dt>Authors:</dt>\n");
+        g_list_foreach (desc->authors, print_author, f);
+        g_fprintf (f,"  <dt>Editors:</dt>\n");
+        g_list_foreach (desc->editors, print_author, f);
+        g_fprintf (f,"  <dt>Contributors:</dt>\n");
+        g_list_foreach (desc->contributors, print_author, f);
+        g_fprintf (f," </dl>\n");
+        g_fprintf (f,"</div>\n");
+        g_fprintf (f,"<p class=\"copyright\"> Copyright &copy; 2009 <a href=\"http://www.nokia.com/\";>Nokia</a><sup>&reg;</sup> The ontologies are made available under the terms of FIXME<a href=\"LICENSE.txt\">software license</a></p>\n");
+
+        g_fprintf (f,"<hr />\n");
+
+
+}
+
+static void
+print_html_footer (FILE *f)
+{
+        g_fprintf (f,"</body>\n");
+        g_fprintf (f,"</html>\n");
+}
+
+
+static void
+print_ontology_class (gpointer key, gpointer value, gpointer user_data) 
+{
+        OntologyClass *def = (OntologyClass *)value;
+        gchar *name, *anchor;
+        FILE *f = (FILE *)user_data;
+
+        g_return_if_fail (f != NULL);
+
+        name = qname_to_shortname (def->classname);
+        anchor = qname_to_link (def->classname);
+        
+        /* Anchor without initial '#' */
+        g_fprintf (f,"<a name=\"%s\">\n", &anchor[1]); 
+        g_free (anchor);
+
+        g_fprintf (f,"<h3>%s</h3>\n", name);
+        g_free (name);
+
+        g_fprintf (f,"<table class=\"doctable\">\n");
+
+        g_fprintf (f,"<tr>");
+        g_fprintf (f,"<td class=\"rowheader\">Superclasses</td>");
+        print_references_list (f, def->superclasses);
+        g_fprintf (f,"</tr>\n");
+
+        g_fprintf (f,"<tr>");
+        g_fprintf (f,"<td class=\"rowheader\">Subclasses</td>");
+        print_references_list (f, def->subclasses);
+        g_fprintf (f,"</tr>\n");
+
+        g_fprintf (f,"<tr>");
+        g_fprintf (f,"<td class=\"rowheader\">In domain of</td>");
+        print_references_list (f, def->in_domain_of);
+        g_fprintf (f,"</tr>\n");
+
+        g_fprintf (f,"<tr>");
+        g_fprintf (f,"<td class=\"rowheader\">In range of</td>");
+        print_references_list (f, def->in_range_of);
+        g_fprintf (f,"</tr>\n");
+
+        g_fprintf (f,"<tr>");
+        g_fprintf (f,"<td class=\"rowheader\">Description</td>");
+        g_fprintf (f,"<td>%s</td>\n", (def->description ? def->description : "--"));
+        g_fprintf (f,"</tr>\n");
+
+        g_fprintf (f,"</table>\n\n");
+
+}
+
+static void
+print_ontology_property (gpointer key, gpointer value, gpointer user_data) 
+{
+        OntologyProperty *def = (OntologyProperty *)value;
+        gchar *name, *anchor;
+        FILE *f = (FILE *)user_data;
+
+        g_return_if_fail (f != NULL);
+
+        name = qname_to_shortname (def->propertyname);
+        anchor = qname_to_link (def->propertyname);
+        
+        /* Anchor without initial '#' */
+        g_fprintf (f,"<a name=\"%s\">", &anchor[1]); 
+        g_free (anchor);
+
+        g_fprintf (f,"<h3>%s</h3>\n", name);
+        g_free (name);
+        g_fprintf (f,"<table class=\"doctable\">\n");
+
+        g_fprintf (f,"<tr>");
+        g_fprintf (f,"<td class=\"rowheader\">Type</td>");
+        print_references_list (f, def->type);
+        g_fprintf (f,"</tr>\n");
+
+        g_fprintf (f,"<tr>");
+        g_fprintf (f,"<td class=\"rowheader\">Domain</td>");
+        print_references_list (f, def->domain);
+        g_fprintf (f,"</tr>\n");
+
+        g_fprintf (f,"<tr>");
+        g_fprintf (f,"<td class=\"rowheader\">Range</td>");
+        print_references_list (f, def->range);
+        g_fprintf (f,"</tr>\n");
+        
+        g_fprintf (f,"<tr>");
+        g_fprintf (f,"<td class=\"rowheader\">Superproperties</td>");
+        print_references_list (f, def->superproperties);
+        g_fprintf (f,"</tr>\n");
+
+        g_fprintf (f,"<tr>");
+        g_fprintf (f,"<td class=\"rowheader\">Subproperties</td>");
+        print_references_list (f, def->subproperties);
+        g_fprintf (f,"</tr>\n");
+
+        if (def->max_cardinality) {
+                g_fprintf (f,"<tr>");
+                g_fprintf (f,"<td class=\"rowheader\">Maximal cardinality</td>");
+                g_fprintf (f,"<td>%s</td", def->max_cardinality);
+                g_fprintf (f,"</tr>\n");
+        }
+
+        g_fprintf (f,"<tr>");
+        g_fprintf (f,"<td class=\"rowheader\">Description</td>");
+        g_fprintf (f,"<td>%s</td>\n", (def->description ? def->description : "--"));
+        g_fprintf (f,"</tr>\n");
+
+        g_fprintf (f,"</table>\n\n");
+}
+
+
+
+void 
+ttl_html_print (OntologyDescription *description,
+                Ontology *ontology,
+                FILE *f)
+{
+
+        local_uri = description->baseUrl;
+        print_html_header (f, description);
+        g_fprintf (f,"<h2>Ontology Classes Descriptions</h2>");
+        g_hash_table_foreach (ontology->classes, print_ontology_class, f);
+        g_fprintf (f,"<h2>Ontology Properties Descriptions</h2>");
+        g_hash_table_foreach (ontology->properties, print_ontology_property, f);
+
+        print_html_footer (f);
+}
diff --git a/utils/services/ttl_html.h b/utils/services/ttl_html.h
new file mode 100644
index 0000000..019b001
--- /dev/null
+++ b/utils/services/ttl_html.h
@@ -0,0 +1,18 @@
+#ifndef __TTL_HTML_H__
+#define __TTL_HTML_H__
+
+#include <gio/gio.h>
+#include "ttl_model.h"
+#include <stdio.h>
+
+G_BEGIN_DECLS
+
+void ttl_html_print (OntologyDescription *description,
+                     Ontology *ontology,
+                     FILE *output);
+
+
+
+G_END_DECLS
+
+#endif
diff --git a/utils/services/ttl_loader.c b/utils/services/ttl_loader.c
new file mode 100644
index 0000000..98a4653
--- /dev/null
+++ b/utils/services/ttl_loader.c
@@ -0,0 +1,357 @@
+#include "ttl_loader.h"
+#include <raptor.h>
+#include <glib/gstdio.h>
+
+typedef void (* TurtleTripleCallback) (void *user_data, const raptor_statement *triple);
+
+/* Ontology classes */
+#define RDFS_CLASS "http://www.w3.org/2000/01/rdf-schema#Class";
+#define RDF_PROPERTY "http://www.w3.org/1999/02/22-rdf-syntax-ns#Property";
+#define RDFS_SUBCLASSOF  "http://www.w3.org/2000/01/rdf-schema#subClassOf";
+#define RDFS_TYPE "http://www.w3.org/1999/02/22-rdf-syntax-ns#type";
+#define RDFS_RANGE "http://www.w3.org/2000/01/rdf-schema#range";
+#define RDFS_DOMAIN "http://www.w3.org/2000/01/rdf-schema#domain";
+#define RDFS_COMMENT "http://www.w3.org/2000/01/rdf-schema#comment";
+#define RDFS_LABEL "http://www.w3.org/2000/01/rdf-schema#label"; 
+#define RDFS_SUBPROPERTYOF "http://www.w3.org/2000/01/rdf-schema#subPropertyOf";
+
+#define NRL_MAX_CARDINALITY "http://www.semanticdesktop.org/ontologies/2007/08/15/nrl#maxCardinality";
+
+#define TRACKER_NAMESPACE "http://www.tracker-project.org/ontologies/tracker#Namespace";
+
+/* Ontology description */
+#define DSC_PREFIX "http://www.tracker-project.org/temp/dsc#";
+
+#define DSC_ONTOLOGY DSC_PREFIX "Ontology"
+#define DSC_TITLE DSC_PREFIX "title"
+#define DSC_AUTHOR DSC_PREFIX "author"
+#define DSC_EDITOR DSC_PREFIX "editor"
+#define DSC_CONTRIBUTOR DSC_PREFIX "contributor"
+#define DSC_BASEURI DSC_PREFIX "baseUrl"
+#define DSC_RELPATH DSC_PREFIX "relativePath"
+
+static gboolean initialized = FALSE;
+
+void
+ttl_loader_init (void)
+{
+        if (!initialized) {
+                raptor_init ();
+                initialized = TRUE;
+        }
+}
+
+void
+ttl_loader_shutdown (void)
+{
+        if (initialized) {
+                raptor_finish ();
+                initialized = FALSE;
+        }
+}
+
+
+static void 
+raptor_error (void *user_data, raptor_locator* locator, const char *message)
+{
+	g_message ("RAPTOR parse error: %s:%d:%d: %s\n", 
+		   (gchar *) user_data,
+		   locator->line,
+		   locator->column,
+		   message);
+}
+
+
+
+static void
+load_in_memory (void                   *user_data,
+                const raptor_statement *triple) 
+{
+
+        gchar *turtle_subject;
+        gchar *turtle_predicate;
+        char  *turtle_object;
+        Ontology *ontology = (Ontology *)user_data;
+
+        g_return_if_fail (ontology != NULL);
+
+	/* set new statement */
+	turtle_subject = g_strdup ((const gchar *) raptor_uri_as_string ((raptor_uri *) triple->subject));
+	turtle_predicate = g_strdup ((const gchar *) raptor_uri_as_string ((raptor_uri *) triple->predicate));
+	turtle_object = g_strdup ((const gchar *) triple->object);
+
+        if (!g_strcmp0 (turtle_predicate, RDFS_TYPE)) {
+                /* It is a definition of class or property */
+                if (!g_strcmp0 (turtle_object, RDFS_CLASS)) {
+                        g_hash_table_insert (ontology->classes, 
+                                             g_strdup (turtle_subject), 
+                                             ttl_model_class_new (turtle_subject));
+
+                } else if (!g_strcmp0 (turtle_object, RDF_PROPERTY)) {
+                        g_hash_table_insert (ontology->properties,
+                                             g_strdup (turtle_subject), 
+                                             ttl_model_property_new (turtle_subject));
+
+                } else {
+                        /* g_print ("FIXME Ignoring %s %s %s\n",
+                                 turtle_subject, turtle_predicate, turtle_object);
+                        */
+                }
+
+        } else if (!g_strcmp0 (turtle_predicate, RDFS_SUBCLASSOF)) {
+                /*
+                 * A subclass of B: 
+                 *  - Add B in A->superclasses list 
+                 *  - Add A in B->subclasses list (if B is in this ontology!)
+                 */
+                OntologyClass *def;
+
+                def = g_hash_table_lookup (ontology->classes, turtle_subject);
+                if (!def) {
+                        g_error ("Something wrong");
+                }
+
+                def->superclasses = g_list_prepend (def->superclasses, 
+                                                    g_strdup (turtle_object));
+
+                def = g_hash_table_lookup (ontology->classes, turtle_object);
+                if (def) {
+                        def->subclasses = g_list_prepend (def->subclasses, 
+                                                          g_strdup (turtle_subject));
+                }
+        } else if (!g_strcmp0 (turtle_predicate, RDFS_COMMENT)) {
+                OntologyClass *klass;
+                OntologyProperty *prop;
+
+                klass = g_hash_table_lookup (ontology->classes, turtle_subject);
+                if (klass) {
+                        klass->description = g_strdup (turtle_object);
+                } else {
+                        prop = g_hash_table_lookup (ontology->properties, turtle_subject);
+                        if (prop) {
+                                prop->description = g_strdup (turtle_object);
+                        } else {
+                                g_error ("UHUMMM %s", turtle_subject);
+                        }
+                }
+
+        } else if (!g_strcmp0 (turtle_predicate, RDFS_DOMAIN)) {
+                /*
+                 * (prop A) has domain (class B)
+                 *  -> add B in A->domain
+                 *  -> add A in B->in_domain_of (if B is defined in this ontology!)
+                 */
+                OntologyProperty *prop;
+                OntologyClass *klass;
+
+                prop = g_hash_table_lookup (ontology->properties, turtle_subject);
+                if (!prop) {
+                        g_error ("Strange error in domain (%s doesnt exist!)",
+                                 turtle_subject);
+                }
+                prop->domain = g_list_prepend (prop->domain, g_strdup (turtle_object));
+
+                klass = g_hash_table_lookup (ontology->classes, turtle_object);
+                if (klass) {
+                        klass->in_domain_of = g_list_prepend (klass->in_domain_of,
+                                                              g_strdup (turtle_subject));
+                }
+                
+        } else if (!g_strcmp0 (turtle_predicate, RDFS_RANGE)) {
+                /*
+                 * (prop A) has range (class B)
+                 *  -> add B in A->range
+                 *  -> add A in B->in_range_of (if B is defined in this ontology!)
+                 */
+                OntologyProperty *prop;
+                OntologyClass *klass;
+
+                prop = g_hash_table_lookup (ontology->properties, turtle_subject);
+                if (!prop) {
+                        g_error ("Strange error in domain (%s doesnt exist!)",
+                                 turtle_subject);
+                }
+                prop->range = g_list_prepend (prop->range, g_strdup (turtle_object));
+
+                klass = g_hash_table_lookup (ontology->classes, turtle_object);
+                if (klass) {
+                        klass->in_range_of = g_list_prepend (klass->in_range_of,
+                                                              g_strdup (turtle_subject));
+                }
+        } else if (!g_strcmp0 (turtle_predicate, NRL_MAX_CARDINALITY)) {
+                OntologyProperty *prop;
+
+                prop = g_hash_table_lookup (ontology->properties, turtle_subject);
+                if (!prop) {
+                        g_error ("Strange error in max cardinality (%s doesnt exist!)",
+                                 turtle_subject);
+                }
+                prop->max_cardinality = g_strdup (turtle_object);
+
+        } else if (!g_strcmp0 (turtle_predicate, RDFS_SUBPROPERTYOF)) {
+                /*
+                 * (prop A) is subproperty of (prop B)
+                 *  -> add B in A->superproperties
+                 *  -> add A in B->subproperties (if B is in this ontology)
+                 */
+                OntologyProperty *propA, *propB;
+                
+                propA = g_hash_table_lookup (ontology->properties, turtle_subject);
+                if (!propA) {
+                        g_error ("Strange error in subpropertyof (%s doesnt exist!)",
+                                 turtle_subject);
+                }
+                propA->superproperties = g_list_prepend (propA->superproperties,
+                                                         g_strdup (turtle_object));
+
+                propB = g_hash_table_lookup (ontology->properties, turtle_object);
+                if (propB) {
+                        propB->subproperties = g_list_prepend (propB->subproperties,
+                                                               g_strdup (turtle_subject));
+                }
+                                                         
+
+
+
+        } else if (!g_strcmp0 (turtle_predicate, RDFS_LABEL)) {
+                /* Intentionalyy ignored */
+        } else {
+                /* DEBUG 
+                g_print ("UNHANDLED %s %s %s\n", 
+                         turtle_subject, turtle_predicate, turtle_object);
+                */
+        }
+
+        g_free (turtle_subject);
+        g_free (turtle_predicate);
+        g_free (turtle_object);
+
+}
+
+static void
+load_description (void                   *user_data,
+                  const raptor_statement *triple) 
+{
+        gchar *turtle_subject;
+        gchar *turtle_predicate;
+        char  *turtle_object;
+        OntologyDescription *desc = (OntologyDescription *)user_data;
+
+	/* set new statement */
+	turtle_subject = g_strdup ((const gchar *) raptor_uri_as_string ((raptor_uri *) triple->subject));
+	turtle_predicate = g_strdup ((const gchar *) raptor_uri_as_string ((raptor_uri *) triple->predicate));
+	turtle_object = g_strdup ((const gchar *) triple->object);
+
+        if (!g_strcmp0 (turtle_predicate, RDFS_TYPE)) {
+                g_assert (!g_strcmp0 (turtle_object, DSC_ONTOLOGY));
+        } else if (!g_strcmp0 (turtle_predicate, DSC_TITLE)) {
+                desc->title = g_strdup (turtle_object);
+        } else if (!g_strcmp0 (turtle_predicate, DSC_AUTHOR)) {
+                desc->authors = g_list_prepend (desc->authors, g_strdup (turtle_object));
+        } else if (!g_strcmp0 (turtle_predicate, DSC_EDITOR)) {
+                desc->editors = g_list_prepend (desc->editors, g_strdup (turtle_object));
+        } else if (!g_strcmp0 (turtle_predicate, DSC_CONTRIBUTOR)) {
+                desc->contributors = g_list_prepend (desc->contributors, 
+                                                     g_strdup (turtle_object));
+        } else if (!g_strcmp0 (turtle_predicate, DSC_BASEURI)) {
+                desc->baseUrl = g_strdup (turtle_object);
+        } else if (!g_strcmp0 (turtle_predicate, DSC_RELPATH)) {
+                desc->relativePath = g_strdup (turtle_object);
+        } else {
+                g_critical ("Unhandled element %s", turtle_predicate);
+        }
+
+        g_free (turtle_subject);
+        g_free (turtle_predicate);
+        g_free (turtle_object);
+}
+
+
+static void 
+process_file (const gchar *ttl_file, 
+              TurtleTripleCallback handler,
+              gpointer user_data)
+{
+        FILE *file;
+        raptor_parser *parser;
+        raptor_uri *uri, *buri, *base_uri;
+	unsigned char  *uri_string;
+
+        file = g_fopen (ttl_file, "r");
+
+	parser = raptor_new_parser ("turtle");
+	base_uri = raptor_new_uri ((unsigned char *) "/");
+
+	raptor_set_statement_handler (parser, user_data, 
+                                      handler);
+	raptor_set_fatal_error_handler (parser, (void *)file, raptor_error);
+	raptor_set_error_handler (parser, (void *)file, raptor_error);
+	raptor_set_warning_handler (parser, (void *)file, raptor_error);
+
+	uri_string = raptor_uri_filename_to_uri_string (ttl_file);
+	uri = raptor_new_uri (uri_string);
+	buri = raptor_new_uri ((unsigned char *) base_uri);
+
+	raptor_parse_file (parser, uri, buri);
+
+        raptor_free_uri (base_uri);
+        raptor_free_uri (buri);
+	raptor_free_uri (uri);
+	raptor_free_parser (parser);
+        g_free (uri_string);
+
+	fclose (file);
+}
+
+
+Ontology *
+ttl_loader_load_ontology (const gchar *ttl_file)
+{
+        Ontology *ontology;
+
+        ontology = g_new0 (Ontology, 1);
+        ontology->classes = g_hash_table_new_full (g_str_hash, 
+                                                   g_str_equal,
+                                                   g_free, 
+                                                   (GDestroyNotify)ttl_model_class_free);
+
+        ontology->properties = g_hash_table_new_full (g_str_hash, 
+                                                      g_str_equal,
+                                                      g_free, 
+                                                      (GDestroyNotify)ttl_model_property_free);
+
+        if (ttl_file) {
+                process_file (ttl_file, load_in_memory, ontology);
+        } else {
+                g_warning ("Unable to open '%s'", ttl_file);
+        }
+
+        return ontology;
+}
+
+OntologyDescription *
+ttl_loader_load_description (const gchar *filename)
+{
+        OntologyDescription *desc;
+        
+        desc = ttl_model_description_new ();
+
+        process_file (filename, load_description, desc);
+
+        return desc;
+}
+
+
+void 
+ttl_loader_free_ontology (Ontology *ontology) 
+{
+        g_hash_table_destroy (ontology->classes);
+        g_hash_table_destroy (ontology->properties);
+        g_free (ontology);
+}
+
+void
+ttl_loader_free_description (OntologyDescription *desc)
+{
+        ttl_model_description_free (desc);
+}
diff --git a/utils/services/ttl_loader.h b/utils/services/ttl_loader.h
new file mode 100644
index 0000000..9fd791b
--- /dev/null
+++ b/utils/services/ttl_loader.h
@@ -0,0 +1,21 @@
+#ifndef __TTL_LOADER_H__
+#define __TTL_LOADER_H__
+
+#include <glib.h>
+#include "ttl_model.h"
+
+G_BEGIN_DECLS
+
+void      ttl_loader_init (void);
+void      ttl_loader_shutdown (void);
+
+Ontology    *ttl_loader_load_ontology (const gchar *filename);
+OntologyDescription *ttl_loader_load_description (const gchar *filename);
+
+void      ttl_loader_free_ontology (Ontology *ontology);
+void      ttl_loader_free_description (OntologyDescription *desc);
+
+
+G_END_DECLS
+
+#endif /* __TTL_LOADER_H__ */
diff --git a/utils/services/ttl_model.c b/utils/services/ttl_model.c
new file mode 100644
index 0000000..c7ef756
--- /dev/null
+++ b/utils/services/ttl_model.c
@@ -0,0 +1,118 @@
+#include "ttl_model.h"
+
+OntologyClass *
+ttl_model_class_new (const gchar *classname)
+{
+        OntologyClass *def = NULL;
+
+        def = g_new0 (OntologyClass, 1);
+
+        def->classname = g_strdup (classname);
+        def->superclasses = NULL;
+        def->subclasses = NULL;
+        def->in_domain_of = NULL;
+        def->in_range_of = NULL;
+        def->description = NULL;
+
+        return def;
+}
+
+void
+ttl_model_class_free (OntologyClass *def) 
+{
+        if (def->classname) {
+                g_free (def->classname);
+        }
+
+        g_list_foreach (def->superclasses, (GFunc) g_free, NULL);
+        g_list_foreach (def->subclasses, (GFunc) g_free, NULL);
+        g_list_foreach (def->in_domain_of, (GFunc) g_free, NULL);
+        g_list_foreach (def->in_range_of, (GFunc) g_free, NULL);
+
+        if (def->description) {
+                g_free (def->description);
+        }
+
+        g_free (def);
+}
+
+OntologyProperty *
+ttl_model_property_new (gchar *propname)
+{
+        OntologyProperty *prop;
+
+        prop = g_new0 (OntologyProperty, 1);
+
+        prop->propertyname = g_strdup (propname);
+        prop->type = NULL;
+        prop->domain = NULL;
+        prop->range = NULL;
+        prop->superproperties = NULL;
+        prop->subproperties = NULL;
+        prop->max_cardinality = NULL;
+        prop->description = NULL;
+
+        return prop;
+}
+
+void
+ttl_model_property_free (OntologyProperty *def)
+{
+        if (def->propertyname) {
+                g_free (def->propertyname);
+        }
+        
+        g_list_foreach (def->type, (GFunc) g_free, NULL);
+        g_list_foreach (def->domain, (GFunc) g_free, NULL);
+        g_list_foreach (def->range, (GFunc) g_free, NULL);
+        g_list_foreach (def->superproperties, (GFunc) g_free, NULL);
+        g_list_foreach (def->subproperties, (GFunc) g_free, NULL);
+
+        if (def->max_cardinality) {
+                g_free (def->max_cardinality);
+        }
+
+        if (def->description) {
+                g_free (def->description);
+        }
+
+        g_free (def);
+}
+
+OntologyDescription *
+ttl_model_description_new ()
+{
+        OntologyDescription *desc;
+
+        desc = g_new0 (OntologyDescription, 1);
+        desc->title = NULL;
+        desc->authors = NULL;
+        desc->editors = NULL;
+        desc->contributors = NULL;
+        desc->baseUrl = NULL;
+        desc->relativePath = NULL;
+
+        return desc;
+}
+
+void
+ttl_model_description_free (OntologyDescription *desc)
+{
+        if (desc->title) {
+                g_free (desc->title);
+        }
+
+        g_list_foreach (desc->authors, (GFunc)g_free, NULL);
+        g_list_foreach (desc->editors, (GFunc)g_free, NULL);
+        g_list_foreach (desc->contributors, (GFunc)g_free, NULL);
+
+        if (desc->baseUrl) {
+                g_free (desc->baseUrl);
+        }
+
+        if (desc->relativePath) {
+                g_free (desc->relativePath);
+        }
+
+        g_free (desc);
+}
diff --git a/utils/services/ttl_model.h b/utils/services/ttl_model.h
new file mode 100644
index 0000000..b527561
--- /dev/null
+++ b/utils/services/ttl_model.h
@@ -0,0 +1,54 @@
+#ifndef __TTL_MODEL_H__
+#define __TTL_MODEL_H__
+
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+typedef struct {
+        gchar *classname;
+        GList *superclasses;
+        GList *subclasses;
+        GList *in_domain_of;
+        GList *in_range_of;
+        gchar *description;
+} OntologyClass;
+
+typedef struct {
+        gchar *propertyname;
+        GList *type;
+        GList *domain;
+        GList *range;
+        GList *superproperties;
+        GList *subproperties;
+        gchar *max_cardinality;
+        gchar *description;
+} OntologyProperty;
+
+typedef struct {
+        gchar *title;
+        GList *authors;
+        GList *editors;
+        GList *contributors;
+        gchar *baseUrl;
+        gchar *relativePath;
+} OntologyDescription;
+
+typedef struct {
+        GHashTable *classes;
+        GHashTable *properties;
+} Ontology;
+
+
+OntologyClass * ttl_model_class_new (const gchar *classname);
+void            ttl_model_class_free (OntologyClass *klass);
+
+OntologyDescription *ttl_model_description_new ();
+void                 ttl_model_description_free (OntologyDescription *desc);
+
+OntologyProperty *ttl_model_property_new (gchar *propname);
+void              ttl_model_property_free (OntologyProperty *property);
+
+G_END_DECLS
+
+#endif /* __TRACKER_TTL_MODEL_H__ */



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]