summaryrefslogtreecommitdiff
path: root/ldp/resource.scm
diff options
context:
space:
mode:
Diffstat (limited to 'ldp/resource.scm')
-rw-r--r--ldp/resource.scm112
1 files changed, 112 insertions, 0 deletions
diff --git a/ldp/resource.scm b/ldp/resource.scm
new file mode 100644
index 0000000..6720499
--- /dev/null
+++ b/ldp/resource.scm
@@ -0,0 +1,112 @@
+(define-module (ldp resource)
+ #:use-module (ldp path)
+ #:use-module (ldp etag)
+ #:use-module (oop goops)
+ #:use-module (web uri))
+
+;; If contained is #f, then this is not a container. Otherwise, this
+;; is a container, possibly empty (null)
+(define-class <resource> ()
+ (path #:init-keyword #:path #:getter resource-path)
+ (etag #:init-keyword #:etag #:getter resource-etag)
+ (content-type #:init-keyword #:content-type #:getter resource-content-type)
+ (contained #:init-keyword #:contained #:getter resource-contained))
+
+(export resource-path
+ resource-etag
+ resource-content-type
+ resource-contained)
+
+(define (the-symbol x)
+ (unless (symbol? x)
+ (scm-error 'wrong-type-arg
+ "the-symbol"
+ "Expected a symbol, got ~s."
+ (list x)
+ (list x)))
+ x)
+
+(define-public (make-resource path etag content-type contained)
+ (unless (or (not contained)
+ (eq? content-type 'text/turtle))
+ (throw 'containers-should-be-rdf))
+ (make <resource>
+ #:path (the-path path)
+ #:etag (the-etag etag)
+ #:content-type (the-symbol content-type)
+ #:contained (and contained
+ (map the-path contained))))
+
+(define-public (resource? x)
+ (is-a? x <resource>))
+
+(define-public (container? x)
+ (and (resource? x)
+ (resource-contained x)))
+
+(define-public (the-resource x)
+ (unless (resource? x)
+ (scm-error 'wrong-type-arg
+ "the-non-container"
+ "Expected a resource from (ldp resource)."
+ '()
+ (list x)))
+ x)
+
+(define-public (the-container x)
+ (unless (container? x)
+ (scm-error 'wrong-type-arg
+ "the-container"
+ "Expected a container from (ldp resource)."
+ '()
+ (list x)))
+ x)
+
+(define-method (has-child? (container <resource>) (child <path>))
+ (define (check list)
+ (and (not (null? list))
+ (or (path-equal? (car list) child)
+ (check (cdr list)))))
+ (check (resource-contained container)))
+
+(export has-child?)
+
+(define-public (add-child container child)
+ (set! container (the-container container))
+ (set! child (the-path child))
+ (if (has-child? container child)
+ (throw 'child-already-exists)
+ (make-resource (resource-path container)
+ (generate-etag)
+ (resource-content-type container)
+ (cons child (resource-contained container)))))
+
+(define-public (remove-child container child)
+ (set! container (the-container container))
+ (set! child (the-path child))
+ (define (check found kept list)
+ (if (null? list)
+ (if found
+ (reverse kept)
+ (throw 'child-does-not-exist))
+ (if (path-equal? (car list) child)
+ (check #t kept (cdr list))
+ (check found (cons (car list) kept) (cdr list)))))
+ (make-resource (resource-path container)
+ (generate-etag)
+ (resource-content-type container)
+ (check #f '() (resource-contained container))))
+
+(define-public (update-children container added removed)
+ (set! container (the-container container))
+ (set! added (map the-path added))
+ (set! removed (map the-path removed))
+ (cond
+ ((and (null? added) (null? removed))
+ container)
+ ((null? added)
+ (update-children (remove-child container (car removed))
+ '() (cdr removed)))
+ (else
+ (update-children (add-child container (car added))
+ (cdr added) removed))))