1 /*
2  * Copyright (C) 2009, Nokia <ivan.frade@nokia.com>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library 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 GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17  * Boston, MA  02110-1301, USA.
18  */
19 
20 #include "config.h"
21 
22 #include <string.h>
23 #include <stdlib.h>
24 
25 #include <glib.h>
26 
27 #include <libtracker-sparql/tracker-ontologies.h>
28 
29 #include "tracker-namespace.h"
30 #include "tracker-ontologies.h"
31 #include "tracker-property.h"
32 
33 #define XSD_BOOLEAN  TRACKER_PREFIX_XSD "boolean"
34 #define XSD_DATE     TRACKER_PREFIX_XSD "date"
35 #define XSD_DATETIME TRACKER_PREFIX_XSD "dateTime"
36 #define XSD_DOUBLE   TRACKER_PREFIX_XSD "double"
37 #define XSD_INTEGER  TRACKER_PREFIX_XSD "integer"
38 #define XSD_STRING   TRACKER_PREFIX_XSD "string"
39 #define RDF_LANGSTRING TRACKER_PREFIX_RDF "langString"
40 
41 typedef struct _TrackerPropertyPrivate TrackerPropertyPrivate;
42 
43 struct _TrackerPropertyPrivate {
44 	gchar         *uri;
45 	gchar         *name;
46 	gchar         *table_name;
47 	GMutex         mutex;
48 
49 	TrackerPropertyType  data_type;
50 	TrackerClass   *domain;
51 	TrackerClass   *domain_index;
52 	TrackerClass   *range;
53 	gint           weight;
54 	gint           id;
55 	guint          use_gvdb : 1;
56 	guint          indexed : 1;
57 	guint          orig_fulltext_indexed : 1;
58 	guint          fulltext_indexed : 1;
59 	guint          multiple_values : 1;
60 	guint          last_multiple_values : 1;
61 	guint          is_inverse_functional_property : 1;
62 	guint          is_new : 1;
63 	guint          db_schema_changed : 1;
64 	guint          writeback : 1;
65 	guint          force_journal : 1;
66 	guint          cardinality_changed : 1;
67 	guint          orig_multiple_values : 1;
68 
69 	TrackerProperty *secondary_index;
70 	GPtrArray     *is_new_domain_index;
71 
72 	GArray        *super_properties;
73 	GArray        *domain_indexes;
74 	GArray        *last_super_properties;
75 
76 	TrackerOntologies *ontologies;
77 };
78 
79 static void property_finalize     (GObject      *object);
80 
81 GType
tracker_property_type_get_type(void)82 tracker_property_type_get_type (void)
83 {
84 	static GType etype = 0;
85 
86 	if (etype == 0) {
87 		static const GEnumValue values[] = {
88 			{ TRACKER_PROPERTY_TYPE_UNKNOWN,
89 			  "TRACKER_PROPERTY_TYPE_UNKNOWN",
90 			  "unknown" },
91 			{ TRACKER_PROPERTY_TYPE_STRING,
92 			  "TRACKER_PROPERTY_TYPE_STRING",
93 			  "string" },
94 			{ TRACKER_PROPERTY_TYPE_BOOLEAN,
95 			  "TRACKER_PROPERTY_TYPE_BOOLEAN",
96 			  "boolean" },
97 			{ TRACKER_PROPERTY_TYPE_INTEGER,
98 			  "TRACKER_PROPERTY_TYPE_INTEGER",
99 			  "integer" },
100 			{ TRACKER_PROPERTY_TYPE_DOUBLE,
101 			  "TRACKER_PROPERTY_TYPE_DOUBLE",
102 			  "double" },
103 			{ TRACKER_PROPERTY_TYPE_DATE,
104 			  "TRACKER_PROPERTY_TYPE_DATE",
105 			  "date" },
106 			{ TRACKER_PROPERTY_TYPE_DATETIME,
107 			  "TRACKER_PROPERTY_TYPE_DATETIME",
108 			  "datetime" },
109 			{ TRACKER_PROPERTY_TYPE_RESOURCE,
110 			  "TRACKER_PROPERTY_TYPE_RESOURCE",
111 			  "resource" },
112 			{ TRACKER_PROPERTY_TYPE_LANGSTRING,
113 			  "TRACKER_PROPERTY_TYPE_LANGSTRING",
114 			  "langString" },
115 			{ 0, NULL, NULL }
116 		};
117 
118 		etype = g_enum_register_static ("TrackerPropertyType", values);
119 	}
120 
121 	return etype;
122 }
123 
124 G_DEFINE_TYPE_WITH_PRIVATE (TrackerProperty, tracker_property, G_TYPE_OBJECT);
125 
126 static void
tracker_property_class_init(TrackerPropertyClass * klass)127 tracker_property_class_init (TrackerPropertyClass *klass)
128 {
129 	GObjectClass *object_class = G_OBJECT_CLASS (klass);
130 
131 	object_class->finalize = property_finalize;
132 }
133 
134 static void
tracker_property_init(TrackerProperty * property)135 tracker_property_init (TrackerProperty *property)
136 {
137 	TrackerPropertyPrivate *priv;
138 
139 	priv = tracker_property_get_instance_private (property);
140 
141 	priv->id = 0;
142 	priv->weight = 1;
143 	priv->multiple_values = TRUE;
144 	priv->force_journal = TRUE;
145 	priv->super_properties = g_array_new (TRUE, TRUE, sizeof (TrackerProperty *));
146 	priv->domain_indexes = g_array_new (TRUE, TRUE, sizeof (TrackerClass *));
147 	priv->last_super_properties = NULL;
148 	priv->cardinality_changed = FALSE;
149 	g_mutex_init (&priv->mutex);
150 }
151 
152 static void
property_finalize(GObject * object)153 property_finalize (GObject *object)
154 {
155 	TrackerPropertyPrivate *priv;
156 
157 	priv = tracker_property_get_instance_private (TRACKER_PROPERTY (object));
158 
159 	g_free (priv->uri);
160 	g_free (priv->name);
161 	g_free (priv->table_name);
162 
163 	if (priv->is_new_domain_index) {
164 		g_ptr_array_unref (priv->is_new_domain_index);
165 	}
166 
167 	if (priv->domain) {
168 		g_object_unref (priv->domain);
169 	}
170 
171 	if (priv->range) {
172 		g_object_unref (priv->range);
173 	}
174 
175 	if (priv->secondary_index) {
176 		g_object_unref (priv->secondary_index);
177 	}
178 
179 	if (priv->last_super_properties) {
180 		g_array_free (priv->last_super_properties, TRUE);
181 	}
182 
183 	g_array_free (priv->super_properties, TRUE);
184 	g_array_free (priv->domain_indexes, TRUE);
185 
186 	(G_OBJECT_CLASS (tracker_property_parent_class)->finalize) (object);
187 }
188 
189 /**
190  * tracker_property_new:
191  *
192  * Creates a new #TrackerProperty instance.
193  *
194  * Returns: The newly created #TrackerProperty
195  **/
196 TrackerProperty *
tracker_property_new(gboolean use_gvdb)197 tracker_property_new (gboolean use_gvdb)
198 {
199 	TrackerProperty *property;
200 	TrackerPropertyPrivate *priv;
201 
202 	property = g_object_new (TRACKER_TYPE_PROPERTY, NULL);
203 
204 	if (use_gvdb) {
205 		priv = tracker_property_get_instance_private (property);
206 		priv->use_gvdb = !!use_gvdb;
207 	}
208 
209 	return property;
210 }
211 
212 static void
tracker_property_maybe_sync_from_gvdb(TrackerProperty * property)213 tracker_property_maybe_sync_from_gvdb (TrackerProperty *property)
214 {
215 	TrackerPropertyPrivate *priv;
216 	GVariant *variant;
217 	const gchar *range_uri;
218 	const gchar *domain_uri;
219 	TrackerClass *domain_index;
220 
221 	priv = tracker_property_get_instance_private (property);
222 
223 	if (!priv->use_gvdb)
224 		return;
225 
226 	g_mutex_lock (&priv->mutex);
227 
228 	/* In case the lock was contended, make the second lose */
229 	if (!priv->use_gvdb)
230 		goto out;
231 
232 	/* Data type */
233 	range_uri = tracker_ontologies_get_property_string_gvdb (priv->ontologies, priv->uri, "range");
234 	if (strcmp (range_uri, XSD_STRING) == 0) {
235 		priv->data_type = TRACKER_PROPERTY_TYPE_STRING;
236 	} else if (strcmp (range_uri, RDF_LANGSTRING) == 0) {
237 		priv->data_type = TRACKER_PROPERTY_TYPE_LANGSTRING;
238 	} else if (strcmp (range_uri, XSD_BOOLEAN) == 0) {
239 		priv->data_type = TRACKER_PROPERTY_TYPE_BOOLEAN;
240 	} else if (strcmp (range_uri, XSD_INTEGER) == 0) {
241 		priv->data_type = TRACKER_PROPERTY_TYPE_INTEGER;
242 	} else if (strcmp (range_uri, XSD_DOUBLE) == 0) {
243 		priv->data_type = TRACKER_PROPERTY_TYPE_DOUBLE;
244 	} else if (strcmp (range_uri, XSD_DATE) == 0) {
245 		priv->data_type = TRACKER_PROPERTY_TYPE_DATE;
246 	} else if (strcmp (range_uri, XSD_DATETIME) == 0) {
247 		priv->data_type = TRACKER_PROPERTY_TYPE_DATETIME;
248 	} else {
249 		priv->data_type = TRACKER_PROPERTY_TYPE_RESOURCE;
250 	}
251 
252 	/* Range */
253 	priv->range = g_object_ref (tracker_ontologies_get_class_by_uri (priv->ontologies, range_uri));
254 
255 	/* Domain */
256 	domain_uri = tracker_ontologies_get_property_string_gvdb (priv->ontologies, priv->uri, "domain");
257 	priv->domain = g_object_ref (tracker_ontologies_get_class_by_uri (priv->ontologies, domain_uri));
258 
259 	/* Domain indexes */
260 	tracker_property_reset_domain_indexes (property);
261 
262 	variant = tracker_ontologies_get_property_value_gvdb (priv->ontologies, priv->uri, "domain-indexes");
263 	if (variant) {
264 		GVariantIter iter;
265 		const gchar *uri;
266 
267 		g_variant_iter_init (&iter, variant);
268 		while (g_variant_iter_loop (&iter, "&s", &uri)) {
269 			domain_index = tracker_ontologies_get_class_by_uri (priv->ontologies, uri);
270 
271 			tracker_property_add_domain_index (property, domain_index);
272 		}
273 
274 		g_variant_unref (variant);
275 	}
276 
277 	/* Fulltext indexed */
278 	variant = tracker_ontologies_get_property_value_gvdb (priv->ontologies, priv->uri, "fulltext-indexed");
279 	if (variant != NULL) {
280 		priv->fulltext_indexed = g_variant_get_boolean (variant);
281 		g_variant_unref (variant);
282 	} else {
283 		priv->fulltext_indexed = FALSE;
284 	}
285 
286 	/* Cardinality */
287 	variant = tracker_ontologies_get_property_value_gvdb (priv->ontologies, priv->uri, "max-cardinality");
288 	if (variant != NULL) {
289 		priv->multiple_values = FALSE;
290 		g_variant_unref (variant);
291 	} else {
292 		priv->multiple_values = TRUE;
293 	}
294 
295 	/* Inverse functional property */
296 	variant = tracker_ontologies_get_property_value_gvdb (priv->ontologies, priv->uri, "inverse-functional");
297 	if (variant != NULL) {
298 		priv->is_inverse_functional_property = g_variant_get_boolean (variant);
299 		g_variant_unref (variant);
300 	} else {
301 		priv->is_inverse_functional_property = FALSE;
302 	}
303 
304 	priv->use_gvdb = FALSE;
305 out:
306 	g_mutex_unlock (&priv->mutex);
307 }
308 
309 const gchar *
tracker_property_get_uri(TrackerProperty * property)310 tracker_property_get_uri (TrackerProperty *property)
311 {
312 	TrackerPropertyPrivate *priv;
313 
314 	g_return_val_if_fail (TRACKER_IS_PROPERTY (property), NULL);
315 
316 	priv = tracker_property_get_instance_private (property);
317 
318 	return priv->uri;
319 }
320 
321 const gchar *
tracker_property_get_name(TrackerProperty * property)322 tracker_property_get_name (TrackerProperty *property)
323 {
324 	TrackerPropertyPrivate *priv;
325 
326 	g_return_val_if_fail (TRACKER_IS_PROPERTY (property), NULL);
327 
328 	priv = tracker_property_get_instance_private (property);
329 
330 	return priv->name;
331 }
332 
333 const gchar *
tracker_property_get_table_name(TrackerProperty * property)334 tracker_property_get_table_name (TrackerProperty *property)
335 {
336 	TrackerPropertyPrivate *priv;
337 
338 	g_return_val_if_fail (TRACKER_IS_PROPERTY (property), NULL);
339 
340 	priv = tracker_property_get_instance_private (property);
341 
342 	if (!priv->table_name) {
343 		if (tracker_property_get_multiple_values (property)) {
344 			priv->table_name = g_strdup_printf ("%s_%s",
345 				tracker_class_get_name (tracker_property_get_domain (property)),
346 				tracker_property_get_name (property));
347 		} else {
348 			priv->table_name = g_strdup (tracker_class_get_name (tracker_property_get_domain (property)));
349 		}
350 	}
351 
352 	return priv->table_name;
353 }
354 
355 TrackerPropertyType
tracker_property_get_data_type(TrackerProperty * property)356 tracker_property_get_data_type (TrackerProperty *property)
357 {
358 	TrackerPropertyPrivate *priv;
359 
360 	g_return_val_if_fail (TRACKER_IS_PROPERTY (property), TRACKER_PROPERTY_TYPE_STRING); //FIXME
361 
362 	priv = tracker_property_get_instance_private (property);
363 
364 	tracker_property_maybe_sync_from_gvdb (property);
365 
366 	return priv->data_type;
367 }
368 
369 TrackerClass *
tracker_property_get_domain(TrackerProperty * property)370 tracker_property_get_domain (TrackerProperty *property)
371 {
372 	TrackerPropertyPrivate *priv;
373 
374 	/* Removed for performance:
375 	 g_return_val_if_fail (TRACKER_IS_PROPERTY (property), NULL); */
376 
377 	g_return_val_if_fail (property != NULL, NULL);
378 
379 	priv = tracker_property_get_instance_private (property);
380 
381 	tracker_property_maybe_sync_from_gvdb (property);
382 
383 	return priv->domain;
384 }
385 
386 TrackerClass **
tracker_property_get_domain_indexes(TrackerProperty * property)387 tracker_property_get_domain_indexes (TrackerProperty *property)
388 {
389 	TrackerPropertyPrivate *priv;
390 
391 	/* Removed for performance:
392 	 g_return_val_if_fail (TRACKER_IS_PROPERTY (property), NULL); */
393 
394 	g_return_val_if_fail (property != NULL, NULL);
395 
396 	priv = tracker_property_get_instance_private (property);
397 
398 	tracker_property_maybe_sync_from_gvdb (property);
399 
400 	return (TrackerClass ** ) priv->domain_indexes->data;
401 }
402 
403 TrackerProperty **
tracker_property_get_last_super_properties(TrackerProperty * property)404 tracker_property_get_last_super_properties (TrackerProperty *property)
405 {
406 	TrackerPropertyPrivate *priv;
407 
408 	g_return_val_if_fail (TRACKER_IS_PROPERTY (property), NULL);
409 	g_return_val_if_fail (property != NULL, NULL);
410 
411 	priv = tracker_property_get_instance_private (property);
412 
413 	return (TrackerProperty **) (priv->last_super_properties ? priv->last_super_properties->data : NULL);
414 }
415 
416 void
tracker_property_reset_super_properties(TrackerProperty * property)417 tracker_property_reset_super_properties (TrackerProperty *property)
418 {
419 	TrackerPropertyPrivate *priv;
420 
421 	g_return_if_fail (TRACKER_IS_PROPERTY (property));
422 
423 	priv = tracker_property_get_instance_private (property);
424 
425 	if (priv->last_super_properties) {
426 		g_array_free (priv->last_super_properties, TRUE);
427 	}
428 
429 	priv->last_super_properties = priv->super_properties;
430 	priv->super_properties = g_array_new (TRUE, TRUE, sizeof (TrackerProperty *));
431 }
432 
433 
434 TrackerClass *
tracker_property_get_range(TrackerProperty * property)435 tracker_property_get_range (TrackerProperty *property)
436 {
437 	TrackerPropertyPrivate *priv;
438 
439 	g_return_val_if_fail (TRACKER_IS_PROPERTY (property), NULL);
440 
441 	priv = tracker_property_get_instance_private (property);
442 
443 	tracker_property_maybe_sync_from_gvdb (property);
444 
445 	return priv->range;
446 }
447 
448 gint
tracker_property_get_weight(TrackerProperty * property)449 tracker_property_get_weight (TrackerProperty *property)
450 {
451 	TrackerPropertyPrivate *priv;
452 
453 	g_return_val_if_fail (TRACKER_IS_PROPERTY (property), -1);
454 
455 	priv = tracker_property_get_instance_private (property);
456 
457 	return priv->weight;
458 }
459 
460 gint
tracker_property_get_id(TrackerProperty * property)461 tracker_property_get_id (TrackerProperty *property)
462 {
463 	TrackerPropertyPrivate *priv;
464 
465 	g_return_val_if_fail (TRACKER_IS_PROPERTY (property), 0);
466 
467 	priv = tracker_property_get_instance_private (property);
468 
469 	return priv->id;
470 }
471 
472 gboolean
tracker_property_get_indexed(TrackerProperty * property)473 tracker_property_get_indexed (TrackerProperty *property)
474 {
475 	TrackerPropertyPrivate *priv;
476 
477 	g_return_val_if_fail (TRACKER_IS_PROPERTY (property), FALSE);
478 
479 	priv = tracker_property_get_instance_private (property);
480 
481 	return priv->indexed;
482 }
483 
484 TrackerProperty *
tracker_property_get_secondary_index(TrackerProperty * property)485 tracker_property_get_secondary_index (TrackerProperty *property)
486 {
487 	TrackerPropertyPrivate *priv;
488 
489 	g_return_val_if_fail (TRACKER_IS_PROPERTY (property), NULL);
490 
491 	priv = tracker_property_get_instance_private (property);
492 
493 	return priv->secondary_index;
494 }
495 
496 gboolean
tracker_property_get_fulltext_indexed(TrackerProperty * property)497 tracker_property_get_fulltext_indexed (TrackerProperty *property)
498 {
499 	TrackerPropertyPrivate *priv;
500 
501 	/* Removed for performance:
502 	 g_return_val_if_fail (TRACKER_IS_PROPERTY (property), NULL); */
503 
504 	g_return_val_if_fail (property != NULL, FALSE);
505 
506 	priv = tracker_property_get_instance_private (property);
507 
508 	tracker_property_maybe_sync_from_gvdb (property);
509 
510 	return priv->fulltext_indexed;
511 }
512 
513 gboolean
tracker_property_get_orig_fulltext_indexed(TrackerProperty * property)514 tracker_property_get_orig_fulltext_indexed (TrackerProperty *property)
515 {
516 	TrackerPropertyPrivate *priv;
517 
518 	g_return_val_if_fail (property != NULL, FALSE);
519 
520 	priv = tracker_property_get_instance_private (property);
521 
522 	return priv->orig_fulltext_indexed;
523 }
524 
525 gboolean
tracker_property_get_is_new(TrackerProperty * property)526 tracker_property_get_is_new (TrackerProperty *property)
527 {
528 	TrackerPropertyPrivate *priv;
529 
530 	g_return_val_if_fail (TRACKER_IS_PROPERTY (property), FALSE);
531 
532 	priv = tracker_property_get_instance_private (property);
533 
534 	return priv->is_new;
535 }
536 
537 gboolean
tracker_property_get_is_new_domain_index(TrackerProperty * property,TrackerClass * class)538 tracker_property_get_is_new_domain_index (TrackerProperty *property,
539                                           TrackerClass    *class)
540 {
541 	TrackerPropertyPrivate *priv;
542 	guint i;
543 
544 	g_return_val_if_fail (TRACKER_IS_PROPERTY (property), FALSE);
545 	g_return_val_if_fail (TRACKER_IS_CLASS (class), FALSE);
546 
547 	priv = tracker_property_get_instance_private (property);
548 
549 	if (!priv->is_new_domain_index) {
550 		return FALSE;
551 	}
552 
553 	for (i = 0; i < priv->is_new_domain_index->len; i++) {
554 		if (g_ptr_array_index (priv->is_new_domain_index, i) == class) {
555 			return TRUE;
556 		}
557 	}
558 
559 	return FALSE;
560 }
561 
562 gboolean
tracker_property_get_writeback(TrackerProperty * property)563 tracker_property_get_writeback (TrackerProperty *property)
564 {
565 	TrackerPropertyPrivate *priv;
566 
567 	g_return_val_if_fail (TRACKER_IS_PROPERTY (property), FALSE);
568 
569 	priv = tracker_property_get_instance_private (property);
570 
571 	return priv->writeback;
572 }
573 
574 gboolean
tracker_property_get_db_schema_changed(TrackerProperty * property)575 tracker_property_get_db_schema_changed (TrackerProperty *property)
576 {
577 	TrackerPropertyPrivate *priv;
578 
579 	g_return_val_if_fail (TRACKER_IS_PROPERTY (property), FALSE);
580 
581 	priv = tracker_property_get_instance_private (property);
582 
583 	return priv->db_schema_changed;
584 }
585 
586 gboolean
tracker_property_get_cardinality_changed(TrackerProperty * property)587 tracker_property_get_cardinality_changed (TrackerProperty *property)
588 {
589 	TrackerPropertyPrivate *priv;
590 
591 	g_return_val_if_fail (TRACKER_IS_PROPERTY (property), FALSE);
592 
593 	priv = tracker_property_get_instance_private (property);
594 
595 	return priv->cardinality_changed;
596 }
597 
598 gboolean
tracker_property_get_multiple_values(TrackerProperty * property)599 tracker_property_get_multiple_values (TrackerProperty *property)
600 {
601 	TrackerPropertyPrivate *priv;
602 
603 	g_return_val_if_fail (TRACKER_IS_PROPERTY (property), FALSE);
604 
605 	priv = tracker_property_get_instance_private (property);
606 
607 	tracker_property_maybe_sync_from_gvdb (property);
608 
609 	return priv->multiple_values;
610 }
611 
612 gboolean
tracker_property_get_last_multiple_values(TrackerProperty * property)613 tracker_property_get_last_multiple_values (TrackerProperty *property)
614 {
615 	TrackerPropertyPrivate *priv;
616 
617 	g_return_val_if_fail (TRACKER_IS_PROPERTY (property), FALSE);
618 
619 	priv = tracker_property_get_instance_private (property);
620 
621 	return priv->last_multiple_values;
622 }
623 
624 gboolean
tracker_property_get_orig_multiple_values(TrackerProperty * property)625 tracker_property_get_orig_multiple_values (TrackerProperty *property)
626 {
627 	TrackerPropertyPrivate *priv;
628 
629 	g_return_val_if_fail (TRACKER_IS_PROPERTY (property), FALSE);
630 
631 	priv = tracker_property_get_instance_private (property);
632 
633 	return priv->orig_multiple_values;
634 }
635 
636 gboolean
tracker_property_get_is_inverse_functional_property(TrackerProperty * property)637 tracker_property_get_is_inverse_functional_property (TrackerProperty *property)
638 {
639 	TrackerPropertyPrivate *priv;
640 
641 	g_return_val_if_fail (TRACKER_IS_PROPERTY (property), FALSE);
642 
643 	priv = tracker_property_get_instance_private (property);
644 
645 	tracker_property_maybe_sync_from_gvdb (property);
646 
647 	return priv->is_inverse_functional_property;
648 }
649 
650 TrackerProperty **
tracker_property_get_super_properties(TrackerProperty * property)651 tracker_property_get_super_properties (TrackerProperty *property)
652 {
653 	TrackerPropertyPrivate *priv;
654 
655 	g_return_val_if_fail (TRACKER_IS_PROPERTY (property), NULL);
656 
657 	priv = tracker_property_get_instance_private (property);
658 
659 	return (TrackerProperty **) priv->super_properties->data;
660 }
661 
662 void
tracker_property_set_uri(TrackerProperty * property,const gchar * value)663 tracker_property_set_uri (TrackerProperty *property,
664                           const gchar     *value)
665 {
666 	TrackerPropertyPrivate *priv;
667 
668 	g_return_if_fail (TRACKER_IS_PROPERTY (property));
669 
670 	priv = tracker_property_get_instance_private (property);
671 
672 	g_free (priv->uri);
673 	g_free (priv->name);
674 	priv->uri = NULL;
675 	priv->name = NULL;
676 
677 	if (value) {
678 		TrackerNamespace *namespace;
679 		gchar *namespace_uri, *hash;
680 
681 		priv->uri = g_strdup (value);
682 
683 		hash = strrchr (priv->uri, '#');
684 		if (hash == NULL) {
685 			/* support ontologies whose namespace uri does not end in a hash, e.g. dc */
686 			hash = strrchr (priv->uri, '/');
687 		}
688 		if (hash == NULL) {
689 			g_critical ("Unknown namespace of property %s", priv->uri);
690 		} else {
691 			namespace_uri = g_strndup (priv->uri, hash - priv->uri + 1);
692 			namespace = tracker_ontologies_get_namespace_by_uri (priv->ontologies, namespace_uri);
693 			if (namespace == NULL) {
694 				g_critical ("Unknown namespace %s of property %s", namespace_uri, priv->uri);
695 			} else {
696 				priv->name = g_strdup_printf ("%s:%s", tracker_namespace_get_prefix (namespace), hash + 1);
697 			}
698 			g_free (namespace_uri);
699 		}
700 	}
701 }
702 
703 void
tracker_property_set_domain(TrackerProperty * property,TrackerClass * value)704 tracker_property_set_domain (TrackerProperty *property,
705                              TrackerClass    *value)
706 {
707 	TrackerPropertyPrivate *priv;
708 
709 	g_return_if_fail (TRACKER_IS_PROPERTY (property));
710 
711 	priv = tracker_property_get_instance_private (property);
712 
713 	if (priv->domain) {
714 		g_object_unref (priv->domain);
715 		priv->domain = NULL;
716 	}
717 
718 	if (value) {
719 		priv->domain = g_object_ref (value);
720 	}
721 }
722 
723 void
tracker_property_add_domain_index(TrackerProperty * property,TrackerClass * value)724 tracker_property_add_domain_index (TrackerProperty *property,
725                                    TrackerClass    *value)
726 {
727 	TrackerPropertyPrivate *priv;
728 
729 	g_return_if_fail (TRACKER_IS_PROPERTY (property));
730 	g_return_if_fail (TRACKER_IS_CLASS (value));
731 
732 	priv = tracker_property_get_instance_private (property);
733 
734 	g_array_append_val (priv->domain_indexes, value);
735 }
736 
737 void
tracker_property_del_domain_index(TrackerProperty * property,TrackerClass * value)738 tracker_property_del_domain_index (TrackerProperty *property,
739                                    TrackerClass    *value)
740 {
741 	TrackerClass **classes;
742 	TrackerPropertyPrivate *priv;
743 	gint i = 0, found = -1;
744 
745 	g_return_if_fail (TRACKER_IS_PROPERTY (property));
746 	g_return_if_fail (TRACKER_IS_CLASS (value));
747 
748 	priv = tracker_property_get_instance_private (property);
749 
750 	classes = (TrackerClass **) priv->domain_indexes->data;
751 	while (*classes) {
752 		if (*classes == value) {
753 			found = i;
754 			break;
755 		}
756 		i++;
757 		classes++;
758 	}
759 
760 	if (found != -1) {
761 		g_array_remove_index (priv->domain_indexes, found);
762 	}
763 }
764 
765 void
tracker_property_reset_domain_indexes(TrackerProperty * property)766 tracker_property_reset_domain_indexes (TrackerProperty *property)
767 {
768 	TrackerPropertyPrivate *priv;
769 
770 	g_return_if_fail (TRACKER_IS_PROPERTY (property));
771 
772 	priv = tracker_property_get_instance_private (property);
773 	g_array_free (priv->domain_indexes, TRUE);
774 	priv->domain_indexes = g_array_new (TRUE, TRUE, sizeof (TrackerClass *));
775 }
776 
777 void
tracker_property_set_secondary_index(TrackerProperty * property,TrackerProperty * value)778 tracker_property_set_secondary_index (TrackerProperty *property,
779                                       TrackerProperty *value)
780 {
781 	TrackerPropertyPrivate *priv;
782 
783 	g_return_if_fail (TRACKER_IS_PROPERTY (property));
784 
785 	priv = tracker_property_get_instance_private (property);
786 
787 	if (priv->secondary_index) {
788 		g_object_unref (priv->secondary_index);
789 		priv->secondary_index = NULL;
790 	}
791 
792 	if (value) {
793 		priv->secondary_index = g_object_ref (value);
794 	}
795 }
796 
797 void
tracker_property_set_range(TrackerProperty * property,TrackerClass * value)798 tracker_property_set_range (TrackerProperty *property,
799                             TrackerClass     *value)
800 {
801 	TrackerPropertyPrivate *priv;
802 	const gchar *range_uri;
803 
804 	g_return_if_fail (TRACKER_IS_PROPERTY (property));
805 	g_return_if_fail (TRACKER_IS_CLASS (value));
806 
807 	priv = tracker_property_get_instance_private (property);
808 
809 	if (priv->range) {
810 		g_object_unref (priv->range);
811 	}
812 
813 	priv->range = g_object_ref (value);
814 
815 	range_uri = tracker_class_get_uri (priv->range);
816 	if (strcmp (range_uri, XSD_STRING) == 0) {
817 		priv->data_type = TRACKER_PROPERTY_TYPE_STRING;
818 	} else if (strcmp (range_uri, RDF_LANGSTRING) == 0) {
819 		priv->data_type = TRACKER_PROPERTY_TYPE_LANGSTRING;
820 	} else if (strcmp (range_uri, XSD_BOOLEAN) == 0) {
821 		priv->data_type = TRACKER_PROPERTY_TYPE_BOOLEAN;
822 	} else if (strcmp (range_uri, XSD_INTEGER) == 0) {
823 		priv->data_type = TRACKER_PROPERTY_TYPE_INTEGER;
824 	} else if (strcmp (range_uri, XSD_DOUBLE) == 0) {
825 		priv->data_type = TRACKER_PROPERTY_TYPE_DOUBLE;
826 	} else if (strcmp (range_uri, XSD_DATE) == 0) {
827 		priv->data_type = TRACKER_PROPERTY_TYPE_DATE;
828 	} else if (strcmp (range_uri, XSD_DATETIME) == 0) {
829 		priv->data_type = TRACKER_PROPERTY_TYPE_DATETIME;
830 	} else {
831 		priv->data_type = TRACKER_PROPERTY_TYPE_RESOURCE;
832 	}
833 }
834 
835 void
tracker_property_set_weight(TrackerProperty * property,gint value)836 tracker_property_set_weight (TrackerProperty *property,
837                              gint             value)
838 {
839 	TrackerPropertyPrivate *priv;
840 	g_return_if_fail (TRACKER_IS_PROPERTY (property));
841 
842 	priv = tracker_property_get_instance_private (property);
843 
844 	priv->weight = value;
845 }
846 
847 
848 void
tracker_property_set_id(TrackerProperty * property,gint value)849 tracker_property_set_id (TrackerProperty *property,
850                          gint             value)
851 {
852 	TrackerPropertyPrivate *priv;
853 	g_return_if_fail (TRACKER_IS_PROPERTY (property));
854 
855 	priv = tracker_property_get_instance_private (property);
856 
857 	priv->id = value;
858 }
859 
860 void
tracker_property_set_indexed(TrackerProperty * property,gboolean value)861 tracker_property_set_indexed (TrackerProperty *property,
862                               gboolean         value)
863 {
864 	TrackerPropertyPrivate *priv;
865 
866 	g_return_if_fail (TRACKER_IS_PROPERTY (property));
867 
868 	priv = tracker_property_get_instance_private (property);
869 
870 	priv->indexed = !!value;
871 }
872 
873 void
tracker_property_set_is_new(TrackerProperty * property,gboolean value)874 tracker_property_set_is_new (TrackerProperty *property,
875                              gboolean         value)
876 {
877 	TrackerPropertyPrivate *priv;
878 
879 	g_return_if_fail (TRACKER_IS_PROPERTY (property));
880 
881 	priv = tracker_property_get_instance_private (property);
882 
883 	priv->is_new = !!value;
884 }
885 
886 void
tracker_property_set_is_new_domain_index(TrackerProperty * property,TrackerClass * class,gboolean value)887 tracker_property_set_is_new_domain_index (TrackerProperty *property,
888                                           TrackerClass    *class,
889                                           gboolean         value)
890 {
891 	TrackerPropertyPrivate *priv;
892 
893 	g_return_if_fail (TRACKER_IS_PROPERTY (property));
894 
895 	if (class) {
896 		g_return_if_fail (TRACKER_IS_CLASS (class));
897 	}
898 
899 	priv = tracker_property_get_instance_private (property);
900 
901 	if (value) {
902 		if (!priv->is_new_domain_index) {
903 			priv->is_new_domain_index = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref);
904 		}
905 		g_ptr_array_add (priv->is_new_domain_index, g_object_ref (class));
906 	} else {
907 		guint i;
908 		gboolean found = FALSE;
909 
910 		if (!priv->is_new_domain_index) {
911 			return;
912 		}
913 
914 		if (!class) {
915 			g_ptr_array_unref (priv->is_new_domain_index);
916 			priv->is_new_domain_index = NULL;
917 			return;
918 		}
919 
920 		for (i = 0; i < priv->is_new_domain_index->len; i++) {
921 			if (g_ptr_array_index (priv->is_new_domain_index, i) == class) {
922 				found = TRUE;
923 				break;
924 			}
925 		}
926 
927 		if (found) {
928 			g_ptr_array_remove_index (priv->is_new_domain_index, i);
929 		}
930 	}
931 }
932 
933 void
tracker_property_set_writeback(TrackerProperty * property,gboolean value)934 tracker_property_set_writeback (TrackerProperty *property,
935                                 gboolean         value)
936 {
937 	TrackerPropertyPrivate *priv;
938 
939 	g_return_if_fail (TRACKER_IS_PROPERTY (property));
940 
941 	priv = tracker_property_get_instance_private (property);
942 
943 	priv->writeback = !!value;
944 }
945 
946 void
tracker_property_set_db_schema_changed(TrackerProperty * property,gboolean value)947 tracker_property_set_db_schema_changed (TrackerProperty *property,
948                                         gboolean         value)
949 {
950 	TrackerPropertyPrivate *priv;
951 
952 	g_return_if_fail (TRACKER_IS_PROPERTY (property));
953 
954 	priv = tracker_property_get_instance_private (property);
955 
956 	priv->db_schema_changed = !!value;
957 }
958 
959 void
tracker_property_set_cardinality_changed(TrackerProperty * property,gboolean value)960 tracker_property_set_cardinality_changed (TrackerProperty *property,
961                                           gboolean         value)
962 {
963 	TrackerPropertyPrivate *priv;
964 
965 	g_return_if_fail (TRACKER_IS_PROPERTY (property));
966 
967 	priv = tracker_property_get_instance_private (property);
968 
969 	priv->cardinality_changed = !!value;
970 }
971 
972 void
tracker_property_set_orig_fulltext_indexed(TrackerProperty * property,gboolean value)973 tracker_property_set_orig_fulltext_indexed (TrackerProperty *property,
974                                             gboolean         value)
975 {
976 	TrackerPropertyPrivate *priv;
977 
978 	g_return_if_fail (TRACKER_IS_PROPERTY (property));
979 
980 	priv = tracker_property_get_instance_private (property);
981 
982 	priv->orig_fulltext_indexed = !!value;
983 }
984 
985 void
tracker_property_set_fulltext_indexed(TrackerProperty * property,gboolean value)986 tracker_property_set_fulltext_indexed (TrackerProperty *property,
987                                        gboolean         value)
988 {
989 	TrackerPropertyPrivate *priv;
990 
991 	g_return_if_fail (TRACKER_IS_PROPERTY (property));
992 
993 	priv = tracker_property_get_instance_private (property);
994 
995 	priv->fulltext_indexed = !!value;
996 }
997 
998 void
tracker_property_set_multiple_values(TrackerProperty * property,gboolean value)999 tracker_property_set_multiple_values (TrackerProperty *property,
1000                                       gboolean         value)
1001 {
1002 	TrackerPropertyPrivate *priv;
1003 
1004 	g_return_if_fail (TRACKER_IS_PROPERTY (property));
1005 
1006 	priv = tracker_property_get_instance_private (property);
1007 
1008 	priv->multiple_values = !!value;
1009 	g_clear_pointer (&priv->table_name, g_free);
1010 }
1011 
1012 void
tracker_property_set_last_multiple_values(TrackerProperty * property,gboolean value)1013 tracker_property_set_last_multiple_values (TrackerProperty *property,
1014                                            gboolean         value)
1015 {
1016 	TrackerPropertyPrivate *priv;
1017 
1018 	g_return_if_fail (TRACKER_IS_PROPERTY (property));
1019 
1020 	priv = tracker_property_get_instance_private (property);
1021 
1022 	priv->last_multiple_values = !!value;
1023 }
1024 
1025 void
tracker_property_set_orig_multiple_values(TrackerProperty * property,gboolean value)1026 tracker_property_set_orig_multiple_values (TrackerProperty *property,
1027                                            gboolean         value)
1028 {
1029 	TrackerPropertyPrivate *priv;
1030 
1031 	g_return_if_fail (TRACKER_IS_PROPERTY (property));
1032 
1033 	priv = tracker_property_get_instance_private (property);
1034 
1035 	priv->orig_multiple_values = !!value;
1036 }
1037 
1038 
1039 void
tracker_property_set_is_inverse_functional_property(TrackerProperty * property,gboolean value)1040 tracker_property_set_is_inverse_functional_property (TrackerProperty *property,
1041                                                      gboolean         value)
1042 {
1043 	TrackerPropertyPrivate *priv;
1044 
1045 	g_return_if_fail (TRACKER_IS_PROPERTY (property));
1046 
1047 	priv = tracker_property_get_instance_private (property);
1048 
1049 	priv->is_inverse_functional_property = !!value;
1050 }
1051 
1052 void
tracker_property_add_super_property(TrackerProperty * property,TrackerProperty * value)1053 tracker_property_add_super_property (TrackerProperty *property,
1054                                      TrackerProperty *value)
1055 {
1056 	TrackerPropertyPrivate *priv;
1057 
1058 	g_return_if_fail (TRACKER_IS_PROPERTY (property));
1059 	g_return_if_fail (TRACKER_IS_PROPERTY (value));
1060 
1061 	priv = tracker_property_get_instance_private (property);
1062 
1063 	g_array_append_val (priv->super_properties, value);
1064 }
1065 
1066 void
tracker_property_del_super_property(TrackerProperty * property,TrackerProperty * value)1067 tracker_property_del_super_property (TrackerProperty *property,
1068                                      TrackerProperty *value)
1069 {
1070 	TrackerPropertyPrivate *priv;
1071 	guint i;
1072 
1073 	g_return_if_fail (TRACKER_IS_PROPERTY (property));
1074 	g_return_if_fail (TRACKER_IS_PROPERTY (value));
1075 
1076 	priv = tracker_property_get_instance_private (property);
1077 
1078 	for (i = 0; priv->super_properties->len; i++) {
1079 		TrackerProperty *c_value = g_array_index (priv->super_properties, TrackerProperty*, i);
1080 
1081 		if (c_value == value) {
1082 			priv->super_properties = g_array_remove_index (priv->super_properties, i);
1083 			return;
1084 		}
1085 	}
1086 }
1087 
1088 void
tracker_property_set_ontologies(TrackerProperty * property,TrackerOntologies * ontologies)1089 tracker_property_set_ontologies (TrackerProperty   *property,
1090                                  TrackerOntologies *ontologies)
1091 {
1092 	TrackerPropertyPrivate *priv;
1093 
1094 	g_return_if_fail (TRACKER_IS_PROPERTY (property));
1095 	g_return_if_fail (ontologies != NULL);
1096 	priv = tracker_property_get_instance_private (property);
1097 
1098 	priv->ontologies = ontologies;
1099 }
1100