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 (rdf rdf)
34
  #:export (compact
35
            expand
36
            flatten
37
            jsonld->rdf))
38
39
(define* (compact input context #:key (options (new-jsonld-options)))
40
  (call-with-values
41
    (lambda ()
42
      ;; TODO: set ordered to #f
43
      (expand-with-base input #:options options))
44
    ;; 2 and 3
45
    (lambda (expanded-input context-base)
46
      (when (string? context)
47
        (set! context
48
          (json-document-document
49
            ((jsonld-options-document-loader options)
50
             context))))
51
      ;; 4
52
      (when (json-has-key? context "@context")
53
        (set! context (assoc-ref context "@context")))
54
      (let* ((base-iri (or (jsonld-options-base options)
55
                           (and (jsonld-options-compact-to-relative? options)
56
                                (string? input)
57
                                input)))
58
             (active-context (context-processing (new-active-context
59
                                                   #:base base-iri)
60
                                                 context context-base
61
                                                 #:options options))
62
             (inverse-context (inverse-context-creation active-context))
63
             (compacted-output
64
               (compaction active-context inverse-context
65
                           #nil ;; active-property
66
                           expanded-input ;; element
67
                           #:compact-arrays? (jsonld-options-compact-arrays? options)
68
                           #:ordered? (jsonld-options-ordered? options)
69
                           #:processing-mode
70
                           (jsonld-options-processing-mode options))))
71
        (if (equal? compacted-output #())
72
            (set! compacted-output '())
73
            (when (json-array? compacted-output)
74
              (set! compacted-output `((,(iri-compaction active-context
75
                                                         inverse-context
76
                                                         "@graph"
77
                                                         #:vocab? #t
78
                                                         #:reverse? #f) .
79
                                         ,compacted-output)))))
80
        (when (and context (not (null? compacted-output)) (not (null? context)))
81
          (set! compacted-output
82
            (cons (cons "@context" context) compacted-output)))
83
        compacted-output))))
84
85
(define* (expand-with-base input #:key (options (new-jsonld-options)))
86
  (let ((document input)
87
        (remote-document #f)
88
        (active-context (new-active-context
89
                          #:base (jsonld-options-base options)
90
                          #:original-base (jsonld-options-base options)))
91
        (document-base (jsonld-options-base options)))
92
    (when (string? input)
93
      ;; 2
94
      (catch #t
95
        (lambda ()
96
          (set! remote-document
97
            ((jsonld-options-document-loader options)
98
             input
99
             #:extract-all-scripts? (jsonld-options-extract-all-scripts? options))))
100
        (lambda (key . value)
101
          (cond
102
            ((member key '(loading-document-failed multiple-context-link-headers
103
                           invalid-script-element))
104
             (apply throw key value))
105
            (else
106
              (apply throw 'loading-document-failed key value)))))
107
      ;; 3
108
      (set! document (json-document-document remote-document))
109
      (set! document-base (json-document-document-url remote-document))
110
      ;; 4
111
      (set! active-context
112
        (update-active-context active-context
113
                               #:base (or (jsonld-options-base options)
114
                                          (json-document-document-url remote-document))
115
                               #:original-base
116
                               (or (json-document-document-url remote-document)
117
                                   (jsonld-options-base options)))))
118
119
    ;; 5
120
    (when (jsonld-options-expand-context options)
121
      (set! active-context
122
        (let* ((local-context (jsonld-options-expand-context options))
123
               (local-context (if (json-has-key? local-context "@context")
124
                                  (assoc-ref local-context "@context")
125
                                  local-context)))
126
          (context-processing active-context local-context
127
                              (active-context-original-base active-context)))))
128
129
    ;; 6
130
    (when (and remote-document (json-document-context-url remote-document))
131
      (let ((context-url (json-document-context-url remote-document)))
132
        (set! active-context
133
          (context-processing active-context context-url context-url))))
134
135
    ;; 7
136
    (let ((expanded-output (expansion active-context #nil document
137
                                      (if remote-document
138
                                          (or (json-document-document-url remote-document)
139
                                              (jsonld-options-base options))
140
                                          (jsonld-options-base options))
141
                                      #:options options)))
142
      (when (and
143
              (json-object? expanded-output)
144
              (json-has-key? expanded-output "@graph")
145
              (null? (filter
146
                       (lambda (kv)
147
                         (not (equal? (car kv) "@graph")))
148
                       expanded-output)))
149
        (set! expanded-output (assoc-ref expanded-output "@graph")))
150
      (when (equal? expanded-output #nil)
151
        (set! expanded-output #()))
152
      (unless (json-array? expanded-output)
153
        (set! expanded-output `#(,expanded-output)))
154
      ;; 8
155
      (values expanded-output document-base))))
156
157
(define* (expand input #:key (options (new-jsonld-options)))
158
  (call-with-values
159
    (lambda ()
160
      (expand-with-base input #:options options))
161
    (lambda (out base)
162
      out)))
163
164
(define* (flatten input #:key (context #f) (options (new-jsonld-options)))
165
  ;; 2
166
  (let* ((expanded-input
167
           (expand input #:options (update-jsonld-options
168
                                     options #:ordered? #t)))
169
         ;; 3
170
         (base-iri (or (jsonld-options-base options)
171
                       (and (jsonld-options-compact-to-relative? options)
172
                            (string? input)
173
                            input)))
174
         ;; 4
175
         (identifier-map '())
176
         ;; 5
177
         (flattened-output (flattening expanded-input
178
                                       #:ordered?
179
                                       (jsonld-options-ordered? options))))
180
    ;; 5.1
181
    (when context
182
      ;; TODO
183
      (set! flattened-output (compact flattened-output context #:options options)))
184
    flattened-output))
185
186
(define* (jsonld->rdf input #:key (options (new-jsonld-options)))
187
  (call-with-values
188
    (lambda ()
189
      ;; TODO: set ordered to #f
190
      (expand-with-base input #:options options))
191
    ;; 2 and 3
192
    (lambda (expanded-input context-base)
193
      (pk 'expanded expanded-input)
194
      (let* ((generate-blank-node (get-generate-blank-node-identifier))
195
             (generate-node-map (get-node-map-generation generate-blank-node))
196
             (node-map (generate-node-map expanded-input '()))
197
             (node-map (assoc-ref node-map "node-map")))
198
        (pk node-map)
199
        (deserialize-jsonld
200
          generate-blank-node node-map (make-rdf-dataset '() '())
201
          #:produce-generalized-rdf?
202
          (jsonld-options-produce-generalized-rdf? options)
203
          #:rdf-direction (jsonld-options-rdf-direction options))))))
204