aboutsummaryrefslogtreecommitdiff
path: root/module/vcomponent/data-stores/vdir.scm
blob: 9320c44ef83c3aa9a3542b22296750fd8c6c7799 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
(define-module (vcomponent data-stores vdir)
  :use-module (hnh util)
  :use-module (oop goops)
  :use-module (vcomponent data-stores common)
  :use-module (srfi srfi-71)
  :use-module ((srfi srfi-88) :select ())
  :use-module (hnh util path)
  :use-module ((vcomponent formats ical) :select (serialize deserialize))
  :use-module ((ice-9 ftw) :select (scandir))
  :use-module (ice-9 rdelim)
  :use-module (srfi srfi-1)
  :use-module (vcomponent base)
  :export ())

(define-class <vdir-data-store> (<calendar-data-store>)
  (path getter: path
        init-keyword: path:)
  (loaded-calendar accessor: loaded-calendar
                   init-value: #f)
  (uid-map accessor: uid-map
           init-value: #f)
  )

(define (make-vdir-store path)
  (make <vdir-data-store> path: path))

(define* (get-attribute path key key: dflt)
  (catch 'system-error
    (lambda () (call-with-input-file (path-append path key) read-line))
    (const dflt)))


(define-method (get-all (this <vdir-data-store>))
  (let ((files (scandir (path this) (lambda (item) (string-ci=? "ics" (filename-extension item)))))
        (calendar
         (fold (swap add-child)
               (set-properties (vcomponent type: 'VCALENDAR)
                               (cons 'NAME  (get-attribute (path this) "displayname"))
                               (cons 'COLOR (get-attribute (path this) "color" "#FFFFFF")))
               (append-map (lambda (file)
                             (define cal
                               (call-with-input-file (path-append (path this) file)
                                 deserialize))
                             (unless (eq? 'VCALENDAR (type cal))
                               (scm-error 'misc-error "get-all<vdir-data-store>"
                                          "Unexpected top level component. Expected VCALENDAR, got ~a. In file ~s"
                                          (list (type cal) file)))
                             (each cal children
                                   (lambda (child)
                                     (prop child '-X-HNH-FILENAME file))))
                           files))))
    (set! (loaded-calendar this) calendar)
    calendar))


(define-method (get-by-uid (this <vdir-data-store>) (uid <string>))
  (unless (uid-map this)
    (let ((cal
           (or (loaded-calendar this)
               (get-all this))))
      (define ht (make-hash-table))
      (for-each (lambda (ev) (hash-set! ht (uid ev) ev))
                (children cal))
      (set! (uid-map this) ht)))
  (hash-ref m uid #f))


(define (wrap-for-output . vcomponents)
  (fold (swap add-child)
        (set-properties (vcomponent type: 'VCALENDAR)
                        (cons 'VERSION "2.0")
                        (cons 'PRODID (prodid))
                        (cons 'CALSCALE "GREGORIAN"))
        vcomponents))

(define-method (queue-write (this <vdir-data-store>) vcomponent)
  ;; TODO Multiple components
  (let ((filename
         (cond ((prop vcomponent '-X-HNH-FILENAME)
                => identity)
               (else
                (format #f "~a.ics" (prop vcomponent 'UID))))))
    (with-atomic-output-to-file (path-append (path this) filename)
      (lambda () (serialize (wrap-for-output vcomponent) (current-output-port))))))

(define-method (flush (this <vdir-data-store>))
  (sync))

;; (define (get-in-date-interval ))