#| -*-Scheme-*-
-$Id: rdf-nt.scm,v 1.7 2006/06/22 19:17:26 cph Exp $
+$Id: rdf-nt.scm,v 1.8 2006/08/02 05:05:10 cph Exp $
Copyright 2006 Massachusetts Institute of Technology
;;;; Decoder
(define (read-rdf/nt-file pathname)
- (fluid-let ((*bnodes* (make-bnode-table)))
+ (fluid-let ((*rdf-bnode-registry* (make-rdf-bnode-registry)))
(call-with-input-file pathname
(lambda (port)
(let loop ((triples '()))
(define (rdf/nt-file->source pathname)
(let ((port (open-input-file pathname))
- (table (make-bnode-table)))
+ (registry (make-rdf-bnode-registry)))
(lambda ()
(let ((triple
- (fluid-let ((*bnodes* table))
+ (fluid-let ((*rdf-bnode-registry* registry))
(%read-rdf/nt port))))
(if (eof-object? triple)
#f
triple)))))
(define (read-rdf/nt port)
- (fluid-let ((*bnodes* (bnode-table port)))
+ (fluid-let ((*rdf-bnode-registry* (port/bnode-registry port)))
(let ((triple (%read-rdf/nt port)))
(if (eof-object? triple)
- (drop-bnode-table port))
+ (port/drop-bnode-registry port))
triple)))
(define (%read-rdf/nt port)
(define parse-node-id
(*parser
- (encapsulate (lambda (v) (make-bnode (vector-ref v 0)))
+ (encapsulate (lambda (v) (make-rdf-bnode (vector-ref v 0)))
(seq "_:"
(match match-bnode-name)))))
(port/set-coding port 'UTF-8)
(loop)))
-\f
-(define *bnodes*)
-
-(define (make-bnode-table)
- (make-string-hash-table))
-
-(define (bnode-table port)
- (or (port/get-property port 'BNODE-TABLE #f)
- (let ((table (make-string-hash-table)))
- (port/set-property! port 'BNODE-TABLE table)
- table)))
-
-(define (drop-bnode-table port)
- (port/remove-property! port 'BNODE-TABLE))
-
-(define (make-bnode name)
- (hash-table/intern! *bnodes* name
- (lambda ()
- (make-rdf-bnode name))))
(define match-ws*
(*matcher (* (char-set char-set:ws))))
#| -*-Scheme-*-
-$Id: rdf-struct.scm,v 1.15 2006/08/01 17:23:49 cph Exp $
+$Id: rdf-struct.scm,v 1.16 2006/08/02 05:05:14 cph Exp $
Copyright 2006 Massachusetts Institute of Technology
(canonicalize-rdf-predicate predicate 'MAKE-RDF-TRIPLE)
(canonicalize-rdf-object object 'MAKE-RDF-TRIPLE)))
+(define (canonicalize-rdf-subject subject #!optional caller)
+ (cond ((rdf-bnode? subject) subject)
+ ((%decode-bnode-uri subject caller))
+ (else (canonicalize-rdf-uri subject caller))))
+
+(define (canonicalize-rdf-predicate predicate #!optional caller)
+ (canonicalize-rdf-uri predicate caller))
+
+(define (canonicalize-rdf-object object #!optional caller)
+ (cond ((rdf-literal? object) object)
+ ((string? object) (make-rdf-literal object #f))
+ (else (canonicalize-rdf-subject object caller))))
+
+(define (canonicalize-rdf-uri uri #!optional caller)
+ (if (rdf-qname? uri)
+ (rdf-qname->uri uri)
+ (->absolute-uri uri caller)))
+
+(define (write-rdf-uri uri port)
+ (let ((qname (uri->rdf-qname uri #f)))
+ (if qname
+ (write-string (symbol-name qname) port)
+ (write-rdf-uri-ref uri port))))
+\f
+;;;; Blank nodes
+
(define-record-type <rdf-bnode>
(%make-rdf-bnode name)
rdf-bnode?
(write-rdf-bnode bnode port))))
(define (make-rdf-bnode #!optional name)
- (%make-rdf-bnode
- (cond ((default-object? name)
- (generate-bnode-name))
- ((and (string? name)
- (complete-match match-bnode-name name))
- name)
- (else
- (error:wrong-type-argument name "RDF bnode name" 'RDF-BNODE)))))
+ (cond ((default-object? name)
+ (let ((name (generate-bnode-name)))
+ (let ((bnode (%make-rdf-bnode name)))
+ (hash-table/put! *rdf-bnode-registry* name bnode)
+ bnode)))
+ ((and (string? name)
+ (complete-match match-bnode-name name))
+ (hash-table/intern! *rdf-bnode-registry* name
+ (lambda ()
+ (%make-rdf-bnode name))))
+ (else
+ (error:wrong-type-argument name "RDF bnode name" 'RDF-BNODE))))
(define (generate-bnode-name)
- (string-append "B" (vector-8b->hexadecimal (random-byte-vector 8))))
+ (let loop ()
+ (let ((name
+ (string-append "B"
+ (vector-8b->hexadecimal (random-byte-vector 8)))))
+ (if (hash-table/get *rdf-bnode-registry* name #f)
+ (loop)
+ name))))
+
+(define (%decode-bnode-uri uri caller)
+ (let ((lookup
+ (lambda (uri)
+ (let ((bnode
+ (hash-table/get *rdf-bnode-registry*
+ (string-tail uri 2)
+ #f)))
+ (if (not bnode)
+ (error:bad-range-argument uri caller))
+ bnode))))
+ (let ((handle-uri
+ (lambda (uri)
+ (cond ((complete-match match-bnode-uri uri) (lookup uri))
+ ((handle->rdf-bnode uri #f))
+ (else #f)))))
+ (cond ((string? uri) (handle-uri uri))
+ ((symbol? uri) (handle-uri (symbol-name uri)))
+ (else #f)))))
+\f
+(define (complete-match matcher string)
+ (let ((buffer (string->parser-buffer string)))
+ (and (matcher buffer)
+ (not (peek-parser-buffer-char buffer)))))
+
+(define match-bnode-uri
+ (*matcher (seq "_:" match-bnode-name)))
+
+(define match-bnode-name
+ (let* ((name-head
+ (char-set-union (ascii-range->char-set #x41 #x5B)
+ (ascii-range->char-set #x61 #x7B)))
+ (name-tail
+ (char-set-union name-head
+ (ascii-range->char-set #x30 #x3A))))
+ (*matcher
+ (seq (char-set name-head)
+ (* (char-set name-tail))))))
+
+(define (make-rdf-bnode-registry)
+ (make-string-hash-table))
+
+(define *rdf-bnode-registry*
+ (make-rdf-bnode-registry))
+
+(define (port/bnode-registry port)
+ (or (port/get-property port 'PORT/BNODE-REGISTRY #f)
+ (let ((table (make-string-hash-table)))
+ (port/set-property! port 'PORT/BNODE-REGISTRY table)
+ table)))
+
+(define (port/drop-bnode-registry port)
+ (port/remove-property! port 'PORT/DROP-BNODE-REGISTRY))
+
+(define (rdf-bnode->handle bnode)
+ (string-append bnode-handle-prefix (number->string (hash bnode))))
+
+(define (handle->rdf-bnode handle #!optional caller)
+ (let ((v
+ (and (string? handle)
+ (parse-bnode-handle (string->parser-buffer handle)))))
+ (if v
+ (unhash (vector-ref v 0))
+ (begin
+ (if caller
+ (error:wrong-type-argument handle "RDF bnode handle" caller))
+ #f))))
+
+(define parse-bnode-handle
+ (let ((prefix
+ (lambda (b) (match-parser-buffer-string b bnode-handle-prefix)))
+ (digits (ascii-range->char-set #x30 #x3A)))
+ (*parser
+ (seq (noise prefix)
+ (map (lambda (s) (string->number s 10 #t))
+ (match (+ (char-set digits))))
+ (noise (end-of-input))))))
+
+(define bnode-handle-prefix
+ "_bnode_:")
+\f
+;;;; Literals
(define-record-type <rdf-literal>
(%make-rdf-literal text type)
type
(->absolute-uri type 'RDF-LITERAL))))
+(define match-language
+ (let* ((language-head (ascii-range->char-set #x61 #x7B))
+ (language-tail
+ (char-set-union language-head
+ (ascii-range->char-set #x30 #x3A))))
+ (*matcher
+ (seq (+ (char-set language-head))
+ (* (seq #\- (+ (char-set language-tail))))))))
+
(define (rdf-literal-type literal)
(let ((type (%rdf-literal-type literal)))
(and (absolute-uri? type)
(and (string=? (rdf-literal-text l1) (rdf-literal-text l2))
(eq? (%rdf-literal-type l1) (%rdf-literal-type l2))))
\f
+;;;; Triples index (deprecated)
+
(define-record-type <rdf-index>
(%make-rdf-index subjects predicates objects)
rdf-index?
(let ((o (rdf-triple-object triple)))
(if (not (rdf-literal? o))
(add o (rdf-index-objects index))))))
-
-(define (canonicalize-rdf-uri uri #!optional caller)
- (or (rdf-qname->uri uri #f)
- (->absolute-uri uri caller)))
-
-(define (write-rdf-uri uri port)
- (let ((qname (uri->rdf-qname uri #f)))
- (if qname
- (write-string (symbol-name qname) port)
- (write-rdf-uri-ref uri port))))
-
-(define (canonicalize-rdf-subject subject #!optional caller)
- (if (rdf-bnode? subject)
- subject
- (canonicalize-rdf-uri subject caller)))
-
-(define (canonicalize-rdf-predicate predicate #!optional caller)
- (canonicalize-rdf-uri predicate caller))
-
-(define (canonicalize-rdf-object object #!optional caller)
- (cond ((or (rdf-bnode? object)
- (rdf-literal? object))
- object)
- ((string? object) (make-rdf-literal object #f))
- (else (canonicalize-rdf-uri object caller))))
-
-(define match-bnode-name
- (let* ((name-head
- (char-set-union (ascii-range->char-set #x41 #x5B)
- (ascii-range->char-set #x61 #x7B)))
- (name-tail
- (char-set-union name-head
- (ascii-range->char-set #x30 #x3A))))
- (*matcher
- (seq (char-set name-head)
- (* (char-set name-tail))))))
-
-(define match-language
- (let* ((language-head (ascii-range->char-set #x61 #x7B))
- (language-tail
- (char-set-union language-head
- (ascii-range->char-set #x30 #x3A))))
- (*matcher
- (seq (+ (char-set language-head))
- (* (seq #\- (+ (char-set language-tail))))))))
-
-(define (complete-match matcher string)
- (let ((buffer (string->parser-buffer string)))
- (and (matcher buffer)
- (not (peek-parser-buffer-char buffer)))))
\f
;;;; Qnames