source: trunk/src/json/JTM/jtm_importer.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: 29.4 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
11(in-package :jtm)
12
13(defun get-item (item-keyword jtm-list)
14  (declare (Keyword item-keyword)
15           (List jtm-list))
16  (rest (find item-keyword jtm-list :key #'first)))
17
18
19(defun make-prefix-list-from-jtm-list (jtm-list)
20  "Creates a plist of the form ((:pref 'pref_1' :value 'value-1')
21   (:pref 'pref_2' :value 'value-2')) if the passed jtm-list is
22   of the form ((:PREF--1 . 'value-1')(:PREF--2 . 'value-2'))."
23  (declare (List jtm-list))
24  (loop for item in jtm-list
25     collect (list :pref (json:lisp-to-camel-case
26                          (subseq (write-to-string (first item)) 1))
27                   :value (rest item))))
28
29
30(defun import-construct-from-jtm-string (jtm-string &key
31                                         (revision *TM-REVISION*)
32                                         (jtm-format :1.1) tm-id
33                                         (create-fragments nil))
34  "Imports the passed jtm-string.
35   Note tm-id needs not to be declared, but if the imported construct
36   is a topicmap and it has no item-identifiers defined, a JTM-error
37   is thrown."
38  (declare (String jtm-string)
39           (type (or Null String) tm-id)
40           (Integer revision)
41           (Keyword jtm-format)
42           (Boolean create-fragments))
43  (let* ((jtm-list (json:decode-json-from-string jtm-string)))
44    (import-construct-from-jtm-decoded-list
45     jtm-list :revision revision :jtm-format jtm-format
46     :tm-id tm-id :create-fragments create-fragments)))
47
48
49(defun import-construct-from-jtm-decoded-list (jtm-list &key
50                                               (revision *TM-REVISION*)
51                                               (jtm-format :1.1) tm-id
52                                               (create-fragments nil))
53  "Imports the passed jtm-decoded-list.
54   Note tm-id needs not to be declared, but if the imported construct
55   is a topicmap and it has no item-identifiers defined, a JTM-error
56   is thrown."
57  (declare (List jtm-list)
58           (Integer revision)
59           (Keyword jtm-format)
60           (type (or Null String) tm-id)
61           (Boolean create-fragments))
62  (let* ((version (get-item :VERSION jtm-list))
63         (item_type (get-item :ITEM--TYPE jtm-list))
64         (prefixes (make-prefix-list-from-jtm-list (get-item :PREFIXES jtm-list)))
65         (format-1.1-p (eql jtm-format :1.1)))
66    (cond ((eql jtm-format :1.0)
67           (unless (string= version "1.0")
68             (error (make-condition 'exceptions:JTM-error :message (format nil "From import-construct-from-jtm-decoded-list(): the member version must be set to \"1.0\" in JTM version 1.0, but is ~a" version))))
69           (when prefixes
70             (error (make-condition 'exceptions:JTM-error :message (format nil "From import-construct-from-jtm-decoded-list(): the member prefixes must not be set when using JTM version 1.0, but found: ~a" prefixes)))))
71          ((eql jtm-format :1.1)
72           (unless (string= version "1.1")
73             (error (make-condition 'exceptions:JTM-error :message (format nil "From import-construct-from-jtm-decoded-list(): the member version must be set to \"1.1\" in JTM version 1.1, but is ~a" version)))))
74          (t
75           (error (make-condition 'exceptions:JTM-error :message (format nil "From import-construct-from-jtm-decoded-list(): only JTM format \"1.0\" and \"1.1\" is supported, but found: \"~a\"" jtm-format)))))
76    (cond ((or (not item_type)
77               (string= item_type item_type-topicmap))
78           (import-topic-map-from-jtm-list
79            jtm-list tm-id :revision revision :prefixes prefixes
80            :instance-of-p format-1.1-p :create-fragments create-fragments))
81          ((string= item_type item_type-topic)
82           (import-topic-stub-from-jtm-list jtm-list nil :revision revision
83                                            :prefixes prefixes)
84           (merge-topic-from-jtm-list jtm-list :instance-of-p format-1.1-p
85                                      :revision revision :prefixes prefixes
86                                      :create-fragment create-fragments))
87          ((string= item_type item_type-name)
88           (import-name-from-jtm-list jtm-list nil :revision revision
89                                      :prefixes prefixes))
90          ((string= item_type item_type-variant)
91           (import-variant-from-jtm-list jtm-list nil :revision revision
92                                         :prefixes prefixes))
93          ((string= item_type item_type-occurrence)
94           (import-occurrence-from-jtm-list jtm-list nil :revision revision
95                                            :prefixes prefixes))
96          ((string= item_type item_type-role)
97           (import-role-from-jtm-list jtm-list nil :revision revision
98                                      :prefixes prefixes))
99          ((string= item_type item_type-association)
100          (import-association-from-jtm-list jtm-list nil :revision revision
101                                            :prefixes prefixes))
102          (t
103           (error (make-condition 'exceptions:JTM-error :message (format nil "From import-construct-from-jtm-decoded-list(): the member \"item_type\" must be set to one of ~a or nil, but found \"~a\". If \"item_type\" is not specified or nil the JTM-data is treated as a topicmap." item_type (list item_type-topicmap item_type-topic item_type-name item_type-variant item_type-occurrence item_type-role item_type-association))))))))
104
105
106(defun import-from-jtm (jtm-path repository-path &key (tm-id (error "you must provide a stable identifier (PSI-style) for this TM")) (revision *TM-REVISION*) (jtm-format :1.1))
107  "Imports the given jtm-file by calling import-construct-from-jtm-string."
108  (declare (type (or Pathname String) jtm-path repository-path)
109           (String tm-id)
110           (Keyword jtm-format)
111           (Integer revision))
112  (open-tm-store repository-path)
113  (import-construct-from-jtm-string (read-file-to-string jtm-path)
114                                    :tm-id tm-id :revision revision
115                                    :jtm-format jtm-format)
116  (close-tm-store))
117
118
119(defun import-topic-map-from-jtm-list (jtm-list tm-id &key (revision *TM-REVISION*)
120                                       prefixes (instance-of-p t)
121                                       (create-fragments nil))
122  "Creates and returns a topic map corresponding to the tm-id or a given
123   item-identifier in the jtm-list and returns the tm construct after all
124   topics and associations contained in the jtm-list has been created."
125  (declare (List jtm-list prefixes)
126           (Integer revision)
127           (Boolean instance-of-p create-fragments))
128  (let* ((iis (let ((value (append (import-identifiers-from-jtm-strings
129                                    (get-item :ITEM--IDENTIFIERS jtm-list)
130                                    :prefixes prefixes)
131                                   (when tm-id
132                                     (list
133                                      (make-construct 'ItemIdentifierC
134                                                      :uri tm-id))))))
135                (unless value
136                  (error (make-condition 'JTM-error :message (format nil "From import-topic-map-from-jtm-list(): no topic-map item-identifier is set for ~a" jtm-list))))
137                value))
138         (j-tops (get-item :TOPICS jtm-list))
139         (j-assocs (get-item :ASSOCIATIONS jtm-list))
140         (tm (make-construct 'TopicMapC :start-revision revision
141                             :item-identifiers iis)))
142    (import-topic-stubs-from-jtm-lists j-tops (list tm) :revision revision
143                                       :prefixes prefixes)
144    (merge-topics-from-jtm-lists j-tops :instance-of-p instance-of-p
145                                 :revision revision :prefixes prefixes
146                                 :create-fragments create-fragments)
147    (import-associations-from-jtm-lists j-assocs (list tm) :revision revision
148                                        :prefixes prefixes)
149    tm))
150
151
152(defun import-associations-from-jtm-lists (jtm-lists parents &key
153                                           (revision *TM-REVISION*) prefixes)
154  "Create a listof AssociationC objects corresponding to the passed jtm-lists
155    and returns it."
156  (declare (List jtm-lists parents prefixes)
157           (Integer revision))
158  (map 'list #'(lambda(jtm-list)
159                 (import-association-from-jtm-list
160                  jtm-list parents :revision revision :prefixes prefixes))
161       jtm-lists))
162
163
164(defun import-role-from-jtm-list (jtm-list parent &key (revision *TM-REVISION*)
165                                  prefixes)
166  "Creates and returns a role object form the given jtm-list."
167    (let* ((iis (import-identifiers-from-jtm-strings
168               (get-item :ITEM--IDENTIFIERS jtm-list)
169               :prefixes prefixes))
170           (type (get-item :TYPE jtm-list))
171           (reifier (get-item :REIFIER jtm-list))
172           (player (get-item :PLAYER jtm-list))
173           (parent-references (get-item :PARENT jtm-list))
174           (local-parent
175            (if parent
176                (list parent)
177                (when parent-references
178                  (get-items-from-jtm-references
179                   parent-references :revision revision :prefixes prefixes)))))
180      (unless local-parent
181        (error (make-condition 'JTM-error :message (format nil "From import-role-from-jtm-list(): the JTM role ~a must have exactly one parent set in its members." jtm-list))))
182      (unless type
183        (error (make-condition 'JTM-error :message (format nil "From import-role-from-jtm-list(): the role ~a must have exactly one type set as member." jtm-list))))
184      (unless player
185        (error (make-condition 'JTM-error :message (format nil "From import-role-from-jtm-list(): the role ~a must have exactly one player set as member." jtm-list))))
186      (make-construct 'RoleC :start-revision revision
187                      :item-identifiers iis
188                      :reifier (when reifier
189                                 (get-item-from-jtm-reference
190                                  reifier :revision revision :prefixes prefixes))
191                      :instance-of (get-item-from-jtm-reference
192                                    type :revision revision :prefixes prefixes)
193                      :player (get-item-from-jtm-reference
194                               player :revision revision :prefixes prefixes)
195                      :parent (first local-parent))))
196
197
198(defun make-plist-of-jtm-role(jtm-list &key (revision *TM-REVISION*) prefixes)
199  "Returns a plist of the form (:start-revision <rev> :player <top>
200   :instance-of <top> :reifier <top> :item-identifiers <ii>)."
201  (unless (and (get-item :PLAYER jtm-list)
202               (get-item :TYPE jtm-list))
203    (error (make-condition 'JTM-error :message (format nil "From make-plist-of-jtm-role(): the role ~a must have a type and player member set." jtm-list))))
204  (list :start-revision revision
205        :player (get-item-from-jtm-reference
206                 (get-item :PLAYER jtm-list)
207                 :revision revision :prefixes prefixes)
208        :instance-of (get-item-from-jtm-reference
209                      (get-item :TYPE jtm-list)
210                      :revision revision :prefixes prefixes)
211        :item-identifiers (import-identifiers-from-jtm-strings
212                           (get-item :ITEM--IDENTIFIERS jtm-list)
213                           :prefixes prefixes)
214        :reifier (when (get-item :REIFIER jtm-list)
215                   (get-item-from-jtm-reference
216                    (get-item :REIFIER jtm-list)
217                    :revision revision :prefixes prefixes))))
218
219
220(defun import-association-from-jtm-list (jtm-list parents &key
221                                         (revision *TM-REVISION*) prefixes)
222  "Create an AssociationC object corresponding to the passed jtm-list and
223   returns it."
224  (declare (List jtm-list parents prefixes)
225           (Integer revision))
226  (let* ((iis (import-identifiers-from-jtm-strings
227               (get-item :ITEM--IDENTIFIERS jtm-list)
228               :prefixes prefixes))
229         (scope (get-item :SCOPE jtm-list))
230         (type (get-item :TYPE jtm-list))
231         (reifier (get-item :REIFIER jtm-list))
232         (parent-references (get-item :PARENT jtm-list))
233         (role-lists
234          (map 'list #'(lambda(role)
235                         (make-plist-of-jtm-role role :revision revision
236                                                 :prefixes prefixes))
237               (get-item :ROLES jtm-list)))
238         (local-parent
239          (if parents
240              parents
241              (when parent-references
242                (get-items-from-jtm-references
243                 parent-references :revision revision :prefixes prefixes)))))
244    (unless local-parent
245      (error (make-condition 'JTM-error :message (format nil "From import-association-from-jtm-list(): the JTM association ~a must have at least one parent set in its members." jtm-list))))
246    (unless role-lists
247      (error (make-condition 'JTM-error :message (format nil "From import-association-from-jtm-list(): the JTM association ~a must have at least one role set in its members." jtm-list))))
248    (unless type
249      (error (make-condition 'JTM-error :message (format nil "From import-association-from-jtm-list(): the association ~a must have exactly one type set as member." jtm-list))))
250    (let ((assoc
251           (make-construct 'AssociationC :start-revision revision
252                           :item-identifiers iis
253                           :themes (get-items-from-jtm-references
254                                    scope :revision revision :prefixes prefixes)
255                           :reifier (when reifier
256                                      (get-item-from-jtm-reference
257                                       reifier :revision revision :prefixes prefixes))
258                           :instance-of (get-item-from-jtm-reference
259                                         type :revision revision :prefixes prefixes)
260                           :roles role-lists)))
261      (dolist (tm local-parent)
262        (add-to-tm tm assoc))
263      (format t "a")
264      assoc)))
265
266
267(defun import-topic-stubs-from-jtm-lists (jtm-lists parents &key
268                                          (revision *TM-REVISION*) prefixes)
269  "Creates and returns a list of topics.
270   Note only the topic identifiers are imported and set in this function,
271   entire topics are imported in merge-topics-from-jtm-lists."
272  (declare (List jtm-lists parents prefixes)
273           (Integer revision))
274  (map 'list #'(lambda(jtm-list)
275                 (import-topic-stub-from-jtm-list
276                  jtm-list parents :revision revision :prefixes prefixes))
277       jtm-lists))
278
279
280(defun import-topic-stub-from-jtm-list(jtm-list parents &key
281                                       (revision *TM-REVISION*) prefixes)
282  "Creates and returns a topic object from the passed jtm
283   list generated by json:decode-json-from-string.
284   Note this function only sets the topic's identifiers."
285  (declare (List jtm-list parents prefixes)
286           (Integer revision))
287  (let* ((t-iis (import-identifiers-from-jtm-strings
288                 (get-item :ITEM--IDENTIFIERS jtm-list)
289                 :prefixes prefixes))
290         (t-psis (import-identifiers-from-jtm-strings
291                  (get-item :SUBJECT--IDENTIFIERS jtm-list)
292                  :prefixes prefixes :identifier-type-symbol 'd:PersistentIdC))
293         (t-sls (import-identifiers-from-jtm-strings
294                 (get-item :SUBJECT--LOCATORS jtm-list)
295                 :prefixes prefixes :identifier-type-symbol 'd:SubjectLocatorC))
296         (parent-references (get-item :PARENT jtm-list))
297         (local-parents
298          (if parents
299              parents
300              (when parent-references
301                (get-items-from-jtm-references
302                 parent-references :revision revision :prefixes prefixes)))))
303    (unless local-parents
304      (error (make-condition 'JTM-error :message (format nil "From import-topic-from-jtm-string(): the JTM topic ~a must have at least one parent set in its members." jtm-list))))
305    (unless (append t-iis t-sls t-psis)
306      (error (make-condition 'JTM-error :message (format nil "From import-topic-from-jtm-string(): the JTM topic ~a must have at least one identifier set in its members." jtm-list))))
307    (let* ((top (make-construct 'TopicC :start-revision revision
308                                :psis t-psis
309                                :item-identifiers t-iis
310                                :locators t-sls)))
311      (dolist (tm local-parents)
312        (add-to-tm tm top))
313      top)))
314
315
316(defun make-instance-of-association (instance-top type-top parents &key
317                                     (revision *TM-REVISION*))
318  "Creates and returns a type-instance-association for the passed
319   instance and type topics."
320  (declare (TopicC instance-top type-top)
321           (List parents)
322           (Integer revision))
323  (unless parents
324    (error (make-condition 'JTM-error :message (format nil "From make-instance-of-association(): parents must contain at least one TopicMapC object, but is nil"))))
325  (let ((t-top (get-item-by-psi *type-psi* :revision revision))
326        (i-top (get-item-by-psi *instance-psi* :revision revision))
327        (ti-top (get-item-by-psi *type-instance-psi* :revision revision)))
328    (unless (and i-top t-top ti-top)
329      (let ((missing-topic (cond ((not t-top) *type-psi*)
330                                 ((not i-top) *instance-psi*)
331                                 (t *type-instance-psi*))))
332        (error (make-condition 'missing-reference-error :message (format nil "From make-instance-of-association(): the core topics ~a, ~a, and ~a are necessary, but ~a cannot be found" *type-psi* *instance-psi* *type-instance-psi* missing-topic) :reference missing-topic))))
333    (let ((assoc
334           (make-construct 'AssociationC :start-revision revision
335                           :instance-of ti-top
336                           :roles (list (list :start-revision revision
337                                              :player instance-top
338                                              :instance-of i-top)
339                                        (list :start-revision revision
340                                              :player type-top
341                                              :instance-of t-top)))))
342      (dolist (tm parents)
343        (add-to-tm tm i-top)
344        (add-to-tm tm t-top)
345        (add-to-tm tm ti-top)
346        (add-to-tm tm assoc))
347      assoc)))
348
349
350(defun merge-topics-from-jtm-lists (jtm-lists &key (instance-of-p t)
351                                    (revision *TM-REVISION*) prefixes
352                                    (create-fragments nil))
353  "Creates and returns a list of topics."
354  (declare (List jtm-lists prefixes)
355           (Boolean instance-of-p create-fragments)
356           (Integer revision))
357  (map 'list #'(lambda(jtm-list)
358                 (merge-topic-from-jtm-list
359                  jtm-list :revision revision :prefixes prefixes
360                  :instance-of-p instance-of-p
361                  :create-fragment create-fragments))
362       jtm-lists))
363
364
365(defun merge-topic-from-jtm-list(jtm-list &key (instance-of-p t)
366                                  (revision *TM-REVISION*) prefixes
367                                 (create-fragment nil))
368  "Creates and returns a topic object from the passed jtm
369   list generated by json:decode-json-from-string.
370   Note that the merged topics are not added explicitly to the parent
371   topic maps, it is only needed for the instance-of-associations -
372   topics are added in the function import-topic-stubs-from-jtm-lists
373   to their topic map elements."
374  (declare (List jtm-list prefixes)
375           (Boolean instance-of-p)
376           (Integer revision)
377           (Boolean create-fragment))
378  (let* ((ids (append (get-item :ITEM--IDENTIFIERS jtm-list)
379                      (get-item :SUBJECT--IDENTIFIERS jtm-list)
380                      (get-item :SUBJECT--LOCATORS jtm-list)))
381         (top (when ids
382                (get-item-by-any-id
383                 (compute-uri-from-jtm-identifier (first ids) prefixes)
384                 :revision revision)))
385         (instanceof (get-items-from-jtm-references
386                      (get-item :INSTANCE--OF jtm-list) :revision revision
387                      :prefixes prefixes))
388         (top-names (import-characteristics-from-jtm-lists
389                     (get-item :NAMES jtm-list) top
390                     #'import-name-from-jtm-list :revision revision
391                     :prefixes prefixes))
392         (top-occs (import-characteristics-from-jtm-lists
393                    (get-item :OCCURRENCES jtm-list) top
394                    #'import-occurrence-from-jtm-list :revision revision
395                    :prefixes prefixes)))
396    (unless ids
397      (error (make-condition 'JTM-error :message (format nil "From merge-topic-from-jtm-list(): the passed topic has to own at least one identifier: ~a" jtm-list))))
398    (unless top
399      (error (make-condition 'JTM-error :message (format nil "From merge-topic-from-jtm-list(): cannot find a topic that matches the corresponding JTM-list: ~a" jtm-list))))
400    (when (and (not instance-of-p) instanceof)
401      (error (make-condition 'JTM-error :message (format nil "From merge-topic-from-jtm-list(): the JTM-topic has an instance_of member set, but JTM version 1.0 does not allow an intance_of member within a topic object: ~a" jtm-list))))
402    (dolist (type-top instanceof)
403      (make-instance-of-association
404       top type-top (in-topicmaps top :revision revision)
405       :revision revision))
406    (dolist (name top-names)
407      (add-name top name :revision revision))
408    (dolist (occ top-occs)
409      (add-occurrence top occ :revision revision))
410    (when create-fragment
411      (let ((all-assocs
412             (remove-null (map 'list (lambda(role)
413                                       (parent role :revision revision))
414                               (player-in-roles top :revision revision)))))
415        (let ((all-tops
416               (remove-null
417                (loop for assoc in all-assocs
418                   append (map 'list (lambda(role)
419                                       (d:player role :revision revision))
420                               (roles assoc :revision revision))))))
421          (map nil (lambda(top)
422                     (map nil #'elephant:drop-instance
423                          (elephant:get-instances-by-value 'FragmentC 'topic top))
424                     (create-latest-fragment-of-topic top))
425               (append all-tops (list top))))))
426    (format t "t")
427    top))
428
429
430(defun import-name-from-jtm-list (jtm-list parent &key
431                                  (revision *TM-REVISION*) prefixes)
432  "Creates and returns a name object from the passed jtm
433   list generated by json:decode-json-from-string."
434  (declare (List jtm-list prefixes)
435           (Integer revision)
436           (type (or Null TopicC) parent))
437  (let* ((iis (import-identifiers-from-jtm-strings
438               (get-item :ITEM--IDENTIFIERS jtm-list)
439               :prefixes prefixes))
440         (scope (get-item :SCOPE jtm-list))
441         (type (get-item :TYPE jtm-list))
442         (value (get-item :VALUE jtm-list))
443         (name-variants (get-item :VARIANTS jtm-list))
444         (reifier (get-item :REIFIER jtm-list))
445         (parent-references (get-item :PARENT jtm-list))
446         (local-parent
447          (if parent
448              (list parent)
449              (when parent-references
450                (get-items-from-jtm-references
451                 parent-references :revision revision :prefixes prefixes)))))
452    (when (/= (length local-parent) 1)
453      (error (make-condition 'JTM-error :message (format nil "From import-name-from-jtm-list(): the JTM name ~a must have exactly one parent set in its members." jtm-list))))
454    (let ((name
455           (make-construct
456            'NameC :start-revision revision
457            :item-identifiers iis
458            :charvalue value
459            :themes (get-items-from-jtm-references
460                     scope :revision revision :prefixes prefixes)
461            :instance-of (if type
462                             (get-item-from-jtm-reference
463                              type :revision revision :prefixes prefixes)
464                             (get-item-by-psi *topic-name-psi*
465                                              :revision revision :error-if-nil t))
466            :parent (first local-parent)
467            :reifier (when reifier
468                       (get-item-from-jtm-reference
469                        reifier :revision revision :prefixes prefixes)))))
470      (import-characteristics-from-jtm-lists name-variants name
471                                             #'import-variant-from-jtm-list
472                                             :revision revision :prefixes prefixes)
473      name)))
474
475
476(defun import-occurrence-from-jtm-list (jtm-list parent &key
477                                        (revision *TM-REVISION*) prefixes)
478  "Creates and returns an occurrence object from the passed jtm
479   list generated by json:decode-json-from-string."
480  (declare (List jtm-list prefixes)
481           (Integer revision)
482           (type (or Null TopicC) parent))
483  (let* ((iis (import-identifiers-from-jtm-strings
484               (get-item :ITEM--IDENTIFIERS jtm-list)
485               :prefixes prefixes))
486         (datatype
487          (let ((curie (jtm::get-item :DATATYPE jtm-list)))
488            (cond ((null curie)
489                   constants:*xml-string*)
490                  ((and (tools:string-starts-with curie "[")
491                        (tools:string-ends-with curie "]"))
492                   (jtm::compute-uri-from-jtm-identifier curie prefixes))
493                  (t
494                   curie))))
495         (scope (get-item :SCOPE jtm-list))
496         (type (get-item :TYPE jtm-list))
497         (value (get-item :VALUE jtm-list))
498         (reifier (get-item :REIFIER jtm-list))
499         (parent-references (get-item :PARENT jtm-list))
500         (local-parent
501          (if parent
502              (list parent)
503              (when parent-references
504                (get-items-from-jtm-references
505                 parent-references :revision revision :prefixes prefixes)))))
506    (when (/= (length local-parent) 1)
507      (error (make-condition 'JTM-error :message (format nil "From import-occurrence-from-jtm-list(): the JTM occurrence ~a must have a parent set in its members." jtm-list))))
508    (unless type
509      (error (make-condition 'JTM-error :message (format nil "From import-occurrence-from-jtm-list(): the JTM occurrence ~a must have a type set in its members." jtm-list))))
510    (make-construct 'OccurrenceC :start-revision revision
511                    :item-identifiers iis
512                    :datatype datatype
513                    :charvalue value
514                    :themes (get-items-from-jtm-references
515                             scope :revision revision :prefixes prefixes)
516                    :instance-of (get-item-from-jtm-reference
517                                  type :revision revision :prefixes prefixes)
518                    :parent (first local-parent)
519                    :reifier (when reifier
520                               (get-item-from-jtm-reference
521                                reifier :revision revision :prefixes prefixes)))))
522
523
524(defun import-characteristics-from-jtm-lists(jtm-lists parent next-fun &key
525                                             (revision *TM-REVISION*) prefixes)
526  "Creates and returns a list of TM-Constructs returned by next-fun."
527  (declare (List jtm-lists prefixes)
528           (Integer revision)
529           (type (or Null ReifiableConstructC) parent)
530           (Function next-fun))
531  (map 'list #'(lambda(jtm-list)
532                 (apply next-fun (list jtm-list parent :revision revision
533                                       :prefixes prefixes)))
534       jtm-lists))
535
536
537(defun import-variant-from-jtm-list(jtm-list parent &key
538                                      (revision *TM-REVISION*) prefixes)
539  "Creates a variant object from the passed jtm list generated by
540   json:decode-json-from-string."
541  (declare (List jtm-list prefixes)
542           (type (or Null NameC) parent)
543           (Integer revision))
544  (let* ((iis (import-identifiers-from-jtm-strings
545               (get-item :ITEM--IDENTIFIERS jtm-list)
546               :prefixes prefixes))
547         (datatype 
548          (let ((curie (jtm::get-item :DATATYPE jtm-list)))
549            (cond ((null curie)
550                   constants:*xml-string*)
551                  ((and (tools:string-starts-with curie "[")
552                        (tools:string-ends-with curie "]"))
553                   (jtm::compute-uri-from-jtm-identifier curie prefixes))
554                  (t
555                   curie))))
556         (value (get-item :VALUE jtm-list))
557         (reifier (get-item :REIFIER jtm-list))
558         (parent-references (get-item :PARENT jtm-list))
559         (local-parent
560          (if parent
561              (list parent)
562              (when parent-references
563                (get-items-from-jtm-references
564                 parent-references :revision revision :prefixes prefixes))))
565         (scopes (when local-parent
566                   (remove-duplicates
567                    (append
568                     (get-items-from-jtm-references
569                      (get-item :SCOPE jtm-list)
570                      :revision revision :prefixes prefixes)
571                     (themes (first local-parent) :revision revision))))))
572    (when (/= (length local-parent) 1)
573      (error (make-condition 'JTM-error :message (format nil "From import-variant-from-jtm-list(): the JTM variant ~a must have exactly one parent set in its members." jtm-list))))
574    (make-construct 'VariantC :start-revision revision
575                    :item-identifiers iis
576                    :datatype (if datatype datatype *xml-string*)
577                    :charvalue value
578                    :themes scopes
579                    :parent (first local-parent)
580                    :reifier (when reifier
581                               (get-item-from-jtm-reference
582                                reifier :revision revision :prefixes prefixes)))))
583
584
585(defun import-identifiers-from-jtm-strings
586    (jtm-strings  &key (identifier-type-symbol 'ItemIdentifierC) prefixes)
587  "Creates and returns a list of identifiers specified by jtm-strings and
588   identifier-type-symbol."
589  (declare (List jtm-strings)
590           (Symbol identifier-type-symbol)
591           (List prefixes))
592  (map 'list #'(lambda(jtm-string)
593                 (import-identifier-from-jtm-string
594                  jtm-string :prefixes prefixes
595                  :identifier-type-symbol identifier-type-symbol))
596       jtm-strings))
597
598
599(defun import-identifier-from-jtm-string
600    (jtm-string &key (identifier-type-symbol 'ItemIdentifierC) prefixes)
601  "Creates and returns an identifier of the type specified by
602   identifier-type-symbol."
603  (declare (String jtm-string)
604           (Symbol identifier-type-symbol)
605           (List prefixes))
606  (let ((uri-value (compute-uri-from-jtm-identifier jtm-string prefixes)))
607    (make-construct identifier-type-symbol
608                    :uri uri-value)))
609 
610
611
612(defun get-item-from-jtm-reference (reference-string &key (revision *TM-REVISION*)
613                                    prefixes)
614  "Returns a ReifiableConstructC that is bound to the reference that is
615   passed to this function. If the construct cannot be found the error
616   tm-reference-error is thrown."
617  (declare (Integer revision)
618           (List prefixes)
619           (String reference-string))
620  (let* ((identifier-type
621          (get-identifier-type-from-jtm-reference reference-string))
622         (identifier-value (subseq reference-string 3))
623         (identifier-uri
624          (compute-uri-from-jtm-identifier identifier-value prefixes))
625         (construct
626          (d::get-item-by-identifier identifier-uri :revision revision
627                                     :identifier-type-symbol identifier-type)))
628    (if construct
629        construct
630        (error (make-condition 'missing-reference-error :message (format nil "From get-item-from-jtm-reference(): cannot find the item identified by \"~a\"(~a)" identifier-uri reference-string)
631                               :reference identifier-uri)))))   
632
633
634(defun get-items-from-jtm-references (reference-strings &key (revision *TM-REVISion*)
635                                      prefixes)
636  "Returns a list of ReifiableConstructCs that are referenced via the
637   string-values in reference-strings."
638  (declare (List reference-strings prefixes)
639           (Integer revision))
640  (map 'list #'(lambda(reference-string)
641                 (get-item-from-jtm-reference reference-string :revision revision
642                                              :prefixes prefixes))
643       reference-strings))
644
645
646(defun compute-uri-from-jtm-identifier (identifier-value prefixes)
647  "Returns the full uri of an identifier string, i.e.
648   * if the value is of the form '[pref:value]' the return value is
649     the concatenation of 'value-of-pref' and 'value'.
650   * if the value is of the form 'full-uri' the return value is
651     'full-uri'"
652  (declare (String identifier-value)
653           (List prefixes))
654  (cond ((and (string-starts-with identifier-value "[")
655              (string-ends-with identifier-value "]"))
656         (let* ((pref-name
657                 (let ((value (string-until identifier-value ":")))
658                   (when value
659                     (subseq value 1))))
660                (suffix
661                 (when pref-name
662                   (let ((value
663                          (subseq identifier-value (1+ (length pref-name)))))
664                     (when value
665                       (subseq value (min 1 (length value))
666                               (max 0 (1- (length value)))))))))
667           (when (or (not pref-name) (not suffix))
668             (error (make-condition 'JTM-error :message (format nil "From compute-uri-from-jtm-identifier: the section within the range of \"[\" and \"]\" must be of the form prefix:suffix, but is: \"~a\"" identifier-value))))
669           (compute-full-uri prefixes pref-name suffix)))
670        ((> (length identifier-value) 0)
671         identifier-value)
672        (t
673         (error (make-condition 'JTM-error :message (format nil "From compute-uri-from-jtm-identifier(): the identifier-value must be of the form \"[pref:value]\" or \"full-uri\", but is: \"~a\"" identifier-value))))))
674
675
676(defun get-identifier-type-from-jtm-reference (identifier-string)
677  "Returns the symbol 'PersistentIdC if identifier-string starts
678   with si:, 'SubjectLocatorC if identifier-string starts with
679   sl:, or 'ItemIdentifierC if identifier-string starts with ii:.
680   If identifier-string do not start with one of these strings
681   the error JTM-error is thrown."
682  (cond ((string-starts-with identifier-string "ii:")
683         'ItemIdentifierC)
684        ((string-starts-with identifier-string "si:")
685         'PersistentIdC)
686        ((string-starts-with identifier-string "sl:")
687         'SubjectLocatorC)
688        (t
689         (error (make-condition 'JTM-error :message (format nil "From get-identifier-type(): the identifier value must start with one of \"ii:\", \"si:\", or \"sl:\", but is: \"~a\"" identifier-string))))))
Note: See TracBrowser for help on using the repository browser.