tracker-0.16.2/docs/tools/ttl_loader.c

No issues found

  1 /*
  2  * Copyright (C) 2009, Nokia <ivan.frade@nokia.com>
  3  *
  4  * This program is free software; you can redistribute it and/or
  5  * modify it under the terms of the GNU General Public License
  6  * as published by the Free Software Foundation; either version 2
  7  * of the License, or (at your option) any later version.
  8  *
  9  * This program is distributed in the hope that it will be useful,
 10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 12  * GNU General Public License for more details.
 13  *
 14  * You should have received a copy of the GNU General Public License
 15  * along with this program; if not, write to the Free Software
 16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 17  * 02110-1301, USA.
 18  */
 19 
 20 #include "ttl_loader.h"
 21 #include <glib/gstdio.h>
 22 
 23 #include <libtracker-data/tracker-sparql-query.h>
 24 
 25 /* Ontology classes */
 26 #define RDFS_CLASS "http://www.w3.org/2000/01/rdf-schema#Class"
 27 #define RDF_PROPERTY "http://www.w3.org/1999/02/22-rdf-syntax-ns#Property"
 28 #define RDFS_SUBCLASSOF  "http://www.w3.org/2000/01/rdf-schema#subClassOf"
 29 #define RDFS_TYPE "http://www.w3.org/1999/02/22-rdf-syntax-ns#type"
 30 #define RDFS_RANGE "http://www.w3.org/2000/01/rdf-schema#range"
 31 #define RDFS_DOMAIN "http://www.w3.org/2000/01/rdf-schema#domain"
 32 #define RDFS_COMMENT "http://www.w3.org/2000/01/rdf-schema#comment"
 33 #define RDFS_LABEL "http://www.w3.org/2000/01/rdf-schema#label"
 34 #define RDFS_SUBPROPERTYOF "http://www.w3.org/2000/01/rdf-schema#subPropertyOf"
 35 
 36 #define NRL_MAX_CARDINALITY "http://www.semanticdesktop.org/ontologies/2007/08/15/nrl#maxCardinality"
 37 
 38 /* #define TRACKER_NAMESPACE "http://www.tracker-project.org/ontologies/tracker#Namespace" */
 39 #define TRACKER_NS "http://www.tracker-project.org/ontologies/tracker#"
 40 #define TRACKER_NOTIFY TRACKER_NS "notify"
 41 #define TRACKER_FTS_INDEXED TRACKER_NS "fulltextIndexed"
 42 #define TRACKER_FTS_WEIGHT TRACKER_NS "weight"
 43 
 44 #define NAO_DEPRECATED "http://www.semanticdesktop.org/ontologies/2007/08/15/nao#deprecated"
 45 
 46 /* Ontology description */
 47 #define DSC_PREFIX "http://www.tracker-project.org/temp/dsc#"
 48 
 49 #define DSC_ONTOLOGY DSC_PREFIX "Ontology"
 50 #define DSC_TITLE DSC_PREFIX "title"
 51 #define DSC_DESCRIPTION DSC_PREFIX "description"
 52 #define DSC_AUTHOR DSC_PREFIX "author"
 53 #define DSC_EDITOR DSC_PREFIX "editor"
 54 #define DSC_CONTRIBUTOR DSC_PREFIX "contributor"
 55 #define DSC_GITLOG DSC_PREFIX "gitlog"
 56 #define DSC_UPSTREAM DSC_PREFIX "upstream"
 57 #define DSC_BASEURI DSC_PREFIX "baseUrl"
 58 #define DSC_RELPATH DSC_PREFIX "relativePath"
 59 #define DSC_LOCALPREFIX DSC_PREFIX "localPrefix"
 60 #define DSC_COPYRIGHT DSC_PREFIX "copyright"
 61 
 62 static gboolean
 63 string_to_boolean (const gchar *str) {
 64 	if (!g_strcmp0 (str, "true")) {
 65 		return TRUE;
 66 	} else if (!g_strcmp0 (str, "false")) {
 67 		return FALSE;
 68 	} else {
 69 		g_error ("Unable to map '%s' into boolean", str);
 70 	}
 71 }
 72 
 73 
 74 static void
 75 load_in_memory (Ontology    *ontology,
 76                 const gchar *turtle_subject,
 77                 const gchar *turtle_predicate,
 78                 const gchar *turtle_object)
 79 {
 80 	g_return_if_fail (ontology != NULL);
 81 
 82 	if (!g_strcmp0 (turtle_predicate, RDFS_TYPE)) {
 83 		/* It is a definition of class or property */
 84 		if (!g_strcmp0 (turtle_object, RDFS_CLASS)) {
 85 			g_hash_table_insert (ontology->classes,
 86 			                     g_strdup (turtle_subject),
 87 			                     ttl_model_class_new (turtle_subject));
 88 
 89 		} else if (!g_strcmp0 (turtle_object, RDF_PROPERTY)) {
 90 			g_hash_table_insert (ontology->properties,
 91 			                     g_strdup (turtle_subject),
 92 			                     ttl_model_property_new (turtle_subject));
 93 
 94 		} else {
 95 			/* xxx:a-default-instance a xxx:Class */
 96 			OntologyClass *def;
 97 
 98 			def = g_hash_table_lookup (ontology->classes, turtle_object);
 99 			if (def) {
100 				def->instances = g_list_prepend (def->instances,
101 				                                 g_strdup (turtle_subject));
102 			}
103 			/* g_print ("FIXME Ignoring %s %s %s\n",
104 			   turtle_subject, turtle_predicate, turtle_object);
105 			*/
106 		}
107 
108 	} else if (!g_strcmp0 (turtle_predicate, RDFS_SUBCLASSOF)) {
109 		/*
110 		 * A subclass of B:
111 		 *  - Add B in A->superclasses list
112 		 *  - Add A in B->subclasses list (if B is in this ontology!)
113 		 */
114 		OntologyClass *def;
115 
116 		def = g_hash_table_lookup (ontology->classes, turtle_subject);
117 		if (!def) {
118 			g_error ("Something wrong");
119 		}
120 
121 		def->superclasses = g_list_prepend (def->superclasses,
122 		                                    g_strdup (turtle_object));
123 
124 		def = g_hash_table_lookup (ontology->classes, turtle_object);
125 		if (def) {
126 			def->subclasses = g_list_prepend (def->subclasses,
127 			                                  g_strdup (turtle_subject));
128 		}
129 	} else if (!g_strcmp0 (turtle_predicate, TRACKER_NOTIFY)) {
130 		/*
131 		 * A tracker:notify TRUE
132 		 */
133 		OntologyClass *def;
134 
135 		def = g_hash_table_lookup (ontology->classes, turtle_subject);
136 		if (!def) {
137 			g_error ("Something wrong");
138 		}
139 
140 		def->notify = string_to_boolean (turtle_object);
141 
142 	} else if (!g_strcmp0 (turtle_predicate, TRACKER_FTS_INDEXED)) {
143 		/*
144 		 * A tracker:fulltextIndexed TRUE
145 		 */
146 		OntologyProperty *prop;
147 
148 		prop = g_hash_table_lookup (ontology->properties, turtle_subject);
149 		if (!prop) {
150 			g_error ("Something wrong");
151 		}
152 
153 		prop->fulltextIndexed = string_to_boolean (turtle_object);
154 
155 	} else if (!g_strcmp0 (turtle_predicate, TRACKER_FTS_WEIGHT)) {
156 		/*
157 		 * A tracker:weight X
158 		 */
159 		OntologyProperty *prop;
160 
161 		prop = g_hash_table_lookup (ontology->properties, turtle_subject);
162 		if (!prop) {
163 			g_error ("Something wrong");
164 		}
165 
166 		prop->weight = g_strdup (turtle_object);
167 
168 	} else if (!g_strcmp0 (turtle_predicate, RDFS_COMMENT)) {
169 		OntologyClass *klass;
170 		OntologyProperty *prop;
171 
172 		klass = g_hash_table_lookup (ontology->classes, turtle_subject);
173 		if (klass) {
174 			klass->description = g_strdup (turtle_object);
175 		} else {
176 			prop = g_hash_table_lookup (ontology->properties, turtle_subject);
177 			if (prop) {
178 				prop->description = g_strdup (turtle_object);
179 			} else {
180 				g_error ("UHUMMM %s", turtle_subject);
181 			}
182 		}
183 
184 	} else if (!g_strcmp0 (turtle_predicate, RDFS_DOMAIN)) {
185 		/*
186 		 * (prop A) has domain (class B)
187 		 *  -> add B in A->domain
188 		 *  -> add A in B->in_domain_of (if B is defined in this ontology!)
189 		 */
190 		OntologyProperty *prop;
191 		OntologyClass *klass;
192 
193 		prop = g_hash_table_lookup (ontology->properties, turtle_subject);
194 		if (!prop) {
195 			g_error ("Strange error in domain (%s doesnt exist!)",
196 			         turtle_subject);
197 		}
198 		prop->domain = g_list_prepend (prop->domain, g_strdup (turtle_object));
199 
200 		klass = g_hash_table_lookup (ontology->classes, turtle_object);
201 		if (klass) {
202 			klass->in_domain_of = g_list_prepend (klass->in_domain_of,
203 			                                      g_strdup (turtle_subject));
204 		}
205 
206 	} else if (!g_strcmp0 (turtle_predicate, RDFS_RANGE)) {
207 		/*
208 		 * (prop A) has range (class B)
209 		 *  -> add B in A->range
210 		 *  -> add A in B->in_range_of (if B is defined in this ontology!)
211 		 */
212 		OntologyProperty *prop;
213 		OntologyClass *klass;
214 
215 		prop = g_hash_table_lookup (ontology->properties, turtle_subject);
216 		if (!prop) {
217 			g_error ("Strange error in domain (%s doesnt exist!)",
218 			         turtle_subject);
219 		}
220 		prop->range = g_list_prepend (prop->range, g_strdup (turtle_object));
221 
222 		klass = g_hash_table_lookup (ontology->classes, turtle_object);
223 		if (klass) {
224 			klass->in_range_of = g_list_prepend (klass->in_range_of,
225 			                                     g_strdup (turtle_subject));
226 		}
227 	} else if (!g_strcmp0 (turtle_predicate, NRL_MAX_CARDINALITY)) {
228 		OntologyProperty *prop;
229 
230 		prop = g_hash_table_lookup (ontology->properties, turtle_subject);
231 		if (!prop) {
232 			g_error ("Strange error in max cardinality (%s doesnt exist!)",
233 			         turtle_subject);
234 		}
235 		prop->max_cardinality = g_strdup (turtle_object);
236 
237 	} else if (!g_strcmp0 (turtle_predicate, RDFS_SUBPROPERTYOF)) {
238 		/*
239 		 * (prop A) is subproperty of (prop B)
240 		 *  -> add B in A->superproperties
241 		 *  -> add A in B->subproperties (if B is in this ontology)
242 		 */
243 		OntologyProperty *propA, *propB;
244 
245 		propA = g_hash_table_lookup (ontology->properties, turtle_subject);
246 		if (!propA) {
247 			g_error ("Strange error in subpropertyof (%s doesnt exist!)",
248 			         turtle_subject);
249 		}
250 		propA->superproperties = g_list_prepend (propA->superproperties,
251 		                                         g_strdup (turtle_object));
252 
253 		propB = g_hash_table_lookup (ontology->properties, turtle_object);
254 		if (propB) {
255 			propB->subproperties = g_list_prepend (propB->subproperties,
256 			                                       g_strdup (turtle_subject));
257 		}
258 
259 	} else if (!g_strcmp0 (turtle_predicate, NAO_DEPRECATED)) {
260 		/*
261 		 * X nao:deprecated true
262 		 *
263 		 * This can apply to classes OR properties!
264 		 */
265 		OntologyProperty *prop;
266 		OntologyClass *klass;
267 
268 		prop = g_hash_table_lookup (ontology->properties, turtle_subject);
269 		if (prop) {
270 			prop->deprecated = string_to_boolean (turtle_object);
271 		} else {
272 			/* Try with a class */
273 			klass = g_hash_table_lookup (ontology->classes, turtle_subject);
274 			if (klass) {
275 				klass->deprecated = string_to_boolean (turtle_object);
276 			} else {
277 				g_error ("'%s' is not a class nor a property!?", turtle_subject);
278 			}
279 		}
280 
281 	} else if (!g_strcmp0 (turtle_predicate, RDFS_LABEL)) {
282 		/* Intentionaly ignored */
283 	} else {
284 		/* DEBUG
285 		   g_print ("UNHANDLED %s %s %s\n",
286 		   turtle_subject, turtle_predicate, turtle_object);
287 		*/
288 	}
289 
290 }
291 
292 static void
293 load_description (OntologyDescription *desc,
294                   const gchar         *turtle_subject,
295                   const gchar         *turtle_predicate,
296                   const gchar         *turtle_object)
297 {
298 	if (!g_strcmp0 (turtle_predicate, RDFS_TYPE)) {
299 		g_assert (!g_strcmp0 (turtle_object, DSC_ONTOLOGY));
300 	} else if (!g_strcmp0 (turtle_predicate, DSC_TITLE)) {
301 		desc->title = g_strdup (turtle_object);
302 	} else if (!g_strcmp0 (turtle_predicate, DSC_DESCRIPTION)) {
303 		desc->description = g_strdup (turtle_object);
304 	} else if (!g_strcmp0 (turtle_predicate, DSC_UPSTREAM)) {
305 		desc->upstream = g_strdup (turtle_object);
306 	} else if (!g_strcmp0 (turtle_predicate, DSC_AUTHOR)) {
307 		desc->authors = g_list_prepend (desc->authors, g_strdup (turtle_object));
308 	} else if (!g_strcmp0 (turtle_predicate, DSC_EDITOR)) {
309 		desc->editors = g_list_prepend (desc->editors, g_strdup (turtle_object));
310 	} else if (!g_strcmp0 (turtle_predicate, DSC_CONTRIBUTOR)) {
311 		desc->contributors = g_list_prepend (desc->contributors,
312 		                                     g_strdup (turtle_object));
313 	} else if (!g_strcmp0 (turtle_predicate, DSC_GITLOG)) {
314 		desc->gitlog = g_strdup (turtle_object);
315 	} else if (!g_strcmp0 (turtle_predicate, DSC_BASEURI)) {
316 		desc->baseUrl = g_strdup (turtle_object);
317 	} else if (!g_strcmp0 (turtle_predicate, DSC_RELPATH)) {
318 		desc->relativePath = g_strdup (turtle_object);
319 	} else if (!g_strcmp0 (turtle_predicate, DSC_LOCALPREFIX)) {
320 		desc->localPrefix = g_strdup (turtle_object);
321 	} else if (!g_strcmp0 (turtle_predicate, DSC_COPYRIGHT)) {
322 		desc->copyright = g_strdup (turtle_object);
323 	} else {
324 		g_critical ("Unhandled element %s", turtle_predicate);
325 	}
326 }
327 
328 
329 Ontology *
330 ttl_loader_load_ontology (const gchar *ttl_file)
331 {
332 	Ontology *ontology;
333 
334 	ontology = g_new0 (Ontology, 1);
335 	ontology->classes = g_hash_table_new_full (g_str_hash,
336 	                                           g_str_equal,
337 	                                           g_free,
338 	                                           (GDestroyNotify)ttl_model_class_free);
339 
340 	ontology->properties = g_hash_table_new_full (g_str_hash,
341 	                                              g_str_equal,
342 	                                              g_free,
343 	                                              (GDestroyNotify)ttl_model_property_free);
344 
345 	if (ttl_file) {
346 		TrackerTurtleReader *reader;
347 		GError *error = NULL;
348 
349 		reader = tracker_turtle_reader_new (ttl_file, NULL);
350 
351 		while (error == NULL && tracker_turtle_reader_next (reader, &error)) {
352 			load_in_memory (ontology,
353 			                tracker_turtle_reader_get_subject (reader),
354 			                tracker_turtle_reader_get_predicate (reader),
355 			                tracker_turtle_reader_get_object (reader));
356 		}
357 
358 		g_object_unref (reader);
359 
360 		if (error) {
361 			g_message ("Turtle parse error: %s", error->message);
362 			g_error_free (error);
363 		}
364 	} else {
365 		g_warning ("Unable to open '%s'", ttl_file);
366 	}
367 
368 	return ontology;
369 }
370 
371 OntologyDescription *
372 ttl_loader_load_description (const gchar *filename)
373 {
374 	OntologyDescription *desc;
375 	TrackerTurtleReader *reader;
376 	GError *error = NULL;
377 
378 	desc = ttl_model_description_new ();
379 
380 
381 	reader = tracker_turtle_reader_new (filename, NULL);
382 
383 	while (error == NULL && tracker_turtle_reader_next (reader, &error)) {
384 		load_description (desc,
385 		                  tracker_turtle_reader_get_subject (reader),
386 		                  tracker_turtle_reader_get_predicate (reader),
387 		                  tracker_turtle_reader_get_object (reader));
388 	}
389 
390 	g_object_unref (reader);
391 
392 	if (error) {
393 		g_message ("Turtle parse error: %s", error->message);
394 		g_error_free (error);
395 	}
396 
397 	return desc;
398 }
399 
400 
401 void
402 ttl_loader_free_ontology (Ontology *ontology)
403 {
404 	g_hash_table_destroy (ontology->classes);
405 	g_hash_table_destroy (ontology->properties);
406 	g_free (ontology);
407 }
408 
409 void
410 ttl_loader_free_description (OntologyDescription *desc)
411 {
412 	ttl_model_description_free (desc);
413 }