source: trunk/src/json/JTM/jtm_tools.lisp

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

trunk: merged branches/gdl-frontend with trunk; fixed all conflicts

File size: 13.7 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(defpackage :jtm
11  (:use :cl :json :datamodel :base-tools :isidorus-threading
12        :constants :exceptions)
13  (:export :import-from-jtm
14           :import-construct-from-jtm-decoded-list
15           :import-construct-from-jtm-string
16           :export-as-jtm
17           :export-as-jtm-string
18           :export-construct-as-jtm-string
19           :item_type-topicmap
20           :item_type-topic
21           :item_type-name
22           :item_type-variant
23           :item_type-occurrence
24           :item_type-association
25           :item_type-role))
26
27(in-package :jtm)
28
29(defvar item_type-topicmap "topicmap")
30
31(defvar item_type-topic "topic")
32
33(defvar item_type-name "name")
34
35(defvar item_type-variant "variant")
36
37(defvar item_type-occurrence "occurrence")
38
39(defvar item_type-association "association")
40
41(defvar item_type-role "role")
42
43
44(defgeneric create-prefix-list-for-construct (construct &key revision)
45  (:documentation "Returns a list of the following structure:
46                   ((:pref 'pref_1' :value 'uri-pref') (...))."))
47
48
49(defun compute-full-uri (prefix-list prefix-name suffix)
50  "Returns a full uri if the prefix-name can found in an item of the form
51   (:pref 'prefix-name' :value 'uri-value/'), the returnvalue would be of
52   the form uri-value/suffix. Otherwise the return value is nil."
53  (declare (List prefix-list)
54           (String prefix-name suffix))
55  (if (= (length suffix) 0)
56      (error (make-condition 'JTM-error :message (format nil "From compute-full-uri(): suffix must no be of length 0, but is \"~a\"" suffix)))
57      (let ((result (loop for item in prefix-list
58                       when (string= (getf item :pref) prefix-name)
59                       return (concat (getf item :value) suffix))))
60        (if result
61            result
62            (error (make-condition 'JTM-error :message (format nil "From compute-full-uri(): prefix \"~a\" not found in the available prefixes \"~a\"" prefix-name prefix-list)))))))
63
64
65(defun export-construct-as-jtm-string (construct &key (revision (get-revision))
66                                       (jtm-format :1.1) (parent-p t))
67  "Exports a name variant as JTM string.
68   jtm-format must be set either to :1.0 or :1.1."
69  (declare (Symbol jtm-format)
70           (Integer revision)
71           (Boolean parent-p)
72           (type (or ReifiableConstructC FragmentC) construct))
73  (with-reader-lock
74    (let* ((prefixes
75            (when (eql jtm-format :1.1)
76              (create-prefix-list-for-construct construct :revision revision)))
77           (prefixes-p (cond ((eql jtm-format :1.1) t)
78                             ((eql jtm-format :1.0) nil)
79                             (t (error (make-condition 'JTM-error :message (format nil "From export-construct-as-jtm-string(): jtm-format must be set to :1.1 or :1.0, but is ~a" jtm-format))))))
80           (version (concat "\"" (symbol-name jtm-format) "\""))
81           (json-str
82            (if (typep construct 'TopicC)
83                (export-to-jtm construct :parent-p parent-p :prefixes prefixes
84                               :prefixes-p prefixes-p :revision revision
85                               :instance-of-p (eql jtm-format :1.1))
86                (export-to-jtm construct :parent-p parent-p :prefixes prefixes
87                               :prefixes-p prefixes-p :revision revision))))
88      (concat "{\"version\":" version "," (subseq json-str 1)))))
89
90
91(defun export-as-jtm-string (&key tm-id (revision (get-revision))
92                             (jtm-format :1.1))
93  "Exports a topic map or all stored constructs as JTM string.
94   jtm-format must be set either to :1.0 or :1.1."
95  (declare (type (or Null String) tm-id)
96           (Symbol jtm-format)
97           (Integer revision))
98  (with-reader-lock
99    (let ((tm 
100           (when tm-id
101             (get-item-by-item-identifier tm-id :revision revision)))
102          (version-1.1-p (eq jtm-format :1.1)))
103      (let* ((tm-tops
104              (if tm
105                  (let ((inner-tops
106                         (delete-if #'(lambda(top)
107                                        (not (find-item-by-revision top revision)))
108                                    (topics tm))))
109                    (if (eql jtm-format :1.1)
110                        (filter-type-instance-topics inner-tops tm
111                                                     :revision revision)
112                        inner-tops))
113                  (get-all-topics revision)))
114             (tm-assocs
115              ;(xtm-exporter::list-extern-associations :revision revision))
116              (let ((assocs
117                     (if tm
118                         (delete-if #'(lambda(assoc)
119                                        (not (find-item-by-revision assoc revision)))
120                                    (associations tm))
121                         (get-all-associations revision))))
122                (if version-1.1-p
123                    (set-difference
124                     assocs
125                     (loop for top in tm-tops
126                        append (instance-of-associations top :revision revision)))
127                    assocs)))
128             (prefixes
129              (when version-1.1-p
130                (create-prefix-list-for-tm tm-tops tm-assocs tm :revision revision)))
131             (version (if version-1.1-p
132                          "\"version\":\"1.1\","
133                          "\"version\":\"1.0\","))
134             (prefix-value (when version-1.1-p
135                              (concat "\"prefixes\":"
136                                      (export-prefix-list-to-jtm prefixes) ",")))
137             (iis (concat "\"item_identifiers\":"
138                          (if tm
139                              (export-identifiers-to-jtm
140                               tm :identifier-type 'ItemIdentifierC :prefixes prefixes
141                               :revision revision)
142                              "null") ","))
143             (topics (concat "\"topics\":"
144                             (export-topics-to-jtm
145                              tm-tops :prefixes prefixes :instance-of-p version-1.1-p
146                              :item-type-p nil :revision revision) ","))
147             (assocs (concat "\"associations\":"
148                             (export-associations-to-jtm
149                              tm-assocs :prefixes prefixes
150                              :item-type-p nil :revision revision) ","))
151             (item-type (concat "\"item_type\":\"" item_type-topicmap "\","))
152             (tm-reifier
153              (concat "\"reifier\":"
154                      (if tm
155                          (export-reifier-to-jtm tm :prefixes prefixes
156                                                 :revision revision)
157                          "null"))))
158        (concat "{" version prefix-value iis topics assocs item-type tm-reifier 
159                "}")))))
160             
161             
162
163(defun export-as-jtm (jtm-path &key tm-id (revision (get-revision))
164                      (jtm-format :1.1))
165  "Exports a topic map or all stored constructs as JTM file by calling
166   export-as-jtm-string."
167  (declare (type (or Null String) tm-id)
168           (type (or String Pathname) jtm-path)
169           (Symbol jtm-format)
170           (Integer revision))
171  (with-open-file (stream jtm-path :direction :output)
172    (format stream (export-as-jtm-string :tm-id tm-id :revision revision
173                                         :jtm-format jtm-format))))
174
175
176(defun export-prefix-list-to-jtm (prefix-list)
177  "Returns a json object that represent an object with namespaces and their
178   prefix qualifiers."
179  (declare (List prefix-list))
180  (if prefix-list
181      (let ((result "{"))
182        (loop for item in prefix-list
183           do (push-string
184               (concat "\"" (getf item :pref) "\":"
185                       (json:encode-json-to-string (getf item :value)) ",")
186               result))
187        (concat (subseq result 0 (1- (length result))) "}"))
188      "null"))
189
190
191(defun create-prefix-list-for-tm (topics associations topic-map &key
192                           (revision *TM-REVISION*))
193  "Returns a list of the following structure: ((:pref 'pref_1'
194   :value 'uri-pref') (...))."
195  (declare (List topics associations)
196           (type (or Null TopicMapC) topic-map)
197           (Integer revision))
198  (let ((identifiers
199         (append (loop for topic in topics
200                    append
201                      (append
202                       (get-all-identifiers-of-construct topic :revision revision)
203                       (loop for name in (names topic :revision revision)
204                          append (append
205                                  (item-identifiers name :revision revision)
206                                  (loop for variant in
207                                       (variants name :revision revision)
208                                     append (append
209                                             (item-identifiers
210                                              variant :revision revision)))))
211                       (loop for occ in (occurrences topic :revision revision)
212                          append (append
213                                  (item-identifiers occ :revision revision)))))
214                 (loop for assoc in associations
215                    append (append
216                            (item-identifiers assoc :revision revision)
217                            (loop for role in (roles assoc :revision revision)
218                               append (item-identifiers role :revision revision))))
219                 (when topic-map
220                   (item-identifiers topic-map :revision revision)))))
221    (create-prefix-list-of-identifiers identifiers)))
222
223
224(defun create-prefix-list-of-identifiers (identifiers)
225  "Returns a list of the following structure: ((:pref 'pref_1'
226   :value 'uri-pref') (...)) the list identifiers can own items of
227   the type IdentifierC and of the form (list :pref 'pref' :value 'value')."
228  (declare (List identifiers))
229  (let ((prefixes
230         (remove-duplicates
231          (remove-null (map 'list  #'(lambda(id)
232                                       (if (typep id 'IdentifierC)
233                                           (prefix-of-uri (uri id))
234                                           (getf id :value)))
235                            identifiers)) :test #'string=)))
236    (let ((result
237           (append
238            (loop for idx to (1- (length prefixes))
239               collect (list :pref (concat "pref_" (write-to-string (1+ idx)))
240                             :value (elt prefixes idx)))
241            (list (list :pref "xsd" :value *xsd-ns*)))))
242      (sort result #'(lambda(x y)
243                       (> (length (getf x :value)) (length (getf y :value))))))))
244
245
246
247(defmethod create-prefix-list-for-construct ((construct FragmentC) &key
248                                             (revision *TM-REVISION*))
249  (declare (Integer revision))
250  (create-prefix-list-for-tm (append (list (topic construct))
251                                     (referenced-topics construct))
252                             (associations construct) nil :revision revision))
253
254
255(defmethod create-prefix-list-for-construct ((construct VariantC) &key
256                                             (revision *TM-REVISION*))
257  (declare (Integer revision))
258  (let ((identifiers
259         (append
260          (loop for scope in (themes construct :revision revision)
261             append (get-all-identifiers-of-construct scope :revision revision))
262          (when (parent construct :revision revision)
263            (get-all-identifiers-of-construct
264             (parent construct :revision revision) :revision revision))
265          (when (reifier construct :revision revision)
266            (get-all-identifiers-of-construct
267             (reifier construct :revision revision))))))
268    (create-prefix-list-of-identifiers identifiers)))
269
270
271(defmethod create-prefix-list-for-construct ((construct NameC) &key
272                                             (revision *TM-REVISION*))
273  (declare (Integer revision))
274  (let ((identifiers
275         (append
276          (loop for scope in (themes construct :revision revision)
277             append (get-all-identifiers-of-construct scope :revision revision))
278          (when (parent construct :revision revision)
279            (get-all-identifiers-of-construct
280             (parent construct :revision revision) :revision revision))
281          (loop for var in (variants construct :revision revision)
282             append (create-prefix-list-for-construct var :revision revision))
283          (when (reifier construct :revision revision)
284            (get-all-identifiers-of-construct
285             (reifier construct :revision revision)))
286          (when (instance-of construct :revision revision)
287            (get-all-identifiers-of-construct
288             (instance-of construct :revision revision))))))
289    (create-prefix-list-of-identifiers identifiers)))
290
291
292(defmethod create-prefix-list-for-construct ((construct OccurrenceC) &key
293                                             (revision *TM-REVISION*))
294  (declare (Integer revision))
295  (let ((identifiers
296         (append
297          (loop for scope in (themes construct :revision revision)
298             append (get-all-identifiers-of-construct scope :revision revision))
299          (when (parent construct :revision revision)
300            (get-all-identifiers-of-construct
301             (parent construct :revision revision) :revision revision))
302          (when (reifier construct :revision revision)
303            (get-all-identifiers-of-construct
304             (reifier construct :revision revision)))
305          (when (instance-of construct :revision revision)
306            (get-all-identifiers-of-construct
307             (instance-of construct :revision revision))))))
308    (create-prefix-list-of-identifiers identifiers)))
309
310
311(defmethod create-prefix-list-for-construct ((construct RoleC) &key
312                                             (revision *TM-REVISION*))
313  (declare (Integer revision))
314  (let ((identifiers
315         (append
316          (when (parent construct :revision revision)
317            (get-all-identifiers-of-construct
318             (parent construct :revision revision) :revision revision))
319          (when (reifier construct :revision revision)
320            (get-all-identifiers-of-construct
321             (reifier construct :revision revision)))
322          (when (player construct :revision revision)
323            (get-all-identifiers-of-construct
324             (player construct :revision revision)))
325          (when (instance-of construct :revision revision)
326            (get-all-identifiers-of-construct
327             (instance-of construct :revision revision))))))
328    (create-prefix-list-of-identifiers identifiers)))
329
330
331(defmethod create-prefix-list-for-construct ((construct AssociationC) &key
332                                             (revision *TM-REVISION*))
333  (declare (Integer revision))
334  (let ((identifiers
335         (append
336          (loop for tm in (in-topicmaps construct :revision revision)
337             append (get-all-identifiers-of-construct tm :revision revision))
338          (when (reifier construct :revision revision)
339            (get-all-identifiers-of-construct
340             (reifier construct :revision revision)))
341          (when (instance-of construct :revision revision)
342            (get-all-identifiers-of-construct
343             (instance-of construct :revision revision)))
344          (loop for scope in (themes construct :revision revision)
345             append (get-all-identifiers-of-construct construct
346                                                      :revision revision))
347          (loop for role in (roles construct :revision revision)
348             append (create-prefix-list-for-construct role :revision revision)))))
349    (create-prefix-list-of-identifiers identifiers)))
350
351
352(defmethod create-prefix-list-for-construct ((construct TopicC) &key
353                                             (revision *TM-REVISION*))
354  (declare (Integer revision))
355  (let ((identifiers
356         (append
357          (get-all-identifiers-of-construct construct :revision revision)
358          (loop for occ in (occurrences construct :revision revision)
359             append (create-prefix-list-for-construct occ :revision revision))
360          (loop for name in (names construct :revision revision)
361             append (create-prefix-list-for-construct name :revision revision))
362          (loop for top in (list-instanceof construct :revision revision)
363             append (get-all-identifiers-of-construct top :revision revision)))))
364    (create-prefix-list-of-identifiers identifiers)))
Note: See TracBrowser for help on using the repository browser.