
Author: lgiessmann Date: Fri Nov 20 05:41:32 2009 New Revision: 144 Log: added some unit-tests for the "reification"-functions; fixed some problems; currently there is still a problem with the versioning of constructs that existed more than one revision and were not merged at the initial version. Added: trunk/src/unit_tests/reification_test.lisp Modified: trunk/src/isidorus.asd trunk/src/model/datamodel.lisp Modified: trunk/src/isidorus.asd ============================================================================== --- trunk/src/isidorus.asd (original) +++ trunk/src/isidorus.asd Fri Nov 20 05:41:32 2009 @@ -143,7 +143,9 @@ (:file "rdf_importer_test" :depends-on ("fixtures")) (:file "rdf_exporter_test" - :depends-on ("fixtures"))) + :depends-on ("fixtures")) + (:file "reification_test" + :depends-on ("fixtures" "unittests-constants"))) :depends-on ("atom" "constants" "model" Modified: trunk/src/model/datamodel.lisp ============================================================================== --- trunk/src/model/datamodel.lisp (original) +++ trunk/src/model/datamodel.lisp Fri Nov 20 05:41:32 2009 @@ -621,80 +621,6 @@ (setf (slot-value construct 'reifier) topic) (setf (reified topic) construct))) -(defgeneric add-reifier (construct reifier-uri) - (:method ((construct ReifiableConstructC) reifier-uri) - (let ((err "From add-reifier(): ")) - (let ((item-identifier - (elephant:get-instance-by-value 'Item-IdentifierC 'uri reifier-uri))) - (unless item-identifier - (error "~ano item-identifier could be found with the uri ~a" - err reifier-uri)) - (let ((reifier-topic (identified-construct item-identifier))) - (unless (typep reifier-topic 'TopicC) - (error "~anitem-identifier ~a must be bound to a topic, but is ~a" - err reifier-uri (type-of reifier-topic))) - (cond - ((and (not (reifier construct)) - (not (reified reifier-topic))) - (setf (reifier construct) reifier-topic) - (setf (reified reifier-topic) construct)) - ((and (not (reified reifier-topic)) - (reifier construct)) - (merge-reifier-topics (reifier construct) reifier-topic)) - ((and (not (reifier construct)) - (reified reifier-topic)) - (error "~a~a reifies already another object ~a" - err reifier-uri (reified reifier-topic))) - (t - (when (not (eql (reified reifier-topic) construct)) - (error "~a~a reifies already another object ~a" - err reifier-uri (reified reifier-topic))) - (merge-reifier-topics (reifier construct) reifier-topic)))))) - construct)) - -(defgeneric merge-reifier-topics (old-topic new-topic) - ;;the reifier topics are not only merged but also bound to the reified-construct - (:method ((old-topic TopicC) (new-topic TopicC)) - (unless (eql old-topic new-topic) - ;merges all identifiers - (move-identifiers old-topic new-topic) - (move-identifiers old-topic new-topic :what 'locators) - (move-identifiers old-topic new-topic :what 'psis) - (move-identifiers old-topic new-topic :what 'topic-identifiers) - ;merges all typed-object-associations - (dolist (typed-construct (used-as-type new-topic)) - (remove-association typed-construct 'instance-of new-topic) - (add-association typed-construct 'instance-of old-topic)) - ;merges all scope-object-associations - (dolist (scoped-construct (used-as-theme new-topic)) - (remove-association scoped-construct 'theme new-topic) - (add-association scoped-construct 'theme old-topic)) - (dolist (tm (in-topicmaps new-topic)) - (add-association tm 'topic old-topic)) ;the new-topic is removed from this tm by deleting it - (dolist (a-role (player-in-roles new-topic)) - (remove-association a-role 'player new-topic) - (add-association a-role 'player old-topic)) - ;merges all names - (dolist (name (names new-topic)) - (remove-association name 'topic new-topic) - (add-association name 'topic old-topic)) - ;merges all occurrences - (dolist (occurrence (occurrences new-topic)) - (remove-association occurrence 'topic new-topic) - (add-association occurrence 'topic old-topic)) - ;merges all version-infos - (let ((versions-to-move - (loop for vrs in (versions new-topic) - when (not (find-if #'(lambda(x) - (and (= (start-revision x) (start-revision vrs)) - (= (end-revision x) (end-revision vrs)))) - (versions old-topic))) - collect vrs))) - (dolist (vrs versions-to-move) - (remove-association vrs 'versioned-construct new-topic) - (add-association vrs 'versioned-construct old-topic)))))) - - (defgeneric item-identifiers (construct &key revision) (:method ((construct ReifiableConstructC) &key (revision *TM-REVISION*)) (filter-slot-value-by-revision construct 'item-identifiers :start-revision revision))) @@ -1654,4 +1580,83 @@ (defmethod in-topicmap ((tm TopicMapC) (ass AssociationC) &key (revision 0)) (when (find-item-by-revision ass revision) - (find (d:internal-id ass) (d:associations tm) :test #'= :key #'d:internal-id))) \ No newline at end of file + (find (d:internal-id ass) (d:associations tm) :test #'= :key #'d:internal-id))) + +;;;;;;;;;;;;;;;;; +;; reification + +(defgeneric add-reifier (construct reifier-uri) + (:method ((construct ReifiableConstructC) reifier-uri) + (let ((err "From add-reifier(): ")) + (let ((item-identifier + (elephant:get-instance-by-value 'Item-IdentifierC 'uri reifier-uri))) + (unless item-identifier + (error "~ano item-identifier could be found with the uri ~a" + err reifier-uri)) + (let ((reifier-topic (identified-construct item-identifier))) + (unless (typep reifier-topic 'TopicC) + (error "~anitem-identifier ~a must be bound to a topic, but is ~a" + err reifier-uri (type-of reifier-topic))) + (cond + ((and (not (reifier construct)) + (not (reified reifier-topic))) + (setf (reifier construct) reifier-topic)) + ((and (not (reified reifier-topic)) + (reifier construct)) + (merge-reifier-topics (reifier construct) reifier-topic)) + ((and (not (reifier construct)) + (reified reifier-topic)) + (error "~a~a reifies already another object ~a" + err reifier-uri (reified reifier-topic))) + (t + (when (not (eql (reified reifier-topic) construct)) + (error "~a~a reifies already another object ~a" + err reifier-uri (reified reifier-topic))) + (merge-reifier-topics (reifier construct) reifier-topic)))))) + construct)) + +(defgeneric merge-reifier-topics (old-topic new-topic) + ;;the reifier topics are not only merged but also bound to the reified-construct + (:method ((old-topic TopicC) (new-topic TopicC)) + (unless (eql old-topic new-topic) + ;merges all identifiers + (move-identifiers old-topic new-topic) + (move-identifiers old-topic new-topic :what 'locators) + (move-identifiers old-topic new-topic :what 'psis) + (move-identifiers old-topic new-topic :what 'topic-identifiers) + ;merges all typed-object-associations + (dolist (typed-construct (used-as-type new-topic)) + (remove-association typed-construct 'instance-of new-topic) + (add-association typed-construct 'instance-of old-topic)) + ;merges all scope-object-associations + (dolist (scoped-construct (used-as-theme new-topic)) + (remove-association scoped-construct 'themes new-topic) + (add-association scoped-construct 'themes old-topic)) + (dolist (tm (in-topicmaps new-topic)) + (add-association tm 'topic old-topic)) ;the new-topic is removed from this tm by deleting it + (dolist (a-role (player-in-roles new-topic)) + (remove-association a-role 'player new-topic) + (add-association a-role 'player old-topic)) + ;merges all names + (dolist (name (names new-topic)) + (remove-association name 'topic new-topic) + (add-association name 'topic old-topic)) + ;merges all occurrences + (dolist (occurrence (occurrences new-topic)) + (remove-association occurrence 'topic new-topic) + (add-association occurrence 'topic old-topic)) + ;merges all version-infos + (let ((versions-to-move + (loop for vrs in (versions new-topic) + when (not (find-if #'(lambda(x) + (and (= (start-revision x) (start-revision vrs)) + (= (end-revision x) (end-revision vrs)))) + (versions old-topic))) + collect vrs))) + (dolist (vrs versions-to-move) + (remove-association vrs 'versioned-construct new-topic) + (add-association vrs 'versioned-construct old-topic))) + (delete-construct new-topic)) + ;TODO: order/repair all version-infos of the topic itself and add all new + ; versions to the original existing objects of the topic + old-topic)) \ No newline at end of file Added: trunk/src/unit_tests/reification_test.lisp ============================================================================== --- (empty file) +++ trunk/src/unit_tests/reification_test.lisp Fri Nov 20 05:41:32 2009 @@ -0,0 +1,178 @@ +;;+----------------------------------------------------------------------------- +;;+ Isidorus +;;+ (c) 2008-2009 Marc Kuester, Christoph Ludwig, Lukas Giessmann +;;+ +;;+ Isidorus is freely distributable under the LGPL license. +;;+ You can find a detailed description in trunk/docs/LGPL-LICENSE.txt. +;;+----------------------------------------------------------------------------- + + +(defpackage :reification-test + (:use + :common-lisp + :datamodel + :it.bese.FiveAM + :unittests-constants + :fixtures) + (:export + :reification-test + :run-reification-tests + :test-merge-reifier-topics)) + + +(in-package :reification-test) + + +(def-suite reification-test + :description "tests various functions of the reification functions") + +(in-suite reification-test) + + +(test test-merge-reifier-topics + "Tests the function merge-reifier-topics." + (let ((db-dir "data_base") + (revision-1 100) + (revision-2 200)) + (clean-out-db db-dir) + (elephant:open-store (xml-importer:get-store-spec db-dir)) + (let ((ii-1-1 (make-instance 'ItemIdentifierC + :uri "ii-1-1" + :start-revision revision-1)) + (ii-1-2 (make-instance 'ItemIdentifierC + :uri "ii-1-2" + :start-revision revision-1)) + (ii-2-1 (make-instance 'ItemIdentifierC + :uri "ii-2-1" + :start-revision revision-2)) + (ii-2-2 (make-instance 'ItemIdentifierC + :uri "ii-2-2" + :start-revision revision-2)) + (psi-1-1 (make-instance 'PersistentIdC + :uri "psi-1-1" + :start-revision revision-1)) + (psi-1-2 (make-instance 'PersistentIdC + :uri "psi-1-2" + :start-revision revision-1)) + (locator-2-1 (make-instance 'SubjectLocatorC + :uri "locator-2-1" + :start-revision revision-2)) + (xtm-id-1 "xtm-id-1") + (xtm-id-2 "xtm-id-2") + (topic-id-1 "topic-id-1") + (topic-id-2 "topic-id-1")) ;should no be merged, since the xtm-id differs + (let ((topic-1 (make-construct 'TopicC + :item-identifiers (list ii-1-1 ii-1-2) + :locators nil + :psis (list psi-1-1 psi-1-2) + :topicid topic-id-1 + :xtm-id xtm-id-1 + :start-revision revision-1)) + (topic-2 (make-construct 'TopicC + :item-identifiers (list ii-2-1 ii-2-2) + :locators (list locator-2-1) + :psis nil + :topicid topic-id-2 + :xtm-id xtm-id-2 + :start-revision revision-2)) + (scope-1 (make-construct 'TopicC + :psis (list (make-instance 'PersistentIdC + :uri "psi-scope-1" + :start-revision revision-1)) + :topicid "scope-1" + :xtm-id xtm-id-1 + :start-revision revision-1)) + (scope-2 (make-construct 'TopicC + :psis (list (make-instance 'PersistentIdC + :uri "psi-scope-2" + :start-revision revision-1)) + :topicid "scope-2" + :xtm-id xtm-id-1 + :start-revision revision-1)) + (name-type (make-construct 'TopicC + :psis (list (make-instance 'PersistentIdC + :uri "psi-name-type" + :start-revision revision-1)) + :topicid "name-type" + :xtm-id xtm-id-1 + :start-revision revision-1)) + (occurrence-type (make-construct 'TopicC + :psis (list (make-instance 'PersistentIdC + :uri "psi-occurrence-type" + :start-revision revision-1)) + :topicid "occurrence-type" + :xtm-id xtm-id-1 + :start-revision revision-1))) + (let ((name-1-1 (make-construct 'NameC + :item-identifiers nil + :topic topic-1 + :themes (list scope-1) + :instance-of name-type + :charvalue "name-1-1" + :start-revision revision-1)) + (name-2-1 (make-construct 'NameC + :item-identifiers (list (make-instance 'ItemIdentifierC + :uri "name-2-1-ii-1" + :start-revision revision-1)) + :topic topic-2 + :themes (list scope-2) + :instance-of nil + :charvalue "name-2-1" + :start-revision revision-2)) + (occurrence-2-1 (make-construct 'OccurrenceC + :item-identifiers (list (make-instance 'ItemIdentifierC + :uri "occurrence-1-1-ii-1" + :start-revision revision-1)) + :topic topic-2 + :themes (list scope-1 scope-2) + :instance-of occurrence-type + :charvalue "occurrence-2-1" + :datatype "datatype" + :start-revision revision-2)) + (occurrence-2-2 (make-construct 'OccurrenceC + :item-identifiers nil + :topic topic-2 + :themes nil + :instance-of occurrence-type + :charvalue "occurrence-2-2" + :datatype "datatype" + :start-revision revision-2)) + (test-name (make-construct 'NameC + :item-identifiers nil + :topic scope-2 + :themes (list scope-1 topic-2) + :instance-of topic-2 + :charvalue "test-name" + :start-revision revision-2))) + (is (= (length (elephant:get-instances-by-class 'TopicC)) 6)) + (datamodel::merge-reifier-topics topic-1 topic-2) + (is (= (length (elephant:get-instances-by-class 'TopicC)) 5)) + (is (= (length (union (list ii-1-1 ii-1-2 ii-2-1 ii-2-2) + (item-identifiers topic-1))) + (length (list ii-1-1 ii-1-2 ii-2-1 ii-2-2)))) + (is (= (length (union (list psi-1-1 psi-1-2) + (psis topic-1))) + (length (list psi-1-1 psi-1-2)))) + (is (= (length (union (list locator-2-1) + (locators topic-1))) + (length (list locator-2-1)))) + (is (= (length (union (names topic-1) + (list name-1-1 name-2-1))) + (length (list name-1-1 name-2-1)))) + (is (= (length (union (occurrences topic-1) + (list occurrence-2-1 occurrence-2-2))) + (length (list occurrence-2-1 occurrence-2-2)))) + (is (= (length (union (d:used-as-type topic-1) + (list test-name))) + (length (list test-name)))) + (is (= (length (union (d:used-as-theme topic-1) + (list test-name))) + (length (list test-name)))) + ;;TODO: roleplayer, topicmap + ;;TODO: check all objects and their version-infos + (elephant:close-store)))))) + + +(defun run-reification-tests () + (it.bese.fiveam:run! 'test-merge-reifier-topics) + ) \ No newline at end of file