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) |