Add fromRdf algorithm
.gitignore
22 | 22 | tests/html.scm | |
23 | 23 | tests/remote-doc.scm | |
24 | 24 | tests/report.scm | |
25 | + | tests/fromrdf.scm | |
25 | 26 | reports |
Makefile.am
22 | 22 | jsonld/node-map-generation.scm \ | |
23 | 23 | jsonld/object-to-rdf.scm \ | |
24 | 24 | jsonld/options.scm \ | |
25 | + | jsonld/rdf-to-object.scm \ | |
26 | + | jsonld/serialize-rdf.scm \ | |
25 | 27 | jsonld/term-selection.scm \ | |
26 | 28 | jsonld/value-compaction.scm \ | |
27 | 29 | jsonld/value-expansion.scm \ | |
… | |||
36 | 38 | tests/expand.scm \ | |
37 | 39 | tests/flatten.scm \ | |
38 | 40 | tests/remote-doc.scm \ | |
39 | - | tests/to-rdf.scm | |
41 | + | tests/fromrdf.scm \ | |
42 | + | tests/tordf.scm | |
40 | 43 | EXTRA_DIST += $(TESTS) | |
41 | 44 | ||
42 | 45 | coverage: |
README.md
128 | 128 | produced by the guile-json library) or a string representing the URL of a JsonLD | |
129 | 129 | document. The options can be used to carry additional configuration information. | |
130 | 130 | ||
131 | + | **Scheme Procedure**: rdf->jsonld dataset [#:options (new-jsonld-options)] | |
132 | + | ||
133 | + | Transforms the given dataset into a JsonLD document in expanded form. This | |
134 | + | procedure takes as input an RDF dataset (as produced by the guile-rdf | |
135 | + | library) and returns the same dataset in JsonLD format, in the expanded form. | |
136 | + | The options can be used to carry additional configuration information. | |
137 | + | ||
131 | 138 | ### The JsonLDOptions Type | |
132 | 139 | ||
133 | 140 | 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/fromrdf.scm], [chmod +x tests/fromrdf.scm]) | |
32 | 33 | AC_CONFIG_FILES([tests/tordf.scm], [chmod +x tests/tordf.scm]) | |
33 | 34 | AC_CONFIG_FILES(Makefile) | |
34 | 35 | AC_REQUIRE_AUX_FILE([tap-driver.sh]) |
jsonld.scm
30 | 30 | #:use-module (jsonld json) | |
31 | 31 | #:use-module (jsonld node-map-generation) | |
32 | 32 | #:use-module (jsonld options) | |
33 | + | #:use-module (jsonld serialize-rdf) | |
33 | 34 | #:use-module (rdf rdf) | |
34 | 35 | #:export (compact | |
35 | 36 | expand | |
36 | 37 | flatten | |
37 | - | jsonld->rdf)) | |
38 | + | jsonld->rdf | |
39 | + | rdf->jsonld)) | |
38 | 40 | ||
39 | 41 | (define* (compact input context #:key (options (new-jsonld-options))) | |
40 | 42 | (call-with-values | |
… | |||
201 | 203 | #:produce-generalized-rdf? | |
202 | 204 | (jsonld-options-produce-generalized-rdf? options) | |
203 | 205 | #:rdf-direction (jsonld-options-rdf-direction options)))))) | |
206 | + | ||
207 | + | (define* (rdf->jsonld input #:key (options (new-jsonld-options))) | |
208 | + | (serialize-rdf input | |
209 | + | #:ordered? (jsonld-options-ordered? options) | |
210 | + | #:rdf-direction (jsonld-options-rdf-direction options) | |
211 | + | #:use-native-types? (jsonld-options-use-native-types? options) | |
212 | + | #:use-rdf-type? (jsonld-options-use-rdf-type? options) | |
213 | + | #:processing-mode (jsonld-options-processing-mode options))) |
jsonld/json.scm
49 | 49 | processing-mode-1.0? | |
50 | 50 | relative-iri? | |
51 | 51 | same-json? | |
52 | + | identical-json? | |
52 | 53 | scalar? | |
53 | 54 | scalar-array? | |
54 | 55 | set-object? | |
… | |||
207 | 208 | (not (json-has-key? o "@list")) | |
208 | 209 | (not (json-has-key? o "@set")))) | |
209 | 210 | ||
210 | - | (define (has-keys-of json other) | |
211 | + | (define (has-identical-keys-of json other) | |
211 | 212 | (let loop ((json json) (result #t)) | |
212 | 213 | (match json | |
213 | 214 | (#f (not other)) | |
214 | 215 | (() result) | |
215 | 216 | (((key . value) json ...) | |
216 | - | (loop json (and result (same-json? value (assoc-ref other key)))))))) | |
217 | + | (loop json (and result (identical-json? value (assoc-ref other key)))))))) | |
217 | 218 | ||
218 | - | (define (has-same-values json other) | |
219 | + | (define (has-identical-values json other) | |
219 | 220 | (let loop ((json json) (other other) (result #t)) | |
220 | 221 | (match json | |
221 | 222 | (() (if (null? other) result #f)) | |
… | |||
223 | 224 | (match other | |
224 | 225 | (() #f) | |
225 | 226 | ((v2 other ...) | |
226 | - | (loop json other (and result (same-json? v v2))))))))) | |
227 | + | (loop json other (and result (identical-json? v v2))))))))) | |
227 | 228 | ||
228 | - | (define (same-json? json other) | |
229 | + | (define (identical-json? json other) | |
229 | 230 | "Compare two Json documents and returns whether they are the same, comparing | |
230 | - | the keys, their values, their order and their presence in both documents." | |
231 | + | the keys, their values, their order and their presence in both documents. | |
232 | + | This variant compares the value of blank nodes." | |
231 | 233 | (match json | |
232 | 234 | ((? array? json) | |
233 | 235 | (and | |
234 | 236 | (array? other) | |
235 | - | (has-same-values (array->list json) (array->list other)))) | |
237 | + | (has-identical-values (array->list json) (array->list other)))) | |
236 | 238 | ((? list? json) | |
237 | - | (and (list? other) (has-keys-of json other) (has-keys-of other json))) | |
239 | + | (and (list? other) (has-identical-keys-of json other) | |
240 | + | (has-identical-keys-of other json))) | |
238 | 241 | (_ (equal? json other)))) | |
239 | 242 | ||
243 | + | (define (has-keys-of json other equivalences) | |
244 | + | (let loop ((json json) (equivalences equivalences)) | |
245 | + | (match json | |
246 | + | (#f (and (not other) equivalences)) | |
247 | + | (() equivalences) | |
248 | + | (((key . value) json ...) | |
249 | + | (if (blank-node? key) | |
250 | + | (if (assoc-ref equivalences key) | |
251 | + | (loop json (included-json? | |
252 | + | value | |
253 | + | (assoc-ref | |
254 | + | other (assoc-ref equivalences key)) equivalences)) | |
255 | + | (let loop2 ((candidates (filter (lambda (e) (blank-node? (car e))) | |
256 | + | other))) | |
257 | + | (match candidates | |
258 | + | (() #f) | |
259 | + | (((k . v) candidates ...) | |
260 | + | (let ((res (included-json? | |
261 | + | value | |
262 | + | v | |
263 | + | (cons (cons key k) equivalences)))) | |
264 | + | (if res res (loop2 candidates))))))) | |
265 | + | (loop json (included-json? value (assoc-ref other key) equivalences))))))) | |
266 | + | ||
267 | + | (define (has-same-values json other equivalences) | |
268 | + | (let loop ((json json) (other other) (equivalences equivalences)) | |
269 | + | (match json | |
270 | + | (() (if (null? other) equivalences #f)) | |
271 | + | ((v json ...) | |
272 | + | (match other | |
273 | + | (() #f) | |
274 | + | ((v2 other ...) | |
275 | + | (loop json other (included-json? v v2 equivalences)))))))) | |
276 | + | ||
277 | + | (define (included-json? json other equivalences) | |
278 | + | (match json | |
279 | + | ((? json-array? json) | |
280 | + | (and | |
281 | + | (array? other) | |
282 | + | (has-same-values (array->list json) (array->list other) equivalences))) | |
283 | + | ((? list? json) | |
284 | + | (and (list? other) (has-keys-of json other equivalences))) | |
285 | + | ((? blank-node? json) | |
286 | + | (and (blank-node? other) | |
287 | + | (if (assoc-ref json equivalences) | |
288 | + | (and (equal? (assoc-ref json equivalences) other) equivalences) | |
289 | + | (cons (cons json other) equivalences)))) | |
290 | + | (_ (and (equal? json other) equivalences)))) | |
291 | + | ||
292 | + | (define (same-json? json other) | |
293 | + | "Compare two Json documents and returns whether they are the same, comparing | |
294 | + | the keys, their values, their order and their presence in both documents. | |
295 | + | This variant tries to map blank nodes from one object to the other." | |
296 | + | (and (included-json? json other '()) (included-json? other json '()))) | |
297 | + | ||
240 | 298 | (define (jsonld-error->string err) | |
241 | 299 | "Convert an error to a string." | |
242 | 300 | (match err |
jsonld/node-map-generation.scm
24 | 24 | (set! array #())) | |
25 | 25 | (unless (json-array? array) | |
26 | 26 | (set! array `#(,array))) | |
27 | - | (not (null? (filter (lambda (o) (same-json? o json)) (array->list array))))) | |
27 | + | (not (null? (filter (lambda (o) (identical-json? o json)) (array->list array))))) | |
28 | 28 | ||
29 | 29 | (define (add-to-list array element) | |
30 | 30 | (when (equal? array #f) | |
… | |||
73 | 73 | (lst #nil)) | |
74 | 74 | ;; 1 | |
75 | 75 | (if (json-array? element) | |
76 | - | (list->array 1 | |
77 | - | (map | |
78 | - | (lambda (item) | |
79 | - | (let ((res (node-map-generation item node-map | |
80 | - | #:active-graph active-graph | |
81 | - | #:active-subject active-subject | |
82 | - | #:active-property active-property | |
83 | - | #:lst lst))) | |
84 | - | (set! node-map (assoc-ref res "node-map")) | |
85 | - | (set! lst (assoc-ref res "list")))) | |
86 | - | (array->list element))) | |
76 | + | (for-each | |
77 | + | (lambda (item) | |
78 | + | (let ((res (node-map-generation item node-map | |
79 | + | #:active-graph active-graph | |
80 | + | #:active-subject active-subject | |
81 | + | #:active-property active-property | |
82 | + | #:lst lst))) | |
83 | + | (set! node-map (assoc-ref res "node-map")) | |
84 | + | (set! lst (assoc-ref res "list")))) | |
85 | + | (array->list element)) | |
87 | 86 | ;; 2: otherwise | |
88 | 87 | (let* ((graph (or (assoc-ref node-map active-graph) '())) | |
89 | 88 | (subject-node (if (equal? active-subject #nil) |
jsonld/rdf-to-object.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 rdf-to-object) | |
19 | + | #:use-module (jsonld deserialize-jsonld) | |
20 | + | #:use-module (jsonld iri) | |
21 | + | #:use-module (jsonld json) | |
22 | + | #:use-module (json) | |
23 | + | #:use-module ((rdf rdf) #:hide (blank-node?)) | |
24 | + | #:use-module ((rdf xsd) #:prefix xsd:) | |
25 | + | #:use-module (srfi srfi-1) | |
26 | + | #:export (rdf-to-object)) | |
27 | + | ||
28 | + | (define* (rdf-to-object value rdf-direction use-native-types? | |
29 | + | #:key processing-mode) | |
30 | + | (if (or (blank-node? value) (absolute-iri? value)) | |
31 | + | `(("@id" . ,value)) | |
32 | + | ;; 2 | |
33 | + | (let ((result '()) | |
34 | + | (converted-value (rdf-literal-lexical-form value)) | |
35 | + | (datatype (rdf-literal-type value)) | |
36 | + | (type #nil)) | |
37 | + | (cond | |
38 | + | ;; 2.4 | |
39 | + | (use-native-types? | |
40 | + | (cond | |
41 | + | ;; 2.4.1 | |
42 | + | ((equal? datatype (xsd-iri "string")) | |
43 | + | (set! converted-value (rdf-literal-lexical-form value))) | |
44 | + | ;; 2.4.2 | |
45 | + | ((equal? datatype (xsd-iri "boolean")) | |
46 | + | (cond | |
47 | + | ((equal? (rdf-literal-lexical-form value) "true") | |
48 | + | (set! converted-value #t)) | |
49 | + | ((equal? (rdf-literal-lexical-form value) "false") | |
50 | + | (set! converted-value #f)) | |
51 | + | (else | |
52 | + | (set! converted-value (rdf-literal-lexical-form value)) | |
53 | + | (set! type (xsd-iri "boolean"))))) | |
54 | + | ;; 2.4.3 | |
55 | + | ((and (equal? datatype (xsd-iri "integer")) | |
56 | + | ((rdf-datatype-lexical? xsd:integer) converted-value)) | |
57 | + | (set! converted-value ((rdf-datatype-lexical->value xsd:integer) | |
58 | + | converted-value))) | |
59 | + | ((and (equal? datatype (xsd-iri "double")) | |
60 | + | ((rdf-datatype-lexical? xsd:double) converted-value)) | |
61 | + | (set! converted-value ((rdf-datatype-lexical->value xsd:double) | |
62 | + | converted-value))) | |
63 | + | (else | |
64 | + | (set! type datatype)))) | |
65 | + | ;; 2.5 | |
66 | + | ((and (not (processing-mode-1.0? processing-mode)) | |
67 | + | (equal? datatype (rdf-iri "JSON"))) | |
68 | + | (set! type "@json") | |
69 | + | (catch #t | |
70 | + | (lambda _ | |
71 | + | (set! converted-value (json-string->scm (rdf-literal-lexical-form value)))) | |
72 | + | (lambda _ | |
73 | + | (throw 'invalid-json-literal)))) | |
74 | + | ;; 2.6 | |
75 | + | ((and (> (string-length datatype) (string-length "https://www.w3.org/ns/i18n#")) | |
76 | + | (equal? (substring datatype 0 (string-length "https://www.w3.org/ns/i18n#")) | |
77 | + | "https://www.w3.org/ns/i18n#") | |
78 | + | (equal? rdf-direction "i18n-datatype")) | |
79 | + | ;; 2.6.1 | |
80 | + | (set! converted-value (rdf-literal-lexical-form value)) | |
81 | + | (let* ((fragment (substring datatype (string-length "https://www.w3.org/ns/i18n#"))) | |
82 | + | (fragment (string-split fragment #\_)) | |
83 | + | (language (car fragment)) | |
84 | + | (direction (cadr fragment))) | |
85 | + | ;; 2.6.2 | |
86 | + | (unless (equal? language "") | |
87 | + | (set! result (alist-set result "@language" language))) | |
88 | + | ;; 2.6.3 | |
89 | + | (unless (equal? direction "") | |
90 | + | (set! result (alist-set result "@direction" direction))))) | |
91 | + | ;; 2.7 | |
92 | + | ((rdf-literal-langtag value) | |
93 | + | (set! result (alist-set result "@language" (rdf-literal-langtag value)))) | |
94 | + | ;; 2.8 | |
95 | + | (else | |
96 | + | (unless (equal? datatype (xsd-iri "string")) | |
97 | + | (set! type datatype)))) | |
98 | + | ;; 2.9 | |
99 | + | (set! result (alist-set result "@value" converted-value)) | |
100 | + | ;; 2.10 | |
101 | + | (when type | |
102 | + | (set! result (alist-set result "@type" type))) | |
103 | + | ;; 2.11 | |
104 | + | result))) |
jsonld/serialize-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 serialize-rdf) | |
19 | + | #:use-module (ice-9 match) | |
20 | + | #:use-module (jsonld deserialize-jsonld) | |
21 | + | #:use-module (jsonld iri) | |
22 | + | #:use-module (jsonld json) | |
23 | + | #:use-module (jsonld object-to-rdf) | |
24 | + | #:use-module (jsonld rdf-to-object) | |
25 | + | #:use-module (json) | |
26 | + | #:use-module ((rdf rdf) #:hide (blank-node?)) | |
27 | + | #:use-module ((rdf rdf) #:select (blank-node?) #:prefix rdf:) | |
28 | + | #:use-module (srfi srfi-1) | |
29 | + | #:export (serialize-rdf)) | |
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 (jsonld-ref object spec) | |
40 | + | (match spec | |
41 | + | (() object) | |
42 | + | (((? string? key) spec ...) | |
43 | + | (jsonld-ref (assoc-ref object key) spec)) | |
44 | + | (((? number? key) spec ...) | |
45 | + | (jsonld-ref (if (array? object) (array-ref object key) #f) spec)))) | |
46 | + | ||
47 | + | (define (jsonld-set object spec value) | |
48 | + | (match spec | |
49 | + | (() value) | |
50 | + | (((? string? key) spec ...) | |
51 | + | (alist-set object key (jsonld-set (assoc-ref object key) spec value))) | |
52 | + | (((? number? key) spec ...) | |
53 | + | (array-set! object (jsonld-set (array-ref object key) spec value) key) | |
54 | + | object))) | |
55 | + | ||
56 | + | (define (convert-blank-nodes dataset) | |
57 | + | (define (node-convert-blank-nodes node) | |
58 | + | (if (rdf:blank-node? node) | |
59 | + | (string-append "_:b" (number->string node)) | |
60 | + | node)) | |
61 | + | ||
62 | + | (define (graph-convert-blank-nodes graph) | |
63 | + | (map | |
64 | + | (match-lambda | |
65 | + | (($ rdf-triple subject predicate object) | |
66 | + | (make-rdf-triple | |
67 | + | (node-convert-blank-nodes subject) | |
68 | + | (node-convert-blank-nodes predicate) | |
69 | + | (node-convert-blank-nodes object)))) | |
70 | + | graph)) | |
71 | + | ||
72 | + | (make-rdf-dataset | |
73 | + | (graph-convert-blank-nodes (rdf-dataset-default-graph dataset)) | |
74 | + | (map | |
75 | + | (lambda (ng) | |
76 | + | (cons (car ng) | |
77 | + | (graph-convert-blank-nodes (cdr ng)))) | |
78 | + | (rdf-dataset-named-graphs dataset)))) | |
79 | + | ||
80 | + | (define (single-element-array? object) | |
81 | + | (and (array? object) (not (string? object)) | |
82 | + | (equal? (array-length object) 1))) | |
83 | + | ||
84 | + | (define* (serialize-rdf dataset | |
85 | + | #:key | |
86 | + | ordered? rdf-direction use-native-types? use-rdf-type? | |
87 | + | processing-mode) | |
88 | + | (set! dataset (convert-blank-nodes dataset)) | |
89 | + | (set! dataset | |
90 | + | (make-rdf-dataset | |
91 | + | (uniq (rdf-dataset-default-graph dataset)) | |
92 | + | (map | |
93 | + | (lambda (ng) | |
94 | + | (cons (car ng) | |
95 | + | (uniq (cdr ng)))) | |
96 | + | (rdf-dataset-named-graphs dataset)))) | |
97 | + | ;; 1 | |
98 | + | (let ((default-graph '()) | |
99 | + | ;; 2 | |
100 | + | (graph-map `(("@default" . ()))) | |
101 | + | ;; 3 | |
102 | + | (referenced-once '()) | |
103 | + | ;; 4 | |
104 | + | (compound-literal-subjects '())) | |
105 | + | ;; 5 | |
106 | + | (for-each-pair | |
107 | + | (lambda (name graph) | |
108 | + | ;; 5.2 | |
109 | + | (unless (json-has-key? graph-map name) | |
110 | + | (set! graph-map (alist-set graph-map name '()))) | |
111 | + | ;; 5.3 | |
112 | + | (unless (json-has-key? compound-literal-subjects name) | |
113 | + | (set! compound-literal-subjects | |
114 | + | (alist-set compound-literal-subjects name '()))) | |
115 | + | (set! default-graph (assoc-ref graph-map "@default")) | |
116 | + | ;; 5.4 | |
117 | + | (unless (or (equal? name "@default") | |
118 | + | (json-has-key? default-graph name)) | |
119 | + | (set! default-graph (alist-set (assoc-ref graph-map "@default") | |
120 | + | name `(("@id" . ,name)))) | |
121 | + | (set! graph-map (alist-set graph-map "@default" default-graph))) | |
122 | + | ;; 5.5 | |
123 | + | (let ((node-map (assoc-ref graph-map name)) | |
124 | + | ;; 5.6 | |
125 | + | (compound-map (assoc-ref compound-literal-subjects name))) | |
126 | + | (for-each | |
127 | + | (match-lambda | |
128 | + | (($ rdf-triple subject predicate object) | |
129 | + | ;; 5.7.1 | |
130 | + | (unless (json-has-key? node-map subject) | |
131 | + | (set! node-map (alist-set node-map subject `(("@id" . ,subject))))) | |
132 | + | ;; 5.7.2 | |
133 | + | (let ((node-ref (list name subject)) | |
134 | + | (node (assoc-ref node-map subject)) | |
135 | + | (continue? #t)) | |
136 | + | ;; 5.7.3 | |
137 | + | (when (and (equal? rdf-direction "compound-literal") | |
138 | + | (equal? predicate (rdf-iri "direction"))) | |
139 | + | (set! compound-map (alist-set compound-map subject #t))) | |
140 | + | (when (or (absolute-iri? object) (blank-node? object)) | |
141 | + | ;; 5.7.4 | |
142 | + | (unless (json-has-key? node-map object) | |
143 | + | (set! node-map (alist-set node-map object `(("@id" . ,object))))) | |
144 | + | ;; 5.7.5 | |
145 | + | (when (and (equal? predicate (rdf-iri "type")) | |
146 | + | (not use-rdf-type?)) | |
147 | + | (let* ((types (or (assoc-ref node "@type") #())) | |
148 | + | (types (array->list types)) | |
149 | + | (types (if (member object types) | |
150 | + | types | |
151 | + | (append types (list object)))) | |
152 | + | (types (list->array 1 types))) | |
153 | + | (set! node (alist-set node "@type" types)) | |
154 | + | (set! node-map (alist-set node-map subject node)) | |
155 | + | (set! continue? #f)))) | |
156 | + | ;; 5.7.6 | |
157 | + | (when continue? | |
158 | + | (let* ((value (rdf-to-object object rdf-direction use-native-types? | |
159 | + | #:processing-mode | |
160 | + | processing-mode)) | |
161 | + | (value-ref (append node-ref (list predicate))) | |
162 | + | ;; 5.7.7 | |
163 | + | (node-value (or (assoc-ref node predicate) #())) | |
164 | + | (node-value (array->list node-value))) | |
165 | + | ;; 5.7.8 | |
166 | + | (let loop ((nodes node-value) (num 0)) | |
167 | + | (match nodes | |
168 | + | (() | |
169 | + | (set! node-value (cons value node-value)) | |
170 | + | (set! value-ref (append value-ref (list num)))) | |
171 | + | ((n nodes ...) | |
172 | + | (if (identical-json? value n) | |
173 | + | (set! value-ref (append value-ref (list num))) | |
174 | + | (loop nodes (1+ num)))))) | |
175 | + | ;; 5.7.7 | |
176 | + | (set! node (alist-set node predicate (list->array 1 node-value))) | |
177 | + | (set! node-map (alist-set node-map subject node)) | |
178 | + | (cond | |
179 | + | ;; 5.7.9 | |
180 | + | ((equal? object (rdf-iri "nil")) | |
181 | + | (let* ((usages (or (assoc-ref (assoc-ref node-map object) | |
182 | + | "usages") | |
183 | + | #())) | |
184 | + | (usages (array->list usages))) | |
185 | + | (set! usages | |
186 | + | (append | |
187 | + | usages | |
188 | + | (list `(("node" . ,node-ref) | |
189 | + | ("property" . ,predicate) | |
190 | + | ("value" . ,value-ref))))) | |
191 | + | (set! node-map | |
192 | + | (jsonld-set | |
193 | + | node-map (list object "usages") | |
194 | + | (list->array 1 usages))))) | |
195 | + | ;; 5.7.10 | |
196 | + | ((json-has-key? referenced-once object) | |
197 | + | (set! referenced-once | |
198 | + | (alist-set referenced-once object #f))) | |
199 | + | ((blank-node? object) | |
200 | + | (set! referenced-once | |
201 | + | (alist-set referenced-once object | |
202 | + | `(("node" . ,node-ref) | |
203 | + | ("property" . ,predicate) | |
204 | + | ("value" . ,value-ref))))))))))) | |
205 | + | graph) | |
206 | + | (set! graph-map (alist-set graph-map name node-map)) | |
207 | + | (set! compound-literal-subjects | |
208 | + | (alist-set compound-literal-subjects name compound-map)))) | |
209 | + | (cons (cons "@default" (rdf-dataset-default-graph dataset)) | |
210 | + | (rdf-dataset-named-graphs dataset))) | |
211 | + | (set! default-graph (assoc-ref graph-map "@default")) | |
212 | + | ;; 6 | |
213 | + | (for-each-pair | |
214 | + | (lambda (name graph-object) | |
215 | + | ;; 6.1 | |
216 | + | (when (list? (assoc-ref compound-literal-subjects name)) | |
217 | + | (for-each-pair | |
218 | + | (lambda (cl _) | |
219 | + | ;; 6.1.1 | |
220 | + | (let ((cl-entry (assoc-ref referenced-once cl))) | |
221 | + | (when (list? cl-entry) | |
222 | + | ;; 6.1.2 | |
223 | + | (let* ((node-ref (assoc-ref cl-entry "node")) | |
224 | + | (node (jsonld-ref graph-map node-ref)) | |
225 | + | ;; 6.1.3 | |
226 | + | (property (assoc-ref cl-entry "property")) | |
227 | + | ;; 6.1.4 | |
228 | + | (value-ref (assoc-ref cl-entry "value")) | |
229 | + | (value (jsonld-ref graph-map value-ref)) | |
230 | + | ;; 6.1.5 | |
231 | + | (cl-node (assoc-ref graph-object cl))) | |
232 | + | (set! graph-object (alist-remove graph-object cl)) | |
233 | + | (when (equal? name "@default") | |
234 | + | (set! default-graph graph-object)) | |
235 | + | (set! graph-map (alist-set graph-map name graph-object)) | |
236 | + | (when (list? cl-node) | |
237 | + | ;; 6.1.6 | |
238 | + | (let* ((refs (array->list (assoc-ref node property)))) | |
239 | + | (set! refs | |
240 | + | (map | |
241 | + | (lambda (cl-reference) | |
242 | + | (when (equal? (assoc-ref cl-reference "@id") cl) | |
243 | + | ;; 6.1.6.1 | |
244 | + | (set! cl-reference (alist-remove cl-reference "@id")) | |
245 | + | ;; 6.1.6.2 | |
246 | + | (let* ((value (assoc-ref cl-node (rdf-iri "value"))) | |
247 | + | (value (array-ref value 0)) | |
248 | + | (value (assoc-ref value "@value"))) | |
249 | + | (set! cl-reference | |
250 | + | (alist-set cl-reference "@value" value))) | |
251 | + | ;; 6.1.6.3 | |
252 | + | (let ((language (assoc-ref cl-node (rdf-iri "language")))) | |
253 | + | (when language | |
254 | + | (let* ((language (array-ref language 0)) | |
255 | + | (language (assoc-ref language "@value"))) | |
256 | + | (set! cl-reference | |
257 | + | (alist-set cl-reference "@language" language)) | |
258 | + | (unless (well-formed-language-tag? language) | |
259 | + | (throw 'invalid-language-tagged-string language))))) | |
260 | + | ;; 6.1.6.4 | |
261 | + | (let ((direction (assoc-ref cl-node (rdf-iri "direction")))) | |
262 | + | (when direction | |
263 | + | (let* ((direction (array-ref direction 0)) | |
264 | + | (direction (assoc-ref direction "@value"))) | |
265 | + | (set! cl-reference | |
266 | + | (alist-set cl-reference "@direction" direction)) | |
267 | + | (unless (member direction '("ltr" "rtl")) | |
268 | + | (throw 'invalid-base-direction direction)))))) | |
269 | + | cl-reference) | |
270 | + | refs)) | |
271 | + | (set! node (alist-set node property (list->array 1 refs)))) | |
272 | + | (set! graph-map (jsonld-set graph-map node-ref node))))))) | |
273 | + | (assoc-ref compound-literal-subjects name))) | |
274 | + | ;; 6.2 | |
275 | + | (when (json-has-key? graph-object (rdf-iri "nil")) | |
276 | + | ;; 6.3 | |
277 | + | (let* ((nil (assoc-ref graph-object (rdf-iri "nil"))) | |
278 | + | (usages (array->list (or (assoc-ref nil "usages") #())))) | |
279 | + | (set! usages | |
280 | + | (sort usages (lambda (a b) | |
281 | + | (or (not (equal? (assoc-ref a "node") (assoc-ref b "node"))) | |
282 | + | (and (equal? (assoc-ref a "property") (rdf-iri "first")) | |
283 | + | (equal? (assoc-ref b "property") (rdf-iri "rest"))))))) | |
284 | + | ;; 6.4 | |
285 | + | (for-each | |
286 | + | (lambda (usage) | |
287 | + | (let* ((node-ref (assoc-ref usage "node")) | |
288 | + | (node (jsonld-ref graph-map node-ref)) | |
289 | + | (property (assoc-ref usage "property")) | |
290 | + | (head-ref (assoc-ref usage "value")) | |
291 | + | (head (jsonld-ref graph-map head-ref)) | |
292 | + | ;; 6.4.2 | |
293 | + | (lst '()) | |
294 | + | (list-nodes '())) | |
295 | + | ;; 6.4.3 | |
296 | + | (let loop () | |
297 | + | (when (and (equal? property (rdf-iri "rest")) | |
298 | + | (blank-node? (assoc-ref node "@id")) | |
299 | + | (list? (assoc-ref referenced-once | |
300 | + | (assoc-ref node "@id"))) | |
301 | + | (single-element-array? (assoc-ref node (rdf-iri "first"))) | |
302 | + | (single-element-array? (assoc-ref node (rdf-iri "rest"))) | |
303 | + | (null? (filter | |
304 | + | (lambda (e) | |
305 | + | (not (member (car e) | |
306 | + | (list (rdf-iri "first") | |
307 | + | (rdf-iri "rest") | |
308 | + | "@type" | |
309 | + | "@id")))) | |
310 | + | node)) | |
311 | + | (or (not (json-has-key? node "@type")) | |
312 | + | (null? | |
313 | + | (filter | |
314 | + | (lambda (t) | |
315 | + | (not (equal? t (rdf-iri "List")))) | |
316 | + | (array->list (assoc-ref node "@type")))))) | |
317 | + | ;; 6.4.3.1 | |
318 | + | (set! lst | |
319 | + | (cons (array-ref (assoc-ref node (rdf-iri "first")) 0) | |
320 | + | lst)) | |
321 | + | ;; 6.4.3.2 | |
322 | + | (set! list-nodes | |
323 | + | (cons (assoc-ref node "@id") list-nodes)) | |
324 | + | ;; 6.4.3.3 | |
325 | + | (let ((node-usage (assoc-ref referenced-once | |
326 | + | (assoc-ref node "@id")))) | |
327 | + | ;; 6.4.3.4 | |
328 | + | (set! node-ref (assoc-ref node-usage "node")) | |
329 | + | (set! node (jsonld-ref graph-map node-ref)) | |
330 | + | (set! property (assoc-ref node-usage "property")) | |
331 | + | (set! head-ref (assoc-ref node-usage "value")) | |
332 | + | (set! head (jsonld-ref graph-map head-ref)) | |
333 | + | (loop)))) | |
334 | + | ;; 6.4.4 | |
335 | + | (set! head (alist-remove head "@id")) | |
336 | + | ;; 6.4.6 | |
337 | + | (set! head (alist-set head "@list" (list->array 1 lst))) | |
338 | + | (set! graph-map (jsonld-set graph-map head-ref head)) | |
339 | + | ;; 6.4.7 | |
340 | + | (for-each | |
341 | + | (lambda (node-id) | |
342 | + | (set! graph-object (alist-remove graph-object node-id)) | |
343 | + | (when (equal? name "@default") | |
344 | + | (set! default-graph graph-object)) | |
345 | + | (set! graph-map (alist-set graph-map name graph-object))) | |
346 | + | list-nodes))) | |
347 | + | usages)))) | |
348 | + | graph-map) | |
349 | + | (set! default-graph (assoc-ref graph-map "@default")) | |
350 | + | ;; 7 | |
351 | + | (let ((result '())) | |
352 | + | ;; 8 | |
353 | + | (for-each-pair | |
354 | + | (lambda (subject node) | |
355 | + | ;; 8.1 | |
356 | + | (when (json-has-key? graph-map subject) | |
357 | + | (let ((new-graph '())) | |
358 | + | (for-each-pair | |
359 | + | (lambda (s n) | |
360 | + | ;; 8.1.2 | |
361 | + | (unless (null? (filter | |
362 | + | (lambda (e) | |
363 | + | (not (member (car e) '("usages" "@id")))) | |
364 | + | n)) | |
365 | + | (set! new-graph | |
366 | + | (append new-graph (list (alist-remove n "usages")))))) | |
367 | + | (if ordered? | |
368 | + | (alist-sort-by-key (or (assoc-ref graph-map subject) '())) | |
369 | + | (or (assoc-ref graph-map subject) '()))) | |
370 | + | ;; 8.1.1 | |
371 | + | (set! node (alist-set node "@graph" (list->array 1 new-graph))))) | |
372 | + | ;; 8.2 | |
373 | + | (unless (null? (filter | |
374 | + | (lambda (e) | |
375 | + | (not (member (car e) '("usages" "@id")))) | |
376 | + | node)) | |
377 | + | (set! result | |
378 | + | (append result (list (alist-remove node "usages")))))) | |
379 | + | (if ordered? | |
380 | + | (alist-sort-by-key default-graph) | |
381 | + | default-graph)) | |
382 | + | ;; 9 | |
383 | + | (list->array 1 result)))) |
test-modules/online.scm
165 | 165 | `(#:rdf-direction | |
166 | 166 | ,(assoc-ref options "rdfDirection")) | |
167 | 167 | '()))))) | |
168 | + | ((member "jld:FromRDFTest" type) | |
169 | + | (rdf->jsonld (download-nq (string-append jsonld-test-url input)) | |
170 | + | #:options | |
171 | + | (apply | |
172 | + | new-jsonld-options | |
173 | + | #:ordered? #t | |
174 | + | #:document-loader document-loader | |
175 | + | `(,@(if (assoc-ref options "base") | |
176 | + | `(#:base ,(assoc-ref options "base")) | |
177 | + | '()) | |
178 | + | ,@(if (assoc-ref options "processingMode") | |
179 | + | `(#:processing-mode ,(assoc-ref options "processingMode")) | |
180 | + | '()) | |
181 | + | ,@(if (assoc-ref options "produceGeneralizedRdf") | |
182 | + | `(#:produce-generalized-rdf? #t) | |
183 | + | `(#:produce-generalized-rdf? #f)) | |
184 | + | ,@(if (assoc-ref options "expandContext") | |
185 | + | `(#:expand-context ,(string-append | |
186 | + | jsonld-test-url | |
187 | + | (assoc-ref options "expandContext"))) | |
188 | + | '()) | |
189 | + | ,@(if (assoc-ref options "useNativeTypes") | |
190 | + | `(#:use-native-types? #t) | |
191 | + | '()) | |
192 | + | ,@(if (assoc-ref options "useRdfType") | |
193 | + | `(#:use-rdf-type? #t) | |
194 | + | '()) | |
195 | + | ,@(if (assoc-ref options "rdfDirection") | |
196 | + | `(#:rdf-direction | |
197 | + | ,(assoc-ref options "rdfDirection")) | |
198 | + | '()))))) | |
168 | 199 | (else (throw 'unrecognized-test type))))) | |
169 | 200 | ||
170 | 201 | (define (run-test test) |
test-modules/testsuite.scm
23 | 23 | html-test-url | |
24 | 24 | remote-doc-test-url | |
25 | 25 | jsonld-test-url | |
26 | + | fromrdf-test-url | |
26 | 27 | tordf-test-url)) | |
27 | 28 | ||
28 | 29 | (define jsonld-test-url "https://w3c.github.io/json-ld-api/tests/") | |
… | |||
42 | 43 | (define remote-doc-test-url | |
43 | 44 | (string-append jsonld-test-url "remote-doc-manifest.jsonld")) | |
44 | 45 | ||
46 | + | (define fromrdf-test-url | |
47 | + | (string-append jsonld-test-url "fromRdf-manifest.jsonld")) | |
48 | + | ||
45 | 49 | (define tordf-test-url | |
46 | 50 | (string-append jsonld-test-url "toRdf-manifest.jsonld")) | |
47 | 51 |
tests/fromrdf.scm.in unknown status 1
1 | + | #!@abs_top_srcdir@/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 fromrdf-test-url expected-failures tap-driver) |