Add toRdf algorithm.
Makefile.am
6 | 6 | jsonld/context-processing.scm \ | |
7 | 7 | jsonld/context.scm \ | |
8 | 8 | jsonld/create-term-definition.scm \ | |
9 | + | jsonld/deserialize-jsonld.scm \ | |
9 | 10 | jsonld/download.scm \ | |
10 | 11 | jsonld/expansion.scm \ | |
11 | 12 | jsonld/flattening.scm \ | |
… | |||
15 | 16 | jsonld/iri-expansion.scm \ | |
16 | 17 | jsonld/iri.scm \ | |
17 | 18 | jsonld/json.scm \ | |
19 | + | jsonld/list-to-rdf.scm \ | |
18 | 20 | jsonld/memoization.scm \ | |
19 | 21 | jsonld/merge-node-maps.scm \ | |
20 | 22 | jsonld/node-map-generation.scm \ | |
23 | + | jsonld/object-to-rdf.scm \ | |
21 | 24 | jsonld/options.scm \ | |
22 | 25 | jsonld/term-selection.scm \ | |
23 | 26 | jsonld/value-compaction.scm \ | |
… | |||
32 | 35 | TESTS = tests/compact.scm \ | |
33 | 36 | tests/expand.scm \ | |
34 | 37 | tests/flatten.scm \ | |
35 | - | #tests/html.scm \ not properly implemented | |
36 | 38 | tests/remote-doc.scm | |
37 | 39 | EXTRA_DIST += $(TESTS) | |
38 | 40 |
README.md
121 | 121 | to carry additional configuration information. An additional context can be | |
122 | 122 | passed in order to run the compaction algorithm on the result. | |
123 | 123 | ||
124 | + | **Scheme Procedure**: jsonld->rdf input [#:options (new-jsonld-options)] | |
125 | + | ||
126 | + | Transforms the given input into an RDF dataset (in the format expected by | |
127 | + | guile-rdf). This procedure takes an input, which can be a Json object (as | |
128 | + | produced by the guile-json library) or a string representing the URL of a JsonLD | |
129 | + | document. The options can be used to carry additional configuration information. | |
130 | + | ||
124 | 131 | ### The JsonLDOptions Type | |
125 | 132 | ||
126 | 133 | The `jsonld-options` type is used to pass various options to the JsonLdProcessor |
configure.ac
29 | 29 | AC_CONFIG_FILES([tests/html.scm], [chmod +x tests/html.scm]) | |
30 | 30 | AC_CONFIG_FILES([tests/remote-doc.scm], [chmod +x tests/remote-doc.scm]) | |
31 | 31 | AC_CONFIG_FILES([tests/report.scm], [chmod +x tests/report.scm]) | |
32 | + | AC_CONFIG_FILES([tests/tordf.scm], [chmod +x tests/tordf.scm]) | |
32 | 33 | AC_CONFIG_FILES(Makefile) | |
33 | 34 | AC_REQUIRE_AUX_FILE([tap-driver.sh]) | |
34 | 35 | AC_PROG_AWK |
jsonld.scm
19 | 19 | #:use-module (jsonld compaction) | |
20 | 20 | #:use-module (jsonld context) | |
21 | 21 | #:use-module (jsonld context-processing) | |
22 | + | #:use-module (jsonld deserialize-jsonld) | |
22 | 23 | #:use-module (jsonld download) | |
23 | 24 | #:use-module (jsonld expansion) | |
24 | 25 | #:use-module (jsonld flattening) | |
26 | + | #:use-module (jsonld generate-blank-node-identifier) | |
25 | 27 | #:use-module (jsonld inverse-context-creation) | |
26 | 28 | #:use-module (jsonld iri) | |
27 | 29 | #:use-module (jsonld iri-compaction) | |
28 | 30 | #:use-module (jsonld json) | |
31 | + | #:use-module (jsonld node-map-generation) | |
29 | 32 | #:use-module (jsonld options) | |
33 | + | #:use-module (rdf rdf) | |
30 | 34 | #:export (compact | |
31 | 35 | expand | |
32 | - | flatten)) | |
36 | + | flatten | |
37 | + | jsonld->rdf)) | |
33 | 38 | ||
34 | 39 | (define* (compact input context #:key (options (new-jsonld-options))) | |
35 | 40 | (call-with-values | |
… | |||
177 | 182 | ;; TODO | |
178 | 183 | (set! flattened-output (compact flattened-output context #:options options))) | |
179 | 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)))))) |
jsonld/deserialize-jsonld.scm unknown status 1
1 | + | ;;;; Copyright (C) 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 deserialize-jsonld) | |
19 | + | #:use-module (ice-9 match) | |
20 | + | #:use-module (jsonld iri) | |
21 | + | #:use-module (jsonld json) | |
22 | + | #:use-module (jsonld generate-blank-node-identifier) | |
23 | + | #:use-module (jsonld object-to-rdf) | |
24 | + | #:use-module ((rdf rdf) #:hide (blank-node?)) | |
25 | + | #:export (deserialize-jsonld | |
26 | + | well-formed? | |
27 | + | rdf-iri | |
28 | + | xsd-iri | |
29 | + | blank-node->rdf-blank-node)) | |
30 | + | ||
31 | + | (define (uniq lst) | |
32 | + | (match lst | |
33 | + | (() '()) | |
34 | + | ((element lst ...) | |
35 | + | (if (member element lst) | |
36 | + | (uniq lst) | |
37 | + | (cons element (uniq lst)))))) | |
38 | + | ||
39 | + | (define (blank-node->rdf-blank-node node) | |
40 | + | "Convert a blank node generated from the generate blank node algorithm to | |
41 | + | a representation suitable for guile-rdf. This involves removing the leading | |
42 | + | _:b and converting to a number." | |
43 | + | (string->number (substring node 3))) | |
44 | + | ||
45 | + | (define (rdf-iri name) | |
46 | + | (string-append "http://www.w3.org/1999/02/22-rdf-syntax-ns#" name)) | |
47 | + | ||
48 | + | (define (xsd-iri name) | |
49 | + | (string-append "http://www.w3.org/2001/XMLSchema#" name)) | |
50 | + | ||
51 | + | (define (well-formed? node) | |
52 | + | (or (absolute-iri? node) (blank-node? node))) | |
53 | + | ||
54 | + | (define* (deserialize-jsonld generate-blank-node node-map dataset | |
55 | + | #:key produce-generalized-rdf? rdf-direction) | |
56 | + | ;; 1 | |
57 | + | (for-each-pair | |
58 | + | (lambda (graph-name graph) | |
59 | + | ;; 1.1 | |
60 | + | (when (or (well-formed? graph-name) (equal? graph-name "@default")) | |
61 | + | ;; 1.2 | |
62 | + | (let ((triples (if (equal? graph-name "@default") | |
63 | + | (rdf-dataset-default-graph dataset) | |
64 | + | '()))) | |
65 | + | ;; 1.3 | |
66 | + | (for-each-pair | |
67 | + | (lambda (subject node) | |
68 | + | ;; 1.3.1 | |
69 | + | (when (well-formed? subject) | |
70 | + | (when (blank-node? subject) | |
71 | + | (set! subject (blank-node->rdf-blank-node subject))) | |
72 | + | ;; 1.3.2 | |
73 | + | (for-each-pair | |
74 | + | (lambda (property values) | |
75 | + | (cond | |
76 | + | ((equal? property "@type") | |
77 | + | (for-each | |
78 | + | (lambda (type) | |
79 | + | (when (well-formed? type) | |
80 | + | (when (blank-node? type) | |
81 | + | (set! type (blank-node->rdf-blank-node type))) | |
82 | + | (set! triples | |
83 | + | (cons | |
84 | + | (make-rdf-triple subject (rdf-iri "type") | |
85 | + | type) | |
86 | + | triples)))) | |
87 | + | (array->list values))) | |
88 | + | ((json-keyword? property) | |
89 | + | #t) | |
90 | + | ((and (blank-node? property) (not produce-generalized-rdf?)) | |
91 | + | #t) | |
92 | + | ((not (well-formed? property)) | |
93 | + | #t) | |
94 | + | (else | |
95 | + | (when (blank-node? property) | |
96 | + | (set! property (blank-node->rdf-blank-node property))) | |
97 | + | (for-each | |
98 | + | (lambda (item) | |
99 | + | (let* ((res | |
100 | + | (object-to-rdf generate-blank-node | |
101 | + | rdf-direction item '())) | |
102 | + | (list-triples (assoc-ref res "list-triples")) | |
103 | + | (res (assoc-ref res "result"))) | |
104 | + | (unless (equal? res #nil) | |
105 | + | (set! triples | |
106 | + | (cons | |
107 | + | (make-rdf-triple subject property res) | |
108 | + | (append triples list-triples)))))) | |
109 | + | (array->list values))))) | |
110 | + | (alist-sort-by-key node)))) | |
111 | + | (alist-sort-by-key graph)) | |
112 | + | ;; 1.2 (cont.) | |
113 | + | (set! triples (uniq triples)) | |
114 | + | (if (equal? graph-name "@default") | |
115 | + | (set! dataset | |
116 | + | (make-rdf-dataset triples (rdf-dataset-named-graphs dataset))) | |
117 | + | (unless (null? triples) | |
118 | + | (set! dataset | |
119 | + | (make-rdf-dataset (rdf-dataset-default-graph dataset) | |
120 | + | (alist-set | |
121 | + | (rdf-dataset-named-graphs dataset) | |
122 | + | (if (blank-node? graph-name) | |
123 | + | (blank-node->rdf-blank-node graph-name) | |
124 | + | graph-name) | |
125 | + | triples)))))))) | |
126 | + | node-map) | |
127 | + | dataset) |
jsonld/iri.scm
111 | 111 | ||
112 | 112 | ;; This algorithm is not always called with sane values, so prevent errors | |
113 | 113 | ;; in some edge cases. | |
114 | - | (if (and base (string? reference)) | |
114 | + | (if (and base (string? reference) (not (string->uri reference)) | |
115 | + | (string->uri-reference reference)) | |
115 | 116 | (uri->string | |
116 | 117 | (transform-references (set-iri-path (string->uri base)) | |
117 | 118 | (string->uri-reference reference))) |
jsonld/list-to-rdf.scm unknown status 1
1 | + | ;;;; Copyright (C) 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 list-to-rdf) | |
19 | + | #:use-module (jsonld deserialize-jsonld) | |
20 | + | #:use-module (jsonld iri) | |
21 | + | #:use-module (jsonld json) | |
22 | + | #:use-module (jsonld object-to-rdf) | |
23 | + | #:use-module (rdf rdf) | |
24 | + | #:export (list-to-rdf)) | |
25 | + | ||
26 | + | (define* (list-to-rdf generate-blank-node rdf-direction lst list-triples) | |
27 | + | (let ((result #nil)) | |
28 | + | (if (null? lst) | |
29 | + | ;; 1 | |
30 | + | (set! result (rdf-iri "nil")) | |
31 | + | ;; 2 | |
32 | + | (let ((bnodes (map | |
33 | + | (lambda _ | |
34 | + | (blank-node->rdf-blank-node (generate-blank-node #nil))) | |
35 | + | lst))) | |
36 | + | ;; 3 | |
37 | + | (let loop ((bnodes bnodes) (lst lst)) | |
38 | + | (unless (null? bnodes) | |
39 | + | ;; 3.2 | |
40 | + | (let* ((subject (car bnodes)) | |
41 | + | (item (car lst)) | |
42 | + | (rest (cdr bnodes)) | |
43 | + | (rest (if (null? rest) (rdf-iri "nil") (car rest))) | |
44 | + | (res (object-to-rdf generate-blank-node rdf-direction | |
45 | + | item '())) | |
46 | + | (object (assoc-ref res "result")) | |
47 | + | (embedded-triples (assoc-ref res "list-triples"))) | |
48 | + | ;; 3.3 | |
49 | + | (unless (equal? object #nil) | |
50 | + | (set! list-triples | |
51 | + | (cons (make-rdf-triple subject (rdf-iri "first") object) | |
52 | + | list-triples))) | |
53 | + | ;; 3.4 | |
54 | + | (set! list-triples | |
55 | + | (cons (make-rdf-triple subject (rdf-iri "rest") rest) | |
56 | + | list-triples)) | |
57 | + | ;; 3.5 | |
58 | + | (set! list-triples | |
59 | + | (append list-triples embedded-triples))) | |
60 | + | (loop (cdr bnodes) (cdr lst)))) | |
61 | + | ;; 4 | |
62 | + | (if (null? bnodes) | |
63 | + | (set! result (rdf-iri "nil")) | |
64 | + | (set! result (car bnodes))))) | |
65 | + | `(("result" . ,result) | |
66 | + | ("list-triples" . ,list-triples)))) |
jsonld/node-map-generation.scm
152 | 152 | ;; 6 | |
153 | 153 | (when (node-object? element) | |
154 | 154 | ;; 6.1 | |
155 | - | (let* ((id (if (json-has-key? element "@id") | |
156 | - | (assoc-ref element "@id") | |
157 | - | #f)) | |
158 | - | (id (if id | |
159 | - | (if (blank-node? id) (generate-blank-node id) id) | |
160 | - | (generate-blank-node #nil)))) | |
155 | + | (let ((id (if (json-has-key? element "@id") | |
156 | + | (if (blank-node? (assoc-ref element "@id")) | |
157 | + | (generate-blank-node (assoc-ref element "@id")) | |
158 | + | (assoc-ref element "@id")) | |
159 | + | (generate-blank-node #nil)))) | |
161 | 160 | ;; 6.3 | |
162 | - | (unless (json-has-key? graph id) | |
161 | + | (unless (or (json-has-key? graph id) (not id)) | |
163 | 162 | (set! graph | |
164 | 163 | (alist-set graph id `(("@id" . ,id)))) | |
165 | 164 | (set! node-map (alist-set node-map active-graph graph))) | |
166 | 165 | ;; 6.4 | |
167 | - | (let ((node (assoc-ref graph id))) | |
166 | + | (let ((node (or (assoc-ref graph id) '()))) | |
168 | 167 | (cond | |
169 | 168 | ;; 6.5 | |
170 | 169 | ((json-object? active-subject) | |
… | |||
175 | 174 | ;; 6.5.1 | |
176 | 175 | (set! node | |
177 | 176 | (alist-set node active-property `#(,active-subject)))) | |
178 | - | (set! graph (alist-set graph id node)) | |
177 | + | (when id | |
178 | + | (set! graph (alist-set graph id node))) | |
179 | 179 | (set! node-map (alist-set node-map active-graph graph))) | |
180 | 180 | ;; 6.6 | |
181 | 181 | ((not (equal? active-property #nil)) | |
… | |||
202 | 202 | (when (json-has-key? element "@type") | |
203 | 203 | (set! node | |
204 | 204 | (append-if-not-in node "@type" (assoc-ref element "@type"))) | |
205 | - | (set! graph | |
206 | - | (alist-set graph id node)) | |
205 | + | (when id | |
206 | + | (set! graph (alist-set graph id node))) | |
207 | 207 | (set! node-map (alist-set node-map active-graph graph))) | |
208 | 208 | ;; 6.8 | |
209 | 209 | (when (json-has-key? element "@index") | |
… | |||
236 | 236 | (set! graph (assoc-ref node-map active-graph)) | |
237 | 237 | (set! subject-node (or (assoc-ref graph active-subject) | |
238 | 238 | '())) | |
239 | - | (set! node (assoc-ref graph id)))) | |
239 | + | (when id | |
240 | + | (set! node (assoc-ref graph id))))) | |
240 | 241 | (array->list values))) | |
241 | 242 | reverse-map) | |
242 | 243 | ;; 6.9.4 | |
… | |||
250 | 251 | (set! node-map (assoc-ref res "node-map")) | |
251 | 252 | (set! graph (assoc-ref node-map active-graph)) | |
252 | 253 | (set! subject-node (or (assoc-ref graph active-subject) '())) | |
253 | - | (set! node (assoc-ref graph id))) | |
254 | + | (when id | |
255 | + | (set! node (assoc-ref graph id)))) | |
254 | 256 | (set! element (alist-remove element "@graph"))) | |
255 | 257 | ;; 6.11 | |
256 | 258 | (when (json-has-key? element "@included") | |
… | |||
261 | 263 | (set! node-map (assoc-ref res "node-map")) | |
262 | 264 | (set! graph (assoc-ref node-map active-graph)) | |
263 | 265 | (set! subject-node (or (assoc-ref graph active-subject) '())) | |
264 | - | (set! node (assoc-ref graph id))) | |
266 | + | (when id | |
267 | + | (set! node (assoc-ref graph id)))) | |
265 | 268 | (set! element (alist-remove element "@included"))) | |
266 | 269 | ;; 6.12 | |
267 | 270 | (for-each-pair | |
… | |||
272 | 275 | ;; 6.12.2 | |
273 | 276 | (unless (json-has-key? node property) | |
274 | 277 | (set! node (alist-set node property #())) | |
275 | - | (set! graph (alist-set graph id node)) | |
278 | + | (when id | |
279 | + | (set! graph (alist-set graph id node))) | |
276 | 280 | (set! node-map (alist-set node-map active-graph graph))) | |
277 | 281 | ;; 6.12.3 | |
278 | 282 | (let ((res (node-map-generation | |
… | |||
282 | 286 | (set! node-map (assoc-ref res "node-map")) | |
283 | 287 | (set! graph (assoc-ref node-map active-graph)) | |
284 | 288 | (set! subject-node (or (assoc-ref graph active-subject) '())) | |
285 | - | (set! node (assoc-ref graph id)))) | |
289 | + | (when id | |
290 | + | (set! node (assoc-ref graph id))))) | |
286 | 291 | (alist-sort-by-key element)) | |
287 | - | (set! graph (alist-set graph id node))))) | |
292 | + | (when id | |
293 | + | (set! graph (alist-set graph id node)))))) | |
288 | 294 | (when (string? active-subject) | |
289 | 295 | (set! graph (alist-set graph active-subject subject-node))) | |
290 | 296 | (set! node-map (alist-set node-map active-graph graph)))) |
jsonld/object-to-rdf.scm unknown status 1
1 | + | ;;;; Copyright (C) 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 object-to-rdf) | |
19 | + | #:use-module (ice-9 match) | |
20 | + | #:use-module (ice-9 regex) | |
21 | + | #:use-module (jsonld deserialize-jsonld) | |
22 | + | #:use-module (jsonld iri) | |
23 | + | #:use-module (jsonld json) | |
24 | + | #:use-module (jsonld list-to-rdf) | |
25 | + | #:use-module (json) | |
26 | + | #:use-module ((rdf rdf) #:hide (blank-node?)) | |
27 | + | #:use-module (srfi srfi-1) | |
28 | + | #:export (object-to-rdf | |
29 | + | well-formed-language-tag?)) | |
30 | + | ||
31 | + | (define (canonical-double value) | |
32 | + | (let ((exponent (inexact->exact (floor (log10 value))))) | |
33 | + | (string-append | |
34 | + | (number->string (exact->inexact (/ value (expt 10 exponent)))) | |
35 | + | "E" | |
36 | + | (number->string exponent)))) | |
37 | + | ||
38 | + | (define (canonical-json value) | |
39 | + | (cond | |
40 | + | ((member value '(#t #f #nil)) | |
41 | + | value) | |
42 | + | ((string? value) value) | |
43 | + | ((number? value) | |
44 | + | (if (integer? (inexact->exact value)) | |
45 | + | (inexact->exact value) | |
46 | + | value)) | |
47 | + | ((list? value) | |
48 | + | (map | |
49 | + | (match-lambda | |
50 | + | ((k . v) | |
51 | + | (cons k (canonical-json v)))) | |
52 | + | (alist-sort-by-key value))) | |
53 | + | ((array? value) | |
54 | + | (list->array | |
55 | + | 1 | |
56 | + | (fold-right | |
57 | + | (lambda (val result) | |
58 | + | (cons (canonical-json val) result)) | |
59 | + | '() | |
60 | + | (array->list value)))))) | |
61 | + | ||
62 | + | (define (well-formed-language-tag? tag) | |
63 | + | (let ((match (string-match "[a-z]{1,8}(-[0-9a-z]{1,8})*" tag))) | |
64 | + | (if match | |
65 | + | (let* ((match (cadr (array->list match))) | |
66 | + | (fst (car match)) | |
67 | + | (snd (cdr match))) | |
68 | + | (and (equal? fst 0) | |
69 | + | (equal? snd (string-length tag)))) | |
70 | + | #f))) | |
71 | + | ||
72 | + | (define* (object-to-rdf generate-blank-node rdf-direction item list-triples) | |
73 | + | (let ((result #nil)) | |
74 | + | (cond | |
75 | + | ;; 1 | |
76 | + | ((and (node-object? item) (not (well-formed? (assoc-ref item "@id")))) | |
77 | + | (set! result #nil)) | |
78 | + | ;; 2 | |
79 | + | ((node-object? item) | |
80 | + | (set! result (assoc-ref item "@id"))) | |
81 | + | ;; 3 | |
82 | + | ((list-object? item) | |
83 | + | (let* ((res (list-to-rdf generate-blank-node rdf-direction | |
84 | + | (array->list (assoc-ref item "@list")) | |
85 | + | list-triples)) | |
86 | + | (lst (assoc-ref res "list-triples")) | |
87 | + | (res (assoc-ref res "result"))) | |
88 | + | (set! result res) | |
89 | + | (set! list-triples lst))) | |
90 | + | (else | |
91 | + | ;; 4 | |
92 | + | (let ((value (assoc-ref item "@value")) | |
93 | + | (datatype (or (assoc-ref item "@type") #nil))) | |
94 | + | (cond | |
95 | + | ;; 6 | |
96 | + | ((and (not (equal? datatype #nil)) (not (equal? datatype "@json")) | |
97 | + | (not (well-formed? datatype))) | |
98 | + | (set! result #nil)) | |
99 | + | ;; 7 | |
100 | + | ((and | |
101 | + | (json-has-key? item "@language") | |
102 | + | (not (well-formed-language-tag? (assoc-ref item "@language")))) | |
103 | + | (set! result #nil)) | |
104 | + | (else | |
105 | + | ;; 8 | |
106 | + | (when (equal? datatype "@json") | |
107 | + | (set! value (scm->json-string (canonical-json value))) | |
108 | + | (set! datatype (rdf-iri "JSON"))) | |
109 | + | (cond | |
110 | + | ;; 9 | |
111 | + | ((boolean? value) | |
112 | + | (when (equal? datatype #nil) | |
113 | + | (set! datatype (xsd-iri "boolean"))) | |
114 | + | (set! value (if value "true" "false"))) | |
115 | + | ;; 10 | |
116 | + | ((and (number? value) | |
117 | + | (or (not (integer? (inexact->exact value))) | |
118 | + | (>= (abs value) (expt 10 21)) | |
119 | + | (equal? datatype (xsd-iri "double")))) | |
120 | + | (when (equal? datatype #nil) | |
121 | + | (set! datatype (xsd-iri "double"))) | |
122 | + | (set! value (canonical-double value))) | |
123 | + | ;; 11 | |
124 | + | ((number? value) | |
125 | + | (set! value (number->string (inexact->exact value))) | |
126 | + | (when (equal? datatype #nil) | |
127 | + | (set! datatype (xsd-iri "integer")))) | |
128 | + | ;; 12 | |
129 | + | ((equal? datatype #nil) | |
130 | + | (set! datatype | |
131 | + | (if (json-has-key? item "@language") | |
132 | + | (rdf-iri "langString") | |
133 | + | (xsd-iri "string"))))) | |
134 | + | (if (and (json-has-key? item "@direction") (not (equal? rdf-direction #f))) | |
135 | + | ;; 13 | |
136 | + | (let* ((language (or (assoc-ref item "@language") "")) | |
137 | + | (language (string-downcase language))) | |
138 | + | (if (equal? rdf-direction "i18n-datatype") | |
139 | + | ;; 13.2 | |
140 | + | (begin | |
141 | + | (set! datatype | |
142 | + | (string-append "https://www.w3.org/ns/i18n#" language "_" | |
143 | + | (assoc-ref item "@direction"))) | |
144 | + | (set! result | |
145 | + | (make-rdf-literal value datatype #f))) | |
146 | + | ;; 13.3 | |
147 | + | (when (equal? rdf-direction "compound-literal") | |
148 | + | (let ((literal (blank-node->rdf-blank-node | |
149 | + | (generate-blank-node #nil)))) | |
150 | + | ;; 13.3.2 | |
151 | + | (set! list-triples | |
152 | + | (cons | |
153 | + | ;; XXX: the spec says "of the @value in item as object", | |
154 | + | ;; but should it be "value" instead? | |
155 | + | (make-rdf-triple literal (rdf-iri "value") | |
156 | + | (make-rdf-literal | |
157 | + | (assoc-ref item "@value") | |
158 | + | (xsd-iri "string") | |
159 | + | #f)) | |
160 | + | list-triples)) | |
161 | + | ;; 13.3.3 | |
162 | + | (when (json-has-key? item "@language") | |
163 | + | (set! list-triples | |
164 | + | (cons | |
165 | + | (make-rdf-triple literal (rdf-iri "language") | |
166 | + | (make-rdf-literal | |
167 | + | language | |
168 | + | (xsd-iri "string") | |
169 | + | #f)) | |
170 | + | list-triples))) | |
171 | + | (set! list-triples | |
172 | + | (cons | |
173 | + | (make-rdf-triple literal (rdf-iri "direction") | |
174 | + | (make-rdf-literal | |
175 | + | (assoc-ref item "@direction") | |
176 | + | (xsd-iri "string") | |
177 | + | #f)) | |
178 | + | list-triples)) | |
179 | + | (set! result literal))))) | |
180 | + | ;; 14 | |
181 | + | (set! result | |
182 | + | (make-rdf-literal value datatype (assoc-ref item "@language"))))))))) | |
183 | + | (when (blank-node? result) | |
184 | + | (set! result (blank-node->rdf-blank-node result))) | |
185 | + | `(("result" . ,result) | |
186 | + | ("list-triples" . ,list-triples)))) |
test-modules/download.scm
21 | 21 | #:use-module (jsonld json) | |
22 | 22 | #:use-module (jsonld memoization) | |
23 | 23 | #:use-module (jsonld options) | |
24 | + | #:use-module (nquads tordf) | |
25 | + | #:use-module (rnrs bytevectors) | |
24 | 26 | #:use-module (test-modules testsuite) | |
25 | 27 | #:use-module (web client) | |
26 | 28 | #:use-module (web response) | |
27 | 29 | #:use-module (web uri) | |
28 | - | #:export (test-http-get get-test-document-loader)) | |
30 | + | #:export (test-http-get get-test-document-loader download-nq)) | |
29 | 31 | ||
30 | 32 | (define* (update-response response | |
31 | 33 | #:key | |
… | |||
93 | 95 | (lambda args | |
94 | 96 | (apply download-json | |
95 | 97 | (append args `(#:http-get ,(test-http-get options))))))) | |
98 | + | ||
99 | + | (define (download-nq url) | |
100 | + | (call-with-values | |
101 | + | (lambda () | |
102 | + | (http-get url)) | |
103 | + | (lambda (hdr body) | |
104 | + | (if (equal? (response-code hdr) 200) | |
105 | + | (nquads->rdf | |
106 | + | (if (string? body) | |
107 | + | body | |
108 | + | (utf8->string body))) | |
109 | + | (throw 'download-error (response-code hdr) url))))) |
test-modules/online.scm
27 | 27 | #:use-module (jsonld) | |
28 | 28 | #:use-module (jsonld options) | |
29 | 29 | #:use-module (jsonld iri) | |
30 | + | #:use-module (rdf rdf) | |
31 | + | #:use-module (nquads fromrdf) | |
30 | 32 | #:export (run-test-suite | |
31 | 33 | run-test-suites | |
32 | 34 | get-test-doc)) | |
… | |||
40 | 42 | ;; us to download a few other JsonLD documents, run a function on them and compare | |
41 | 43 | ;; the result. This is what this file does. | |
42 | 44 | ||
45 | + | (define (download-document url) | |
46 | + | (match (car (reverse (string-split url #\.))) | |
47 | + | ("nq" (download-nq url)) | |
48 | + | (_ (json-document-document (download-json url))))) | |
49 | + | ||
50 | + | (define (good-result? result expected) | |
51 | + | (if (rdf-dataset? result) | |
52 | + | (begin | |
53 | + | (with-output-to-file "test-result.nq" | |
54 | + | (lambda _ | |
55 | + | (format #t "~a~%" (rdf->nquads result)))) | |
56 | + | (pk 'result result) | |
57 | + | (pk 'expected expected) | |
58 | + | (rdf-dataset-isomorphic? result expected)) | |
59 | + | (same-json? result expected))) | |
60 | + | ||
43 | 61 | (define (execute-test test) | |
44 | 62 | "Execute one test described by a Json object @var{test}. Return a Json object | |
45 | 63 | as the output of the test, or throws an exception if something went wrong." | |
… | |||
48 | 66 | (context (assoc-ref document "context")) | |
49 | 67 | (type (array->list (assoc-ref document "@type"))) | |
50 | 68 | (options (assoc-ref document "option")) | |
69 | + | (requires (assoc-ref document "requires")) | |
51 | 70 | (spec-version (assoc-ref options "specVersion")) | |
52 | 71 | (document-loader (get-test-document-loader options))) | |
53 | 72 | (cond | |
… | |||
119 | 138 | ,@(if (json-has-key? options "compactArrays") | |
120 | 139 | `(#:compact-arrays? ,(assoc-ref options "compactArrays")) | |
121 | 140 | '()))))) | |
141 | + | ((member "jld:ToRDFTest" type) | |
142 | + | (when (equal? requires "GeneralizedRdf") | |
143 | + | (throw 'cannot-run-test "Expected file is not in a valid nquads format")) | |
144 | + | (jsonld->rdf (string-append jsonld-test-url input) | |
145 | + | #:options | |
146 | + | (apply | |
147 | + | new-jsonld-options | |
148 | + | #:ordered? #t | |
149 | + | #:document-loader document-loader | |
150 | + | `(,@(if (assoc-ref options "base") | |
151 | + | `(#:base ,(assoc-ref options "base")) | |
152 | + | '()) | |
153 | + | ,@(if (assoc-ref options "processingMode") | |
154 | + | `(#:processing-mode ,(assoc-ref options "processingMode")) | |
155 | + | '()) | |
156 | + | ,@(if (assoc-ref options "produceGeneralizedRdf") | |
157 | + | `(#:produce-generalized-rdf? #t) | |
158 | + | `(#:produce-generalized-rdf? #f)) | |
159 | + | ,@(if (assoc-ref options "expandContext") | |
160 | + | `(#:expand-context ,(string-append | |
161 | + | jsonld-test-url | |
162 | + | (assoc-ref options "expandContext"))) | |
163 | + | '()) | |
164 | + | ,@(if (assoc-ref options "rdfDirection") | |
165 | + | `(#:rdf-direction | |
166 | + | ,(assoc-ref options "rdfDirection")) | |
167 | + | '()))))) | |
122 | 168 | (else (throw 'unrecognized-test type))))) | |
123 | 169 | ||
124 | 170 | (define (run-test test) | |
… | |||
155 | 201 | (update-test-case test | |
156 | 202 | #:result 'skip | |
157 | 203 | #:reason "unsupported JsonLD version")) | |
204 | + | ((equal? key 'cannot-run-test) | |
205 | + | (update-test-case test | |
206 | + | #:result 'skip | |
207 | + | #:reason (format #f "impossible to run test: ~a" value))) | |
158 | 208 | ((equal? (jsonld-error->string key) expect-error) | |
159 | 209 | (update-test-case test #:result 'pass)) | |
160 | 210 | (else | |
… | |||
182 | 232 | (update-test-case test | |
183 | 233 | #:result 'skip | |
184 | 234 | #:reason "unsupported JsonLD version")) | |
235 | + | ((equal? key 'cannot-run-test) | |
236 | + | (update-test-case test | |
237 | + | #:result 'skip | |
238 | + | #:reason (format #f "impossible to run test: ~a" value))) | |
185 | 239 | (else | |
186 | 240 | (update-test-case test | |
187 | 241 | #:result 'fail | |
188 | 242 | #:reason (format #f "Expected success but got ~a: ~a" | |
189 | 243 | key value))))) | |
190 | - | (_ (let ((expected (json-document-document | |
191 | - | (download-json | |
192 | - | (string-append jsonld-test-url expect))))) | |
193 | - | (if (same-json? result expected) | |
194 | - | (update-test-case test #:result 'pass) | |
195 | - | (update-test-case test | |
196 | - | #:result 'fail | |
197 | - | #:reason (format #f "Expected ~a but got ~a" | |
198 | - | expected result))))))))) | |
244 | + | (_ (if (member "jld:PositiveSyntaxTest" type) | |
245 | + | (update-test-case test #:result 'pass) | |
246 | + | (let ((expected (download-document | |
247 | + | (string-append jsonld-test-url expect)))) | |
248 | + | (if (good-result? result expected) | |
249 | + | (update-test-case test #:result 'pass) | |
250 | + | (update-test-case test | |
251 | + | #:result 'fail | |
252 | + | #:reason (format #f "Expected ~a but got ~a" | |
253 | + | expected result)))))))))) | |
199 | 254 | ||
200 | 255 | (define (run-tests tests expected-failures driver) | |
201 | 256 | "Run all the tests of the @var{tests} test suite, using identifiers starting |
test-modules/testsuite.scm
22 | 22 | flatten-test-url | |
23 | 23 | html-test-url | |
24 | 24 | remote-doc-test-url | |
25 | - | jsonld-test-url)) | |
25 | + | jsonld-test-url | |
26 | + | tordf-test-url)) | |
26 | 27 | ||
27 | 28 | (define jsonld-test-url "https://w3c.github.io/json-ld-api/tests/") | |
28 | 29 | ||
… | |||
41 | 42 | (define remote-doc-test-url | |
42 | 43 | (string-append jsonld-test-url "remote-doc-manifest.jsonld")) | |
43 | 44 | ||
45 | + | (define tordf-test-url | |
46 | + | (string-append jsonld-test-url "toRdf-manifest.jsonld")) | |
47 | + | ||
44 | 48 | (define expected-failures | |
45 | 49 | `(("https://w3c.github.io/json-ld-api/tests/html-manifest.jsonld#te010" . | |
46 | 50 | "entities are not preserved by xml->sxml") |
tests/tordf.scm unknown status 1
1 | + | #!/data/tyreunom/projects/guile-jsonld/pre-inst-env guile | |
2 | + | !# | |
3 | + | ;;;; Copyright (C) 2020 Julien Lepiller <julien@lepiller.eu> | |
4 | + | ;;;; | |
5 | + | ;;;; This library is free software; you can redistribute it and/or | |
6 | + | ;;;; modify it under the terms of the GNU Lesser General Public | |
7 | + | ;;;; License as published by the Free Software Foundation; either | |
8 | + | ;;;; version 3 of the License, or (at your option) any later version. | |
9 | + | ;;;; | |
10 | + | ;;;; This library is distributed in the hope that it will be useful, | |
11 | + | ;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | + | ;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
13 | + | ;;;; Lesser General Public License for more details. | |
14 | + | ;;;; | |
15 | + | ;;;; You should have received a copy of the GNU Lesser General Public | |
16 | + | ;;;; License along with this library; if not, write to the Free Software | |
17 | + | ;;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
18 | + | ;;;; | |
19 | + | ||
20 | + | (use-modules (test-modules online)) | |
21 | + | (use-modules (test-modules result)) | |
22 | + | (use-modules (test-modules testsuite)) | |
23 | + | ||
24 | + | (run-test-suite tordf-test-url expected-failures tap-driver) |