1 /* biji-tracker.c
2 * Copyright (C) Pierre-Yves LUYTEN 2012, 2013 <py@luyten.fr>
3 *
4 * bijiben is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the
6 * Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
8 *
9 * bijiben is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 * See the GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18 #include "config.h"
19
20 #include "biji-item.h"
21 #include "biji-tracker.h"
22
23
24
25 typedef enum
26 {
27 BIJI_URN_COL,
28 BIJI_TITLE_COL,
29 BIJI_MTIME_COL,
30 BIJI_CONTENT_COL,
31 BIJI_CREATED_COL,
32 BIJI_NO_COL
33
34 } BijiTrackerColumns;
35
36
37
38 /* To perform something after async tracker query
39 * TODO : implemet this with GObject */
40 typedef struct {
41
42 BijiManager *manager;
43
44 /* usually a query */
45
46 gchar *str;
47 BijiInfoSet *info;
48
49 /* after the query, _one of_ the callbacks */
50
51 BijiBoolCallback bool_cb;
52 BijiInfoCallback info_cb;
53 BijiItemCallback item_cb;
54 BijiItemsListCallback list_cb;
55 BijiInfoSetsHCallback hash_cb;
56
57
58 gpointer user_data;
59
60 } BijiTrackerFinisher;
61
62
63 /* finisher stores _one of the possible callbacks _
64 * we could cast as well */
65
66
67 static BijiTrackerFinisher *
biji_tracker_finisher_new(BijiManager * manager,gchar * str,BijiInfoSet * info,BijiBoolCallback bool_cb,BijiInfoCallback info_cb,BijiItemCallback item_cb,BijiItemsListCallback list_cb,BijiInfoSetsHCallback hash_cb,gpointer user_data)68 biji_tracker_finisher_new (BijiManager *manager,
69 gchar *str,
70 BijiInfoSet *info,
71 BijiBoolCallback bool_cb,
72 BijiInfoCallback info_cb,
73 BijiItemCallback item_cb,
74 BijiItemsListCallback list_cb,
75 BijiInfoSetsHCallback hash_cb,
76 gpointer user_data)
77 {
78 BijiTrackerFinisher *retval = g_slice_new (BijiTrackerFinisher);
79
80 retval->manager = manager;
81 retval->str = str;
82 retval->info = info;
83 retval->bool_cb = bool_cb;
84 retval->info_cb = info_cb;
85 retval->item_cb = item_cb;
86 retval->list_cb = list_cb;
87 retval->hash_cb = hash_cb;
88 retval->user_data = user_data;
89
90 return retval;
91 }
92
93
94 /* Only heap is str */
95
96 static void
biji_tracker_finisher_free(BijiTrackerFinisher * f)97 biji_tracker_finisher_free (BijiTrackerFinisher *f)
98 {
99 g_clear_pointer (&f->str, g_free);
100 g_slice_free (BijiTrackerFinisher, f);
101 }
102
103
104 static TrackerSparqlConnection*
get_connection(BijiManager * manager)105 get_connection (BijiManager *manager)
106 {
107 return biji_manager_get_tracker_connection (manager);
108 }
109
110
111 /* TODO : populate the boolean */
112
113 static void
biji_finish_update(GObject * source_object,GAsyncResult * res,gpointer user_data)114 biji_finish_update (GObject *source_object,
115 GAsyncResult *res,
116 gpointer user_data)
117 {
118 TrackerSparqlConnection *self;
119 BijiTrackerFinisher *finisher;
120 GError *error;
121 gchar *query;
122
123
124 self = TRACKER_SPARQL_CONNECTION (source_object);
125 finisher = user_data;
126 error = NULL;
127 query = finisher->str;
128
129 tracker_sparql_connection_update_finish (self, res, &error);
130
131 if (error)
132 {
133 g_warning ("%s : query=|||%s|||", error->message, query);
134 g_error_free (error);
135 }
136
137 /* See if the query has something to perform afterward */
138 if (finisher->bool_cb)
139 finisher->bool_cb (TRUE, finisher->user_data);
140
141 biji_tracker_finisher_free (finisher);
142 }
143
144
145 static void
biji_perform_update_async_and_free(TrackerSparqlConnection * connection,gchar * query,BijiBoolCallback f,gpointer user_data)146 biji_perform_update_async_and_free (TrackerSparqlConnection *connection,
147 gchar *query,
148 BijiBoolCallback f,
149 gpointer user_data)
150 {
151 BijiTrackerFinisher *finisher;
152
153 finisher = biji_tracker_finisher_new
154 (NULL, query, NULL, f, NULL, NULL, NULL, NULL, user_data);
155 tracker_sparql_connection_update_async (connection,
156 query,
157 #if !HAVE_TRACKER3
158 0, // priority
159 #endif
160 NULL,
161 biji_finish_update,
162 finisher);
163 }
164
165
166 /* Don't worry too much. We just want plain text here */
167 static gchar *
tracker_str(const gchar * string)168 tracker_str (const gchar * string )
169 {
170 g_return_val_if_fail (string != NULL, g_strdup (""));
171
172 return biji_str_mass_replace (string, "\n", " ", "'", " ", NULL);
173 }
174
175
176
177 static gchar *
get_note_url(BijiNoteObj * note)178 get_note_url (BijiNoteObj *note)
179 {
180 return g_strdup_printf ("file://%s", biji_item_get_uuid (BIJI_ITEM (note)));
181 }
182
183
184
185 static void
biji_query_info_hash_finish(GObject * source_object,GAsyncResult * res,gpointer user_data)186 biji_query_info_hash_finish (GObject *source_object,
187 GAsyncResult *res,
188 gpointer user_data)
189 {
190 TrackerSparqlConnection *self;
191 TrackerSparqlCursor *cursor;
192 GError *error;
193 GHashTable *result;
194 BijiTrackerFinisher *finisher;
195
196 self = TRACKER_SPARQL_CONNECTION (source_object);
197 finisher = (BijiTrackerFinisher*) user_data;
198 error = NULL;
199 result = g_hash_table_new_full (
200 g_str_hash, g_str_equal, NULL, (GDestroyNotify) biji_info_set_free);
201
202 cursor = tracker_sparql_connection_query_finish (self,
203 res,
204 &error);
205
206 if (error)
207 {
208 g_warning ("%s", error->message);
209 g_error_free (error);
210 }
211
212 if (cursor)
213 {
214
215 while (tracker_sparql_cursor_next (cursor, NULL, NULL))
216 {
217 BijiInfoSet *set = biji_info_set_new ();
218
219 set->tracker_urn = g_strdup (tracker_sparql_cursor_get_string (cursor, BIJI_URN_COL, NULL));
220 set->title = g_strdup (tracker_sparql_cursor_get_string (cursor, BIJI_TITLE_COL, NULL));
221 set->mtime = iso8601_to_gint64 (tracker_sparql_cursor_get_string (cursor, BIJI_MTIME_COL, NULL));
222
223 g_hash_table_replace (result, set->tracker_urn, set);
224 }
225
226 g_object_unref (cursor);
227 }
228
229 finisher->hash_cb (result, finisher->user_data);
230 biji_tracker_finisher_free (finisher);
231 return;
232 }
233
234
235 static void
biji_query_items_list_finish(GObject * source_object,GAsyncResult * res,gpointer user_data)236 biji_query_items_list_finish (GObject *source_object,
237 GAsyncResult *res,
238 gpointer user_data)
239 {
240 TrackerSparqlConnection *self;
241 TrackerSparqlCursor *cursor;
242 BijiTrackerFinisher *finisher;
243 GError *error;
244 GList *result;
245
246 self = TRACKER_SPARQL_CONNECTION (source_object);
247 result = NULL;
248 error = NULL;
249 finisher = (BijiTrackerFinisher *) user_data;
250
251 if (finisher->list_cb == NULL)
252 return;
253
254 cursor = tracker_sparql_connection_query_finish (self, res, &error);
255
256 if (error)
257 {
258 g_warning ("%s", error->message);
259 g_error_free (error);
260 }
261
262 if (cursor)
263 {
264 const gchar *full_path;
265 gchar *path;
266 BijiItem *item = NULL;
267
268 while (tracker_sparql_cursor_next (cursor, NULL, NULL))
269 {
270 full_path = tracker_sparql_cursor_get_string (cursor, 0, NULL);
271
272 if (g_str_has_prefix (full_path, "file://"))
273 {
274 GString *string;
275
276 string = g_string_new (full_path);
277 g_string_erase (string, 0, 7);
278 path = g_string_free (string, FALSE);
279 }
280
281 else
282 {
283 path = g_strdup (full_path);
284 }
285
286 item = biji_manager_get_item_at_path (finisher->manager, path);
287
288 /* Sorting is done in another place */
289 if (item)
290 result = g_list_prepend (result, item);
291 }
292
293 g_object_unref (cursor);
294 }
295
296 finisher->list_cb (result, finisher->user_data);
297 biji_tracker_finisher_free (finisher);
298 }
299
300
301
302 static void
bjb_query_async(BijiManager * manager,gchar * query,BijiInfoSetsHCallback hash_cb,BijiItemsListCallback list_cb,gpointer user_data)303 bjb_query_async (BijiManager *manager,
304 gchar *query,
305 BijiInfoSetsHCallback hash_cb,
306 BijiItemsListCallback list_cb,
307 gpointer user_data)
308 {
309 BijiTrackerFinisher *finisher;
310 GAsyncReadyCallback callback = NULL;
311
312 finisher = biji_tracker_finisher_new (manager, NULL, NULL, NULL, NULL, NULL, list_cb, hash_cb, user_data);
313
314 if (hash_cb != NULL)
315 callback = biji_query_info_hash_finish;
316
317 else if (list_cb != NULL)
318 callback = biji_query_items_list_finish;
319
320 if (callback)
321 tracker_sparql_connection_query_async (
322 get_connection (manager), query, NULL, callback, finisher);
323 }
324
325
326 void
biji_get_all_notebooks_async(BijiManager * manager,BijiInfoSetsHCallback cb,gpointer user_data)327 biji_get_all_notebooks_async (BijiManager *manager,
328 BijiInfoSetsHCallback cb,
329 gpointer user_data)
330 {
331 gchar *query = g_strconcat (
332 "SELECT ?c ?title ?mtime ",
333 "WHERE { ?c a nfo:DataContainer ;",
334 "nie:title ?title ; ",
335 "nie:contentLastModified ?mtime ;"
336 "nie:generator 'Bijiben'}",
337 NULL);
338
339 bjb_query_async (manager, query, cb, NULL, user_data);
340
341 g_free (query);
342 }
343
344
345
346
347 /* FIXME: returns file://$PATH while we want $PATH
348 * workaround in biji_query_items_list_finish */
349 void
biji_get_items_with_notebook_async(BijiManager * manager,const gchar * notebook,BijiItemsListCallback list_cb,gpointer user_data)350 biji_get_items_with_notebook_async (BijiManager *manager,
351 const gchar *notebook,
352 BijiItemsListCallback list_cb,
353 gpointer user_data)
354 {
355 gchar *query;
356
357 query = g_strdup_printf ("SELECT ?s WHERE {?c nie:isPartOf ?s; nie:title '%s'}",
358 notebook);
359
360 bjb_query_async (manager, query, NULL, list_cb, user_data);
361 }
362
363
364
365
366 void
biji_get_items_matching_async(BijiManager * manager,BijiItemsGroup group,gchar * needle,BijiItemsListCallback list_cb,gpointer user_data)367 biji_get_items_matching_async (BijiManager *manager,
368 BijiItemsGroup group,
369 gchar *needle,
370 BijiItemsListCallback list_cb,
371 gpointer user_data)
372 {
373 gchar *lower;
374 gchar *query;
375
376
377 lower = g_utf8_strdown (needle, -1);
378
379 /* We want to retrieve the key that noteBook uses.
380 * for notes: that is url. A file path is unique.
381 * for notebooks: we have no url, directly use urn:uuid */
382
383 query = g_strconcat (
384 "SELECT tracker:coalesce (?url, ?urn) WHERE ",
385 "{",
386 " { ?urn a nfo:Note",
387 " .?urn nie:title ?title",
388 " .?urn nie:plainTextContent ?content",
389 " .?urn nie:url ?url",
390 " .?urn nie:generator 'Bijiben'",
391 " .FILTER (",
392 " fn:contains (fn:lower-case (?content), '", lower, "' ) || ",
393 " fn:contains (fn:lower-case (?title) , '", lower, "'))} ",
394 "UNION",
395 " { ?urn a nfo:DataContainer",
396 " .?urn nie:title ?title",
397 " .?urn nie:generator 'Bijiben'",
398 " .FILTER (",
399 " fn:contains (fn:lower-case (?title), '", lower, "'))}",
400 "}",
401 NULL);
402
403 g_free (lower);
404 bjb_query_async (manager, query, NULL, list_cb, user_data);
405 }
406
407
408 static void
on_new_notebook_query_executed(GObject * source_object,GAsyncResult * res,gpointer user_data)409 on_new_notebook_query_executed (GObject *source_object, GAsyncResult *res, gpointer user_data)
410 {
411 BijiTrackerFinisher *finisher = user_data;
412 TrackerSparqlConnection *connection = TRACKER_SPARQL_CONNECTION (source_object);
413 GError *error;
414 GVariant *variant;
415 GVariant *child;
416 gchar *key = NULL;
417 gchar *val = NULL;
418 gchar *urn = NULL;
419 BijiNotebook *notebook = NULL;
420
421 error = NULL;
422 variant = tracker_sparql_connection_update_blank_finish (connection, res, &error);
423 if (error != NULL)
424 {
425 g_warning ("Unable to create notebook: %s", error->message);
426 g_error_free (error);
427 goto out;
428 }
429
430 child = g_variant_get_child_value (variant, 0); /* variant is now aa{ss} */
431 g_variant_unref (variant);
432 variant = child;
433
434 child = g_variant_get_child_value (variant, 0); /* variant is now s{ss} */
435 g_variant_unref (variant);
436 variant = child;
437
438 child = g_variant_get_child_value (variant, 0); /* variant is now {ss} */
439 g_variant_unref (variant);
440 variant = child;
441
442 child = g_variant_get_child_value (variant, 0);
443 key = g_variant_dup_string (child, NULL);
444 g_variant_unref (child);
445
446 child = g_variant_get_child_value (variant, 1);
447 val = g_variant_dup_string (child, NULL);
448 g_variant_unref (child);
449
450 g_variant_unref (variant);
451
452 if (g_strcmp0 (key, "res") == 0)
453 urn = val;
454
455 /* Update the note manager */
456 if (urn)
457 {
458 notebook = biji_notebook_new (
459 G_OBJECT (finisher->manager),
460 urn,
461 finisher->str,
462 g_get_real_time () / G_USEC_PER_SEC);
463 biji_manager_add_item (finisher->manager, BIJI_ITEM (notebook), BIJI_LIVING_ITEMS, TRUE);
464 }
465
466 /* Run the callback from the caller */
467
468 out:
469 if (finisher->item_cb != NULL)
470 (*finisher->item_cb) (BIJI_ITEM (notebook), finisher->user_data);
471
472 g_free (val);
473 g_free (key);
474 biji_tracker_finisher_free (finisher);
475 }
476
477
478 /* This func creates the notebook,
479 * gives the urn to the notemanager,
480 * then run the 'afterward' callback */
481 void
biji_create_new_notebook_async(BijiManager * manager,const gchar * name,BijiItemCallback item_cb,gpointer user_data)482 biji_create_new_notebook_async (BijiManager *manager,
483 const gchar *name,
484 BijiItemCallback item_cb,
485 gpointer user_data)
486 {
487 gchar *query;
488 g_autoptr(GDateTime) dt = g_date_time_new_now_utc ();
489 g_autofree char *time = g_date_time_format_iso8601 (dt);
490 BijiTrackerFinisher *finisher;
491
492 query = g_strdup_printf ("INSERT { _:res a nfo:DataContainer ; a nie:DataObject ; "
493 "nie:contentLastModified '%s' ; "
494 "nie:title '%s' ; "
495 "nie:generator 'Bijiben' }",
496 time,
497 name);
498
499 /* The finisher has all the pointers we want.
500 * And the callback will free it */
501 finisher = biji_tracker_finisher_new (manager, g_strdup (name), NULL, NULL, NULL, item_cb, NULL, NULL, user_data);
502 tracker_sparql_connection_update_blank_async (get_connection (manager),
503 query,
504 #if !HAVE_TRACKER3
505 G_PRIORITY_DEFAULT,
506 #endif
507 NULL,
508 on_new_notebook_query_executed,
509 finisher);
510 }
511
512
513 /* removes the tag EVEN if files associated. */
514
515 void
biji_remove_notebook_from_tracker(BijiManager * manager,const gchar * urn)516 biji_remove_notebook_from_tracker (BijiManager *manager, const gchar *urn)
517 {
518 gchar *query;
519
520 query = g_strdup_printf ("DELETE {'%s' a nfo:DataContainer}", urn);
521 biji_perform_update_async_and_free (get_connection (manager), query, NULL, NULL);
522 }
523
524
525 void
biji_push_existing_notebook_to_note(BijiNoteObj * note,gchar * title,BijiBoolCallback afterward,gpointer user_data)526 biji_push_existing_notebook_to_note (BijiNoteObj *note,
527 gchar *title,
528 BijiBoolCallback afterward,
529 gpointer user_data)
530 {
531 gchar *url, *query;
532
533 url = get_note_url (note);
534 query = g_strdup_printf ("INSERT {?urn nie:isPartOf '%s'} WHERE {?urn a nfo:DataContainer; nie:title '%s'; nie:generator 'Bijiben'}",
535 url, title);
536
537 biji_perform_update_async_and_free (
538 get_connection (biji_item_get_manager (BIJI_ITEM (note))), query, afterward, user_data);
539 g_free (url);
540 }
541
542
543
544 void
biji_remove_notebook_from_note(BijiNoteObj * note,BijiItem * coll,BijiBoolCallback afterward,gpointer user_data)545 biji_remove_notebook_from_note (BijiNoteObj *note,
546 BijiItem *coll,
547 BijiBoolCallback afterward,
548 gpointer user_data)
549 {
550 gchar *url, *query;
551
552 url = get_note_url (note);
553
554 query = g_strdup_printf (
555 "DELETE {'%s' nie:isPartOf '%s'}",
556 biji_item_get_uuid (coll), url);
557
558
559 biji_perform_update_async_and_free (get_connection (biji_item_get_manager (coll)), query, afterward, user_data);
560 g_free (url);
561 }
562
563
564 void
biji_note_delete_from_tracker(BijiNoteObj * note)565 biji_note_delete_from_tracker (BijiNoteObj *note)
566 {
567 BijiItem *item;
568 gchar *query;
569 const gchar *uuid;
570 BijiManager *manager;
571
572 item = BIJI_ITEM (note);
573 manager = biji_item_get_manager (item);
574 uuid = biji_item_get_uuid (item);
575 query = g_strdup_printf ("DELETE { <%s> a rdfs:Resource }", uuid);
576 biji_perform_update_async_and_free (get_connection (manager), query, NULL, NULL);
577 }
578
579
580
581 void
biji_tracker_trash_resource(BijiManager * manager,gchar * tracker_urn)582 biji_tracker_trash_resource (BijiManager *manager,
583 gchar *tracker_urn)
584 {
585 gchar *query;
586
587 query = g_strdup_printf ("DELETE { <%s> a rdfs:Resource }", tracker_urn);
588 biji_perform_update_async_and_free (get_connection (manager), query, NULL, NULL);
589 }
590
591
592 static void
update_resource(BijiTrackerFinisher * finisher,gchar * tracker_urn_uuid)593 update_resource (BijiTrackerFinisher *finisher, gchar *tracker_urn_uuid )
594 {
595 BijiManager *manager = finisher->manager;
596 BijiInfoSet *info = finisher->info;
597 g_autoptr(GDateTime) dt_created = g_date_time_new_from_unix_utc (info->created);
598 g_autoptr(GDateTime) dt_mtime = g_date_time_new_from_unix_utc (info->mtime);
599 g_autofree char *created = g_date_time_format_iso8601 (dt_created);
600 g_autofree char *mtime = g_date_time_format_iso8601 (dt_mtime);
601 char *query, *content;
602
603 content = tracker_str (info->content);
604
605 g_message ("Updating resource <%s> %s", info->title, tracker_urn_uuid);
606
607 query = g_strdup_printf (
608 "INSERT OR REPLACE { <%s> a nfo:Note , nie:DataObject ; "
609 "nie:url '%s' ; "
610 "nie:contentLastModified '%s' ; "
611 "nie:contentCreated '%s' ; "
612 "nie:title '%s' ; "
613 "nie:plainTextContent '%s' ; "
614 "nie:dataSource '%s' ;"
615 "nie:generator 'Bijiben' . }",
616 tracker_urn_uuid,
617 info->url,
618 mtime,
619 created,
620 info->title,
621 content,
622 info->datasource_urn);
623
624 biji_perform_update_async_and_free (get_connection (manager), query, NULL, NULL);
625
626 g_free (tracker_urn_uuid);
627 g_free (content);
628 biji_tracker_finisher_free (finisher);
629 }
630
631
632 static void
push_new_note(BijiTrackerFinisher * finisher)633 push_new_note (BijiTrackerFinisher *finisher)
634 {
635 BijiManager *manager = finisher->manager;
636 BijiInfoSet *info = finisher->info;
637 g_autoptr(GDateTime) dt_created = g_date_time_new_from_unix_utc (info->created);
638 g_autoptr(GDateTime) dt_mtime = g_date_time_new_from_unix_utc (info->mtime);
639 g_autofree char *created_time = g_date_time_format_iso8601 (dt_created);
640 g_autofree char *mtime = g_date_time_format_iso8601 (dt_mtime);
641 gchar *query, *content;
642
643 g_message ("Creating resource <%s> %s", info->title, info->url);
644
645 content = tracker_str (info->content);
646
647 query = g_strconcat (
648 "INSERT { _:res a nfo:Note ; ",
649 " a nie:DataObject ; ",
650 " nie:contentLastModified '", mtime, "' ;",
651 " nie:contentCreated '", created_time, "' ;",
652 " nie:title '", info->title, "' ;",
653 " nie:url '", info->url, "' ;",
654 " nie:plainTextContent '", content, "' ;",
655 " nie:dataSource '", info->datasource_urn, "' ;",
656 " nie:generator 'Bijiben' }",
657 NULL);
658
659
660 g_debug ("%s", query);
661
662 tracker_sparql_connection_update_blank_async (get_connection (manager),
663 query,
664 #if !HAVE_TRACKER3
665 G_PRIORITY_DEFAULT,
666 #endif
667 NULL,
668 NULL, // callback,
669 NULL); // user_data);
670
671
672 g_free (query);
673 g_free (content);
674 biji_tracker_finisher_free (finisher);
675 }
676
677
678 static void
ensure_resource_callback(GObject * source_object,GAsyncResult * res,gpointer user_data)679 ensure_resource_callback (GObject *source_object,
680 GAsyncResult *res,
681 gpointer user_data)
682 {
683 TrackerSparqlConnection *connection;
684 TrackerSparqlCursor *cursor;
685 BijiTrackerFinisher *finisher;
686 GError *error;
687 gchar *urn_found;
688
689
690 connection = TRACKER_SPARQL_CONNECTION (source_object);
691 finisher = user_data;
692 error = NULL;
693 urn_found = NULL;
694 cursor = tracker_sparql_connection_query_finish (connection, res, &error);
695
696 if (error)
697 {
698 g_warning ("ENSURE RESOURCE : error %s", error->message);
699 g_error_free (error);
700 biji_tracker_finisher_free (finisher);
701 return;
702 }
703
704 /* Queried resource found into tracker */
705
706 if (cursor)
707 {
708
709 if (tracker_sparql_cursor_next (cursor, NULL, NULL))
710 urn_found = g_strdup (tracker_sparql_cursor_get_string (cursor, 0, NULL));
711
712 g_object_unref (cursor);
713 }
714
715
716 if (urn_found != NULL)
717 update_resource (finisher, urn_found);
718
719 else
720 push_new_note (finisher);
721 }
722
723
724
725 void
biji_tracker_ensure_resource_from_info(BijiManager * manager,BijiInfoSet * info)726 biji_tracker_ensure_resource_from_info (BijiManager *manager,
727 BijiInfoSet *info)
728 {
729 gchar *query;
730 BijiTrackerFinisher *finisher;
731
732
733 query = g_strconcat (
734 "SELECT ?urn ?time WHERE { ?urn a nfo:Note ;",
735 " nie:title ?title ;",
736 " nie:contentLastModified ?time ;",
737 " nie:url '", info->url, "' }",
738 NULL);
739
740
741 /* No matter user callback or not,
742 * we'll need our own to push if needed */
743
744 finisher = biji_tracker_finisher_new (
745 manager,
746 NULL,
747 info,
748 NULL,
749 NULL,
750 NULL,
751 NULL,
752 NULL,
753 NULL); // user_data);
754
755 tracker_sparql_connection_query_async (
756 get_connection (manager), query, NULL, ensure_resource_callback, finisher);
757
758 g_free (query);
759 }
760
761
762
763
764
765 void
biji_tracker_ensure_datasource(BijiManager * manager,const gchar * datasource,const gchar * identifier,BijiBoolCallback cb,gpointer user_data)766 biji_tracker_ensure_datasource (BijiManager *manager,
767 const gchar *datasource,
768 const gchar *identifier,
769 BijiBoolCallback cb,
770 gpointer user_data)
771 {
772 gchar *query;
773
774
775 query = g_strdup_printf (
776 "INSERT OR REPLACE INTO <%s> {"
777 " <%s> a nie:DataSource ; nao:identifier \"%s\" }",
778 datasource,
779 datasource,
780 identifier);
781
782 biji_perform_update_async_and_free (
783 get_connection (manager), query, cb, user_data);
784 }
785
786
787
788 static void
on_info_queried(GObject * source_object,GAsyncResult * res,gpointer user_data)789 on_info_queried (GObject *source_object,
790 GAsyncResult *res,
791 gpointer user_data)
792 {
793 TrackerSparqlConnection *connection;
794 TrackerSparqlCursor *cursor;
795 BijiTrackerFinisher *finisher;
796 GError *error;
797 BijiInfoSet *retval;
798
799 connection = TRACKER_SPARQL_CONNECTION (source_object);
800 finisher = user_data;
801 error = NULL;
802 retval = NULL;
803 cursor = tracker_sparql_connection_query_finish (connection, res, &error);
804
805 if (error)
806 {
807 g_warning ("Check for Info : error %s", error->message);
808 g_error_free (error);
809
810 /* Something went wrong, callback and free memory
811 & leave tracker alone */
812 if (finisher->info_cb != NULL)
813 finisher->info_cb (retval, finisher->user_data);
814 biji_tracker_finisher_free (finisher);
815 return;
816 }
817
818 /* Queried resource found into tracker */
819 if (cursor)
820 {
821 if (tracker_sparql_cursor_next (cursor, NULL, NULL))
822 {
823 retval = biji_info_set_new ();
824
825 retval->url = g_strdup (tracker_sparql_cursor_get_string (cursor, 0, NULL));
826 retval->title = g_strdup (tracker_sparql_cursor_get_string (cursor, 1, NULL));
827 retval->mtime = iso8601_to_gint64 (tracker_sparql_cursor_get_string (cursor, 2, NULL));
828
829 retval->content = biji_str_replace (
830 tracker_sparql_cursor_get_string (cursor, 3, NULL), "b<br/>", "\n");
831
832 retval->created = iso8601_to_gint64 (tracker_sparql_cursor_get_string (cursor, 4, NULL));
833
834
835 /* Check if the resource is up to date */
836
837 if (finisher->info->mtime != retval->mtime)
838 g_clear_pointer (&retval, biji_info_set_free);
839 }
840
841 g_object_unref (cursor);
842 }
843
844
845 /* No matter retval or not, we are supposed to callback
846 * (REMEMBER CALLER IS RESPONSIBLE FOR FREEING INFO SET) */
847 if (finisher->info_cb != NULL)
848 finisher->info_cb (retval, finisher->user_data);
849
850
851 biji_tracker_finisher_free (finisher);
852 }
853
854
855 void
biji_tracker_check_for_info(BijiManager * manager,gchar * url,gint64 mtime,BijiInfoCallback callback,gpointer user_data)856 biji_tracker_check_for_info (BijiManager *manager,
857 gchar *url,
858 gint64 mtime,
859 BijiInfoCallback callback,
860 gpointer user_data)
861 {
862 BijiInfoSet *info;
863 BijiTrackerFinisher *finisher;
864 gchar *query;
865
866 query = g_strconcat (
867 " SELECT ?urn ?title ?time ?content ?created",
868 " WHERE { ?urn a nfo:Note ;",
869 " nie:title ?title ;",
870 " nie:contentLastModified ?time ;",
871 " nie:plainTextContent ?content ;",
872 " nie:contentCreated ?created ;",
873 " nie:url '", url, "' }",
874 NULL);
875
876 /* No matter user callback or not,
877 * we'll need our own to push if needed */
878 info = biji_info_set_new ();
879 info->url = url;
880 info->mtime = mtime;
881
882 finisher = biji_tracker_finisher_new (
883 manager,
884 NULL,
885 info,
886 NULL,
887 callback,
888 NULL,
889 NULL,
890 NULL,
891 user_data);
892
893 tracker_sparql_connection_query_async (
894 get_connection (manager), query, NULL, on_info_queried, finisher);
895
896
897 g_free (query);
898 }
899