Coverage Report

Created: 2025-11-02 06:49

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/tinysparql/src/libtinysparql/tracker-deserializer-json-ld.c
Line
Count
Source
1
/*
2
 * Copyright (C) 2022, Red Hat Inc.
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
 * Author: Carlos Garnacho <carlosg@gnome.org>
20
 */
21
22
/* Deserialization to cursors for the JSON format defined at:
23
 *  https://www.w3.org/TR/json-ld/
24
 */
25
26
#include "config.h"
27
28
#include "tracker-deserializer-json-ld.h"
29
30
#include <json-glib/json-glib.h>
31
32
enum {
33
  STATE_INITIAL,
34
  STATE_ROOT_LIST,
35
  STATE_MAYBE_GRAPH,
36
  STATE_OBJECT_LIST,
37
  STATE_PROPERTIES,
38
  STATE_VALUE_LIST,
39
  STATE_VALUE,
40
  STATE_VALUE_AS_OBJECT,
41
  STATE_FINAL,
42
};
43
44
enum {
45
  STACK_ARRAY,
46
  STACK_OBJECT,
47
};
48
49
typedef struct {
50
  guint type;
51
  guint state;
52
  union {
53
    struct {
54
      gint idx;
55
      guint elements;
56
    } array;
57
    struct {
58
      gint idx;
59
      gchar **members;
60
      gchar *id;
61
      gboolean is_graph;
62
    } object;
63
  } data;
64
} StateStack;
65
66
struct _TrackerDeserializerJsonLD {
67
  TrackerDeserializer parent_instance;
68
  JsonParser *parser;
69
  JsonReader *reader;
70
  GArray *state_stack;
71
  gchar *default_lang;
72
  gchar *cur_graph;
73
  gchar *cur_subject;
74
  gchar *cur_predicate;
75
  gchar *cur_object;
76
  gchar *cur_object_lang;
77
  TrackerSparqlValueType object_type;
78
  guint state;
79
  gboolean has_row;
80
  guint blank_node_idx;
81
  GError *init_error;
82
};
83
84
0
G_DEFINE_TYPE (TrackerDeserializerJsonLD,
85
0
               tracker_deserializer_json_ld,
86
0
               TRACKER_TYPE_DESERIALIZER_RDF)
87
0
88
0
static void
89
0
tracker_deserializer_json_ld_finalize (GObject *object)
90
0
{
91
0
  TrackerDeserializerJsonLD *deserializer =
92
0
    TRACKER_DESERIALIZER_JSON_LD (object);
93
94
0
  tracker_sparql_cursor_close (TRACKER_SPARQL_CURSOR (deserializer));
95
96
0
  g_clear_object (&deserializer->reader);
97
0
  g_clear_object (&deserializer->parser);
98
0
  g_array_unref (deserializer->state_stack);
99
0
  g_clear_pointer (&deserializer->default_lang, g_free);
100
0
  g_clear_pointer (&deserializer->cur_graph, g_free);
101
0
  g_clear_pointer (&deserializer->cur_subject, g_free);
102
0
  g_clear_pointer (&deserializer->cur_predicate, g_free);
103
0
  g_clear_pointer (&deserializer->cur_object, g_free);
104
0
  g_clear_pointer (&deserializer->cur_object_lang, g_free);
105
106
0
  G_OBJECT_CLASS (tracker_deserializer_json_ld_parent_class)->finalize (object);
107
0
}
108
109
static void
110
tracker_deserializer_json_ld_constructed (GObject *object)
111
0
{
112
0
  TrackerDeserializerJsonLD *deserializer =
113
0
    TRACKER_DESERIALIZER_JSON_LD (object);
114
0
  GInputStream *stream;
115
116
0
  G_OBJECT_CLASS (tracker_deserializer_json_ld_parent_class)->constructed (object);
117
118
0
  stream = tracker_deserializer_get_stream (TRACKER_DESERIALIZER (object));
119
120
0
  if (json_parser_load_from_stream (deserializer->parser,
121
0
                                    stream,
122
0
                                    NULL,
123
0
                                    &deserializer->init_error)) {
124
0
    JsonNode *root;
125
126
0
    root = json_parser_get_root (deserializer->parser);
127
0
    deserializer->reader = json_reader_new (root);
128
0
  }
129
0
}
130
131
static void
132
state_clear (gpointer user_data)
133
0
{
134
0
  StateStack *elem = user_data;
135
136
0
  if (elem->type == STACK_OBJECT) {
137
0
    g_strfreev (elem->data.object.members);
138
0
    g_free (elem->data.object.id);
139
0
  }
140
0
}
141
142
static gboolean
143
advance_stack (TrackerDeserializerJsonLD *deserializer)
144
0
{
145
0
  StateStack *elem;
146
147
0
  g_assert (deserializer->state_stack->len > 0);
148
149
0
  elem = &g_array_index (deserializer->state_stack,
150
0
                         StateStack,
151
0
                         deserializer->state_stack->len - 1);
152
153
0
  if (elem->type == STACK_ARRAY) {
154
0
    if (elem->data.array.idx >= 0)
155
0
      json_reader_end_element (deserializer->reader);
156
157
0
    elem->data.array.idx++;
158
159
0
    if (elem->data.array.idx >= (gint) elem->data.array.elements)
160
0
      return FALSE;
161
162
0
    return json_reader_read_element (deserializer->reader,
163
0
                                     elem->data.array.idx);
164
0
  } else if (elem->type == STACK_OBJECT) {
165
0
    if (elem->data.object.idx >= 0)
166
0
      json_reader_end_member (deserializer->reader);
167
168
0
    elem->data.object.idx++;
169
170
0
    if (elem->data.object.members[elem->data.array.idx] == NULL)
171
0
      return FALSE;
172
173
0
    return json_reader_read_member (deserializer->reader,
174
0
                                    elem->data.object.members[elem->data.array.idx]);
175
0
  }
176
177
0
  return FALSE;
178
0
}
179
180
static void
181
push_stack (TrackerDeserializerJsonLD *deserializer,
182
            guint                      state)
183
0
{
184
0
  StateStack elem = { 0 };
185
0
  const gchar *id = NULL;
186
187
0
  if (json_reader_is_array (deserializer->reader)) {
188
0
    elem.type = STACK_ARRAY;
189
0
    elem.data.array.idx = -1;
190
0
    elem.data.array.elements =
191
0
      json_reader_count_elements (deserializer->reader);
192
0
  } else if (json_reader_is_object (deserializer->reader)) {
193
0
    elem.type = STACK_OBJECT;
194
0
    elem.data.object.idx = -1;
195
0
    elem.data.object.members =
196
0
      json_reader_list_members (deserializer->reader);
197
198
0
    elem.data.object.is_graph =
199
0
      json_reader_read_member (deserializer->reader, "@graph");
200
0
    json_reader_end_member (deserializer->reader);
201
202
0
    if (json_reader_read_member (deserializer->reader, "@id"))
203
0
      id = json_reader_get_string_value (deserializer->reader);
204
0
    json_reader_end_member (deserializer->reader);
205
206
0
    if (id) {
207
0
      TrackerNamespaceManager *namespaces;
208
209
0
      namespaces = tracker_deserializer_get_namespaces (TRACKER_DESERIALIZER (deserializer));
210
0
      elem.data.object.id =
211
0
        tracker_namespace_manager_expand_uri (namespaces, id);
212
0
    }
213
0
  } else {
214
0
    g_assert_not_reached ();
215
0
  }
216
217
0
  elem.state = state;
218
0
  g_array_append_val (deserializer->state_stack, elem);
219
0
  deserializer->state = state;
220
0
}
221
222
static void
223
pop_stack (TrackerDeserializerJsonLD *deserializer)
224
0
{
225
0
  StateStack *elem;
226
227
0
  g_assert (deserializer->state_stack->len > 0);
228
229
0
  g_array_set_size (deserializer->state_stack,
230
0
                    deserializer->state_stack->len - 1);
231
232
0
  if (deserializer->state_stack->len > 0) {
233
0
    elem = &g_array_index (deserializer->state_stack,
234
0
                           StateStack,
235
0
                           deserializer->state_stack->len - 1);
236
0
    deserializer->state = elem->state;
237
0
  } else {
238
0
    deserializer->state = STATE_FINAL;
239
0
  }
240
0
}
241
242
static guint
243
stack_state (TrackerDeserializerJsonLD *deserializer)
244
0
{
245
0
  StateStack *elem;
246
247
0
  g_assert (deserializer->state_stack->len > 0);
248
249
0
  elem = &g_array_index (deserializer->state_stack,
250
0
                         StateStack,
251
0
                         deserializer->state_stack->len - 1);
252
253
0
  return elem->state;
254
0
}
255
256
static const gchar *
257
current_member (TrackerDeserializerJsonLD *deserializer)
258
0
{
259
0
  StateStack *elem;
260
0
  gint i;
261
262
0
  g_assert (deserializer->state_stack->len > 0);
263
264
0
  for (i = (gint) deserializer->state_stack->len - 1; i >= 0; i--) {
265
0
    elem = &g_array_index (deserializer->state_stack,
266
0
                           StateStack, i);
267
268
0
    if (elem->type == STACK_OBJECT) {
269
0
      return elem->data.object.idx >= 0 ?
270
0
             elem->data.object.members[elem->data.object.idx] :
271
0
             NULL;
272
0
    }
273
0
  }
274
275
0
  return NULL;
276
0
}
277
278
static const gchar *
279
current_id (TrackerDeserializerJsonLD *deserializer)
280
0
{
281
0
  StateStack *elem;
282
0
  gint i;
283
284
0
  g_assert (deserializer->state_stack->len > 0);
285
286
0
  for (i = (gint) deserializer->state_stack->len - 1; i >= 0; i--) {
287
0
    elem = &g_array_index (deserializer->state_stack,
288
0
                           StateStack, i);
289
0
    if (elem->type == STACK_OBJECT &&
290
0
        !elem->data.object.is_graph &&
291
0
        elem->data.object.id)
292
0
      return elem->data.object.id;
293
0
  }
294
295
0
  return NULL;
296
0
}
297
298
static const gchar *
299
current_graph (TrackerDeserializerJsonLD *deserializer)
300
0
{
301
0
  StateStack *elem;
302
0
  gint i;
303
304
0
  g_assert (deserializer->state_stack->len > 0);
305
306
0
  for (i = (gint) deserializer->state_stack->len - 1; i >= 0; i--) {
307
0
    elem = &g_array_index (deserializer->state_stack,
308
0
                           StateStack, i);
309
0
    if (elem->type == STACK_OBJECT &&
310
0
        elem->data.object.is_graph)
311
0
      return elem->data.object.id;
312
0
  }
313
314
0
  return NULL;
315
0
}
316
317
static gchar *
318
object_to_value (TrackerDeserializerJsonLD  *deserializer,
319
                 TrackerNamespaceManager    *namespaces,
320
                 gchar                     **langtag,
321
                 TrackerSparqlValueType     *value_type)
322
0
{
323
0
  const gchar *value = NULL, *type = NULL;
324
325
0
  if (json_reader_read_member (deserializer->reader, "@value"))
326
0
    value = json_reader_get_string_value (deserializer->reader);
327
0
  json_reader_end_member (deserializer->reader);
328
329
0
  if (json_reader_read_member (deserializer->reader, "@language"))
330
0
    *langtag = g_strdup (json_reader_get_string_value (deserializer->reader));
331
0
  json_reader_end_member (deserializer->reader);
332
333
0
  if (json_reader_read_member (deserializer->reader, "@type"))
334
0
    type = json_reader_get_string_value (deserializer->reader);
335
0
  json_reader_end_member (deserializer->reader);
336
337
0
  if (g_strcmp0 (type, TRACKER_PREFIX_XSD "string") == 0 ||
338
0
      g_strcmp0 (type, TRACKER_PREFIX_RDF "langString") == 0)
339
0
    *value_type = TRACKER_SPARQL_VALUE_TYPE_STRING;
340
0
  else if (g_strcmp0 (type, TRACKER_PREFIX_XSD "integer") == 0)
341
0
    *value_type = TRACKER_SPARQL_VALUE_TYPE_INTEGER;
342
0
  else if (g_strcmp0 (type, TRACKER_PREFIX_XSD "boolean") == 0)
343
0
    *value_type = TRACKER_SPARQL_VALUE_TYPE_BOOLEAN;
344
0
  else if (g_strcmp0 (type, TRACKER_PREFIX_XSD "double") == 0)
345
0
    *value_type = TRACKER_SPARQL_VALUE_TYPE_DOUBLE;
346
0
  else if (g_strcmp0 (type, TRACKER_PREFIX_XSD "date") == 0 ||
347
0
           g_strcmp0 (type, TRACKER_PREFIX_XSD "dateTime") == 0)
348
0
    *value_type = TRACKER_SPARQL_VALUE_TYPE_DATETIME;
349
0
  else
350
0
    *value_type = TRACKER_SPARQL_VALUE_TYPE_STRING;
351
352
0
  return g_strdup (value);
353
0
}
354
355
static gchar *
356
node_to_value (JsonNode                *node,
357
               TrackerNamespaceManager *namespaces,
358
               TrackerSparqlValueType  *value_type)
359
0
{
360
0
  GValue value = G_VALUE_INIT;
361
0
  GType type;
362
0
  gchar *str = NULL;
363
364
0
  json_node_get_value (node, &value);
365
0
  type = json_node_get_value_type (node);
366
367
0
  if (type == G_TYPE_INT64) {
368
0
    *value_type = TRACKER_SPARQL_VALUE_TYPE_INTEGER;
369
0
    str = g_strdup_printf ("%" G_GINT64_FORMAT, g_value_get_int64 (&value));
370
0
  } else if (type == G_TYPE_STRING) {
371
0
    *value_type = TRACKER_SPARQL_VALUE_TYPE_STRING;
372
0
    str = tracker_namespace_manager_expand_uri (namespaces, g_value_get_string (&value));
373
0
  } else if (type == G_TYPE_DOUBLE) {
374
0
    gchar buf[G_ASCII_DTOSTR_BUF_SIZE];
375
376
0
    g_ascii_dtostr (buf, G_ASCII_DTOSTR_BUF_SIZE, g_value_get_double (&value));
377
0
    *value_type = TRACKER_SPARQL_VALUE_TYPE_DOUBLE;
378
0
    str = g_strdup (buf);
379
0
  } else if (type == G_TYPE_BOOLEAN) {
380
0
    *value_type = TRACKER_SPARQL_VALUE_TYPE_BOOLEAN;
381
0
    str = g_strdup (g_value_get_boolean (&value) ? "true" : "false");
382
0
  } else {
383
0
    *value_type = TRACKER_SPARQL_VALUE_TYPE_UNBOUND;
384
0
  }
385
386
0
  g_value_unset (&value);
387
388
0
  return str;
389
0
}
390
391
static void
392
load_special_key (TrackerDeserializerJsonLD *deserializer,
393
                  const gchar               *key)
394
0
{
395
0
  const gchar *value;
396
397
0
  if (json_reader_read_member (deserializer->reader, key)) {
398
0
    value = json_reader_get_string_value (deserializer->reader);
399
400
0
    if (g_strcmp0 (key, "@language") == 0) {
401
0
      g_clear_pointer (&deserializer->default_lang, g_free);
402
0
      deserializer->default_lang = g_strdup (value);
403
0
    }
404
0
  }
405
406
0
  json_reader_end_member (deserializer->reader);
407
0
}
408
409
static void
410
load_context (TrackerDeserializerJsonLD *deserializer)
411
0
{
412
0
  TrackerNamespaceManager *namespaces;
413
414
0
  namespaces = tracker_deserializer_get_namespaces (TRACKER_DESERIALIZER (deserializer));
415
416
0
  if (json_reader_read_member (deserializer->reader, "@context")) {
417
0
    gchar **members = json_reader_list_members (deserializer->reader);
418
0
    guint i;
419
420
0
    for (i = 0; members && members[i] != NULL; i++) {
421
0
      if (members[i][0] == '@') {
422
0
        load_special_key (deserializer, members[i]);
423
0
        continue;
424
0
      }
425
426
0
      if (tracker_namespace_manager_lookup_prefix (namespaces, members[i]))
427
0
        continue;
428
429
0
      if (json_reader_read_member (deserializer->reader, members[i])) {
430
0
        const gchar *expanded = json_reader_get_string_value (deserializer->reader);
431
0
        tracker_namespace_manager_add_prefix (namespaces, members[i], expanded);
432
0
      }
433
434
0
      json_reader_end_member (deserializer->reader);
435
0
    }
436
437
0
    g_strfreev (members);
438
0
  }
439
440
0
  json_reader_end_member (deserializer->reader);
441
0
}
442
443
static void
444
forward_state_for_value (TrackerDeserializerJsonLD *deserializer)
445
0
{
446
0
  if (json_reader_is_object (deserializer->reader)) {
447
0
    if (json_reader_read_member (deserializer->reader, "@value")) {
448
0
      json_reader_end_member (deserializer->reader);
449
0
      deserializer->state = STATE_VALUE_AS_OBJECT;
450
0
    } else {
451
0
      json_reader_end_member (deserializer->reader);
452
0
      push_stack (deserializer, STATE_PROPERTIES);
453
0
      deserializer->state = STATE_MAYBE_GRAPH;
454
0
    }
455
0
  } else {
456
0
    deserializer->state = STATE_VALUE;
457
0
  }
458
0
}
459
460
static gboolean
461
forward_state (TrackerDeserializerJsonLD  *deserializer,
462
               GError                    **error)
463
0
{
464
0
  TrackerNamespaceManager *namespaces;
465
0
  const gchar *member;
466
467
0
  namespaces = tracker_deserializer_get_namespaces (TRACKER_DESERIALIZER (deserializer));
468
469
0
  switch (deserializer->state) {
470
0
  case STATE_INITIAL:
471
0
    if (json_reader_is_array (deserializer->reader)) {
472
0
      push_stack (deserializer, STATE_ROOT_LIST);
473
0
    } else if (json_reader_is_object (deserializer->reader)) {
474
0
      push_stack (deserializer, STATE_PROPERTIES);
475
0
      deserializer->state = STATE_MAYBE_GRAPH;
476
0
    }
477
0
    break;
478
0
  case STATE_ROOT_LIST:
479
0
    if (!advance_stack (deserializer)) {
480
0
      pop_stack (deserializer);
481
0
      break;
482
0
    }
483
484
0
    if (json_reader_is_object (deserializer->reader)) {
485
0
      push_stack (deserializer, STATE_MAYBE_GRAPH);
486
0
    } else {
487
0
      g_set_error (error,
488
0
                   TRACKER_SPARQL_ERROR,
489
0
                   TRACKER_SPARQL_ERROR_PARSE,
490
0
                   "Expected graph or resource object");
491
0
      return FALSE;
492
0
    }
493
0
    break;
494
0
  case STATE_MAYBE_GRAPH:
495
0
    load_context (deserializer);
496
497
0
    if (json_reader_read_member (deserializer->reader, "@graph")) {
498
0
      g_clear_pointer (&deserializer->cur_graph, g_free);
499
0
      deserializer->cur_graph = g_strdup (current_graph (deserializer));
500
501
0
      if (json_reader_is_array (deserializer->reader)) {
502
0
        push_stack (deserializer, STATE_OBJECT_LIST);
503
0
      } else {
504
0
        g_set_error (error,
505
0
                     TRACKER_SPARQL_ERROR,
506
0
                     TRACKER_SPARQL_ERROR_PARSE,
507
0
                     "Expected resource list");
508
0
        return FALSE;
509
0
      }
510
0
    } else {
511
0
      json_reader_end_member (deserializer->reader);
512
0
      g_clear_pointer (&deserializer->cur_subject, g_free);
513
0
      deserializer->cur_subject = g_strdup (current_id (deserializer));
514
0
      deserializer->state = STATE_PROPERTIES;
515
0
    }
516
0
    break;
517
0
  case STATE_OBJECT_LIST:
518
0
    if (!advance_stack (deserializer)) {
519
      /* Pop the graph array, close manually the @graph
520
       * member, and pop the graph object too
521
       */
522
0
      pop_stack (deserializer);
523
0
      json_reader_end_member (deserializer->reader);
524
0
      pop_stack (deserializer);
525
0
      break;
526
0
    }
527
528
0
    if (json_reader_is_object (deserializer->reader)) {
529
0
      push_stack (deserializer, STATE_PROPERTIES);
530
0
      deserializer->state = STATE_MAYBE_GRAPH;
531
0
    } else {
532
0
      g_set_error (error,
533
0
                   TRACKER_SPARQL_ERROR,
534
0
                   TRACKER_SPARQL_ERROR_PARSE,
535
0
                   "Expected resource object");
536
0
      return FALSE;
537
0
    }
538
0
    break;
539
0
  case STATE_PROPERTIES:
540
0
    if (!advance_stack (deserializer)) {
541
0
      pop_stack (deserializer);
542
543
0
      if (deserializer->state == STATE_PROPERTIES ||
544
0
          deserializer->state == STATE_VALUE_LIST) {
545
0
        gchar *nested_object_id;
546
547
        /* The state popped belonged to a nested object,
548
         * switch subject/predicate back to the parent
549
         * object, and finalize the property that defined it.
550
         */
551
0
        nested_object_id = g_steal_pointer (&deserializer->cur_subject);
552
553
0
        deserializer->cur_subject = g_strdup (current_id (deserializer));
554
0
        g_clear_pointer (&deserializer->cur_predicate, g_free);
555
0
        deserializer->cur_predicate =
556
0
          tracker_namespace_manager_expand_uri (namespaces, current_member (deserializer));
557
0
        g_clear_pointer (&deserializer->cur_object, g_free);
558
0
        g_clear_pointer (&deserializer->cur_object_lang, g_free);
559
0
        deserializer->cur_object = nested_object_id;
560
0
        deserializer->object_type = TRACKER_SPARQL_VALUE_TYPE_STRING;
561
0
        deserializer->has_row = TRUE;
562
0
      }
563
564
0
      break;
565
0
    }
566
567
0
    member = current_member (deserializer);
568
0
    g_clear_pointer (&deserializer->cur_predicate, g_free);
569
570
0
    if (g_strcmp0 (member, "@type") == 0)
571
0
      deserializer->cur_predicate = g_strdup (TRACKER_PREFIX_RDF "type");
572
0
    else if (member[0] != '@')
573
0
      deserializer->cur_predicate = tracker_namespace_manager_expand_uri (namespaces, member);
574
0
    else
575
0
      break;
576
577
0
    if (json_reader_is_array (deserializer->reader))
578
0
      push_stack (deserializer, STATE_VALUE_LIST);
579
0
    else
580
0
      forward_state_for_value (deserializer);
581
0
    break;
582
0
  case STATE_VALUE_LIST:
583
0
    if (!advance_stack (deserializer)) {
584
0
      pop_stack (deserializer);
585
0
      break;
586
0
    }
587
588
0
    forward_state_for_value (deserializer);
589
0
    break;
590
0
  case STATE_VALUE_AS_OBJECT:
591
0
    g_clear_pointer (&deserializer->cur_object, g_free);
592
0
    g_clear_pointer (&deserializer->cur_object_lang, g_free);
593
0
    deserializer->cur_object = object_to_value (deserializer,
594
0
                                                namespaces,
595
0
                                                &deserializer->cur_object_lang,
596
0
                                                &deserializer->object_type);
597
0
    deserializer->has_row = TRUE;
598
599
0
    deserializer->state = stack_state (deserializer);
600
0
    break;
601
0
  case STATE_VALUE:
602
0
    g_clear_pointer (&deserializer->cur_object, g_free);
603
0
    g_clear_pointer (&deserializer->cur_object_lang, g_free);
604
0
    deserializer->cur_object = node_to_value (json_reader_get_value (deserializer->reader),
605
0
                                              namespaces,
606
0
                                              &deserializer->object_type);
607
0
    deserializer->has_row = TRUE;
608
609
0
    deserializer->state = stack_state (deserializer);
610
0
    break;
611
0
  case STATE_FINAL:
612
0
    break;
613
0
  }
614
615
0
  return deserializer->state_stack->len > 0;
616
0
}
617
618
static TrackerSparqlValueType
619
tracker_deserializer_json_ld_get_value_type (TrackerSparqlCursor  *cursor,
620
                                             gint                  column)
621
0
{
622
0
  TrackerDeserializerJsonLD *deserializer =
623
0
    TRACKER_DESERIALIZER_JSON_LD (cursor);
624
625
0
  switch (column) {
626
0
  case TRACKER_RDF_COL_SUBJECT:
627
0
    if (!deserializer->cur_subject)
628
0
      return TRACKER_SPARQL_VALUE_TYPE_UNBOUND;
629
0
    else if (strncmp (deserializer->cur_subject, "_:", 2) == 0)
630
0
      return TRACKER_SPARQL_VALUE_TYPE_BLANK_NODE;
631
0
    else
632
0
      return TRACKER_SPARQL_VALUE_TYPE_URI;
633
0
    break;
634
0
  case TRACKER_RDF_COL_PREDICATE:
635
0
    if (!deserializer->cur_predicate)
636
0
      return TRACKER_SPARQL_VALUE_TYPE_UNBOUND;
637
0
    else
638
0
      return TRACKER_SPARQL_VALUE_TYPE_URI;
639
0
    break;
640
0
  case TRACKER_RDF_COL_OBJECT:
641
0
    if (!deserializer->cur_object)
642
0
      return TRACKER_SPARQL_VALUE_TYPE_UNBOUND;
643
0
    else
644
0
      return deserializer->object_type;
645
0
    break;
646
0
  case TRACKER_RDF_COL_GRAPH:
647
0
    if (!deserializer->cur_graph)
648
0
      return TRACKER_SPARQL_VALUE_TYPE_UNBOUND;
649
0
    else
650
0
      return TRACKER_SPARQL_VALUE_TYPE_URI;
651
0
    break;
652
0
  default:
653
0
    return TRACKER_SPARQL_VALUE_TYPE_UNBOUND;
654
0
  }
655
0
}
656
657
static const gchar *
658
tracker_deserializer_json_ld_get_string (TrackerSparqlCursor  *cursor,
659
                                         gint                  column,
660
                                         const gchar         **langtag,
661
                                         glong                *length)
662
0
{
663
0
  TrackerDeserializerJsonLD *deserializer =
664
0
    TRACKER_DESERIALIZER_JSON_LD (cursor);
665
0
  const gchar *str = NULL;
666
667
0
  if (length)
668
0
    *length = 0;
669
0
  if (langtag)
670
0
    *langtag = NULL;
671
672
0
  switch (column) {
673
0
  case TRACKER_RDF_COL_SUBJECT:
674
0
    str = deserializer->cur_subject;
675
0
    break;
676
0
  case TRACKER_RDF_COL_PREDICATE:
677
0
    str = deserializer->cur_predicate;
678
0
    break;
679
0
  case TRACKER_RDF_COL_OBJECT:
680
0
    if (langtag) {
681
0
      if (deserializer->cur_object_lang)
682
0
        *langtag = deserializer->cur_object_lang;
683
0
      else
684
0
        *langtag = deserializer->default_lang;
685
0
    }
686
687
0
    str = deserializer->cur_object;
688
0
    break;
689
0
  case TRACKER_RDF_COL_GRAPH:
690
0
    str = deserializer->cur_graph;
691
0
    break;
692
0
  default:
693
0
    break;
694
0
  }
695
696
0
  if (length && str)
697
0
    *length = strlen (str);
698
699
0
  return str;
700
0
}
701
702
static gboolean
703
tracker_deserializer_json_ld_next (TrackerSparqlCursor  *cursor,
704
                                   GCancellable         *cancellable,
705
                                   GError              **error)
706
0
{
707
0
  TrackerDeserializerJsonLD *deserializer =
708
0
    TRACKER_DESERIALIZER_JSON_LD (cursor);
709
710
0
  if (deserializer->init_error) {
711
0
    GError *init_error;
712
713
0
    init_error = g_steal_pointer (&deserializer->init_error);
714
0
    g_propagate_error (error, init_error);
715
0
    return FALSE;
716
0
  }
717
718
0
  deserializer->has_row = FALSE;
719
720
0
  while (!deserializer->has_row) {
721
0
    GError *inner_error = NULL;
722
723
0
    if (g_cancellable_set_error_if_cancelled (cancellable, error))
724
0
      return FALSE;
725
726
0
    if (!forward_state (deserializer, &inner_error)) {
727
0
      if (inner_error) {
728
0
        g_propagate_error (error, inner_error);
729
0
      } else {
730
0
        const GError *reader_error;
731
732
0
        reader_error = json_reader_get_error (deserializer->reader);
733
0
        if (error && reader_error)
734
0
          *error = g_error_copy (reader_error);
735
0
      }
736
737
0
      return FALSE;
738
0
    }
739
0
  }
740
741
0
  if (!deserializer->cur_subject)
742
0
    deserializer->cur_subject = g_strdup_printf ("_:%d", deserializer->blank_node_idx++);
743
744
0
  return TRUE;
745
0
}
746
747
static void
748
tracker_deserializer_json_ld_close (TrackerSparqlCursor *cursor)
749
0
{
750
0
}
751
752
gboolean
753
tracker_deserializer_json_ld_get_parser_location (TrackerDeserializer *deserializer,
754
                                                  goffset             *line_no,
755
                                                  goffset             *column_no)
756
0
{
757
0
  return FALSE;
758
0
}
759
760
static void
761
tracker_deserializer_json_ld_class_init (TrackerDeserializerJsonLDClass *klass)
762
0
{
763
0
  GObjectClass *object_class = G_OBJECT_CLASS (klass);
764
0
  TrackerSparqlCursorClass *cursor_class =
765
0
    TRACKER_SPARQL_CURSOR_CLASS (klass);
766
0
  TrackerDeserializerClass *deserializer_class =
767
0
    TRACKER_DESERIALIZER_CLASS (klass);
768
769
0
  object_class->finalize = tracker_deserializer_json_ld_finalize;
770
0
  object_class->constructed = tracker_deserializer_json_ld_constructed;
771
772
0
  cursor_class->get_value_type = tracker_deserializer_json_ld_get_value_type;
773
0
  cursor_class->get_string = tracker_deserializer_json_ld_get_string;
774
0
  cursor_class->next = tracker_deserializer_json_ld_next;
775
0
  cursor_class->close = tracker_deserializer_json_ld_close;
776
777
0
  deserializer_class->get_parser_location =
778
0
    tracker_deserializer_json_ld_get_parser_location;
779
0
}
780
781
static void
782
tracker_deserializer_json_ld_init (TrackerDeserializerJsonLD *deserializer)
783
0
{
784
0
  deserializer->parser = json_parser_new ();
785
0
  deserializer->state_stack = g_array_new (FALSE, FALSE, sizeof (StateStack));
786
0
  g_array_set_clear_func (deserializer->state_stack, state_clear);
787
0
}
788
789
TrackerSparqlCursor *
790
tracker_deserializer_json_ld_new (GInputStream            *stream,
791
                                  TrackerNamespaceManager *namespaces)
792
0
{
793
0
  return g_object_new (TRACKER_TYPE_DESERIALIZER_JSON_LD,
794
0
                       "stream", stream,
795
0
                       "namespace-manager", namespaces,
796
                       NULL);
797
0
}