source: branches/gdl-frontend/src/rest_interface/set-up-json-interface.lisp

Last change on this file was 871, checked in by lgiessmann, 13 years ago

gdl-backend: removed the json-interface-caching mechanism of the gdl-frontend (for now)

File size: 24.9 KB
Line 
1;;+-----------------------------------------------------------------------------
2;;+  Isidorus
3;;+  (c) 2008-2010 Marc Kuester, Christoph Ludwig, Lukas Georgieff
4;;+
5;;+  Isidorus is freely distributable under the LLGPL license.
6;;+  You can find a detailed description in trunk/docs/LLGPL-LICENSE.txt and
7;;+  trunk/docs/LGPL-LICENSE.txt.
8;;+-----------------------------------------------------------------------------
9
10(in-package :rest-interface)
11
12;caching tables
13(defparameter *type-table* nil "Cointains integer==OIDs that represent a topic
14                                instance of a vylid type-topic")
15(defparameter *instance-table* nil "Cointains integer==OIDs that represent a topic
16                                    instance of a valid instance-topic")
17
18(defparameter *cache-initialised* nil "determines wheter the cache has been
19                                       already set or not")
20
21(defparameter *fragments-initialised* nil "determines wheter the fragments has
22                                           been already initialised or not.")
23
24;the prefix to get a fragment by the psi -> localhost:8000/json/get/<fragment-psi>
25(defparameter *json-get-prefix* "/json/get/(.+)$")
26;the prefix to get a fragment by the psi -> localhost:8000/json/rdf/get/<fragment-psi>
27(defparameter *get-rdf-prefix* "/json/get/rdf/(.+)$")
28;the url to commit a json fragment by "put" or "post"
29(defparameter *json-commit-url* "/json/commit/?$")
30;the url to commit a TM-fragment in XTM 2.0 format, the regular
31;expression represents the topic map id
32(defparameter *xtm-commit-prefix* "/import/xtm/2.0/(.+)$")
33;the url to get all topic psis of isidorus -> localhost:8000/json/psis
34(defparameter *json-get-all-psis* "/json/psis/?$")
35;the url to get a summary of all topic stored in isidorus; you have to set the
36;GET-parameter "start" for the start index of all topics within elephant and the
37;GET-paramter "end" for the last index of the topic sequence
38; -> http://localhost:8000/json/summary/?start=12&end=13
39(defparameter *json-get-summary-url* "/json/summary/?$")
40;returns a list of all psis that can be a type
41(defparameter *json-get-all-type-psis* "/json/tmcl/types/?$")
42;returns a list of all psis that belongs to a valid topic-instance
43(defparameter *json-get-all-instance-psis* "/json/tmcl/instances/?$")
44;the json prefix for getting some topic stub information of a topic
45(defparameter *json-get-topic-stub-prefix* "/json/topicstubs/(.+)$")
46;the json url for getting some tmcl information of a topic treated as a type
47(defparameter *json-get-type-tmcl-url* "/json/tmcl/type/?$")
48;the json url for getting some tmcl information of a topic treated as an instance
49(defparameter *json-get-instance-tmcl-url* "/json/tmcl/instance/?$")
50;returns a json-object representing a tree view
51(defparameter *json-get-overview* "/json/tmcl/overview/?$")
52;the url to the user interface
53(defparameter *ajax-user-interface-url* "/isidorus")
54;the url to the css files of the user interface
55(defparameter *ajax-user-interface-css-prefix* "/css")
56;the directory contains the css files
57(defparameter *ajax-user-interface-css-directory-path* "ajax/css")
58;the file path to the HTML file implements the user interface
59(defparameter *ajax-user-interface-file-path* "ajax/isidorus.html")
60;the directory which contains all necessary javascript files
61(defparameter *ajax-javascript-directory-path* "ajax/javascripts")
62;the url prefix of all javascript files
63(defparameter *ajax-javascript-url-prefix* "/javascripts")
64;the url suffix that calls the mark-as-deleted handler
65(defparameter *mark-as-deleted-url* "/mark-as-deleted")
66;the get url to request the latest revision of the storage
67(defparameter *latest-revision-url* "/json/latest-revision/?$")
68;the ulr to invoke a SPARQL query
69(defparameter *sparql-url* "/json/tm-sparql/?$")
70
71
72(defun set-up-json-interface (&key (json-get-prefix *json-get-prefix*)
73                              (get-rdf-prefix *get-rdf-prefix*)
74                              (json-get-all-psis *json-get-all-psis*)
75                              (json-commit-url *json-commit-url*)
76                              (json-get-summary-url *json-get-summary-url*)
77                              (json-get-all-type-psis *json-get-all-type-psis*)
78                              (json-get-all-instance-psis *json-get-all-instance-psis*)
79                              (json-get-topic-stub-prefix *json-get-topic-stub-prefix*)
80                              (json-get-type-tmcl-url *json-get-type-tmcl-url*)
81                              (json-get-instance-tmcl-url *json-get-instance-tmcl-url*)
82                              (json-get-overview *json-get-overview*)
83                              (ajax-user-interface-url *ajax-user-interface-url*)
84                              (ajax-user-interface-file-path *ajax-user-interface-file-path*)
85                              (ajax-user-interface-css-prefix *ajax-user-interface-css-prefix*)
86                              (ajax-user-interface-css-directory-path *ajax-user-interface-css-directory-path*)
87                              (ajax-javascripts-directory-path *ajax-javascript-directory-path*)
88                              (ajax-javascripts-url-prefix *ajax-javascript-url-prefix*)
89                              (mark-as-deleted-url *mark-as-deleted-url*)
90                              (latest-revision-url *latest-revision-url*)
91                              (xtm-commit-prefix *xtm-commit-prefix*)
92                              (sparql-url *sparql-url*))
93  "registers the json im/exporter to the passed base-url in hunchentoot's dispatch-table
94   and also registers a file-hanlder to the html-user-interface"
95
96  ;initializes cache and fragments
97  (init-cache nil)
98  (format t "~%")
99  (init-fragments nil)
100
101  ;; registers the http-code 500 for an internal server error to the standard
102  ;; return codes. so there won't be attached a hunchentoot default message,
103  ;; this is necessary to be able to send error messages in an individual way/syntax
104  ;; e.g. a json error-message.
105  (push hunchentoot:+http-internal-server-error+ hunchentoot:*approved-return-codes*)
106  ;; === html and css files ====================================================
107  (push
108   (create-static-file-dispatcher-and-handler ajax-user-interface-url ajax-user-interface-file-path "text/html")
109   hunchentoot:*dispatch-table*)
110
111  (dolist (script-path-and-url (make-file-path-and-url ajax-user-interface-css-directory-path ajax-user-interface-css-prefix))
112    (let ((script-path (getf script-path-and-url :path))
113          (script-url (getf script-path-and-url :url)))
114      (push 
115       (create-static-file-dispatcher-and-handler script-url script-path)
116       hunchentoot:*dispatch-table*)))
117
118
119  ;; === ajax frameworks and javascript files ==================================
120  (dolist (script-path-and-url (make-file-path-and-url ajax-javascripts-directory-path ajax-javascripts-url-prefix))
121    (let ((script-path (getf script-path-and-url :path))
122          (script-url (getf script-path-and-url :url)))
123      (push
124       (create-static-file-dispatcher-and-handler script-url script-path)
125       hunchentoot:*dispatch-table*)))
126 
127
128  ;; === rest interface ========================================================
129  (push
130   (create-regex-dispatcher json-get-all-psis #'return-all-topic-psis)
131   hunchentoot:*dispatch-table*)
132  (push
133   (create-regex-dispatcher json-get-prefix #'return-json-fragment)
134   hunchentoot:*dispatch-table*)
135  (push
136   (create-regex-dispatcher get-rdf-prefix #'return-json-rdf-fragment)
137   hunchentoot:*dispatch-table*)
138  (push
139   (create-regex-dispatcher json-get-topic-stub-prefix #'return-topic-stub-of-psi)
140   hunchentoot:*dispatch-table*)
141  (push
142   (create-regex-dispatcher json-get-all-type-psis #'return-all-tmcl-types)
143   hunchentoot:*dispatch-table*)
144  (push
145   (create-regex-dispatcher json-get-all-instance-psis #'return-all-tmcl-instances)
146   hunchentoot:*dispatch-table*)
147  (push
148   (create-regex-dispatcher json-get-type-tmcl-url #'(lambda(&optional param)
149                                                       (declare (ignorable param))
150                                                       (return-tmcl-info-of-psis 'json-tmcl::type)))
151   hunchentoot:*dispatch-table*)
152  (push
153   (create-regex-dispatcher json-get-instance-tmcl-url #'(lambda(&optional param)
154                                                           (declare (ignorable param))
155                                                           (return-tmcl-info-of-psis 'json-tmcl::instance)))
156   hunchentoot:*dispatch-table*)
157  (push
158   (create-regex-dispatcher json-get-overview #'return-overview)
159   hunchentoot:*dispatch-table*)
160  (push
161   (create-regex-dispatcher json-commit-url #'json-commit)
162   hunchentoot:*dispatch-table*)
163  (push
164   (create-regex-dispatcher json-get-summary-url #'return-topic-summaries)
165   hunchentoot:*dispatch-table*)
166  (push
167   (create-regex-dispatcher mark-as-deleted-url #'mark-as-deleted-handler)
168   hunchentoot:*dispatch-table*)
169  (push
170   (create-regex-dispatcher xtm-commit-prefix #'xtm-import-handler)
171   hunchentoot:*dispatch-table*)
172  (push
173   (create-regex-dispatcher latest-revision-url #'return-latest-revision)
174   hunchentoot:*dispatch-table*)
175  (push
176   (create-regex-dispatcher sparql-url #'return-tm-sparql)
177   hunchentoot:*dispatch-table*))
178
179;; =============================================================================
180;; --- some handlers for the json-rest-interface -------------------------------
181;; =============================================================================
182(defun return-all-tmcl-types(&optional param)
183  "Returns all topic-psi that are valid types -> so they have to be valid to the
184   topictype-constraint (if it exists) and the can't be abstract."
185  (declare (ignorable param))
186  (handler-case (let ((topic-types 
187                         (with-reader-lock
188                           (map 'list #'(lambda (oid)
189                                          (elephant::controller-recreate-instance
190                                           elephant::*store-controller* oid))
191                                *type-table*))))
192                  (setf (hunchentoot:content-type*) "application/json") ;RFC 4627
193                  (json:encode-json-to-string
194                   (map 'list #'(lambda(y)
195                                  (map 'list #'uri y))
196                        (map 'list #'psis topic-types))))
197    (condition (err) (progn
198                       (setf (hunchentoot:return-code*) hunchentoot:+http-internal-server-error+)
199                       (setf (hunchentoot:content-type*) "text")
200                       (format nil "Condition: \"~a\"" err)))))
201
202
203(defun return-all-tmcl-instances(&optional param)
204  "Returns all topic-psis that are valid instances of any topic type.
205   The validity is only oriented on the typing of topics, e.g.
206   type-instance or supertype-subtype."
207  (declare (ignorable param))
208  (handler-case (let ((topic-instances 
209                         (with-reader-lock
210                           (map 'list #'(lambda (oid)
211                                          (elephant::controller-recreate-instance
212                                           elephant::*store-controller* oid))
213                                *instance-table*))))
214                  (setf (hunchentoot:content-type*) "application/json") ;RFC 4627
215                  (json:encode-json-to-string
216                   (map 'list #'(lambda(y)
217                                  (map 'list #'uri y))
218                        (map 'list #'psis topic-instances))))
219    (condition (err) (progn
220                       (setf (hunchentoot:return-code*) hunchentoot:+http-internal-server-error+)
221                       (setf (hunchentoot:content-type*) "text")
222                       (format nil "Condition: \"~a\"" err)))))
223
224
225(defun return-topic-stub-of-psi(&optional psi)
226  "Returns a json string of a topic depending on the
227   passed psi as a topic-stub-construct."
228  (assert psi)
229  (let ((topic (d:get-item-by-psi psi)))
230    (if topic
231        (let ((topic-json
232               (handler-case
233                   (with-reader-lock
234                     (json-exporter::to-json-topicStub-string topic :revision 0))
235                 (condition (err) (progn
236                                    (setf (hunchentoot:return-code*) hunchentoot:+http-internal-server-error+)
237                                    (setf (hunchentoot:content-type*) "text")
238                                    (format nil "Condition: \"~a\"" err))))))
239          (setf (hunchentoot:content-type*) "application/json") ;RFC 4627
240          topic-json)
241        (progn
242          (setf (hunchentoot:return-code*) hunchentoot:+http-not-found+)
243          (setf (hunchentoot:content-type*) "text")
244          (format nil "Condition: Topic \"~a\" not found" psi)))))
245
246
247(defun return-tmcl-info-of-psis(treat-as)
248  "Returns a json string which represents the defined tmcl-constraints of the
249   topic and the associations where this topic can be a player."
250  (let ((http-method (hunchentoot:request-method*)))
251    (if (or (eq http-method :POST)
252            (eq http-method :PUT))
253        (let ((external-format
254               (flexi-streams:make-external-format :UTF-8 :eol-style :LF)))
255          (let ((json-data
256                 (hunchentoot:raw-post-data :external-format external-format
257                                            :force-text t)))
258            (handler-case
259                (let ((psis
260                       (json:decode-json-from-string json-data)))
261                  (let ((tmcl
262                         (with-reader-lock
263                           (json-tmcl:get-constraints-of-fragment
264                            psis :treat-as treat-as :revision 0))))
265                    (if tmcl
266                        (progn
267                          (setf (hunchentoot:content-type*)
268                                "application/json") ;RFC 4627
269                          tmcl)
270                        (progn
271                          (setf (hunchentoot:return-code*)
272                                hunchentoot:+http-not-found+)
273                          (setf (hunchentoot:content-type*) "text")
274                          (format nil "Topic \"~a\" not found." psis)))))
275              (condition ()
276                (setf (hunchentoot:content-type*) "application/json") ;RFC 4627
277                "{\"topicConstraints\":{\"exclusiveInstances\":null,\"subjectIdentifierConstraints\":null,\"subjectLocatorConstraints\":null,\"topicNameConstraints\":null,\"topicOccurrenceConstraints\":null,\"abstractConstraint\":false},\"associationsConstraints\":null}"))))
278        (setf (hunchentoot:return-code*) hunchentoot:+http-bad-request+))))
279
280
281(defun return-all-topic-psis (&optional param)
282  "return all psis currently existing in isidorus as a list of list. every topic is a list
283   of psis and the entire list contains a list of topics"
284  (declare (ignorable param))
285  (let ((http-method (hunchentoot:request-method*)))
286    (if (eq http-method :GET)
287        (progn
288          (setf (hunchentoot:content-type*) "application/json") ;RFC 4627
289          (handler-case (with-reader-lock
290                          (get-all-topic-psis :revision 0))
291            (condition (err) (progn
292                               (setf (hunchentoot:return-code*) hunchentoot:+http-internal-server-error+)
293                               (setf (hunchentoot:content-type*) "text")
294                               (format nil "Condition: \"~a\"" err)))))
295        (setf (hunchentoot:return-code*) hunchentoot:+http-bad-request+))))
296
297
298(defun return-json-fragment(&optional psi)
299  "returns the json-fragmen belonging to the psi passed by the parameter psi"
300  (assert psi)
301  (let ((http-method (hunchentoot:request-method*)))
302    (if (eq http-method :GET)
303        (let ((identifier (string-replace psi "%23" "#")))
304          (setf (hunchentoot:content-type*) "application/json") ;RFC 4627
305          (let ((fragment
306                 (with-reader-lock
307                   (get-latest-fragment-of-topic identifier))))
308            (if fragment
309                (handler-case (with-reader-lock
310                                (export-construct-as-isidorus-json-string
311                                 fragment :revision 0))
312                  (condition (err)
313                    (progn
314                      (setf (hunchentoot:return-code*) hunchentoot:+http-internal-server-error+)
315                      (setf (hunchentoot:content-type*) "text")
316                      (format nil "Condition: \"~a\"" err))))
317                (progn
318                  (setf (hunchentoot:return-code*) hunchentoot:+http-not-found+)
319                  (setf (hunchentoot:content-type*) "text")
320                  (format nil "Topic \"~a\" not found" psi)))))
321        (setf (hunchentoot:return-code*) hunchentoot:+http-bad-request+))))
322
323
324(defun return-json-rdf-fragment(&optional psi)
325  "returns the json-fragmen belonging to the psi passed by the parameter psi"
326  (assert psi)
327  (let ((http-method (hunchentoot:request-method*)))
328    (if (eq http-method :GET)
329        (let ((identifier (string-replace psi "%23" "#")))
330          (setf (hunchentoot:content-type*) "application/json") ;RFC 4627
331          (let ((fragment
332                 (with-reader-lock
333                   (get-latest-fragment-of-topic identifier))))
334            (if fragment
335                (handler-case (with-reader-lock
336                                (rdf-exporter:to-rdf-string fragment))
337                  (condition (err)
338                    (progn
339                      (setf (hunchentoot:return-code*) hunchentoot:+http-internal-server-error+)
340                      (setf (hunchentoot:content-type*) "text")
341                      (format nil "Condition: \"~a\"" err))))
342                (progn
343                  (setf (hunchentoot:return-code*) hunchentoot:+http-not-found+)
344                  (setf (hunchentoot:content-type*) "text")
345                  (format nil "Topic \"~a\" not found" psi)))))
346        (setf (hunchentoot:return-code*) hunchentoot:+http-bad-request+))))
347
348
349(defun json-commit(&optional param)
350  "calls the import-from-isidorus-json method for a json-fragment and
351   imports it to elephant"
352  (declare (ignorable param)) ;param is currently not used
353  (let ((http-method (hunchentoot:request-method*)))
354    (if (or (eq http-method :PUT)
355            (eq http-method :POST))
356        (let ((external-format (flexi-streams:make-external-format :UTF-8 :eol-style :LF)))
357          (let ((json-data (hunchentoot:raw-post-data :external-format external-format :force-text t)))
358            (handler-case
359                (with-writer-lock 
360                  (let ((frag (json-importer:import-from-isidorus-json json-data)))
361                    (when frag
362                      (push-to-cache (d:topic frag)))))
363              (condition (err)
364                (progn
365                  (setf (hunchentoot:return-code*) hunchentoot:+http-internal-server-error+)
366                  (setf (hunchentoot:content-type*) "text")
367                  (format nil "Condition: \"~a\"" err))))))
368        (setf (hunchentoot:return-code*) hunchentoot:+http-bad-request+))))
369
370
371(defun return-topic-summaries(&optional param)
372  "returns a summary of the requested topics"
373  (declare (ignorable param))
374  (let ((start-idx 
375         (handler-case (parse-integer (hunchentoot:get-parameter "start"))
376           (condition () 0)))
377        (end-idx
378         (handler-case (parse-integer (hunchentoot:get-parameter "end"))
379           (condition () nil))))
380    (handler-case (with-reader-lock
381                    (let ((topics 
382                           (elephant:get-instances-by-class 'd:TopicC)))
383                      (let ((end
384                             (cond
385                               ((not end-idx)
386                                (length topics))
387                               ((> end-idx (length topics))
388                                (length topics))
389                               ((< end-idx 0)
390                                0)
391                               (t
392                                end-idx))))
393                        (let ((start
394                               (cond
395                                 ((> start-idx (length topics))
396                                  end)
397                                 ((< start-idx 0)
398                                  0)
399                                 (t
400                                  start-idx))))
401                          (let ((topics-in-range
402                                 (if (<= start end)
403                                     (subseq topics start end)
404                                     (reverse (subseq topics end start)))))
405                            (setf (hunchentoot:content-type*) "application/json") ;RFC 4627
406                            (json-exporter:make-topic-summary topics-in-range))))))
407      (condition (err) (progn
408                         (setf (hunchentoot:return-code*) hunchentoot:+http-internal-server-error+)
409                         (setf (hunchentoot:content-type*) "text")
410                         (format nil "Condition: \"~a\"" err))))))
411
412
413(defun return-overview (&optional param)
414  "Returns a json-object representing a topic map overview as a tree(s)"
415  (declare (ignorable param))
416  (with-reader-lock
417      (handler-case
418          (let ((json-string
419                 (json-tmcl::tree-view-to-json-string
420                  (json-tmcl::make-tree-view :revision 0))))
421            (setf (hunchentoot:content-type*) "application/json") ;RFC 4627
422            json-string)
423        (Condition (err)
424          (progn
425            (setf (hunchentoot:return-code*) hunchentoot:+http-internal-server-error+)
426            (setf (hunchentoot:content-type*) "text")
427            (format nil "Condition: \"~a\"" err))))))
428
429
430(defun mark-as-deleted-handler (&optional param)
431  "Marks the corresponding elem as deleted."
432  (declare (ignorable param)) ;param is currently not used
433  (let ((http-method (hunchentoot:request-method*)))
434    (if (or (eq http-method :DELETE)
435            (eq http-method :POST)) ;not nice - but the current ui-library can't send http-delete messages
436        (let ((external-format (flexi-streams:make-external-format :UTF-8 :eol-style :LF)))
437          (let ((json-data (hunchentoot:raw-post-data :external-format external-format :force-text t)))
438            (handler-case
439                (with-writer-lock
440                  (let ((result (json-delete-interface:mark-as-deleted-from-json
441                                 json-data :revision (d:get-revision))))
442                    (if result
443                        (progn
444                          (when (typep result 'd:TopicC)
445                            (append ;;the append function is used only for suppress
446                                    ;;style warnings of unused delete return values
447                             (delete (elephant::oid result) *type-table*)
448                             (delete (elephant::oid result) *instance-table*)))
449                          (format nil "")) ;operation succeeded
450                        (progn
451                          (setf (hunchentoot:return-code*) hunchentoot:+http-not-found+)
452                          (format nil "object not found")))))
453              (condition (err)
454                (progn
455                  (setf (hunchentoot:return-code*) hunchentoot:+http-internal-server-error+)
456                  (setf (hunchentoot:content-type*) "text")
457                  (format nil "Condition: \"~a\"" err))))))
458        (setf (hunchentoot:return-code*) hunchentoot:+http-bad-request+))))
459
460
461(defun return-latest-revision ()
462  "Returns an integer that represents the latest revision that
463   is used in the storage."
464  (handler-case
465      (if (eql (hunchentoot:request-method*) :GET)
466            (let ((sorted-revisions
467                   (with-reader-lock (sort (d:get-all-revisions) #'>))))
468              (when sorted-revisions
469                (setf (hunchentoot:content-type*) "application/json") ;RFC 4627
470                (format nil "~a" (first sorted-revisions))))
471            (setf (hunchentoot:return-code*) hunchentoot:+http-bad-request+))
472    (condition (err)
473      (progn
474        (setf (hunchentoot:return-code*) hunchentoot:+http-internal-server-error+)
475        (setf (hunchentoot:content-type*) "text")
476        (format nil "Condition: \"~a\"" err)))))
477
478
479(defun xtm-import-handler (&optional tm-id)
480  "Imports the received data as XTM 2.0 topic map."
481  (assert tm-id)
482  (handler-case
483      (if (eql (hunchentoot:request-method*) :POST)
484          (let ((external-format (flexi-streams:make-external-format
485                                  :UTF-8 :eol-style :LF)))
486            (let ((xml-data (hunchentoot:raw-post-data
487                             :external-format external-format
488                             :force-text t)))
489              (let ((xml-dom
490                     (dom:document-element
491                      (cxml:parse xml-data (cxml-dom:make-dom-builder)))))
492                (xtm-importer:importer xml-dom :tm-id tm-id
493                                       :xtm-id (xtm-importer::get-uuid))
494                (format nil ""))))
495          (setf (hunchentoot:return-code*) hunchentoot:+http-bad-request+))
496    (condition (err)
497      (progn
498        (setf (hunchentoot:return-code*) hunchentoot:+http-internal-server-error+)
499        (setf (hunchentoot:content-type*) "text")
500        (format nil "Condition: \"~a\"" err)))))
501
502
503(defun return-tm-sparql (&optional param)
504  "Returns a JSON object representing a SPARQL response."
505  (declare (Ignorable param))
506  (handler-case
507      (if (eql (hunchentoot:request-method*) :POST)
508          (let ((external-format (flexi-streams:make-external-format
509                                  :UTF-8 :eol-style :LF)))
510            (let ((sparql-request (hunchentoot:raw-post-data
511                                   :external-format external-format
512                                   :force-text t)))
513              (export-construct-as-isidorus-json-string
514               (make-instance 'SPARQL-Query :query sparql-request
515                              :revision 0))))
516          (setf (hunchentoot:return-code*) hunchentoot:+http-bad-request+))
517    (condition (err)
518      (progn
519        (setf (hunchentoot:return-code*) hunchentoot:+http-internal-server-error+)
520        (setf (hunchentoot:content-type*) "text")
521        (if (typep err 'SPARQL-Parser-Error)
522            (format nil "SPARQL-Parser-Error: \"~a\"" (exceptions::message err))
523            (format nil "Condition: \"~a\"" err))))))
524
525;; =============================================================================
526;; --- some helper functions ---------------------------------------------------
527;; =============================================================================
528(defun make-file-path-and-url (path-to-files-directory url-prefix)
529  "returns a list of lists which contains an absolute file path and a file-url
530   concatenated of the url-prefix and the relative path of all all files in the
531   passed directory and its subdirectories"
532  (let ((start-position-of-relative-path
533         (- (length (write-to-string (com.gigamonkeys.pathnames:file-exists-p
534                                      path-to-files-directory))) 2)))
535    (let ((files-and-urls nil))
536      (com.gigamonkeys.pathnames:walk-directory
537       path-to-files-directory
538       #'(lambda(current-path)
539           (let ((current-path-string
540                  (write-to-string current-path)))
541             (let ((last-position-of-current-path
542                    (- (length current-path-string) 1)))
543               (let ((current-url
544                      (concat
545                       url-prefix
546                       (subseq current-path-string start-position-of-relative-path
547                               last-position-of-current-path))))
548                 (push (list :path current-path :url current-url) files-and-urls))))))
549      files-and-urls)))
550
551
552(defun init-cache(force-init)
553  "Initializes the type and instance cache-tables with all valid types/instances"
554  (declare (Boolean force-init))
555  (when (or force-init (not *cache-initialised*))
556    (with-writer-lock
557      (setf *type-table* nil)
558      (setf *instance-table* nil)
559      (let ((topictype (get-item-by-psi json-tmcl-constants::*topictype-psi*
560                                        :revision 0))
561            (topictype-constraint (json-tmcl::is-type-constrained :revision 0)))
562        (format t "~%initializing cache: ")
563        (map 'list #'(lambda(top)
564                       (format t ".")
565                       (push-to-cache top topictype topictype-constraint))
566             (elephant:get-instances-by-class 'TopicC))))
567    (setf *cache-initialised* t)))
568
569
570(defun push-to-cache (topic-instance &optional
571                      (topictype
572                       (get-item-by-psi
573                        json-tmcl::*topictype-psi* :revision 0))
574                      (topictype-constraint
575                       (json-tmcl::is-type-constrained :revision 0)))
576  "Pushes the given topic-instance into the correspondng cache-tables"
577  (when (not (json-tmcl::abstract-p topic-instance :revision 0))
578    (handler-case (progn
579                    (json-tmcl::topictype-p
580                     topic-instance topictype topictype-constraint nil 0)
581                    (pushnew (elephant::oid topic-instance) *type-table*))
582      (condition () nil)))
583  (handler-case (progn
584                  (json-tmcl::valid-instance-p topic-instance nil nil 0)
585                  (pushnew (elephant::oid topic-instance) *instance-table*))
586    (condition () nil)))
587
588
589(defun init-fragments (force-init)
590  "Creates fragments of all topics that have a PSI."
591  (declare (Boolean force-init))
592  (when (or force-init (not *fragments-initialised*))
593    (format t "creating fragments: ")
594    (map 'list #'(lambda(top)
595                   (let ((psis-of-top (psis top)))
596                     (when psis-of-top
597                       (format t ".")
598                       (create-latest-fragment-of-topic (uri (first psis-of-top))))))
599         (elephant:get-instances-by-class 'd:TopicC))
600    (setf *fragments-initialised* t)))
Note: See TracBrowser for help on using the repository browser.