source: trunk/src/json/isidorus-json/json_exporter.lisp

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

trunk: datamodel: improved caching of serialized fragments

  • Property svn:eol-style set to native
File size: 16.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(defpackage :json-exporter
11  (:use :cl :json :datamodel :TM-SPARQL :base-tools :constants)
12  (:export :export-construct-as-isidorus-json-string
13           :get-all-topic-psis
14           :to-json-string-summary
15           :make-topic-summary
16           :serialize-fragment))
17
18(in-package :json-exporter)
19
20;; the json schema for our datamodel is in ".../docs/xtm_json.txt"
21
22
23;; =============================================================================
24;; --- main json data model ----------------------------------------------------
25;; =============================================================================
26(defgeneric export-construct-as-isidorus-json-string (instance &key xtm-id revision)
27  (:documentation "converts the Topic Map construct instance to a json string"))
28
29
30(defun identifiers-to-json-string (parent-construct &key (what 'd:psis)
31                                   (revision *TM-REVISION*))
32  "returns the identifiers of a TopicMapConstructC as a json list"
33  (declare (TopicMapConstructC parent-construct)
34           (symbol what)
35           (type (or integer null) revision))
36  (when (and parent-construct
37             (or (eql what 'psis)
38                 (eql what 'item-identifiers)
39                 (eql what 'locators)))
40    (let ((items
41           (map 'list #'uri
42                (funcall what parent-construct :revision revision))))
43      (json:encode-json-to-string items))))
44
45
46(defun resourceX-to-json-string (value datatype &key (xtm-id d:*current-xtm*))
47  "returns a resourceRef and resourceData json object"
48  (if (string= datatype "http://www.w3.org/2001/XMLSchema#anyURI")
49      (concat "\"resourceRef\":"                   
50              (let ((inner-value
51                     (let ((ref-topic
52                            (when (and (> (length value) 0)
53                                       (eql (elt value 0) #\#))
54                              (get-item-by-id (subseq value 1) :xtm-id xtm-id))))
55                       (if ref-topic
56                           (concat "#" (topic-id ref-topic))
57                           value))))
58                (json:encode-json-to-string inner-value))
59              ",\"resourceData\":null")
60      (concat "\"resourceRef\":null,"
61              "\"resourceData\":{\"datatype\":"
62              (json:encode-json-to-string datatype)
63              ",\"value\":"
64              (json:encode-json-to-string value) "}")))
65
66
67(defun ref-topics-to-json-string (topics &key (revision *TM-REVISION*))
68  "returns a json string of all psi-uris of the passed topics as a list of lists"
69  (declare (list topics)
70           (type (or integer null) revision))
71  (if topics
72      (let ((psis (json:encode-json-to-string
73                   (map 'list #'(lambda(topic)
74                                  (declare (topicC topic))
75                                  (map 'list #'uri (psis topic :revision revision)))
76                        topics))))
77        (declare (list topics))
78        psis)
79      "null"))
80
81
82(defun type-to-json-string (parent-elem &key (revision *TM-REVISION*))
83  "returns a json string of the type of the passed parent-elem"
84  (declare (TypableC parent-elem)
85           (type (or integer null) revision))
86  (concat "\"type\":"
87          (if (instance-of parent-elem :revision revision)
88              (json:encode-json-to-string
89               (map 'list #'uri (psis (instance-of parent-elem :revision revision)
90                                      :revision revision)))
91              "null")))
92
93
94(defmethod export-construct-as-isidorus-json-string
95    ((instance VariantC) &key (xtm-id d:*current-xtm*)
96     (revision *TM-REVISION*))
97  "transforms a VariantC object to a json string"
98  (declare (type (or string null) xtm-id)
99           (type (or integer null) revision))
100  (let ((itemIdentity
101         (concat "\"itemIdentities\":"
102                 (identifiers-to-json-string instance :what 'item-identifiers
103                                             :revision revision)))
104        (scope
105         (concat "\"scopes\":"
106                 (ref-topics-to-json-string
107                  (set-difference (themes instance :revision revision)
108                                  (when-do name (parent instance :revision revision)
109                                           (themes name :revision revision)))
110                  :revision revision)))
111        (resourceX
112         (let ((value
113                (when (slot-boundp instance 'charvalue)
114                  (charvalue instance)))
115               (type
116                (when (slot-boundp instance 'datatype)
117                  (datatype instance))))
118           (resourceX-to-json-string value type :xtm-id xtm-id))))
119    (concat "{" itemIdentity "," scope "," resourceX "}")))
120
121
122(defmethod export-construct-as-isidorus-json-string
123    ((instance NameC) &key (xtm-id d:*current-xtm*)
124     (revision *TM-REVISION*))
125  "transforms a NameC object to a json string"
126  (declare (type (or string null) xtm-id)
127           (type (or integer null) revision))
128  (let ((itemIdentity
129         (concat "\"itemIdentities\":"
130                 (identifiers-to-json-string instance :what 'item-identifiers
131                                             :revision revision)))
132        (type
133         (if (eql (instance-of instance :revision revision)
134                  (get-item-by-psi *topic-name-psi* :revision revision))
135             "\"type\":null"
136             (type-to-json-string instance :revision revision)))
137        (scope
138         (concat "\"scopes\":"
139                 (ref-topics-to-json-string (themes instance :revision revision)
140                                            :revision revision)))
141        (value
142         (concat "\"value\":"
143                 (if (slot-boundp instance 'charvalue)
144                     (json:encode-json-to-string (charvalue instance))
145                     "null")))
146        (variant
147         (if (variants instance :revision revision)
148             (concat
149              "\"variants\":"
150              (let ((j-variants "["))
151                (loop for variant in (variants instance :revision revision)
152                   do (push-string
153                       (concat (export-construct-as-isidorus-json-string
154                                variant :xtm-id xtm-id :revision revision)
155                               ",")
156                       j-variants))
157                (concat (subseq j-variants 0 (- (length j-variants) 1)) "]")))
158             (concat "\"variants\":null"))))
159    (concat "{" itemIdentity "," type "," scope "," value "," variant "}")))
160
161
162(defmethod export-construct-as-isidorus-json-string
163    ((instance OccurrenceC) &key (xtm-id d:*current-xtm*)
164     (revision *TM-REVISION*))
165  "transforms an OccurrenceC object to a json string"
166  (declare (type (or string null) xtm-id)
167           (type (or integer null) revision))
168  (let ((itemIdentity
169         (concat "\"itemIdentities\":"
170                 (identifiers-to-json-string instance :what 'item-identifiers
171                                             :revision revision)))
172        (type
173         (type-to-json-string instance :revision revision))
174        (scope
175         (concat "\"scopes\":"
176                 (ref-topics-to-json-string (themes instance :revision revision)
177                                            :revision revision)))
178        (resourceX
179         (let ((value
180                (when (slot-boundp instance 'charvalue)
181                  (charvalue instance)))
182               (type
183                (when (slot-boundp instance 'datatype)
184                  (datatype instance))))
185           (resourceX-to-json-string value type :xtm-id xtm-id))))
186    (concat "{" itemIdentity "," type "," scope "," resourceX "}")))
187
188
189(defmethod export-construct-as-isidorus-json-string
190    ((instance TopicC) &key (xtm-id d:*current-xtm*)
191     (revision *TM-REVISION*))
192  "transforms an TopicC object to a json string"
193  (declare (type (or string null) xtm-id)
194           (type (or integer null) revision))
195  (let ((id
196         (concat "\"id\":"
197                 (json:encode-json-to-string (topic-id instance revision))))
198        (itemIdentity
199         (concat "\"itemIdentities\":"
200                 (identifiers-to-json-string instance :what 'item-identifiers
201                                             :revision revision)))
202        (subjectLocator 
203         (concat "\"subjectLocators\":"
204                 (identifiers-to-json-string instance :what 'locators
205                                             :revision revision)))
206        (subjectIdentifier
207         (concat "\"subjectIdentifiers\":"
208                 (identifiers-to-json-string instance :what 'psis
209                                             :revision revision)))
210        (instanceOf
211         (concat "\"instanceOfs\":"
212                 (ref-topics-to-json-string
213                  (list-instanceOf instance :revision revision)
214                  :revision revision)))
215        (name
216         (concat "\"names\":"
217                 (if (names instance :revision revision)
218                     (let ((j-names "["))
219                       (loop for item in (names instance :revision revision)
220                          do (push-string
221                              (concat
222                               (export-construct-as-isidorus-json-string
223                                item :xtm-id xtm-id
224                                :revision revision) ",")
225                              j-names))
226                       (concat (subseq j-names 0 (- (length j-names) 1)) "]"))
227                     "null")))
228        (occurrence
229         (concat
230          "\"occurrences\":"
231          (if (occurrences instance :revision revision)
232              (let ((j-occurrences "["))
233                (loop for item in (occurrences instance :revision revision)
234                   do (push-string
235                       (concat
236                        (export-construct-as-isidorus-json-string
237                         item :xtm-id xtm-id :revision revision)
238                        ",")
239                       j-occurrences))
240                (concat (subseq j-occurrences 0 (- (length j-occurrences) 1)) "]"))
241              "null"))))
242    (concat "{" id "," itemIdentity "," subjectLocator "," subjectIdentifier ","
243            instanceOf "," name "," occurrence "}")))
244
245
246(defun to-json-topicStub-string (topic &key (revision *TM-REVISION*))
247  "transforms the passed TopicC object to a topic stub
248   string in the json format, which contains an id,
249   all itemIdentities, all subjectLocators and all
250   subjectIdentifiers"
251  (declare (type (or TopicC null) topic)
252           (type (or integer null) revision))
253  (when topic
254    (let ((id
255           (concat "\"id\":"
256                   (json:encode-json-to-string (topic-id topic revision))))
257          (itemIdentity
258           (concat "\"itemIdentities\":"
259                   (identifiers-to-json-string topic :what 'item-identifiers
260                                               :revision revision)))
261          (subjectLocator 
262           (concat "\"subjectLocators\":"
263                   (identifiers-to-json-string topic :what 'locators :revision revision)))
264          (subjectIdentifier
265           (concat "\"subjectIdentifiers\":"
266                   (identifiers-to-json-string topic :what 'psis :revision revision))))
267      (concat "{" id "," itemIdentity "," subjectLocator "," subjectIdentifier "}"))))
268
269
270(defmethod export-construct-as-isidorus-json-string
271    ((instance RoleC) &key (xtm-id d:*current-xtm*)
272     (revision *TM-REVISION*))
273  "transforms an RoleC object to a json string"
274  (declare (ignorable xtm-id)
275           (type (or integer null) revision))
276  (let ((itemIdentity
277         (concat "\"itemIdentities\":"
278                 (identifiers-to-json-string instance :what 'item-identifiers
279                                             :revision revision)))
280        (type
281         (type-to-json-string instance :revision revision))
282        (topicRef
283         (concat "\"topicRef\":"
284                 (if (player instance :revision revision)
285                     (json:encode-json-to-string
286                      (map 'list #'uri (psis (player instance :revision revision)
287                                             :revision revision)))
288                     "null"))))
289    (concat "{" itemIdentity "," type "," topicRef "}")))
290
291
292(defmethod export-construct-as-isidorus-json-string
293    ((instance AssociationC) &key (xtm-id d:*current-xtm*)
294     (revision *TM-REVISION*))
295  "transforms an AssociationC object to a json string"
296  (let ((itemIdentity
297         (concat "\"itemIdentities\":"
298                 (identifiers-to-json-string instance :what 'item-identifiers
299                                             :revision revision)))
300        (type
301         (type-to-json-string instance :revision revision))
302        (scope
303         (concat "\"scopes\":"
304                 (ref-topics-to-json-string (themes instance :revision revision)
305                                            :revision revision)))
306        (role
307         (concat "\"roles\":"
308                 (if (roles instance :revision revision)
309                     (let ((j-roles "["))
310                       (loop for item in (roles instance :revision revision)
311                          do (push-string
312                              (concat
313                               (export-construct-as-isidorus-json-string
314                                item :xtm-id xtm-id
315                                :revision revision) ",")
316                              j-roles))
317                       (concat (subseq j-roles 0 (- (length j-roles) 1)) "]"))
318                     "null"))))
319    (concat "{" itemIdentity "," type "," scope "," role "}")))
320
321
322(defmethod export-construct-as-isidorus-json-string
323    ((instance TopicMapC) &key (xtm-id d:*current-xtm*)
324     (revision *TM-REVISION*))
325  "returns the ItemIdentifier's uri"
326  (declare (ignorable xtm-id)
327           (type (or integer null) revision))
328  (let ((ii (item-identifiers instance :revision revision)))
329    (when ii
330      (uri (first ii)))))
331
332
333(defmethod export-construct-as-isidorus-json-string
334    ((instance FragmentC) &key (xtm-id d:*current-xtm*)
335     (revision *TM-REVISION*))
336  "transforms an FragmentC object to a json string,
337   which contains the main topic, all depending topicStubs
338   and all associations depending on the main topic"
339  (declare (type (or string null) xtm-id)
340           (type (or integer null) revision))
341  (let ((main-topic
342         (concat "\"topic\":"
343                 (export-construct-as-isidorus-json-string
344                  (topic instance) :xtm-id xtm-id :revision revision)))
345        (topicStubs
346         (concat "\"topicStubs\":"
347                 (if (referenced-topics instance)
348                     (let ((j-topicStubs "["))
349                       (loop for item in (referenced-topics instance)
350                          do (push-string
351                              (concat (to-json-topicStub-string item :revision revision)
352                                      ",")
353                              j-topicStubs))
354                       (concat (subseq j-topicStubs 0 (- (length j-topicStubs) 1)) "]"))
355                     "null")))
356        (associations
357         (let ((filtered-assocs
358                (remove-null
359                 (map 'list #'(lambda(assoc)
360                                (when (find-item-by-revision assoc revision)
361                                  assoc))
362                      (associations instance)))))
363           (concat "\"associations\":"
364                   (if filtered-assocs
365                       (let ((j-associations "["))
366                         (loop for item in filtered-assocs
367                            do (push-string
368                                (concat (export-construct-as-isidorus-json-string
369                                         item :xtm-id xtm-id
370                                         :revision revision) ",")
371                                j-associations))
372                         (concat (subseq j-associations 0
373                                         (- (length j-associations) 1)) "]"))
374                       "null"))))
375        (tm-ids
376         (concat "\"tmIds\":"
377                 (let ((uris
378                        (loop for tm in (in-topicmaps (topic instance))
379                           collect (when (item-identifiers tm)
380                                     (uri (first (item-identifiers
381                                                  tm :revision revision)))))))
382                   (json:encode-json-to-string uris)))))
383    (concat "{" main-topic "," topicStubs "," associations "," tm-ids "}")))
384
385
386;; =============================================================================
387;; --- json data summeries -----------------------------------------------------
388;; =============================================================================
389(defun get-all-topic-psis(&key (revision *TM-REVISION*))
390  "returns all topic psis as a json list of the form
391   [[topic-1-psi-1, topic-1-psi-2],[topic-2-psi-1, topic-2-psi-2],...]"
392  (declare (type (or integer null) revision))
393  (let ((psi-lists
394         (map 'list (lambda(top)
395                      (when (d:find-item-by-revision top revision)
396                        (let ((psis (d:psis top :revision revision)))
397                          (when psis
398                            (map 'list #'d:uri psis)))))
399              (elephant:get-instances-by-class 'd:TopicC))))
400    (json:encode-json-to-string (tools:remove-null psi-lists))))
401
402
403(defun to-json-string-summary (topic &key (revision *TM-REVISION*))
404  "creates a json string of called topic element. the following elements are within this
405   summary:
406    *topic id
407    *all identifiers
408    *names (only the real name value)
409    *occurrences (jonly the resourceRef and resourceData elements)"
410  (declare (TopicC topic)
411           (type (or integer null) revision))
412  (let ((id
413         (concat "\"id\":\"" (topic-id topic revision) "\""))
414        (itemIdentity
415         (concat "\"itemIdentities\":"
416                 (identifiers-to-json-string topic :what 'item-identifiers
417                                             :revision revision)))
418        (subjectLocator 
419         (concat "\"subjectLocators\":"
420                 (identifiers-to-json-string topic :what 'locators :revision revision)))
421        (subjectIdentifier
422         (concat "\"subjectIdentifiers\":"
423                 (identifiers-to-json-string topic :what 'psis :revision revision)))
424        (instanceOf
425         (concat "\"instanceOfs\":"
426                 (ref-topics-to-json-string (list-instanceOf topic :revision revision)
427                                            :revision revision)))
428        (name
429         (concat "\"names\":"
430                 (if (names topic :revision revision)
431                     (json:encode-json-to-string
432                      (loop for name in (names topic :revision revision)
433                         when (slot-boundp name 'charvalue)
434                         collect (charvalue name)))
435                     "null")))
436        (occurrence
437         (concat "\"occurrences\":"
438                 (if (occurrences topic :revision revision)
439                     (json:encode-json-to-string
440                      (loop for occurrence in (occurrences topic :revision revision)
441                         when (slot-boundp occurrence 'charvalue)
442                         collect (charvalue occurrence)))
443                     "null"))))
444    (concat "{" id "," itemIdentity "," subjectLocator "," subjectIdentifier
445            "," instanceOf "," name "," occurrence "}")))
446
447
448(defun make-topic-summary (topic-list &key (revision *TM-REVISION*))
449  "creates a json list of the produced json-strings by to-json-string-summary"
450  (declare (list topic-list)
451           (type (or integer null) revision))
452  (if topic-list
453      (let ((json-string
454             (let ((inner-string nil))
455               (loop for topic in topic-list
456                  do (push-string 
457                      (concat (to-json-string-summary topic :revision revision) ",")
458                      inner-string))
459               (subseq inner-string 0 (- (length inner-string) 1)))))
460        (concat "[" json-string "]"))
461      "null"))
462
463
464;; =============================================================================
465;; --- json data sparql-results ------------------------------------------------
466;; =============================================================================
467
468(defmethod export-construct-as-isidorus-json-string
469    ((construct SPARQL-Query) &key xtm-id revision)
470  "Returns a JSON string that represents the object query result."
471  (declare (Ignorable revision xtm-id))
472  (let ((query-result (result construct)))
473    (if (not query-result)
474        "null"
475        (let ((j-str "{"))
476          (loop for entry in query-result
477             do (push-string
478                 (concat
479                  (json:encode-json-to-string (getf entry :variable)) ":"
480                  (json:encode-json-to-string (getf entry :result)) ",")
481                 j-str))
482          (concat (subseq j-str 0 (- (length j-str) 1)) "}")))))
Note: See TracBrowser for help on using the repository browser.