;;;; Copyright (C) 2019, 2020 Julien Lepiller ;;;; ;;;; This library is free software; you can redistribute it and/or ;;;; modify it under the terms of the GNU Lesser General Public ;;;; License as published by the Free Software Foundation; either ;;;; version 3 of the License, or (at your option) any later version. ;;;; ;;;; This library is distributed in the hope that it will be useful, ;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ;;;; Lesser General Public License for more details. ;;;; ;;;; You should have received a copy of the GNU Lesser General Public ;;;; License along with this library; if not, write to the Free Software ;;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ;;;; (define-module (jsonld iri-expansion) #:use-module (iri iri) #:use-module (jsonld context) #:use-module (jsonld create-term-definition) #:use-module (jsonld download) #:use-module (jsonld json) #:use-module (jsonld options) #:use-module (json) #:use-module (web uri) #:use-module (rnrs bytevectors) #:use-module (ice-9 match) #:use-module (srfi srfi-9) #:export (iri-expansion expand-key json-key-expanded-to?)) (define (expand-key active-context key) (assoc-ref (iri-expansion active-context key #:vocab? #t) "iri")) (define (json-key-expanded-to? active-context element value) (and (json-object? element) (not (null? (filter (lambda (kv) (equal? value (expand-key active-context (car kv)))) element))))) (define* (iri-expansion active-context iri #:key document-relative? vocab? (local-context '()) (defined '()) (options (new-jsonld-options))) "Expand an IRI. This is an implementation of the IRI expansion algorithm defined in the JsonLD API specification." ;; 2 (when (and (keyword-form? iri) (not (json-keyword? iri))) ;; Should give a warning and return null, we only return null without warning (set! iri json-null)) ;; if not 1 or 2 (unless (or (json-keyword? iri) (json-null? iri)) ;; 3 (when (and local-context (json-has-key? local-context iri)) (let ((def (assoc-ref defined iri))) (unless (or (equal? def 'true) (equal? def #f)) (let ((result (create-term-definition active-context local-context iri defined #:options options))) (set! active-context (assoc-ref result "active-context")) (set! defined (assoc-ref result "defined")))))) (cond ((not (string? iri)) #t) ;; 4 ((and (term-definition? (term-definition-ref active-context iri)) (json-keyword? (term-definition-iri (term-definition-ref active-context iri)))) (set! iri (term-definition-iri (term-definition-ref active-context iri)))) ;; 5 ((and vocab? (term-definition? (term-definition-ref active-context iri))) (set! iri (term-definition-iri (term-definition-ref active-context iri)))) ;; 6 ((and (not (equal? iri "")) (string-index (substring iri 1) #\:)) ;; 6.1 (let ((prefix (car (string-split iri #\:))) (suffix (string-join (cdr (string-split iri #\:)) ":"))) (if (or (equal? prefix "_") (and (> (string-length suffix) 1) (equal? (substring suffix 0 2) "//"))) ;; 6.2 (set! iri iri) (begin ;; 6.3 (when (and (json-object? local-context) (json-has-key? local-context prefix)) (let ((def (assoc-ref defined prefix))) (unless (or (equal? def 'true)) (let* ((result (create-term-definition active-context local-context prefix defined #:options options))) (set! active-context (assoc-ref result "active-context")) (set! defined (assoc-ref result "defined")))))) ;; 6.4 (if (and (term-definition? (term-definition-ref active-context prefix)) (not-null-or-false (term-definition-iri (term-definition-ref active-context prefix))) (term-definition-prefix? (term-definition-ref active-context prefix))) (set! iri (string-append (term-definition-iri (term-definition-ref active-context prefix)) suffix)) ;; 6.5 (cond ((absolute-iri? iri) (set! iri iri)) ;; 7 ((and vocab? (not-null-or-false (active-context-vocab active-context))) (set! iri (string-append (not-null-or-false (active-context-vocab active-context)) iri))) (else (if (and document-relative? (not-null-or-false (active-context-base active-context))) ;; 8 (set! iri (resolve-iri (or (active-context-base active-context) (jsonld-options-base options)) iri)) ;; 9 (set! iri iri))))))))) ;; 7 ((and vocab? (not-null-or-false (active-context-vocab active-context))) (set! iri (string-append (active-context-vocab active-context) iri))) (else (if (and document-relative? (not-null-or-false (active-context-base active-context))) ;; 8 (set! iri (resolve-iri (or (active-context-base active-context) (jsonld-options-base options)) iri)) ;; 9 (set! iri iri))))) ;; return an alist of potentially modified objects: iri (the return iri), ;; defined and active-context. `(("iri" . ,iri) ("active-context" . ,active-context) ("defined" . ,defined)))