source: branches/gdl-frontend/src/json/isidorus-json/json_exporter.lisp

Last change on this file was 470, checked in by lgiessmann, 14 years ago

fixed ticket #111 and adapted all unit-tests

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