guile-jsonld/jsonld.scm

jsonld.scm

1
;;;; Copyright (C) 2019, 2020 Julien Lepiller <julien@lepiller.eu>
2
;;;; 
3
;;;; This library is free software; you can redistribute it and/or
4
;;;; modify it under the terms of the GNU Lesser General Public
5
;;;; License as published by the Free Software Foundation; either
6
;;;; version 3 of the License, or (at your option) any later version.
7
;;;; 
8
;;;; This library is distributed in the hope that it will be useful,
9
;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
10
;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11
;;;; Lesser General Public License for more details.
12
;;;; 
13
;;;; You should have received a copy of the GNU Lesser General Public
14
;;;; License along with this library; if not, write to the Free Software
15
;;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
;;;; 
17
18
(define-module (jsonld)
19
  #:use-module (jsonld compaction)
20
  #:use-module (jsonld context)
21
  #:use-module (jsonld context-processing)
22
  #:use-module (jsonld deserialize-jsonld)
23
  #:use-module (jsonld download)
24
  #:use-module (jsonld expansion)
25
  #:use-module (jsonld flattening)
26
  #:use-module (jsonld generate-blank-node-identifier)
27
  #:use-module (jsonld inverse-context-creation)
28
  #:use-module (jsonld iri)
29
  #:use-module (jsonld iri-compaction)
30
  #:use-module (jsonld json)
31
  #:use-module (jsonld node-map-generation)
32
  #:use-module (jsonld options)
33
  #:use-module (jsonld serialize-rdf)
34
  #:use-module (rdf rdf)
35
  #:export (compact
36
            expand
37
            flatten
38
            jsonld->rdf
39
            rdf->jsonld))
40
41
(define* (compact input context #:key (options (new-jsonld-options)))
42
  (call-with-values
43
    (lambda ()
44
      ;; TODO: set ordered to #f
45
      (expand-with-base input #:options options))
46
    ;; 2 and 3
47
    (lambda (expanded-input context-base)
48
      (when (string? context)
49
        (set! context
50
          (json-document-document
51
            ((jsonld-options-document-loader options)
52
             context))))
53
      ;; 4
54
      (when (json-has-key? context "@context")
55
        (set! context (assoc-ref context "@context")))
56
      (pk expanded-input)
57
      (pk context)
58
      (let* ((base-iri (or (jsonld-options-base options)
59
                           (and (jsonld-options-compact-to-relative? options)
60
                                (string? input)
61
                                input)))
62
             (active-context (context-processing (new-active-context
63
                                                   #:base base-iri)
64
                                                 context context-base
65
                                                 #:options options))
66
             (inverse-context (inverse-context-creation active-context))
67
             (compacted-output
68
               (compaction active-context inverse-context
69
                           json-null ;; active-property
70
                           expanded-input ;; element
71
                           #:compact-arrays? (jsonld-options-compact-arrays? options)
72
                           #:ordered? (jsonld-options-ordered? options)
73
                           #:processing-mode
74
                           (jsonld-options-processing-mode options))))
75
        (pk 'compacted-output compacted-output)
76
        (if (equal? compacted-output #())
77
            (set! compacted-output '())
78
            (when (json-array? compacted-output)
79
              (set! compacted-output `((,(iri-compaction active-context
80
                                                         inverse-context
81
                                                         "@graph"
82
                                                         #:vocab? #t
83
                                                         #:reverse? #f) .
84
                                         ,compacted-output)))))
85
        (when (and context (not (null? compacted-output)) (not (null? context)))
86
          (set! compacted-output
87
            (cons (cons "@context" context) compacted-output)))
88
        compacted-output))))
89
90
(define* (expand-with-base input #:key (options (new-jsonld-options)))
91
  (let ((document input)
92
        (remote-document #f)
93
        (active-context (new-active-context
94
                          #:base (jsonld-options-base options)
95
                          #:original-base (jsonld-options-base options)))
96
        (document-base (jsonld-options-base options)))
97
    (when (string? input)
98
      ;; 2
99
      (catch #t
100
        (lambda ()
101
          (set! remote-document
102
            ((jsonld-options-document-loader options)
103
             input
104
             #:extract-all-scripts? (jsonld-options-extract-all-scripts? options))))
105
        (lambda (key . value)
106
          (cond
107
            ((member key '(loading-document-failed multiple-context-link-headers
108
                           invalid-script-element))
109
             (apply throw key value))
110
            (else
111
              (apply throw 'loading-document-failed key value)))))
112
      ;; 3
113
      (set! document (json-document-document remote-document))
114
      (set! document-base (json-document-document-url remote-document))
115
      ;; 4
116
      (set! active-context
117
        (update-active-context active-context
118
                               #:base (or (jsonld-options-base options)
119
                                          (json-document-document-url remote-document))
120
                               #:original-base
121
                               (or (json-document-document-url remote-document)
122
                                   (jsonld-options-base options)))))
123
124
    ;; 5
125
    (when (jsonld-options-expand-context options)
126
      (set! active-context
127
        (let* ((local-context (jsonld-options-expand-context options))
128
               (local-context (if (json-has-key? local-context "@context")
129
                                  (assoc-ref local-context "@context")
130
                                  local-context)))
131
          (context-processing active-context local-context
132
                              (active-context-original-base active-context)))))
133
134
    ;; 6
135
    (when (and remote-document (json-document-context-url remote-document))
136
      (let ((context-url (json-document-context-url remote-document)))
137
        (set! active-context
138
          (context-processing active-context context-url context-url))))
139
140
    ;; 7
141
    (let ((expanded-output (expansion active-context json-null document
142
                                      (if remote-document
143
                                          (or (json-document-document-url remote-document)
144
                                              (jsonld-options-base options))
145
                                          (jsonld-options-base options))
146
                                      #:options options)))
147
      (when (and
148
              (json-object? expanded-output)
149
              (json-has-key? expanded-output "@graph")
150
              (null? (filter
151
                       (lambda (kv)
152
                         (not (equal? (car kv) "@graph")))
153
                       expanded-output)))
154
        (set! expanded-output (assoc-ref expanded-output "@graph")))
155
      (when (json-null? expanded-output)
156
        (set! expanded-output #()))
157
      (unless (json-array? expanded-output)
158
        (set! expanded-output `#(,expanded-output)))
159
      ;; 8
160
      (values expanded-output document-base))))
161
162
(define* (expand input #:key (options (new-jsonld-options)))
163
  (call-with-values
164
    (lambda ()
165
      (expand-with-base input #:options options))
166
    (lambda (out base)
167
      out)))
168
169
(define* (flatten input #:key (context #f) (options (new-jsonld-options)))
170
  ;; 2
171
  (let* ((expanded-input
172
           (expand input #:options (update-jsonld-options
173
                                     options #:ordered? #t)))
174
         ;; 3
175
         (base-iri (or (jsonld-options-base options)
176
                       (and (jsonld-options-compact-to-relative? options)
177
                            (string? input)
178
                            input)))
179
         ;; 4
180
         (identifier-map '())
181
         ;; 5
182
         (flattened-output (flattening expanded-input
183
                                       #:ordered?
184
                                       (jsonld-options-ordered? options))))
185
    ;; 5.1
186
    (when context
187
      ;; TODO
188
      (set! flattened-output (compact flattened-output context #:options options)))
189
    flattened-output))
190
191
(define* (jsonld->rdf input #:key (options (new-jsonld-options)))
192
  (call-with-values
193
    (lambda ()
194
      ;; TODO: set ordered to #f
195
      (expand-with-base input #:options options))
196
    ;; 2 and 3
197
    (lambda (expanded-input context-base)
198
      (pk 'expanded expanded-input)
199
      (let* ((generate-blank-node (get-generate-blank-node-identifier))
200
             (generate-node-map (get-node-map-generation generate-blank-node))
201
             (node-map (generate-node-map expanded-input '()))
202
             (node-map (assoc-ref node-map "node-map")))
203
        (pk node-map)
204
        (deserialize-jsonld
205
          generate-blank-node node-map (make-rdf-dataset '() '())
206
          #:produce-generalized-rdf?
207
          (jsonld-options-produce-generalized-rdf? options)
208
          #:rdf-direction (jsonld-options-rdf-direction options))))))
209
210
(define* (rdf->jsonld input #:key (options (new-jsonld-options)))
211
  (serialize-rdf input
212
                 #:ordered? (jsonld-options-ordered? options)
213
                 #:rdf-direction (jsonld-options-rdf-direction options)
214
                 #:use-native-types? (jsonld-options-use-native-types? options)
215
                 #:use-rdf-type? (jsonld-options-use-rdf-type? options)
216
                 #:processing-mode (jsonld-options-processing-mode options)))
217