Author: lgiessmann Date: Mon May 4 11:02:44 2009 New Revision: 28
Log: added the tmcl-json-model to the json-model; added a rest-api for the json-tmcl part, so it is possible to get all tmcl-standard-constraints for a topic as a json-string; added the topicmap example "poems.xtm" with tmcl-constraints to the unit_tests folder.
Added: trunk/src/json/json_tmcl.lisp trunk/src/json/json_tmcl_constants.lisp trunk/src/unit_tests/poems.xtm Modified: trunk/docs/xtm_json.txt trunk/src/ajax/javascripts/make_fragment_node.js trunk/src/constants.lisp trunk/src/isidorus.asd trunk/src/model/changes.lisp trunk/src/rest_interface/rest-interface.lisp trunk/src/rest_interface/set-up-json-interface.lisp
Modified: trunk/docs/xtm_json.txt ============================================================================== --- trunk/docs/xtm_json.txt (original) +++ trunk/docs/xtm_json.txt Mon May 4 11:02:44 2009 @@ -2,6 +2,7 @@ //+ Overview: //+ *Part 1: XTM - data model //+ *Part 2: Object summaries +//+ *Part 3: TMCL - data model //+-----------------------------------------------------------------------------
@@ -158,7 +159,7 @@
//+----------------------------------------------------------------------------- //+ topicSummary -//+ contains the topic id,subjetcIdentifiers, itemIdentities, +//+ Contains the topic id,subjetcIdentifiers, itemIdentities, //+ subjectLocators, nameSummaries and occurrenceSummaries //+----------------------------------------------------------------------------- { @@ -173,229 +174,228 @@
+//+----------------------------------------------------------------------------- +//+ Part 3: TMCL - data model +//+ This part explains how the tmcl-rules/suggestions of isidorus are +//+ sent via HTTP as JSON-data. +//+----------------------------------------------------------------------------- + + +//+----------------------------------------------------------------------------- +//+ exclusiveInstances +//+ This message constains a list of topics represented as a list of topic +//+ psis which are exclusive instances for the owner. +//+----------------------------------------------------------------------------- +[ [ "topic-1-psi-1", "topic-2-psi-2", "..." ], [ "topic-2-psi", "..." ], <...> ] + + +//+----------------------------------------------------------------------------- +//+ simpleConstraint +//+ This object contains a regexp member with the regular expression of the +//+ constraint, a cardMin member with the minimum cardinality of +//+ the referenced element which is represented as an unsignedInt +//+ and a cardMax member which describes the maximum cardinality of this +//+ element, this member contains an unsigendInt or the string +//+ "MAX_INT". +//+----------------------------------------------------------------------------- +{ + "regexp" : "regular expression", + "cardMin" : "unsigned integer in string representation", + "cardMax" : "unsigend integer in string representation or the string MAX_INT" +} + + +//+----------------------------------------------------------------------------- +//+ subjectIdentifierConstraint +//+ This object contains a regexp member with the regular expression of the +//+ subjectIdentifier, a cardMin member with the minimum cardinality of +//+ this subjectIdentifier in a topic which is represented as an unsignedInt +//+ and a cardMax member which describes the maximum cardinality of this +//+ subjectIdentifier, this member contains an unsigendInt or the string +//+ "MAX_INT". +//+----------------------------------------------------------------------------- +<simpleConstraint> + + +//+----------------------------------------------------------------------------- +//+ subjectLocatorConstraint +//+ This object contains a regexp member with the regular expression of the +//+ subjectLocator, a cardMin member with the minimum cardinality of +//+ this subjectLocator in a topic which is represented as an unsignedInt +//+ and a cardMax member which describes the maximum cardinality of this +//+ subjectLocator, this member contains an unsigendInt or the string +//+ "MAX_INT". +//+----------------------------------------------------------------------------- +<simepleConstraint> + + +//+----------------------------------------------------------------------------- +//+ scopeConstraint +//+ The scopeConstraint-Object contains a list of all available scopes of +//+ for an association/name/occurrence element - this depends where this +//+ json-onbject is contained. +//+ The member availableScopeTypes contains a list of topics in psi-list +//+ representation which can be used as scope. +//+ cardMin defines the minimum number of all scopes of the parent element +//+ (association/name/occurrence). +//+ cardMax defines the maximum number of all scopes of the parent element. +//+----------------------------------------------------------------------------- +{ + "scopeTypes" : [ [ "topic-1-psi-1", "topic-1-psi-2", "..." ], [ "topic-2-psi-1", "..." ] <...> ], + "cardMin" : "unsigned integer in string representation", + "cardMax" : "unsigend integer in string representation or the string MAX_INT" +} + + +//+----------------------------------------------------------------------------- +//+ topicNameConstraint +//+ The topicNameConstraint describes how the topic's names have to be +//+ defined. +//+ The nameType is a topic representation in form of a list of psis of the +//+ topic representing the name's type. +//+ regexp defines the content of the name. +//+ cardMin defines the minimum number of names a topic must have. +//+ cardMax defines the maximum number of names a topic must have. +//+ nameTypeScopes describes how many scopes there must exist and of what +//+ type the scopes have to be . +//+----------------------------------------------------------------------------- +{ + "nameType" : [ "topic-psi-1", "topic-psi-2", "..." ], + "constraints" : [ <simpleConstraint>, < ... > ], + "scopeConstraints" : { <scopeConstraint> } +}
+//+----------------------------------------------------------------------------- +//+ uniqueOccurrenceConstraint +//+ This object owns a regexp member with the regular expression of the +//+ occurrence which should be unique. So only occurrences that match the +//+ occurrenceType and the regexp will be checked. +//+ occurrenceType represents the topictype of the occurrence. +//+ cardMin describes the minimum number of all matched occurrences within +//+ all instances of this topictype's instances. +//+ cardMax describes the maximum number of all matched occurrences within +//+ all instances of this topictype's instances. +//+----------------------------------------------------------------------------- +<simpleConstraint>
+//+----------------------------------------------------------------------------- +//+ topicOccurrenceConstraint +//+ The topicOccurrenceConstraint describes how the topic's occurrences have +//+ to be defined. +//+ +//+----------------------------------------------------------------------------- +{ + "occurrenceType" : [ "topic-psi-1", "topic-psi-2", "..." ], + "constraints" : [ <simpleConstraint>, < ... > ], + "scopeConstraints" : { <scopeConstraint> }, + "dataConstraint" : "datatype", + "uniqueConstraints" : [ <uniqueOccurrenceConstraint>, <...> ] +}
+//+----------------------------------------------------------------------------- +//+ associationRoleConstraint +//+ This object defines a list of psis of the roletype topic of which +//+ the role is an instance of. +//+ cardMin and cardMax defines the number of roles with the defined roletype +//+ in an association of a certain associationtype (the objects owner). +//+----------------------------------------------------------------------------- +{ + "roleType" : [ "topic-psi-1", "topic-psi-2", "..." ], + "cardMin" : "unsigned integer in string representation", + "cardMax" : "unsigend integer in string representation or the string MAX_INT" +}
+//+----------------------------------------------------------------------------- +//+ rolePlayerConstraint +//+ Defines the player of a certain role with a given type in an association +//+ with a given type. +//+ playerType is the psi-list representation of the player-topic. +//+ roleType is the is a list of topic-psis representing a topic which can +//+ be a player in the given role. +//+ cardMin and cardMax defines the number of times the topicType (= player) +//+ can be the player in a role of a given type (= roleTypes) in an +//+ association of a given type (= objects owner). +//+----------------------------------------------------------------------------- +{ + "playerType" : [ "topic-psi-1", "topic-psi-2", "..." ], + "roleType" : [ "topic-psi-1", "topic-psi-2", "..." ], + "cardMin" : "unsigned integer in string representation", + "cardMax" : "unsigend integer in string representation or the string MAX_INT" +}
+//+----------------------------------------------------------------------------- +//+ otherRoleConstraint +//+ This JSON-Object defines the number and types of (other-) roles in an +//+ association of a given type with a role of a give type. +//+ roleType is a allowed role with the player topicType. +//+ otherRoleType is the second role with the player otherTopicType. +//+ The values cardMin and cardMax defines the cardinality of otherRoleType. +//+----------------------------------------------------------------------------- +{ + "playerType" : [ "topic-psi-1", "topic-psi-2", "..." ], + "roleType" : [ "topic-psi-1", "topic-psi-2", "..." ], + "otherRoleType" : [ "topic-psi-1", "topic-psi-2", "..." ], + "otherPlayerType" : [ "topic-psi-1", "topic-psi-2", "..." ], + "cardMin" : "unsigned integer in string representation", + "cardMax" : "unsigend integer in string representation or the string MAX_INT" +}
+//+----------------------------------------------------------------------------- +//+ associationConstraint +//+ The associationConstraint describes how an association of a given type +//+ has to be defined. +//+ associationRoleTypeConstraint constains all available roletypes for this +//+ association. +//+ rolePlayerConstraint constains all players for certain roles of a given +//+ type. +//+ associationTypeScopes contains all available scopes for this association. +//+----------------------------------------------------------------------------- +{ + "associationRoleConstraints" : [ <associationRoleConstraint>, <...> ], + "rolePlayerConstraints" : [ <rolePlayerConstraints>, <...> ], + "otherRoleConstraints" : [ <otherRoleConstraint>, <...> ], + "scopeConstraints" : { <scopeConstraint> } +}
+//+----------------------------------------------------------------------------- +//+ topicConstraint +//+ The topicConstraint contains the members: +//+ *subjectIdentifierConstraints which defines the subjectIdentifiers +//+ *subjectLocatorConstraints which defines the subjectLocators +//+ *topicNameConstraints which defines the topic names +//+ *topicOccurrenceConstraints which defines the topic occurrences +//+ *uniqueOccurrenceConstraints which defines the uniqueness of topic +//+ occurrences +//+----------------------------------------------------------------------------- +{ + "exclusiveInstances" : <exclusiveInstances>, + "subjectIdentifierConstraints" : [ <subjectIdentifierConstraint>, <...> ], + "subjectLocatorConstraints" : [ <subjectLocatorConstraint>, <...> ], + "topicNameConstraints" : [ <topoicNameConstriant>, <...> ], + "topicOccurrenceConstraints" : [ <topicOccurrenceConstraint>, <...> ], + "abstractConstraint" : <boolean> +} + + +//+----------------------------------------------------------------------------- +//+ fragmentConstraint +//+ This JSON-Object contains all constraints necessary for an entire +//+ fragment but not the exclusive-instance-constraint. +//+ The exclusive-instance-constraint should be sent before a +//+ fragmentConstraint separately. +//+ topicConstraint contains an object with all constraints of all baseTypes +//+ of the mainTopic. +//+ associationConstraints contains a list of all association constraints +//+ depending on all baseTypes of the main topic. +//+----------------------------------------------------------------------------- { - "topic" : { - "id" : "t403", - "itemIdentities" : [ "http : //psi.egovpt.org/itemIdentifiers#t100" ], - "subjectLocators" : null, - "subjectIdentifiers" : [ "http : //psi.egovpt.org/standard/ISO+19115%3A+Geographic+Information+-+Metadata" ], - "instanceOfs" : [ [ "http : //psi.egovpt.org/types/semanticstandard" ] ], - "names" : [ { - "itemIdentities" : [ "http : //psi.egovpt.org/itemIdentifiers#t100_n1" ], - "type" : null, - "scopes" : null, - "value" : "ISO 19115", - "variants" : [ { - "itemIdentities" : [ "http : //psi.egovpt.org/itemIdentifiers#t100_n1_v1" ], - "scopes" : [ [ "http : //www.topicmaps.org/xtm/1.0/core.xtm#display" ] ], - "resourceRef" : null, - "resourceData" : { - "datatype" : "http : //www.w3.org/2001/XMLSchema#string", - "value" : "Geographic Information - Metadata" - } - }, - { - "itemIdentities" : [ "http : //psi.egovpt.org/itemIdentifiers#t100_n1_v2" ], - "scopes" : [ [ "http : //www.topicmaps.org/xtm/1.0/core.xtm#sort" ] ], - "resourceRef" : null, - "resourceData" : { - "datatype" : "http : //www.w3.org/2001/XMLSchema#string", - "value" : "ISO-19115" - } - } - ] - } - ], - "occurrences" : [ { - "itemIdentities" : [ "http : //psi.egovpt.org/itemIdentifiers#t100_o1" ], - "type" : [ "http : //psi.egovpt.org/types/standardHasStatus" ], - "scopes" : null, - "resourceRef" : "http : //www.budabe.de/","resourceData" : null - }, - { - "itemIdentities" : [ "http : //psi.egovpt.org/itemIdentifiers#t100_o2" ], - "type" : [ "http : //psi.egovpt.org/types/description" ], - "scopes" : null, - "resourceRef" : null, - "resourceData" : { - "datatype" : "http : //www.w3.org/2001/XMLSchema#string", - "value" : "The ISO 19115 standard ..." - } - }, - { - "itemIdentities" : [ "http : //psi.egovpt.org/itemIdentifiers#t100_o3" ], - "type" : [ "http : //psi.egovpt.org/types/standardValidFromDate" ], - "scopes" : null, - "resourceRef" : null, - "resourceData" : { - "datatype" : "http : //www.w3.org/2001/XMLSchema#date", - "value" : "2003-01-01" - } - }, - { - "itemIdentities" : [ "http : //psi.egovpt.org/itemIdentifiers#t100_o4" ], - "type" : [ "http : //psi.egovpt.org/types/links" ], - "scopes" : null, - "resourceRef" : "http : //www.editeur.org/standards/ISO19115.pdf", - "resourceData" : null - } - ] - }, - "topicStubs" : [ { - "id" : "t227", - "itemIdentities" : [ "http : //psi.egovpt.org/itemIdentifiers#t3a" ], - "subjectLocators" : null, - "subjectIdentifiers" : [ "http : //psi.egovpt.org/types/semanticstandard" ] - }, - { - "id" : "t73", - "itemIdentities" : null, - "subjectLocators" : null, - "subjectIdentifiers" : [ "http : //www.topicmaps.org/xtm/1.0/core.xtm#display" ] - }, - { - "id" : "t67", - "itemIdentities" : null, - "subjectLocators" : null, - "subjectIdentifiers" : [ "http : //www.topicmaps.org/xtm/1.0/core.xtm#sort" ] - }, - { - "id" : "t291", - "itemIdentities" : [ "http : //psi.egovpt.org/itemIdentifiers#t51" ], - "subjectLocators" : null, - "subjectIdentifiers" : [ "http : //psi.egovpt.org/types/standardHasStatus" ] - }, - { - "id" : "t307", - "itemIdentities" : [ "http : //psi.egovpt.org/itemIdentifiers#t53" ], - "subjectLocators" : null, - "subjectIdentifiers" : [ "http : //psi.egovpt.org/types/description" ] - }, - { - "id" : "t315", - "itemIdentities" : [ "http : //psi.egovpt.org/itemIdentifiers#t54" ], - "subjectLocators" : null, - "subjectIdentifiers" : [ "http : //psi.egovpt.org/types/standardValidFromDate" ] - }, - { - "id" : "t323", - "itemIdentities" : [ "http : //psi.egovpt.org/itemIdentifiers#t55" ], - "subjectLocators" : null, - "subjectIdentifiers" : [ "http : //psi.egovpt.org/types/links" ] - }, - { - "id" : "t433", - "itemIdentities" : null, - "subjectLocators" : null, - "subjectIdentifiers" : [ "http : //psi.egovpt.org/subject/GeoData" ] - }, - { - "id" : "t363", - "itemIdentities" : [ "http : //psi.egovpt.org/itemIdentifiers#t60" ], - "subjectLocators" : null, - "subjectIdentifiers" : [ "http : //psi.egovpt.org/types/standardIsAboutSubject" ] - }, - { - "id" : "t371", - "itemIdentities" : [ "http : //psi.egovpt.org/itemIdentifiers#t61" ], - "subjectLocators" : null, - "subjectIdentifiers" : [ "http : //psi.egovpt.org/types/SubjectRoleType" ] - }, - { - "id" : "t421", - "itemIdentities" : null, - "subjectLocators" : null, - "subjectIdentifiers" : [ "http : //psi.egovpt.org/subject/Semantic+Description" ] - }, - { - "id" : "t395", - "itemIdentities" : [ "http : //psi.egovpt.org/itemIdentifiers#t64" ], - "subjectLocators" : null, - "subjectIdentifiers" : [ "http : //psi.egovpt.org/types/serviceUsesStandard" ] - }, - { - "id" : "t387", - "itemIdentities" : [ "http : //psi.egovpt.org/itemIdentifiers#t63" ], - "subjectLocators" : null, - "subjectIdentifiers" : [ "http : //psi.egovpt.org/types/ServiceRoleType" ] - }, - { - "id" : "t451", - "itemIdentities" : null, - "subjectLocators" : null, - "subjectIdentifiers" : [ "http : //psi.egovpt.org/service/Google+Maps", - "http : //maps.google.com" ] - }, - { - "id" : "t379", - "itemIdentities" : [ "http : //psi.egovpt.org/itemIdentifiers#t62" ], - "subjectLocators" : null, - "subjectIdentifiers" : [ "http : //psi.egovpt.org/types/StandardRoleType" ] - } - ], - "associations" : [ { - "itemIdentities" : null, - "type" : [ "http : //psi.egovpt.org/types/standardIsAboutSubject" ], - "scopes" : null, - "roles" : [ { - "itemIdentities" : null, - "type" : [ "http : //psi.egovpt.org/types/StandardRoleType" ], - "topicRef" : [ "http : //psi.egovpt.org/standard/ISO+19115%3A+Geographic+Information+-+Metadata" ] - }, - { - "itemIdentities" : null, - "type" : [ "http : //psi.egovpt.org/types/SubjectRoleType" ], - "topicRef" : [ "http : //psi.egovpt.org/subject/GeoData" ] - } - ] - }, - { - "itemIdentities" : null, - "type" : [ "http : //psi.egovpt.org/types/standardIsAboutSubject" ], - "scopes" : null, - "roles" : [ { - "itemIdentities" : null, - "type" : [ "http : //psi.egovpt.org/types/StandardRoleType" ], - "topicRef" : [ "http : //psi.egovpt.org/standard/ISO+19115%3A+Geographic+Information+-+Metadata" ] - }, - { - "itemIdentities" : null, - "type" : [ "http : //psi.egovpt.org/types/SubjectRoleType" ], - "topicRef" : [ "http : //psi.egovpt.org/subject/Semantic+Description" ] - } - ] - }, - { - "itemIdentities" : [ "http : //psi.egovpt.org/itemIdentifiers#assoc_7" ], - "type" : [ "http : //psi.egovpt.org/types/serviceUsesStandard" ], - "scopes" : null, - "roles" : [ { - "itemIdentities" : null, - "type" : [ "http : //psi.egovpt.org/types/ServiceRoleType" ], - "topicRef" : [ "http : //psi.egovpt.org/service/Google+Maps", - "http : //maps.google.com" ] - }, - { - "itemIdentities" : null, - "type" : [ "http : //psi.egovpt.org/types/StandardRoleType" ], - "topicRef" : [ "http : //psi.egovpt.org/standard/ISO+19115%3A+Geographic+Information+-+Metadata" ] - } - ] - } - ], - "tmIds" : [ "test-tm"] + "topicConstraints" : <topicConstraint>, + "associationsConstraints" : [ <associationConstraint>, <...> ] }
Modified: trunk/src/ajax/javascripts/make_fragment_node.js ============================================================================== --- trunk/src/ajax/javascripts/make_fragment_node.js (original) +++ trunk/src/ajax/javascripts/make_fragment_node.js Mon May 4 11:02:44 2009 @@ -1296,7 +1296,7 @@ // --- the ajax-request error handler function onFailureHandler(xhr) { - window.alert("Something went wrong ...\n" + xhr.status + ": " + xhr.statusText); + }
// --- the real ajax request @@ -1305,6 +1305,6 @@ var request = new Ajax.Request(requestUrl, {"method" : "get", "onSuccess" : onSuccessHandler, - "onFailure" : onFailureHandler + "onFailure" : function(xhr){ window.alert("Something went wrong ...\n" + xhr.status + ": " + xhr.statusText + "\n" + xhr.responseText); } }); } \ No newline at end of file
Modified: trunk/src/constants.lisp ============================================================================== --- trunk/src/constants.lisp (original) +++ trunk/src/constants.lisp Mon May 4 11:02:44 2009 @@ -15,6 +15,9 @@ :*isidorus-system* :*type-instance-psi* :*type-psi* + :*supertype-subtype-psi* + :*supertype-psi* + :*subtype-psi* :*xtm2.0-ns* :*xtm1.0-ns* :*xtm1.0-xlink*)) @@ -36,4 +39,10 @@
(defparameter *instance-psi* "http://psi.topicmaps.org/iso13250/model/instance")
+(defparameter *supertype-subtype-psi* "http://psi.topicmaps.org/iso13250/model/supertype-subtype") + +(defparameter *supertype-psi* "http://psi.topicmaps.org/iso13250/model/supertype") + +(defparameter *subtype-psi* "http://psi.topicmaps.org/iso13250/model/subtype") + (defparameter *isidorus-system* (asdf:find-system "isidorus"))
Modified: trunk/src/isidorus.asd ============================================================================== --- trunk/src/isidorus.asd (original) +++ trunk/src/isidorus.asd Mon May 4 11:02:44 2009 @@ -127,7 +127,10 @@ "json")) (:module "json" :components ((:file "json_exporter") - (:file "json_importer")) + (:file "json_importer") + (:file "json_tmcl_constants") + (:file "json_tmcl" + :depends-on ("json_tmcl_constants" "json_exporter"))) :depends-on ("model" "xml")) (:module "ajax" :components ((:static-file "isidorus.html")
Added: trunk/src/json/json_tmcl.lisp ============================================================================== --- (empty file) +++ trunk/src/json/json_tmcl.lisp Mon May 4 11:02:44 2009 @@ -0,0 +1,1201 @@ +;;+----------------------------------------------------------------------------- +;;+ 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 :json-tmcl + (:use :cl :datamodel :constants :json-tmcl-constants) + (:export :get-constraints-of-fragment + :topictype-p + :abstract-p)) + +(in-package :json-tmcl) + + +;; ----------------------------------------------------------------------------- +;; --- all fragment constraints ------------------------------------------------ +;; ----------------------------------------------------------------------------- +(defun get-constraints-of-fragment(topic-psi &key (treat-as 'type)) + (let ((associationtype (get-item-by-psi *associationtype-psi*)) + (associationtype-constraint (get-item-by-psi *associationtype-constraint-psi*)) + (topic + (let ((psi + (elephant:get-instance-by-value 'PersistentIdC 'uri topic-psi))) + (when psi + (identified-construct psi))))) + (when topic + (let ((topic-constraints + (let ((value + (get-constraints-of-topic topic :treat-as treat-as))) + (concatenate 'string ""topicConstraints":" value)))) + (let ((available-associations ;what's with association which have only a associationrole-constraint? + (get-available-associations-of-topic topic :treat-as treat-as))) + (dolist (item available-associations) + (topictype-p item associationtype associationtype-constraint)) + (let ((associations-constraints + (concatenate 'string ""associationsConstraints":" + (let ((inner-associations-constraints "[")) + (loop for available-association in available-associations + do (let ((value + (get-constraints-of-association available-association))) + (setf inner-associations-constraints + (concatenate 'string inner-associations-constraints value ",")))) + (if (string= inner-associations-constraints "[") + (setf inner-associations-constraints "null") + (setf inner-associations-constraints + (concatenate 'string (subseq inner-associations-constraints 0 (- (length inner-associations-constraints) 1)) "]"))))))) + (let ((json-string + (concatenate 'string + "{" topic-constraints "," associations-constraints "}"))) + json-string))))))) + + +;; ----------------------------------------------------------------------------- +;; --- all association constraints --------------------------------------------- +;; ----------------------------------------------------------------------------- +(defun get-constraints-of-association (associationtype-topic) + "Returns a list of constraints which are describing associations of the + passed associationtype-topic." + (let ((constraint-topics + (get-all-constraint-topics-of-association associationtype-topic))) + (let ((associationtypescope-constraints + (let ((value (get-typescope-constraints associationtype-topic :what 'association))) + (concatenate 'string ""scopeConstraints":" value))) + (associationrole-constraints + (let ((value + (get-associationrole-constraints (getf constraint-topics :associationrole-constraints)))) + (concatenate 'string ""associationRoleConstraints":" value))) + (roleplayer-constraints + (let ((value + (get-roleplayer-constraints (getf constraint-topics :roleplayer-constraints)))) + (concatenate 'string ""rolePlayerConstraints":" value))) + (otherrole-constraints + (let ((value + (get-otherrole-constraints (getf constraint-topics :otherrole-constraints)))) + (concatenate 'string ""otherRoleConstraints":" value)))) + (let ((json-string + (concatenate 'string "{" associationrole-constraints "," roleplayer-constraints "," + otherrole-constraints "," associationtypescope-constraints "}"))) + json-string)))) + + +(defun get-otherrole-constraints (constraint-topics) + "Returns a list of the form + ((::role <topic> :player <topic> :otherrole <topic> :othertopic <topic> :card-min <string> :card-max <string>) <...>) + which describes an otherrole constraint for the parent-association of a give type." + (let ((applies-to (get-item-by-psi *applies-to-psi*)) + (constraint-role (get-item-by-psi *constraint-role-psi*)) + (topictype-role (get-item-by-psi *topictype-role-psi*)) + (roletype-role (get-item-by-psi *roletype-role-psi*)) + (othertopictype-role (get-item-by-psi *othertopictype-role-psi*)) + (otherroletype-role (get-item-by-psi *otherroletype-role-psi*)) + (roletype (get-item-by-psi *roletype-psi*)) + (roletype-constraint (get-item-by-psi *roletype-constraint-psi*))) + (let ((otherrole-constraints + (loop for constraint-topic in constraint-topics + append (let ((players nil) + (roletypes nil) + (otherplayers nil) + (otherroletypes nil) + (constraint-list + (get-constraint-topic-values constraint-topic))) + (loop for role in (player-in-roles constraint-topic) + when (and (eq constraint-role (instance-of role)) + (eq applies-to (instance-of (parent role)))) + do (loop for other-role in (roles (parent role)) + do (let ((current-player (player other-role)) + (current-role (instance-of other-role))) + (cond + ((eq topictype-role current-role) + (push current-player players)) + ((eq roletype-role current-role) + (push current-player roletypes)) + ((eq othertopictype-role current-role) + (push current-player otherplayers)) + ((eq otherroletype-role current-role) + (push current-player otherroletypes)))))) + (when (and (append players roletypes otherplayers otherroletypes) + (or (not players) (not roletypes) (not otherplayers) (not otherroletypes))) + (error "otherroletype-constraint ~a is not complete:~%players: ~a~%roletypes: ~a~%otherplayers: ~a~%otherroletypes: ~a~%" + (uri (first (psis constraint-topic))) + (map 'list #'(lambda(x)(uri (first (psis x)))) players) + (map 'list #'(lambda(x)(uri (first (psis x)))) roletypes) + (map 'list #'(lambda(x)(uri (first (psis x)))) otherplayers) + (map 'list #'(lambda(x)(uri (first (psis x)))) otherroletypes))) + (let ((cross-product-1 + (loop for player in players + append (loop for roletype in roletypes + collect (list :player player :role roletype)))) + (cross-product-2 + (loop for otherplayer in otherplayers + append (loop for otherroletype in otherroletypes + collect (list :otherplayer otherplayer :otherrole otherroletype))))) + (let ((cross-product + (loop for tupple-1 in cross-product-1 + append (loop for tupple-2 in cross-product-2 + collect (append tupple-1 tupple-2 (list :constraint constraint-list)))))) + cross-product)))))) + (let ((involved-topic-tupples + (remove-duplicates + (loop for otherrole-constraint in otherrole-constraints + collect (let ((player (getf otherrole-constraint :player)) + (role-type (getf otherrole-constraint :role)) + (otherplayer (getf otherrole-constraint :otherplayer)) + (otherrole-type (getf otherrole-constraint :otherrole))) + (topictype-p player) + (topictype-p role-type roletype roletype-constraint) + (topictype-p otherplayer) + (topictype-p otherrole-type roletype roletype-constraint) + (list :player player + :role role-type + :otherplayer otherplayer + :otherrole otherrole-type))) + :test #'(lambda(x y) + (and (eq (getf x :player) (getf y :player)) + (eq (getf x :role) (getf y :role)) + (eq (getf x :otherplayer) (getf y :otherplayer)) + (eq (getf x :otherrole) (getf y :otherrole))))))) + (let ((cleaned-otherrole-constraints "[")) + (loop for involved-topic-tupple in involved-topic-tupples + do (let ((constraint-lists + (remove-duplicate-constraints + (loop for otherrole-constraint in otherrole-constraints + when (and (eq (getf otherrole-constraint :player) (getf involved-topic-tupple :player)) + (eq (getf otherrole-constraint :role) (getf involved-topic-tupple :role)) + (eq (getf otherrole-constraint :otherplayer) (getf involved-topic-tupple :otherplayer)) + (eq (getf otherrole-constraint :otherrole) (getf involved-topic-tupple :otherrole))) + collect (getf otherrole-constraint :constraint))))) + (when (> (length constraint-lists) 1) + (error "found contrary otherrole-constraints:~%player: ~a~%role: ~a~%otherplayer: ~a~%otherrole: ~a~% ~a~%" + (uri (first (psis (getf involved-topic-tupple :player)))) + (uri (first (psis (getf involved-topic-tupple :role)))) + (uri (first (psis (getf involved-topic-tupple :otherplayer)))) + (uri (first (psis (getf involved-topic-tupple :otherrole)))) + constraint-lists)) + (let ((json-player + (concatenate 'string ""playerType":" + (json-exporter::identifiers-to-json-string (getf involved-topic-tupple :player)))) + (json-role + (concatenate 'string ""roleType":" + (json-exporter::identifiers-to-json-string (getf involved-topic-tupple :role)))) + (json-otherplayer + (concatenate 'string ""otherPlayerType":" + (json-exporter::identifiers-to-json-string (getf involved-topic-tupple :player)))) + (json-otherrole + (concatenate 'string ""otherRoleType":" + (json-exporter::identifiers-to-json-string (getf involved-topic-tupple :role)))) + (card-min + (concatenate 'string ""cardMin":" (getf (first constraint-lists) :card-min))) + (card-max + (concatenate 'string ""cardMax":" (getf (first constraint-lists) :card-max)))) + (setf cleaned-otherrole-constraints + (concatenate 'string cleaned-otherrole-constraints + "{" json-player "," json-role "," json-otherplayer "," json-otherrole "," card-min "," card-max "},"))))) + (if (string= cleaned-otherrole-constraints "[") + (setf cleaned-otherrole-constraints "null") + (setf cleaned-otherrole-constraints + (concatenate 'string (subseq cleaned-otherrole-constraints 0 (- (length cleaned-otherrole-constraints) 1)) "]"))) + cleaned-otherrole-constraints))))) + + +(defun get-roleplayer-constraints (constraint-topics) + "Returns a list of the form + ((:role <topic> :player <topic> :card-min <string> :card-max <string>) <...>) + which describes the cardinality of topctypes used as players in roles of given + types in an association of a given type which is also the parent if this list." + (let ((applies-to (get-item-by-psi *applies-to-psi*)) + (constraint-role (get-item-by-psi *constraint-role-psi*)) + (topictype-role (get-item-by-psI *topictype-role-psi*)) + (roletype-role (get-item-by-psi *roletype-role-psi*)) + (roletype (get-item-by-psi *roletype-psi*)) + (roletype-constraint (get-item-by-psi *roletype-constraint-psi*))) + (let ((roleplayer-constraints + (loop for constraint-topic in constraint-topics + append (let ((constraint-list + (get-constraint-topic-values constraint-topic))) + (let ((players + (loop for role in (player-in-roles constraint-topic) + when (and (eq constraint-role (instance-of role)) + (eq applies-to (instance-of (parent role)))) + append (loop for other-role in (roles (parent role)) + when (eq topictype-role (instance-of other-role)) + collect (player other-role)))) + (roles + (loop for role in (player-in-roles constraint-topic) + when (and (eq constraint-role (instance-of role)) + (eq applies-to (instance-of (parent role)))) + append (loop for other-role in (roles (parent role)) + when (eq roletype-role (instance-of other-role)) + collect (player other-role))))) + (when (or (and players (not roles)) + (and roles (not players))) + (error "roleplayer-constraint ~a is not complete:~%players: ~a~%roles: ~a~%" + (uri (first (psis constraint-topic))) + (map 'list #'(lambda(x)(uri (first (psis x)))) players) + (map 'list #'(lambda(x)(uri (first (psis x)))) roles))) + (let ((cross-product + (loop for player in players + append (loop for role in roles + collect (list :player player :role role :constraint constraint-list))))) + cross-product)))))) + + (let ((role-player-tupples + (remove-duplicates + (loop for roleplayer-constraint in roleplayer-constraints + collect (let ((current-player (getf roleplayer-constraint :player)) + (current-role (getf roleplayer-constraint :role))) + (topictype-p current-player) + (topictype-p current-role roletype roletype-constraint) + (list :player current-player + :role current-role))) + :test #'(lambda(x y) + (and (eq (getf x :player) (getf y :player)) + (eq (getf x :role) (getf y :role))))))) + + (let ((cleaned-roleplayer-constraints "[")) + (loop for role-player-tupple in role-player-tupples + do (let ((constraint-lists + (remove-duplicate-constraints + (loop for roleplayer-constraint in roleplayer-constraints + when (and (eq (getf roleplayer-constraint :player) (getf role-player-tupple :player)) + (eq (getf roleplayer-constraint :role) (getf role-player-tupple :role))) + collect (getf roleplayer-constraint :constraint))))) + (when (> (length constraint-lists) 1) + (error "found contrary roleplayer-constraints:~%role: ~a~%player: ~a~% ~a ~%" + (uri (first (psis (getf role-player-tupple :role)))) + (uri (first (psis (getf role-player-tupple :player)))) + constraint-lists)) + (let ((json-player + (concatenate 'string ""playerType":" + (json-exporter::identifiers-to-json-string (getf role-player-tupple :player)))) + (json-role + (concatenate 'string ""roleType":" + (json-exporter::identifiers-to-json-string (getf role-player-tupple :role)))) + (card-min + (concatenate 'string ""cardMin":" (getf (first constraint-lists) :card-min))) + (card-max + (concatenate 'string ""cardMax":" (getf (first constraint-lists) :card-max)))) + (setf cleaned-roleplayer-constraints + (concatenate 'string cleaned-roleplayer-constraints + "{" json-player "," json-role "," card-min "," card-max "},"))))) + (if (string= cleaned-roleplayer-constraints "[") + (setf cleaned-roleplayer-constraints "null") + (setf cleaned-roleplayer-constraints + (concatenate 'string (subseq cleaned-roleplayer-constraints 0 (- (length cleaned-roleplayer-constraints) 1)) "]"))) + cleaned-roleplayer-constraints))))) + + +(defun get-associationrole-constraints (constraint-topics) + "Returns a list of the form + ((:associationroletype <topic> :card-min <string> :card-max <string>), <...>) + which describes all associationrole-constraints of the passed + constraint-topics." + (let ((applies-to (get-item-by-psi *applies-to-psi*)) + (roletype-role (get-item-by-psi *roletype-role-psi*)) + (constraint-role (get-item-by-psi *constraint-role-psi*)) + (roletype (get-item-by-psi *roletype-psi*)) + (roletype-constraint (get-item-by-psi *roletype-constraint-psi*))) + (let ((associationrole-constraints + (loop for constraint-topic in constraint-topics + append (let ((constraint-list + (get-constraint-topic-values constraint-topic))) + (loop for role in (player-in-roles constraint-topic) + when (and (eq constraint-role (instance-of role)) + (eq applies-to (instance-of (parent role)))) + append (loop for other-role in (roles (parent role)) + when (eq roletype-role (instance-of other-role)) + collect (list :associationroletype (player other-role) + :constraint constraint-list))))))) + (let ((associationroletype-topics + (remove-duplicates (map 'list #'(lambda(x) + (let ((associationroletype (getf x :associationroletype))) + (topictype-p associationroletype roletype roletype-constraint) + associationroletype)) + associationrole-constraints)))) + (let ((cleaned-associationrole-constraints "[")) + (loop for associationroletype-topic in associationroletype-topics + do (let ((constraint-lists + (remove-duplicate-constraints + (loop for associationrole-constraint in associationrole-constraints + when (eq associationroletype-topic (getf associationrole-constraint :associationroletype)) + collect (getf associationrole-constraint :constraint))))) + (when (> (length constraint-lists) 1) + (error "found contrary associationrole-constraints: ~a ~a~%" (uri (first (psis associationroletype-topic))) constraint-lists)) + (setf cleaned-associationrole-constraints + (concatenate 'string + cleaned-associationrole-constraints + "{"roleType":" (json-exporter::identifiers-to-json-string associationroletype-topic) + ","cardMin":" (getf (first constraint-lists) :card-min) + ","cardMax":" (getf (first constraint-lists) :card-max) "},")))) + + (if (string= cleaned-associationrole-constraints "[") + (setf cleaned-associationrole-constraints "null") + (setf cleaned-associationrole-constraints + (concatenate 'string (subseq cleaned-associationrole-constraints 0 (- (length cleaned-associationrole-constraints) 1)) "]"))) + cleaned-associationrole-constraints))))) + + +;; ----------------------------------------------------------------------------- +;; --- all topic constraints --------------------------------------------------- +;; ----------------------------------------------------------------------------- +(defun get-constraints-of-topic (topic-instance &key(treat-as 'type)) + "Returns a constraint list with the constraints: + subjectidentifier-constraints, subjectlocator-constraints, + topicname-constraints, topicoccurrence-constraints and + uniqueoccurrence-constraints." + (let ((constraint-topics + (get-all-constraint-topics-of-topic topic-instance :treat-as treat-as))) + (let ((exclusive-instance-constraints + (let ((value + (get-exclusive-instance-constraints (getf constraint-topics :exclusive-instance-constraints)))) + (concatenate 'string ""exclusiveInstances":" value))) + (subjectidentifier-constraints + (let ((value + (get-simple-constraints (getf constraint-topics :subjectidentifier-constraints) :error-msg-constraint-name "subjectidentifier"))) + (concatenate 'string ""subjectIdentifierConstraints":" value))) + (subjectlocator-constraints + (let ((value + (get-simple-constraints (getf constraint-topics :subjectlocator-constraints) :error-msg-constraint-name "subjectlocator"))) + (concatenate 'string ""subjectLocatorConstraints":" value))) + (topicname-constraints + (let ((value + (get-topicname-constraints (getf constraint-topics :topicname-constraints)))) + (concatenate 'string ""topicNameConstraints":" value))) + (topicoccurrence-constraints + (let ((value + (get-topicoccurrence-constraints (getf constraint-topics :topicoccurrence-constraints) + (getf constraint-topics :uniqueoccurrence-constraints)))) + (concatenate 'string ""topicOccurrenceConstraints":" value))) + (abstract-constraint + (concatenate 'string ""abstractConstraint":" + (if (getf constraint-topics :abstract-constraint) + "true" + "false")))) + (let ((json-string + (concatenate 'string "{" exclusive-instance-constraints "," subjectidentifier-constraints + "," subjectlocator-constraints "," topicname-constraints "," + topicoccurrence-constraints "," abstract-constraint "}"))) + json-string)))) + + +(defun get-exclusive-instance-constraints(exclusive-instances-lists) + "Returns a list of psis which represents some topics." + (let ((constraint-role (get-item-by-psi *constraint-role-psi*)) + (applies-to (get-item-by-psi *applies-to-psi*)) + (topictype-role (get-item-by-psi *topictype-role-psi*))) + (let ((topics + (remove-duplicates + (loop for exclusive-instances-list in exclusive-instances-lists + append (let ((owner (getf exclusive-instances-list :owner)) + (exclusive-constraints (getf exclusive-instances-list :exclusive-constraints))) + (loop for exclusive-constraint in exclusive-constraints + append (loop for role in (player-in-roles exclusive-constraint) + when (and (eq constraint-role (instance-of role)) + (eq applies-to (instance-of (parent role)))) + append (loop for other-role in (roles (parent role)) + when (and (eq topictype-role (instance-of other-role)) + (not (eq owner (player other-role)))) + collect (player other-role))))))))) + (json:encode-json-to-string (map 'list #'(lambda(y) + (map 'list #'uri y)) + (map 'list #'psis topics)))))) + + +(defun get-simple-constraints(constraint-topics &key (error-msg-constraint-name "uniqueoccurrence")) + "Returns a list of the form + ((:regexp <string> :card-min <string> :card-max <string>)) + which contains the subjectidentifier, subjectlocator or + unique-occurrence constraints. This depends on the passed + constraint-topics." + (let ((all-values + (remove-duplicate-constraints + (loop for constraint-topic in constraint-topics + collect (get-constraint-topic-values constraint-topic))))) + (let ((contrary-constraints (find-contrary-constraints all-values))) + (when contrary-constraints + (error "found contrary ~a-constraints: ~a~%" error-msg-constraint-name contrary-constraints))) + (simple-constraints-to-json all-values))) + + +(defun simple-constraints-to-json(simple-constraints) + "Transforms a list of simple constraint lists of the form + ((:regexp <string> :card-min <string> :card-max <string>) <...>) + to a valid json list of the form + [{"regexp":"expr","cardMin":"123","cardMax":"456"}, <...>]." + (let ((constraints "[")) + (loop for constraint in simple-constraints + do (let ((constraint (concatenate 'string "{"regexp":" + (json:encode-json-to-string (getf constraint :regexp)) + ","cardMin":" + (json:encode-json-to-string (getf constraint :card-min)) + ","cardMax":" + (json:encode-json-to-string (getf constraint :card-max)) + "}"))) + (if (string= constraints "[") + (setf constraints (concatenate 'string constraints constraint)) + (setf constraints (concatenate 'string constraints "," constraint))))) + (if (string= constraints "[") + (setf constraints "null") + (setf constraints (concatenate 'string constraints "]"))) + constraints)) + + +(defun get-topicname-constraints(constraint-topics) + "Returns all topicname constraints as a list of the following form: + ( ( :type <nametype-topic> + :constraints ( ( :regexp <string> :card-min <string> :card-max <string>) + <...>) + :scopes ( ( :scope <scope-topic> :regexp <string> :card-min <string> :card-max <string>) + <...>)) + <...>)." + (let ((constraint-role (get-item-by-psi *constraint-role-psi*)) + (applies-to (get-item-by-psi *applies-to-psi*)) + (nametype-role (get-item-by-psi *nametype-role-psi*)) + (nametype (get-item-by-psi *nametype-psi*)) + (nametype-constraint (get-item-by-psi *nametype-constraint-psi*))) + (let ((topicname-constraints + (remove-if #'null + (loop for constraint-topic in constraint-topics + append (loop for role in (player-in-roles constraint-topic) + when (and (eq constraint-role (instance-of role)) + (eq applies-to (instance-of (parent role)))) + append (loop for other-role in (roles (parent role)) + when (eq nametype-role (instance-of other-role)) + collect (let ((nametype-topic (player other-role)) + (constraint-list (get-constraint-topic-values constraint-topic))) + (list :type nametype-topic :constraint constraint-list)))))))) + + (let ((nametype-topics + (remove-duplicates (map 'list #'(lambda(x) + (let ((topicname-type + (getf x :type))) + (topictype-p topicname-type nametype nametype-constraint) + topicname-type)) + topicname-constraints)))) + (let ((cleaned-topicname-constraints "[")) + (loop for nametype-topic in nametype-topics + do (let ((constraint-lists + (remove-duplicate-constraints + (loop for topicname-constraint in topicname-constraints + when (eq nametype-topic (getf topicname-constraint :type)) + collect (getf topicname-constraint :constraint))))) + (let ((contrary-constraints + (find-contrary-constraints constraint-lists))) + (when contrary-constraints + (error "found contrary topicname-constraints: ~a~%" contrary-constraints))) + (let ((typescope-constraints + (let ((current-scopes + (get-typescope-constraints nametype-topic :what 'topicname))) + (concatenate 'string ""scopeConstraints":" current-scopes))) + (json-constraint-lists + (concatenate 'string ""constraints":" (simple-constraints-to-json constraint-lists))) + (type-topic + (concatenate 'string ""nameType":" + (json-exporter::identifiers-to-json-string nametype-topic)))) + (setf cleaned-topicname-constraints + (concatenate 'string cleaned-topicname-constraints "{" type-topic "," json-constraint-lists "," typescope-constraints "},"))))) + (if (string= cleaned-topicname-constraints "[") + (setf cleaned-topicname-constraints "null") + (setf cleaned-topicname-constraints + (concatenate 'string (subseq cleaned-topicname-constraints 0 (- (length cleaned-topicname-constraints) 1)) "]"))) + cleaned-topicname-constraints))))) + + +(defun get-topicoccurrence-constraints(constraint-topics unique-constraint-topics) + "Returns all topicoccurrence constraints as a list of the following form: + ( ( :type <occurrencetype-topic> + :constraints ( ( :regexp <string> :card-min <string> :card-max <string>) + <...>) + :scopes ( ( :scope <scope-topic> :regexp <string> :card-min <string> :card-max <string>) + <...>) + :datatype <string> + :uniqe ( ( :regexp <string> :dard-min <string> :card-max <string> ) ) + <...>)." + (let ((constraint-role (get-item-by-psi *constraint-role-psi*)) + (applies-to (get-item-by-psi *applies-to-psi*)) + (occurrencetype-role (get-item-by-psi *occurrencetype-role-psi*)) + (occurrencetype (get-item-by-psi *occurrencetype-psi*)) + (occurrencetype-constraint (get-item-by-psi *occurrencetype-constraint-psi*))) + (let ((topicoccurrence-constraints + (remove-if #'null + (loop for constraint-topic in constraint-topics + append (loop for role in (player-in-roles constraint-topic) + when (and (eq constraint-role (instance-of role)) + (eq applies-to (instance-of (parent role)))) + append (loop for other-role in (roles (parent role)) + when (eq occurrencetype-role (instance-of other-role)) + collect (let ((occurrencetype-topic (player other-role)) + (constraint-list (get-constraint-topic-values constraint-topic))) + (list :type occurrencetype-topic :constraint constraint-list)))))))) + (let ((occurrencetype-topics + (remove-duplicates (map 'list #'(lambda(x) + (let ((occurrence-type (getf x :type))) + (topictype-p occurrence-type occurrencetype occurrencetype-constraint) + occurrence-type)) + topicoccurrence-constraints)))) + (let ((cleaned-topicoccurrence-constraints "[")) + (loop for occurrencetype-topic in occurrencetype-topics + do (let ((constraint-lists + (remove-duplicate-constraints + (loop for topicoccurrence-constraint in topicoccurrence-constraints + when (eq occurrencetype-topic (getf topicoccurrence-constraint :type)) + collect (getf topicoccurrence-constraint :constraint))))) + (let ((contrary-constraints + (find-contrary-constraints constraint-lists))) + (when contrary-constraints + (error "found contrary topicname-constraints: ~a~%" contrary-constraints))) + (let ((type-topic + (concatenate 'string ""occurrenceType":" + (json-exporter::identifiers-to-json-string occurrencetype-topic))) + (typescope-constraints + (let ((current-scopes + (get-typescope-constraints occurrencetype-topic :what 'topicoccurrence))) + (concatenate 'string ""scopeConstraints":" current-scopes))) + (datatype-constraint + (concatenate 'string ""datatypeConstraint":" + (get-occurrence-datatype-constraint occurrencetype-topic))) + (unique-constraints + (concatenate 'string ""uniqueConstraints":" + (get-simple-constraints unique-constraint-topics))) + (json-constraint-lists + (concatenate 'string ""constraints":" (simple-constraints-to-json constraint-lists)))) + (setf cleaned-topicoccurrence-constraints + (concatenate 'string cleaned-topicoccurrence-constraints + "{" type-topic "," json-constraint-lists "," typescope-constraints "," datatype-constraint "," unique-constraints "},"))))) + (if (string= cleaned-topicoccurrence-constraints "[") + (setf cleaned-topicoccurrence-constraints "null") + (setf cleaned-topicoccurrence-constraints + (concatenate 'string (subseq cleaned-topicoccurrence-constraints 0 (- (length cleaned-topicoccurrence-constraints) 1)) "]"))) + cleaned-topicoccurrence-constraints))))) + + +(defun get-occurrence-datatype-constraint(occurrencetype-topic) + "Return a datatype qualifier as a string." + (let ((constraint-role (get-item-by-psi *constraint-role-psi*)) + (applies-to (get-item-by-psi *applies-to-psi*)) + (occurrencetype-role (get-item-by-psi *occurrencetype-role-psi*)) + (datatype (get-item-by-psi *datatype-psi*)) + (occurrencedatatype-constraint (get-item-by-psi *occurrencedatatype-constraint-psi*))) + (let ((datatype-constraints + (remove-duplicates + (loop for role in (player-in-roles occurrencetype-topic) + when (and (eq occurrencetype-role (instance-of role)) + (eq applies-to (instance-of (parent role)))) + append (loop for other-role in (roles (parent role)) + when (and (eq constraint-role (instance-of other-role)) + (topictype-of-p (player other-role) occurrencedatatype-constraint)) + collect (player other-role)))))) + (let ((datatype-constraint + (remove-duplicates + (map 'list #'(lambda(constraint-topic) + (loop for occurrence in (occurrences constraint-topic) + when (and (eq (instance-of occurrence) datatype) + (slot-boundp occurrence 'charvalue)) + return (charvalue occurrence))) + datatype-constraints)))) + (when (> (length datatype-constraint) 1) + (error "found contrary occurrence-datatype-constraints: ~a~%" datatype-constraints)) + (if datatype-constraint + (json:encode-json-to-string (first datatype-constraint)) + nil))))) + + +(defun get-typescope-constraints(element-type-topic &key(what 'topicname)) + "Returns a list of scopes for the element-typetopic which is the type topic of + a topicname, a topicoccurrence or an association. To specifiy of what kind + of element the scopes should be there is the key-variable what. + It can be set to 'topicname, 'topicoccurrence or 'association. + The return value is of the form + ( :scope <scope-topic> + :constraint (:card-min <string> :card-max <string> ))." + (let ((element-type-role-and-scope-constraint + (cond + ((eq what 'topicname) + (list (get-item-by-psi *nametype-role-psi*) + (get-item-by-psi *nametypescope-constraint-psi*))) + ((eq what 'topicoccurrence) + (list + (get-item-by-psi *occurrencetype-role-psi*) + (get-item-by-psi *occurrencetypescope-constraint-psi*))) + ((eq what 'association) + (list + (get-item-by-psi *associationtype-role-psi*) + (get-item-by-psi *associationtypescope-constraint-psi*))))) + (scopetype-role (get-item-by-psi *scopetype-role-psi*)) + (constraint-role (get-item-by-psi *constraint-role-psi*)) + (applies-to (get-item-by-psi *applies-to-psi*))) + (when (and (= (length element-type-role-and-scope-constraint) 2) + (first element-type-role-and-scope-constraint) + (second element-type-role-and-scope-constraint)) + (let ((type-role (first element-type-role-and-scope-constraint)) + (typescope-constraint (second element-type-role-and-scope-constraint))) + (let ((typescope-constraints + (loop for role in (player-in-roles element-type-topic) + when (and (eq type-role (instance-of role)) + (eq applies-to (instance-of (parent role)))) + append (loop for other-role in (roles (parent role)) + when (and (eq constraint-role (instance-of other-role)) + (topictype-of-p (player other-role) typescope-constraint)) + collect (let ((scopes nil) + (constraint nil)) + (loop for c-role in (player-in-roles (player other-role)) + when (and (eq constraint-role (instance-of c-role)) + (eq applies-to (instance-of (parent c-role)))) + do (progn + (setf constraint (get-constraint-topic-values (player c-role))) + (loop for c-other-role in (roles (parent c-role)) + when (eq scopetype-role (instance-of c-other-role)) + do (push (player c-other-role) scopes)))) + (list :scopes scopes :constraint constraint)))))) + (let ((scopetype-groups + (remove-duplicates (map 'list #'(lambda(x) + (let ((scopes (getf x :scopes))) + (when scopes + scopes))) + typescope-constraints) + :test #'(lambda(x y) + (when (and (= (length x) (length y)) + (= (length x) (length (intersection x y)))) + t))))) + (let ((cleaned-typescope-constraints "[")) + (loop for scopetype-group in scopetype-groups + do (let ((constraint-lists + (remove-duplicate-constraints + (loop for typescope-constraint in typescope-constraints + when (and (= (length (getf typescope-constraint :scopes)) + (length scopetype-group)) + (= (length (getf typescope-constraint :scopes)) + (length (intersection (getf typescope-constraint :scopes) scopetype-group)))) + collect (getf typescope-constraint :constraint))))) + (when (> (length constraint-lists) 1) + (error "found contrary scopetype-constraints for ~a: ~a~%" + (map 'list #'(lambda(x)(uri (first (psis x)))) scopetype-group) + constraint-lists)) + (let ((card-min (getf (first constraint-lists) :card-min)) + (card-max (getf (first constraint-lists) :card-max))) + (let ((json-scopes ""scopeTypes":[")) + (dolist (item scopetype-group) + (let ((json-list (json-exporter::identifiers-to-json-string item))) + (setf json-scopes (concatenate 'string json-scopes json-list ",")))) + (setf json-scopes (subseq json-scopes 0 (- (length json-scopes) 1))) + (let ((current-json-string + (concatenate 'string "{" json-scopes "],"cardMin":"" card-min "","cardMax":"" card-max ""}"))) + (setf cleaned-typescope-constraints + (concatenate 'string cleaned-typescope-constraints current-json-string ","))))))) + (if (string= cleaned-typescope-constraints "[") + (setf cleaned-typescope-constraints "null") + (setf cleaned-typescope-constraints + (concatenate 'string (subseq cleaned-typescope-constraints 0 (- (length cleaned-typescope-constraints) 1)) "]"))) + cleaned-typescope-constraints))))))) + + +;; ----------------------------------------------------------------------------- +;; --- some basic helpers ------------------------------------------------------ +;; ----------------------------------------------------------------------------- +(defun get-constraint-topic-values(topic) + "Returns all constraint values of the passed topic in the + following form (list :regexp regexp :card-min card-min :card-max card-max)" + (let ((regexp + (get-constraint-occurrence-value topic)) + (card-min + (get-constraint-occurrence-value topic :what 'card-min)) + (card-max + (get-constraint-occurrence-value topic :what 'card-max))) + (when (and (string/= "MAX_INT" card-max) + (> (parse-integer card-min) (parse-integer card-max))) + (error "card-min (~a) must be < card-max (~a)" card-min card-max)) + (list :regexp regexp :card-min card-min :card-max card-max))) + + +(defun get-constraint-occurrence-value(topic &key (what 'regexp)) + "Checks the occurrence-value of a regexp, card-min or card-max + constriant-occurrence. + If what = 'regexp and the occurrence-value is empty there will be returned + the value '.*!'. + If what = 'card-min and the occurrence-value is empty there will be returned + the value '0'. + If what = 'card-max and the occurrence-value is empty there will be returned + the value 'MAX_INT'" + (let ((occurrence-type + (get-item-by-psi + (cond + ((eq what 'regexp) + *regexp-psi*) + ((eq what 'card-min) + *card-min-psi*) + ((eq what 'card-max) + *card-max-psi*) + (t + ""))))) + (when occurrence-type + (let ((occurrence-value + (let ((occurrence + (find occurrence-type (occurrences topic) :key #'instance-of))) + (if (and occurrence + (slot-boundp occurrence 'charvalue) + (> (length (charvalue occurrence)) 0)) + (charvalue occurrence) + (cond + ((eq what 'regexp) + ".*") + ((eq what 'card-min) + "0") + ((eq what 'card-max) + "MAX_INT")))))) + (cond + ((eq what 'card-min) + (let ((is-valid + (handler-case (let ((card-min + (parse-integer occurrence-value))) + (when (>= card-min 0) + t)) + (condition () nil)))) + (unless is-valid + (error "card-min in ~a is "~a" but should be >= 0" + (uri (first (psis topic))) + occurrence-value)))) + ((eq what 'card-max) + (let ((is-valid + (handler-case (let ((card-max + (parse-integer occurrence-value))) + (when (>= card-max 0) + t)) + (condition () (when (string= occurrence-value "MAX_INT") + t))))) + (unless is-valid + (error "card-max in ~a is "~a" but should be >= 0 or "MAX_INT"" + (uri (first (psis topic))) + occurrence-value))))) + occurrence-value)))) + + +(defun find-contrary-constraints(constraint-lists) + "Returns a list which contains a list of minimum two contrary constraints + or nil if there are no contrary constraints. + The list is of the form + (list (list :regexp <regexp> :card-min <card-min> :card-max <card-max>) (list ...))." + (let ((current-constraint nil)) + (loop for constraint-list in constraint-lists + do (progn + (when (> (length current-constraint) 0) + (return-from find-contrary-constraints current-constraint)) + (setf current-constraint (remove-if #'null (map 'list #'(lambda(x) + (contrary-constraint-list x constraint-list)) + constraint-lists))))))) + +(defun contrary-constraint-list (lst-1 lst-2) + "Returns both passed lists when they have the same + regular expression but different card-min or card-max values." + (when (and (typep lst-1 'list) (typep lst-2 'list) + (= 6 (length lst-1) (length lst-2))) + (when (and (string= (getf lst-1 :regexp) (getf lst-2 :regexp)) + (or (string/= (getf lst-1 :card-min) (getf lst-2 :card-min)) + (string/= (getf lst-1 :card-max) (getf lst-2 :card-max)))) + (list lst-1 lst-2)))) + + +(defun remove-duplicate-constraints(constraint-lists) + "Removes duplicate constraints of the passed constraint list. + This list should have the form + (list (list :regexp <regexp> :card-min <card-min> :card-max <card-max>) (list ...)). + A constraint is defined as equal whan all three value (regexp, card-min and card-max + are equal." + (remove-duplicates constraint-lists :test #'eql-constraint-list)) + + + +(defun eql-constraint-list (lst-1 lst-2) + "Compares two constraint lists of the form (list <string> <string> string>) + or (list <topic> <string> <string> <string>." + (when (and (typep lst-1 'list) (typep lst-2 'list) + (= 6 (length lst-1) (length lst-2))) + (and (string= (getf lst-1 :regexp) (getf lst-2 :regexp)) + (string= (getf lst-1 :card-min) (getf lst-2 :card-min)) + (string= (getf lst-1 :card-max) (getf lst-2 :card-max))))) + + +;; --- checks if the given topic is a valid topictype -------------------------- +(defun get-direct-types-of-topic(topic-instance) + "Returns the direct types of the topic as a list passed to this function. + This function only returns the types of the type-instance-relationship -> TMDM 7.2" + (let ((type-instance (get-item-by-psi *type-instance-psi*)) + (instance (get-item-by-psi *instance-psi*)) + (type (get-item-by-psi *type-psi*))) + (let ((topic-types + (loop for role in (player-in-roles topic-instance) + when (eq instance (instance-of role)) + collect (loop for other-role in (roles (parent role)) + when (and (not (eq role other-role)) + (eq type-instance (instance-of (parent role))) + (eq type (instance-of other-role))) + return (player other-role))))) + (when topic-types + (remove-if #'null topic-types))))) + + +(defun get-direct-supertypes-of-topic(topic-instance) + "Returns the direct supertypes of the topic as a list passed to this function. + This function only returns the types of the supertype-subtype-relationship -> TMDM 7.3" + (let ((supertype-subtype (get-item-by-psi *supertype-subtype-psi*)) + (supertype (get-item-by-psi *supertype-psi*)) + (subtype (get-item-by-psi *subtype-psi*))) + (let ((supertypes + (loop for role in (player-in-roles topic-instance) + when (eq subtype (instance-of role)) + append (loop for other-role in (roles (parent role)) + when (and (not (eq role other-role)) + (eq supertype-subtype (instance-of (parent role))) + (eq supertype (instance-of other-role))) + collect (player other-role))))) + (remove-if #'null supertypes)))) + + +(defun subtype-p (topic-instance &optional (topictype (get-item-by-psi *topictype-psi*)) (checked-topics nil)) + "Returns a list of all supertypes of the passed topic if the passed topic + is not an instanceOf any other topic but a subtype of some supertypes + of topictype or it is the topictype-topic itself." + ;(format t "~%~%subtype-p ~a~%" (uri (first (psis topic-instance)))) + (let ((current-checked-topics (remove-duplicates (append checked-topics (list topic-instance))))) + + (when (eq topictype topic-instance) + (return-from subtype-p current-checked-topics)) + + (when (get-direct-types-of-topic topic-instance) + (return-from subtype-p nil)) + + (let ((supertypes-of-this (get-direct-supertypes-of-topic topic-instance))) + (when (not supertypes-of-this) + (return-from subtype-p nil)) + (when supertypes-of-this + (loop for supertype-of-this in supertypes-of-this + when (not (find supertype-of-this current-checked-topics :test #'eq)) + do (let ((further-supertypes (subtype-p topictype supertype-of-this current-checked-topics))) + (when (not further-supertypes) + (return-from subtype-p nil)) + + (dolist (item further-supertypes) + (pushnew item current-checked-topics)))))) + + current-checked-topics)) + + +(defun topictype-p (topic-instance &optional (topictype (get-item-by-psi *topictype-psi*)) + (topictype-constraint (get-item-by-psi *topictype-constraint-psi*)) + (checked-topics nil)) + "Returns a list of all instanceOf-topics and all Supertypes of this topic + if this topic is a valid topic (-type). I.e. the passed topic is the + topictype or it is an instanceOf of the topictype or it is a subtype of + the topictype. TMDM 7.2 + TMDM 7.3" + ;(format t "~%~%topictype-p ~a~%" (uri (first (psis topic-instance)))) + (let ((current-checked-topics (append checked-topics (list topic-instance))) + (akos-of-this (get-direct-supertypes-of-topic topic-instance)) + (isas-of-this (get-direct-types-of-topic topic-instance))) + + (when (eq topictype topic-instance) + (return-from topictype-p current-checked-topics)) + + (when (not (union akos-of-this isas-of-this :test #'eq)) + (when topictype-constraint + ;(return-from topictype-p nil)) + (error "~a is not a valid type for ~a" (uri (first (psis topic-instance))) (uri (first (psis topictype))))) + (return-from topictype-p current-checked-topics)) + + (let ((akos-are-topictype nil)) + (loop for ako-of-this in akos-of-this + when (not (find ako-of-this current-checked-topics)) + do (let ((further-topics (topictype-p ako-of-this topictype topictype-constraint))) + (if further-topics + (progn + (dolist (item further-topics) + (pushnew item current-checked-topics)) + (pushnew ako-of-this akos-are-topictype)) + (when topictype-constraint + ;(return-from topictype-p nil))))) + (error "~a is not a valid type for ~a" (uri (first (psis topic-instance))) (uri (first (psis topictype)))))))) + + (when isas-of-this + (let ((topictype-topics-of-isas nil)) + (loop for isa-of-this in isas-of-this + do (let ((topic-akos (subtype-p isa-of-this topictype))) + (when topic-akos + (pushnew isa-of-this topictype-topics-of-isas) + (pushnew isa-of-this current-checked-topics) + (dolist (item topic-akos) + (pushnew item current-checked-topics))))) + + (when (and (not topictype-topics-of-isas) + (not akos-are-topictype) + topictype-constraint) + ;(return-from topictype-p nil)) + (error "~a is not a valid type for ~a" (uri (first (psis topic-instance))) (uri (first (psis topictype))))) + + (loop for isa-of-this in isas-of-this + when (and (not (find isa-of-this current-checked-topics :test #'eq)) + (not (find isa-of-this topictype-topics-of-isas :test #'eq))) + do (let ((further-topic-types (topictype-p isa-of-this topictype topictype-constraint current-checked-topics))) + (if further-topic-types + (dolist (item further-topic-types) + (pushnew item current-checked-topics)) + (when topictype-constraint + ;(return-from topictype-p nil)))))))) + (error "~a is not a valid type for ~a" (uri (first (psis topic-instance))) (uri (first (psis topictype))))))))))) + current-checked-topics)) + + +(defun topictype-of-p (topic-instance type-instance &optional checked-topics) + "Returns a list of all types and supertypes of this topic if this topic is a + valid instance-topic of the type-topic called type-instance. TMCL 4.4.2" + (let ((current-checked-topics (append checked-topics (list topic-instance))) + (topictype (get-item-by-psi *topictype-psi*)) + (isas-of-this (get-direct-types-of-topic topic-instance)) + (akos-of-this (get-direct-supertypes-of-topic topic-instance))) + + (when (eq topic-instance topictype) + t) + + (when (and (not isas-of-this) + (not akos-of-this)) + (return-from topictype-of-p nil)) + + (loop for isa-of-this in isas-of-this + do (let ((found-topics (topictype-p isa-of-this))) + (when (not found-topics) + (return-from topictype-of-p nil)) + (dolist (item found-topics) + (pushnew item current-checked-topics)))) + + (loop for ako-of-this in akos-of-this + when (not (find ako-of-this current-checked-topics :test #'eq)) + do (let ((found-topics (topictype-of-p ako-of-this type-instance current-checked-topics))) + (when (not found-topics) + (return-from topictype-of-p nil)) + (dolist (item found-topics) + (pushnew item current-checked-topics)))) + + (when (find type-instance current-checked-topics) + current-checked-topics))) + + +;; --- gets all constraint topics ---------------------------------------------- +(defun get-direct-constraint-topics-of-topic (topic-instance) + "Returns all constraint topics defined for the passed topic-instance" + (let ((constraint-role (get-item-by-psi *constraint-role-psi*)) + (topictype-role (get-item-by-psi *topictype-role-psi*)) + (applies-to (get-item-by-psi *applies-to-psi*)) + (abstract-topictype-constraint (get-item-by-psi *abstract-topictype-constraint-psi*)) + (exclusive-instance-constraint (get-item-by-psi *exclusive-instance-psi*)) + (subjectidentifier-constraint (get-item-by-psi *subjectidentifier-constraint-psi*)) + (subjectlocator-constraint (get-item-by-psi *subjectlocator-constraint-psi*)) + (topicname-constraint (get-item-by-psi *topicname-constraint-psi*)) + (topicoccurrence-constraint (get-item-by-psi *topicoccurrence-constraint-psi*)) + (uniqueoccurrence-constraint (get-item-by-psi *uniqueoccurrence-constraint-psi*)) + (roleplayer-constraint (get-item-by-psi *roleplayer-constraint-psi*)) + (otherrole-constraint (get-item-by-psi *otherrole-constraint-psi*)) + (abstract-topictype-constraints nil) + (exclusive-instance-constraints nil) + (subjectidentifier-constraints nil) + (subjectlocator-constraints nil) + (topicname-constraints nil) + (topicoccurrence-constraints nil) + (uniqueoccurrence-constraints nil)) + + (loop for role in (player-in-roles topic-instance) + when (and (eq topictype-role (instance-of role)) + (eq applies-to (instance-of (parent role)))) + do (loop for other-role in (roles (parent role)) + when (eq constraint-role (instance-of other-role)) + do (let ((constraint-topic (player other-role))) + (cond + ((topictype-of-p constraint-topic abstract-topictype-constraint) + (pushnew constraint-topic abstract-topictype-constraints)) + ((topictype-of-p constraint-topic exclusive-instance-constraint) + (pushnew constraint-topic exclusive-instance-constraints)) + ((topictype-of-p constraint-topic subjectidentifier-constraint) + (pushnew constraint-topic subjectidentifier-constraints)) + ((topictype-of-p constraint-topic subjectlocator-constraint) + (pushnew constraint-topic subjectlocator-constraints)) + ((topictype-of-p constraint-topic topicname-constraint) + (pushnew constraint-topic topicname-constraints)) + ((topictype-of-p constraint-topic topicoccurrence-constraint) + (pushnew constraint-topic topicoccurrence-constraints)) + ((topictype-of-p constraint-topic uniqueoccurrence-constraint) + (pushnew constraint-topic uniqueoccurrence-constraints)) + (t + (unless (or (topictype-of-p constraint-topic roleplayer-constraint) + (topictype-of-p constraint-topic otherrole-constraint)) + (error "Constraint-Topic "~a" could not be handled" (uri (first (psis constraint-topic)))))))))) + (list :abstract-topictype-constraints abstract-topictype-constraints + :exclusive-instance-constraints (list :exclusive-constraints exclusive-instance-constraints + :owner topic-instance) + :subjectidentifier-constraints subjectidentifier-constraints + :subjectlocator-constraints subjectlocator-constraints + :topicname-constraints topicname-constraints + :topicoccurrence-constraints topicoccurrence-constraints + :uniqueoccurrence-constraints uniqueoccurrence-constraints))) + + +(defmethod get-all-constraint-topics-of-topic (topic-instance &key (treat-as 'type)) + "Returns a list of constraint-topics of the topics-instance's base type(s). + If topic c is instanceOf a and b, there will be returned all + constraint-topics of the topic types a and b. + If treat-as is set to instance there will be only the constraints collected + defined for the supertypes or the types of the passed topic - all constraints + defined directly for the passed topic are ignored, unless the passed topic is + an instance of itself." + (let ((akos-and-isas-of-this + (remove-duplicates + (if (eql treat-as 'type) + (topictype-p topic-instance) + (loop for topic in (union (get-direct-types-of-topic topic-instance) (get-direct-supertypes-of-topic topic-instance)) + append (topictype-p topic)))))) + (let ((all-abstract-topictype-constraints nil) + (all-exclusive-instance-constraints nil) + (all-subjectidentifier-constraints nil) + (all-subjectlocator-constraints nil) + (all-topicname-constraints nil) + (all-topicoccurrence-constraints nil) + (all-uniqueoccurrence-constraints nil)) + (loop for topic in akos-and-isas-of-this + do (let ((constraint-topics-of-topic (get-direct-constraint-topics-of-topic topic))) + (when (eq topic topic-instance) + (dolist (item (getf constraint-topics-of-topic :abstract-topictype-constraints)) + (pushnew item all-abstract-topictype-constraints))) + (let ((exclusive-instance-constraints + (getf constraint-topics-of-topic :exclusive-instance-constraints))) + (when (getf exclusive-instance-constraints :exclusive-constraints) + (push exclusive-instance-constraints all-exclusive-instance-constraints))) + (dolist (item (getf constraint-topics-of-topic :subjectidentifier-constraints)) + (pushnew item all-subjectidentifier-constraints)) + (dolist (item (getf constraint-topics-of-topic :subjectlocator-constraints)) + (pushnew item all-subjectlocator-constraints)) + (dolist (item (getf constraint-topics-of-topic :topicname-constraints)) + (pushnew item all-topicname-constraints)) + (dolist (item (getf constraint-topics-of-topic :topicoccurrence-constraints)) + (pushnew item all-topicoccurrence-constraints)) + (dolist (item (getf constraint-topics-of-topic :uniqueoccurrence-constraints)) + (pushnew item all-uniqueoccurrence-constraints)))) + (list :abstract-topictype-constraints all-abstract-topictype-constraints + :exclusive-instance-constraints all-exclusive-instance-constraints + :subjectidentifier-constraints all-subjectidentifier-constraints + :subjectlocator-constraints all-subjectlocator-constraints + :topicname-constraints all-topicname-constraints + :topicoccurrence-constraints all-topicoccurrence-constraints + :uniqueoccurrence-constraints all-uniqueoccurrence-constraints)))) + + +(defun abstract-p (topic-instance) + "Returns t if this topic type is an abstract topic type." + (let ((constraint-role (get-item-by-psi *constraint-role-psi*)) + (topictype-role (get-item-by-psi *topictype-role-psi*)) + (applies-to (get-item-by-psi *applies-to-psi*)) + (abstract-topictype-constraint (get-item-by-psi *abstract-topictype-constraint-psi*))) + + (loop for role in (player-in-roles topic-instance) + when (and (eq topictype-role (instance-of role)) + (eq applies-to (instance-of (parent role)))) + return (loop for other-role in (roles (parent role)) + when (and (eq constraint-role (instance-of other-role)) + (eq abstract-topictype-constraint (player other-role))) + return t)))) + + +(defun get-direct-constraint-topics-of-association(associationtype-topic) + "Returns all direct constraint topics defined for associations if + the passed associationtype-topic" + (let ((constraint-role (get-item-by-psi *constraint-role-psi*)) + (associationtype-role (get-item-by-psi *associationtype-role-psi*)) + (applies-to (get-item-by-psi *applies-to-psi*)) + (associationtypescope-constraint (get-item-by-psi *associationtypescope-constraint-psi*)) + (associationrole-constraint (get-item-by-psi *associationrole-constraint-psi*)) + (roleplayer-constraint (get-item-by-psi *roleplayer-constraint-psi*)) + (otherrole-constraint (get-item-by-psi *otherrole-constraint-psi*)) + (associationrole-constraints nil) + (roleplayer-constraints nil) + (otherrole-constraints nil)) + + (loop for role in (player-in-roles associationtype-topic) + when (and (eq associationtype-role (instance-of role)) + (eq applies-to (instance-of (parent role)))) + do (loop for other-role in (roles (parent role)) + when (eq constraint-role (instance-of other-role)) + do (let ((constraint-topic (player other-role))) + (cond + ((topictype-of-p constraint-topic associationtypescope-constraint) + t) ;do nothing + ((topictype-of-p constraint-topic associationrole-constraint) + (pushnew constraint-topic associationrole-constraints)) + ((topictype-of-p constraint-topic roleplayer-constraint) + (pushnew constraint-topic roleplayer-constraints)) + ((topictype-of-p constraint-topic otherrole-constraint) + (pushnew constraint-topic otherrole-constraints)) + (t + (error "Constraint-Topic "~a" could not be handled" (uri (first (psis constraint-topic))))))))) + + (list :associationrole-constraints associationrole-constraints + :roleplayer-constraints roleplayer-constraints + :otherrole-constraints otherrole-constraints))) + + +(defun get-all-constraint-topics-of-association(associationtype-topic) + "Returns all constraint topics defined for associations if + the passed associationtype-topic." + (let ((akos-and-isas-of-this + (topictype-p associationtype-topic (get-item-by-psi *associationtype-psi*) (get-item-by-psi *associationtype-constraint-psi*)))) + (let ((all-associationrole-constraints nil) + (all-roleplayer-constraints nil) + (all-otherrole-constraints nil)) + (loop for topic in akos-and-isas-of-this + do (let ((constraint-topics-of-topic + (get-direct-constraint-topics-of-association topic))) + (dolist (item (getf constraint-topics-of-topic :associationrole-constraints)) + (pushnew item all-associationrole-constraints)) + (dolist (item (getf constraint-topics-of-topic :roleplayer-constraints)) + (pushnew item all-roleplayer-constraints)) + (dolist (item (getf constraint-topics-of-topic :otherrole-constraints)) + (pushnew item all-otherrole-constraints)))) + (list :associationrole-constraints all-associationrole-constraints + :roleplayer-constraints all-roleplayer-constraints + :otherrole-constraints all-otherrole-constraints)))) + + +(defun get-available-associations-of-topic(topic-instance &key (treat-as 'type)) + "Returns a list of topics decribing the available associationtype for the + passed topic." + (let ((applies-to (get-item-by-psi *applies-to-psi*)) + (topictype-role (get-item-by-psi *topictype-role-psi*)) + (constraint-role (get-item-by-psi *constraint-role-psi*)) + (othertopictype-role (get-item-by-psi *othertopictype-role-psi*)) + (associationtype-role (get-item-by-psi *associationtype-role-psi*)) + (roleplayer-constraint (get-item-by-psi *roleplayer-constraint-psi*)) + (otherrole-constraint (get-item-by-psi *otherrole-constraint-psi*)) + (all-possible-player-topics + (remove-duplicates + (if (eql treat-as 'type) + (topictype-p topic-instance) + (loop for topic in (union (get-direct-types-of-topic topic-instance) (get-direct-supertypes-of-topic topic-instance)) + append (topictype-p topic)))))) + + + ;what's with associationrole-constraints without a player-constraint??? + (let ((all-available-associationtypes + (remove-duplicates + (loop for possible-player-topic in all-possible-player-topics + append (loop for role in (player-in-roles possible-player-topic) + when (and (or (eq topictype-role (instance-of role)) + (eq othertopictype-role (instance-of role))) + (eq applies-to (instance-of (parent role)))) + append (loop for other-role in (roles (parent role)) + when (and (eq constraint-role (instance-of other-role)) + (or (topictype-of-p (player other-role) roleplayer-constraint) + (topictype-of-p (player other-role) otherrole-constraint))) + append (loop for c-role in (player-in-roles (player other-role)) + when (and (eq constraint-role (instance-of c-role)) + (eq applies-to (instance-of (parent c-role)))) + append (loop for type-role in (roles (parent c-role)) + when (eq associationtype-role (instance-of type-role)) + collect (player type-role))))))))) + all-available-associationtypes))) \ No newline at end of file
Added: trunk/src/json/json_tmcl_constants.lisp ============================================================================== --- (empty file) +++ trunk/src/json/json_tmcl_constants.lisp Mon May 4 11:02:44 2009 @@ -0,0 +1,92 @@ +;;+----------------------------------------------------------------------------- +;;+ 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 :json-tmcl-constants + (:use :cl) + (:export :*topictype-psi* + :*topictype-constraint-psi* + :*associationtype-psi* + :*associationtype-constraint-psi* + :*roletype-psi* + :*roletype-constraint-psi* + :*occurrencetype-psi* + :*occurrencetype-constraint-psi* + :*nametype-psi* + :*nametype-constraint-psi* + :*scopetype-psi* + :*topictype-role-psi* + :*applies-to-psi* + :*constraint-role-psi* + :*regexp-psi* + :*card-min-psi* + :*card-max-psi* + :*datatype-psi* + :*subjectidentifier-constraint-psi* + :*subjectlocator-constraint-psi* + :*abstract-topictype-constraint-psi* + :*exclusive-instance-psi* + :*topicname-constraint-psi* + :*topicoccurrence-constraint-psi* + :*occurrencedatatype-constraint-psi* + :*uniqueoccurrence-constraint-psi* + :*roleplayer-constraint-psi* + :*otherrole-constraint-psi* + :*nametype-role-psi* + :*scopetype-role-psi* + :*occurrencetype-role-psi* + :*othertopictype-role-psi* + :*otherroletype-role-psi* + :*associationtype-role-psi* + :*nametypescope-constraint-psi* + :*occurrencetypescope-constraint-psi* + :*associationtypescope-constraint-psi* + :*associationrole-constraint-psi* + :*roletype-role-psi*)) + +(in-package :json-tmcl-constants) + +(defparameter *topictype-psi* "http://psi.topicmaps.org/tmcl/topic-type") +(defparameter *topictype-constraint-psi* "http://psi.topicmaps.org/tmcl/topic-type-constraint") +(defparameter *associationtype-psi* "http://psi.topicmaps.org/tmcl/association-type") +(defparameter *associationtype-constraint-psi* "http://psi.topicmaps.org/tmcl/association-type-constraint") +(defparameter *roletype-psi* "http://psi.topicmaps.org/tmcl/role-type") +(defparameter *roletype-constraint-psi* "http://psi.topicmaps.org/tmcl/role-type-constraint") +(defparameter *occurrencetype-psi* "http://psi.topicmaps.org/tmcl/occurrence-type") +(defparameter *occurrencetype-constraint-psi* "http://psi.topicmaps.org/tmcl/occurrence-type-constraint") +(defparameter *nametype-psi* "http://psi.topicmaps.org/tmcl/name-type") +(defparameter *nametype-constraint-psi* "http://psi.topicmaps.org/tmcl/name-type-constraint") +(defparameter *scopetype-psi* "http://psi.topicmaps.org/tmcl/scope-type") +(defparameter *topictype-role-psi* "http://psi.topicmaps.org/tmcl/topic-type-role") +(defparameter *applies-to-psi* "http://psi.topicmaps.org/tmcl/applies-to") +(defparameter *constraint-role-psi* "http://psi.topicmaps.org/tmcl/constraint-role") +(defparameter *regexp-psi* "http://psi.topicmaps.org/tmcl/reg-exp") +(defparameter *card-min-psi* "http://psi.topicmaps.org/tmcl/card-min") +(defparameter *card-max-psi* "http://psi.topicmaps.org/tmcl/card-max") +(defparameter *datatype-psi* "http://psi.topicmaps.org/tmcl/datatype") +(defparameter *subjectidentifier-constraint-psi* "http://psi.topicmaps.org/tmcl/subject-identifier-constraint") +(defparameter *subjectlocator-constraint-psi* "http://psi.topicmaps.org/tmcl/subject-locator-constraint") +(defparameter *abstract-topictype-constraint-psi* "http://psi.topicmaps.org/tmcl/abstract-topic-type-constraint") +(defparameter *exclusive-instance-psi* "http://psi.topicmaps.org/tmcl/exclusive-instance") +(defparameter *topicname-constraint-psi* "http://psi.topicmaps.org/tmcl/topic-name-constraint") +(defparameter *topicoccurrence-constraint-psi* "http://psi.topicmaps.org/tmcl/topic-occurrence-constraint") +(defparameter *occurrencedatatype-constraint-psi* "http://psi.topicmaps.org/tmcl/occurrence-datatype-constraint") +(defparameter *uniqueoccurrence-constraint-psi* "http://psi.topicmaps.org/tmcl/unique-occurrence-constraint") +(defparameter *roleplayer-constraint-psi* "http://psi.topicmaps.org/tmcl/role-player-constraint") +(defparameter *otherrole-constraint-psi* "http://psi.topicmaps.org/tmcl/other-role-constraint") +(defparameter *nametypescope-constraint-psi* "http://psi.topicmaps.org/tmcl/name-type-scope-constraint") +(defparameter *occurrencetypescope-constraint-psi* "http://psi.topicmaps.org/tmcl/occurrence-type-scope-constraint") +(defparameter *associationtypescope-constraint-psi* "http://psi.topicmaps.org/tmcl/association-type-scope-constraint") +(defparameter *nametype-role-psi* "http://psi.topicmaps.org/tmcl/name-type-role") +(defparameter *scopetype-role-psi* "http://psi.topicmaps.org/tmcl/scope-type-role") +(defparameter *occurrencetype-role-psi* "http://psi.topicmaps.org/tmcl/occurrence-type-role") +(defparameter *othertopictype-role-psi* "http://psi.topicmaps.org/tmcl/other-topic-type-role") +(defparameter *otherroletype-role-psi* "http://psi.topicmaps.org/tmcl/other-role-type-role") +(defparameter *associationtype-role-psi* "http://psi.topicmaps.org/tmcl/association-type-role") +(defparameter *associationrole-constraint-psi* "http://psi.topicmaps.org/tmcl/association-role-constraint") +(defparameter *roletype-role-psi* "http://psi.topicmaps.org/tmcl/role-type-role") \ No newline at end of file
Modified: trunk/src/model/changes.lisp ============================================================================== --- trunk/src/model/changes.lisp (original) +++ trunk/src/model/changes.lisp Mon May 4 11:02:44 2009 @@ -286,4 +286,13 @@ (elephant:get-instances-by-value 'FragmentC 'topic topic))) ;; maybe there are more fragments of this topic in different revisions, ;; so we need to search the fragment with a certain revision - (first (sort fragments #'> :key 'revision))))))))) \ No newline at end of file + (let ((found-fragment + (if fragments + (first (sort fragments #'> :key 'revision)) + ;; if there exist a topic but always no fragment, there will be generated a new fragment of the latest version for the searched topic + (make-instance 'FragmentC + :revision (first (sort (versions topic) #'> :key 'start-revision)) + :associations (find-associations-for-topic topic) + :referenced-topics (find-referenced-topics topic) + :topic topic)))) + found-fragment)))))))) \ No newline at end of file
Modified: trunk/src/rest_interface/rest-interface.lisp ============================================================================== --- trunk/src/rest_interface/rest-interface.lisp (original) +++ trunk/src/rest_interface/rest-interface.lisp Mon May 4 11:02:44 2009 @@ -28,7 +28,11 @@ :*json-get-prefix* :*json-commit-url* :*json-get-all-psis* - :*json-get-summary-prefix** + :*json-get-summary-prefix* + :*json-get-all-type-psis* + :*json-get-topic-stub-prefix* + :*json-get-type-tmcl-prefix* + :*json-get-instance-tmcl-prefix* :*ajax-user-interface-url* :*ajax-user-interface-file-path* :*ajax-javascript-directory-path* @@ -110,11 +114,13 @@
-(defvar *acceptor*) +(defvar *server-acceptor* nil)
(defun start-tm-engine (repository-path &key (conffile "atom/conf.lisp") (host-name "localhost") (port 8000)) "Start the Topic Map Engine on a given port, assuming a given -hostname. Use the repository under repository-path" + hostname. Use the repository under repository-path" + (when *server-acceptor* + (error "Ther server is already running")) (setf hunchentoot:*show-lisp-errors-p* t) ;for now ;(setf hunchentoot:*show-lisp-backtraces-p* t) ;hunchentoot 0.15.7 (setf hunchentoot:*hunchentoot-default-external-format* @@ -125,12 +131,13 @@ (load conffile) (publish-feed atom:*tm-feed*) (set-up-json-interface) - (setf *acceptor* (make-instance 'hunchentoot:acceptor :address host-name :port port)) + (setf *server-acceptor* (make-instance 'hunchentoot:acceptor :address host-name :port port)) (setf hunchentoot:*lisp-errors-log-level* :info) (setf hunchentoot:*message-log-pathname* "./hunchentoot-errors.log") - (hunchentoot:start *acceptor*)) + (hunchentoot:start *server-acceptor*))
(defun shutdown-tm-engine () "Shut down the Topic Map Engine" - (hunchentoot:stop *acceptor*) + (hunchentoot:stop *server-acceptor*) + (setf *server-acceptor* nil) (elephant:close-store)) \ No newline at end of file
Modified: trunk/src/rest_interface/set-up-json-interface.lisp ============================================================================== --- trunk/src/rest_interface/set-up-json-interface.lisp (original) +++ trunk/src/rest_interface/set-up-json-interface.lisp Mon May 4 11:02:44 2009 @@ -13,6 +13,10 @@ (defparameter *json-commit-url* "/json/commit/?$") ;the url to commit a json fragment by "put" or "post" (defparameter *json-get-all-psis* "/json/psis/?$") ;the url to get all topic psis of isidorus -> localhost:8000/json/psis (defparameter *json-get-summary-url* "/json/summary/?$") ;the url to get a summary od all topic stored in isidorus; you have to set the GET-parameter "start" for the start index of all topics within elephant and the GET-paramter "end" for the last index of the topic sequence -> http://localhost:8000/json/summary/?start=12&end=13 +(defparameter *json-get-all-type-psis* "/json/tmcl/types/?$") ;returns a list of all psis that can be a type +(defparameter *json-get-topic-stub-prefix* "/json/tmcl/topicstubs/(.+)$") ;the json prefix for getting some topic stub information of a topic and its "derived" topics +(defparameter *json-get-type-tmcl-prefix* "/json/tmcl/type/(.+)$") ;the json prefix for getting some tmcl information of a topic treated as a type +(defparameter *json-get-instance-tmcl-prefix* "/json/tmcl/instance/(.+)$") ;the json prefix for getting some tmcl information of a topic treated as an instance (defparameter *ajax-user-interface-url* "/isidorus/?$") ;the url to the user interface; if you want to get all topics set start=0&end=nil -> localhost:8000/isidorus (defparameter *ajax-user-interface-css-prefix* "/css") ;the url to the css files of the user interface (defparameter *ajax-user-interface-css-directory-path* "ajax/css") ;the directory contains the css files @@ -20,11 +24,14 @@ (defparameter *ajax-javascript-directory-path* "ajax/javascripts") ;the directory which contains all necessary javascript files (defparameter *ajax-javascript-url-prefix* "/javascripts") ; the url prefix of all javascript files
- (defun set-up-json-interface (&key (json-get-prefix *json-get-prefix*) (json-get-all-psis *json-get-all-psis*) (json-commit-url *json-commit-url*) (json-get-summary-url *json-get-summary-url*) + (json-get-all-type-psis *json-get-all-type-psis*) + (json-get-topic-stub-prefix *json-get-topic-stub-prefix*) + (json-get-type-tmcl-prefix *json-get-type-tmcl-prefix*) + (json-get-instance-tmcl-prefix *json-get-instance-tmcl-prefix*) (ajax-user-interface-url *ajax-user-interface-url*) (ajax-user-interface-file-path *ajax-user-interface-file-path*) (ajax-user-interface-css-prefix *ajax-user-interface-css-prefix*) @@ -71,16 +78,103 @@ (create-regex-dispatcher json-get-prefix #'return-json-fragment) hunchentoot:*dispatch-table*) (push + (create-regex-dispatcher json-get-topic-stub-prefix #'return-topic-stub-of-psi) + hunchentoot:*dispatch-table*) + (push + (create-regex-dispatcher json-get-all-type-psis #'return-all-tmcl-types) + hunchentoot:*dispatch-table*) + (push + (create-regex-dispatcher json-get-type-tmcl-prefix #'(lambda(&optional psi) + (return-tmcl-info-of-psi 'json-tmcl::type psi))) + hunchentoot:*dispatch-table*) + (push + (create-regex-dispatcher json-get-instance-tmcl-prefix #'(lambda(&optional psi) + (return-tmcl-info-of-psi 'json-tmcl::instance psi))) + hunchentoot:*dispatch-table*) + (push (create-regex-dispatcher json-commit-url #'json-commit) hunchentoot:*dispatch-table*) (push (create-regex-dispatcher json-get-summary-url #'return-topic-summaries) hunchentoot:*dispatch-table*))
- ;; ============================================================================= ;; --- some handlers for the json-rest-interface ------------------------------- ;; ============================================================================= +(defun return-all-tmcl-types(&optional param) + (declare (ignorable param)) + (handler-case (let ((all-topics + (elephant:get-instances-by-class 'd:TopicC)) + (topictype (get-item-by-psi json-tmcl-constants::*topictype-psi*)) + (topictype-constraint (get-item-by-psi json-tmcl-constants::*topictype-constraint-psi*))) + (let ((all-types + (remove-if #'null + (map 'list #'(lambda(x) + (handler-case (progn + (json-tmcl::topictype-p x topictype topictype-constraint) + x) + (condition () nil))) all-topics)))) + (let ((not-abstract-types + (remove-if #'null + (map 'list #'(lambda(x) + (unless (json-tmcl:abstract-p x) + x)) + all-types)))) + (setf (hunchentoot:content-type*) "application/json") ;RFC 4627 + (json:encode-json-to-string + (map 'list #'(lambda(y) + (map 'list #'uri y)) + (map 'list #'psis not-abstract-types)))))) + (condition (err) (progn + (setf (hunchentoot:return-code*) hunchentoot:+http-internal-server-error+) + (setf (hunchentoot:content-type*) "text") + (format nil "Condition: "~a"" err))))) + +(defun return-topic-stub-of-psi(&optional psi) + "Returns a json string of a topic depending on the + passed psi as a topic-stub-construct." + (assert psi) + (let ((topic (d:get-item-by-psi psi))) + (if topic + (let ((topic-json + (handler-case (json-exporter::to-json-topicStub-string topic) + (condition (err) (progn + (setf (hunchentoot:return-code*) hunchentoot:+http-internal-server-error+) + (setf (hunchentoot:content-type*) "text") + (format nil "Condition: "~a"" err)))))) + (setf (hunchentoot:content-type*) "application/json") ;RFC 4627 + topic-json) + (progn + (setf (hunchentoot:return-code*) hunchentoot:+http-not-found+) + (setf (hunchentoot:content-type*) "text") + (format nil "Condition: Topic "~a" not found" psi))))) + + +(defun return-tmcl-info-of-psi(treat-as &optional psi) + "Returns a json string which represents the defined tmcl-constraints of the + topic and the associations where this topic can be a player." + (assert psi) + (let ((http-method (hunchentoot:request-method*))) + (if (eq http-method :GET) + (let ((identifier (string-replace psi "%23" "#"))) + (setf (hunchentoot:content-type*) "application/json") ;RFC 4627 + (handler-case (let ((tmcl + (json-tmcl:get-constraints-of-fragment identifier :treat-as treat-as))) + (if tmcl + (progn + (setf (hunchentoot:content-type*) "application/json") ;RFC 4627 + tmcl) + (progn + (setf (hunchentoot:return-code*) hunchentoot:+http-not-found+) + (setf (hunchentoot:content-type*) "text") + (format nil "Topic "~a" not found." psi)))) + (condition (err) (progn + (setf (hunchentoot:return-code*) hunchentoot:+http-internal-server-error+) + (setf (hunchentoot:content-type*) "text") + (format nil "Condition: "~a"" err))))) + (setf (hunchentoot:return-code*) hunchentoot:+http-bad-request+)))) + + (defun return-all-topic-psis (&optional param) "return all psis currently existing in isidorus as a list of list. every topic is a list of psis and the entire list contains a list of topics" @@ -102,14 +196,7 @@ (assert psi) (let ((http-method (hunchentoot:request-method*))) (if (eq http-method :GET) - (let ((identifier (let ((pos (search "%23" psi))) - (if pos - (let ((str-1 (subseq psi 0 pos)) - (str-2 (if (> (length psi) (+ pos 3)) - (subseq psi (+ pos 3)) - ""))) - (concatenate 'string str-1 "#" str-2)) - psi)))) + (let ((identifier (string-replace psi "%23" "#"))) (setf (hunchentoot:content-type*) "application/json") ;RFC 4627 (let ((fragment (get-latest-fragment-of-topic identifier))) @@ -120,7 +207,10 @@ (setf (hunchentoot:return-code*) hunchentoot:+http-internal-server-error+) (setf (hunchentoot:content-type*) "text") (format nil "Condition: "~a"" err)))) - "{}"))) + (progn + (setf (hunchentoot:return-code*) hunchentoot:+http-not-found+) + (setf (hunchentoot:content-type*) "text") + (format nil "Topic "~a" not found" psi))))) (setf (hunchentoot:return-code*) hunchentoot:+http-bad-request+))))
@@ -201,4 +291,27 @@ (concatenate 'string url-prefix (subseq current-path-string start-position-of-relative-path last-position-of-current-path)))) (push (list :path current-path :url current-url) files-and-urls)))))) - files-and-urls))) \ No newline at end of file + files-and-urls))) + + +(defun string-replace (str search-str replace-str) + "replaces all sub-strings in str of the form search-str with + the string replace-str and returns the new generated string" + (if (= (length search-str) 0) + str + (progn + (let ((ret-str "") + (idx 0)) + (loop + (if (string= str search-str + :start1 idx + :end1 (min (length str) + (+ idx (length search-str)))) + (progn + (setf ret-str (concatenate 'string ret-str replace-str)) + (incf idx (length search-str))) + (progn + (setf ret-str (concatenate 'string ret-str (subseq str idx (1+ idx)))) + (incf idx))) + (unless (< idx (length str)) + (return ret-str))))))) \ No newline at end of file
Added: trunk/src/unit_tests/poems.xtm ============================================================================== --- (empty file) +++ trunk/src/unit_tests/poems.xtm Mon May 4 11:02:44 2009 @@ -0,0 +1,1857 @@ +<?xml version="1.0" encoding="UTF-8"?> +<tm:topicMap version="2.0" xmlns:tm="http://www.topicmaps.org/xtm/%22%3E + + <!-- === association-test ================================================ --> + <tm:topic id="test-scope-1"> + <tm:subjectIdentifier href="test-scope-1"/> + tm:instanceOf<tm:topicRef href="#scopetype"/></tm:instanceOf> + </tm:topic> + + <tm:topic id="test-scope-2"> + <tm:subjectIdentifier href="test-scope-2"/> + tm:instanceOf<tm:topicRef href="#scopetype"/></tm:instanceOf> + </tm:topic> + + <tm:topic id="written-by-test-scope-constraint"> + <tm:subjectIdentifier href="written-by-test-scope-constraint"/> + tm:instanceOf<tm:topicRef href="#associationtypescope-constraint"/></tm:instanceOf> + tm:occurrence + tm:type + <tm:topicRef href="#card-min"/> + </tm:type> + <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#unsignedInt%22%3E1</tm:resourceData> + </tm:occurrence> + tm:occurrence + tm:type + <tm:topicRef href="#card-max"/> + </tm:type> + <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#unsignedInt%22%3E1</tm:resourceData> + </tm:occurrence> + </tm:topic> + + tm:association + tm:type + <tm:topicRef href="#applies-to"/> + </tm:type> + tm:role + tm:type + <tm:topicRef href="#constraint-role"/> + </tm:type> + <tm:topicRef href="#written-by-test-scope-constraint"/> + </tm:role> + tm:role + tm:type + <tm:topicRef href="#associationtype-role"/> + </tm:type> + <tm:topicRef href="#written-by"/> + </tm:role> + </tm:association> + + tm:association + tm:type + <tm:topicRef href="#applies-to"/> + </tm:type> + tm:role + tm:type + <tm:topicRef href="#constraint-role"/> + </tm:type> + <tm:topicRef href="#written-by-test-scope-constraint"/> + </tm:role> + tm:role + tm:type + <tm:topicRef href="#scopetype-role"/> + </tm:type> + <tm:topicRef href="#test-scope-1"/> + </tm:role> + </tm:association> + + tm:association + tm:type + <tm:topicRef href="#applies-to"/> + </tm:type> + tm:role + tm:type + <tm:topicRef href="#constraint-role"/> + </tm:type> + <tm:topicRef href="#written-by-test-scope-constraint"/> + </tm:role> + tm:role + tm:type + <tm:topicRef href="#scopetype-role"/> + </tm:type> + <tm:topicRef href="#test-scope-2"/> + </tm:role> + </tm:association> + <!-- === end association-test ============================================ --> + + + <!-- ===================================================================== --> + <!-- === TMCL meta-model topics ========================================== --> + <!-- ===================================================================== --> + <tm:topic id="topictype"> + <tm:subjectIdentifier href="http://psi.topicmaps.org/tmcl/topic-type%22/%3E <!-- naming of psis: Prague, March 25-27, 2008, page 12 --> + tm:instanceOf<tm:topicRef href="#topictype"/></tm:instanceOf> + </tm:topic> + + <tm:topic id="occurrencetype"> + <tm:subjectIdentifier href="http://psi.topicmaps.org/tmcl/occurrence-type%22/%3E + tm:instanceOf<tm:topicRef href="#topictype"/></tm:instanceOf> + </tm:topic> + + <tm:topic id="associationtype"> + <tm:subjectIdentifier href="http://psi.topicmaps.org/tmcl/association-type%22/%3E + tm:instanceOf<tm:topicRef href="#topictype"/></tm:instanceOf> + </tm:topic> + + <tm:topic id="roletype"> + <tm:subjectIdentifier href="http://psi.topicmaps.org/tmcl/role-type%22/%3E + tm:instanceOf<tm:topicRef href="#topictype"/></tm:instanceOf> + </tm:topic> + + <tm:topic id="nametype"> + <tm:subjectIdentifier href="http://psi.topicmaps.org/tmcl/name-type%22/%3E + tm:instanceOf<tm:topicRef href="#topictype"/></tm:instanceOf> + </tm:topic> + + <tm:topic id="scopetype"> + <tm:subjectIdentifier href="http://psi.topicmaps.org/tmcl/scope-type%22/%3E + tm:instanceOf<tm:topicRef href="#topictype"/></tm:instanceOf> + </tm:topic> + + <!-- role types used to include the topictype metatypes in associations --> + <tm:topic id="topictype-role"> + <tm:subjectIdentifier href="http://psi.topicmaps.org/tmcl/topic-type-role%22/%3E + tm:instanceOf<tm:topicRef href="#roletype"/></tm:instanceOf> + </tm:topic> + + <tm:topic id="occurrencetype-role"> + <tm:subjectIdentifier href="http://psi.topicmaps.org/tmcl/occurrence-type-role%22/%3E + tm:instanceOf<tm:topicRef href="#roletype"/></tm:instanceOf> + </tm:topic> + + <tm:topic id="associationtype-role"> + <tm:subjectIdentifier href="http://psi.topicmaps.org/tmcl/association-type-role%22/%3E + tm:instanceOf<tm:topicRef href="#roletype"/></tm:instanceOf> + </tm:topic> + + <tm:topic id="roletype-role"> + <tm:subjectIdentifier href="http://psi.topicmaps.org/tmcl/role-type-role%22/%3E + tm:instanceOf<tm:topicRef href="#roletype"/></tm:instanceOf> + </tm:topic> + + <tm:topic id="otherroletype-role"> + <tm:subjectIdentifier href="http://psi.topicmaps.org/tmcl/other-role-type-role%22/%3E + tm:instanceOf<tm:topicRef href="#roletype"/></tm:instanceOf> + </tm:topic> + + <tm:topic id="othertopictype-role"> + <tm:subjectIdentifier href="http://psi.topicmaps.org/tmcl/other-topic-type-role%22/%3E + tm:instanceOf<tm:topicRef href="#roletype"/></tm:instanceOf> + </tm:topic> + + <tm:topic id="nametype-role"> + <tm:subjectIdentifier href="http://psi.topicmaps.org/tmcl/name-type-role%22/%3E + tm:instanceOf<tm:topicRef href="#roletype"/></tm:instanceOf> + </tm:topic> + + <tm:topic id="scopetype-role"> + <tm:subjectIdentifier href="http://psi.topicmaps.org/tmcl/scope-type-role%22/%3E + tm:instanceOf<tm:topicRef href="#roletype"/></tm:instanceOf> + </tm:topic> + + <!-- the constraint roletype --> + <tm:topic id="constraint-role"> + <tm:subjectIdentifier href="http://psi.topicmaps.org/tmcl/constraint-role%22/%3E + tm:instanceOf<tm:topicref href="#roletype"/></tm:instanceOf> + </tm:topic> + + <!-- ===================================================================== --> + <!-- === TMCL model topics =============================================== --> + <!-- ===================================================================== --> + + <!-- the constraint topic is the common supertype of all constraint types + defined by TMCL. --> + <tm:topic id="constraint"> + <tm:subjectIdentifier href="http://psi.topicmaps.org/tmcl/constraint%22/%3E + tm:instanceOf<tm:topicRef href="#topictype"/></tm:instanceOf> + </tm:topic> + + <!-- this occurrence type is used to type a single occurrence on each + constraint type. This occurrence holds the TMQL value used to + evaluate constraint instances for validity. --> + <tm:topic id="validation-expression"> + <tm:subjectIdentifier href="http://psi.topicmaps.org/tmcl/validation-expression%22/%3E + tm:instanceOf<tm:topicRef href="#occurrencetype"/></tm:instanceOf> + </tm:topic> + + <!-- the association type used to bind different components into a + constraint --> + <tm:topic id="applies-to"> + <tm:subjectIdentifier href="http://psi.topicmaps.org/tmcl/applies-to%22/%3E + tm:instanceOf<tm:topicRef href="#associationtype"/></tm:instanceOf> + </tm:topic> + + <!-- the card min facet is used on many constraint types --> + <tm:topic id="card-min"> + <tm:subjectIdentifier href="http://psi.topicmaps.org/tmcl/card-min%22/%3E + tm:instanceOf<tm:topicRef href="#occurrencetype"/></tm:instanceOf> + </tm:topic> + + <!-- the card max facet is used on many constraint types --> + <tm:topic id="card-max"> + <tm:subjectIdentifier href="http://psi.topicmaps.org/tmcl/card-max%22/%3E + tm:instanceOf<tm:topicRef href="#occurrencetype"/></tm:instanceOf> + </tm:topic> + + <!-- the reg exp facet is used on many constraint types --> + <tm:topic id="regexp"> + <tm:subjectIdentifier href="http://psi.topicmaps.org/tmcl/reg-exp%22/%3E + tm:instanceOf<tm:topicRef href="#occurrencetype"/></tm:instanceOf> + </tm:topic> + + <!-- the datatype facet is used on many constraint types --> + <tm:topic id="datatype"> + <tm:subjectIdentifier href="http://psi.topicmaps.org/tmcl/datatype%22/%3E + tm:instanceOf<tm:topicRef href="#occurrencetype"/></tm:instanceOf> + </tm:topic> + + <!-- ===================================================================== --> + <!-- === topics for super-subtype-associations (ako) ===================== --> + <!-- ===================================================================== --> + + <tm:topic id="supertype-subtype"> + <tm:subjectIdentifier href="http://psi.topicmaps.org/iso13250/model/supertype-subtype%22/%3E + </tm:topic> + + <tm:topic id="supertype"> + <tm:subjectIdentifier href="http://psi.topicmaps.org/iso13250/model/supertype%22/%3E + </tm:topic> + + <tm:topic id="subtype"> + <tm:subjectIdentifier href="http://psi.topicmaps.org/iso13250/model/subtype%22/%3E + </tm:topic> + + + <!-- ===================================================================== --> + <!-- === schema type and ?schema definitions ============================= --> + <!-- ===================================================================== --> + + <!-- constraints can be bound to a schema --> + <tm:topic id="schema"> + <tm:subjectIdentifier href="http://psi.topicmaps.org/tmcl/schema%22/%3E + tm:instanceOf<tm:topicref href="#topictype"/></tm:instanceOf> + </tm:topic> + + + <!-- ===================================================================== --> + <!-- === TMCL constraint types =========================================== --> + <!-- ===================================================================== --> + + <!-- topictype-constraint --> + <tm:topic id="topictype-constraint"> + <tm:subjectIdentifier href="http://psi.topicmaps.org/tmcl/topic-type-constraint%22/%3E + </tm:topic> <!-- standard constraints doesn't own a valiadtion-expression-occurrence: Prague, March 25-27, 2008, page 34-36 --> + + tm:association + tm:type<tm:topicRef href="#supertype-subtype"/></tm:type> + tm:role + tm:type<tm:topicRef href="#subtype"/></tm:type> + <tm:topicRef href="#topictype-constraint"/> + </tm:role> + tm:role + tm:type<tm:topicRef href="#supertype"/></tm:type> + <tm:topicRef href="#constraint"/> + </tm:role> + </tm:association> + + <!-- associationtype-constraint --> + <tm:topic id="associationtype-constraint"> + <tm:subjectIdentifier href="http://psi.topicmaps.org/tmcl/association-type-constraint%22/%3E + </tm:topic> + + tm:association + tm:type<tm:topicRef href="#supertype-subtype"/></tm:type> + tm:role + tm:type<tm:topicRef href="#subtype"/></tm:type> + <tm:topicRef href="#associationtype-constraint"/> + </tm:role> + tm:role + tm:type<tm:topicRef href="#supertype"/></tm:type> + <tm:topicRef href="#constraint"/> + </tm:role> + </tm:association> + + <!-- roletype-constraint --> + <tm:topic id="roletype-constraint"> + <tm:subjectIdentifier href="http://psi.topicmaps.org/tmcl/role-type-constraint%22/%3E + </tm:topic> + + tm:association + tm:type<tm:topicRef href="#supertype-subtype"/></tm:type> + tm:role + tm:type<tm:topicRef href="#subtype"/></tm:type> + <tm:topicRef href="#roletype-constraint"/> + </tm:role> + tm:role + tm:type<tm:topicRef href="#supertype"/></tm:type> + <tm:topicRef href="#constraint"/> + </tm:role> + </tm:association> + + <!-- occurrencetype-constraint --> + <tm:topic id="occurrencetype-constraint"> + <tm:subjectIdentifier href="http://psi.topicmaps.org/tmcl/occurrence-type-constraint%22/%3E + </tm:topic> + + tm:association + tm:type<tm:topicRef href="#supertype-subtype"/></tm:type> + tm:role + tm:type<tm:topicRef href="#subtype"/></tm:type> + <tm:topicRef href="#occurrencetype-constraint"/> + </tm:role> + tm:role + tm:type<tm:topicRef href="#supertype"/></tm:type> + <tm:topicRef href="#constraint"/> + </tm:role> + </tm:association> + + <!-- nametype-constraint --> + <tm:topic id="nametype-constraint"> + <tm:subjectIdentifier href="http://psi.topicmaps.org/tmcl/name-type-constraint%22/%3E + </tm:topic> + + tm:association + tm:type<tm:topicRef href="#supertype-subtype"/></tm:type> + tm:role + tm:type<tm:topicRef href="#subtype"/></tm:type> + <tm:topicRef href="#nametype-constraint"/> + </tm:role> + tm:role + tm:type<tm:topicRef href="#supertype"/></tm:type> + <tm:topicRef href="#constraint"/> + </tm:role> + </tm:association> + + <!-- abstract-topictype-constraint --> + <tm:topic id="abstract-topictype-constraint"> + <tm:subjectIdentifier href="http://psi.topicmaps.org/tmcl/abstract-topic-type-constraint%22/%3E + </tm:topic> + + tm:association + tm:type<tm:topicRef href="#supertype-subtype"/></tm:type> + tm:role + tm:type<tm:topicRef href="#subtype"/></tm:type> + <tm:topicRef href="#abstract-topictype-constraint"/> + </tm:role> + tm:role + tm:type<tm:topicRef href="#supertype"/></tm:type> + <tm:topicRef href="#constraint"/> + </tm:role> + </tm:association> + + + <!-- exclusive-instance --> + <tm:topic id="exclusive-instance"> + <tm:subjectIdentifier href="http://psi.topicmaps.org/tmcl/exclusive-instance%22/%3E + </tm:topic> + + tm:association + tm:type<tm:topicRef href="#supertype-subtype"/></tm:type> + tm:role + tm:type<tm:topicRef href="#subtype"/></tm:type> + <tm:topicRef href="#exclusive-instance"/> + </tm:role> + tm:role + tm:type<tm:topicRef href="#supertype"/></tm:type> + <tm:topicRef href="#constraint"/> + </tm:role> + </tm:association> + + + <!-- ===================================================================== --> + <!-- === subjectidentifier/locator constraints =========================== --> + <!-- ===================================================================== --> + + <!-- subjectlocator-constraint --> + <tm:topic id="subjectlocator-constraint"> + <tm:subjectIdentifier href="http://psi.topicmaps.org/tmcl/subject-locator-constraint%22/%3E + </tm:topic> + + tm:association + tm:type<tm:topicRef href="#supertype-subtype"/></tm:type> + tm:role + tm:type<tm:topicRef href="#subtype"/></tm:type> + <tm:topicRef href="#subjectlocator-constraint"/> + </tm:role> + tm:role + tm:type<tm:topicRef href="#supertype"/></tm:type> + <tm:topicRef href="#constraint"/> + </tm:role> + </tm:association> + + <!-- subjectidentifier-constraint --> + <tm:topic id="subjectidentifier-constraint"> + <tm:subjectIdentifier href="http://psi.topicmaps.org/tmcl/subject-identifier-constraint%22/%3E + </tm:topic> + + tm:association + tm:type<tm:topicRef href="#supertype-subtype"/></tm:type> + tm:role + tm:type<tm:topicRef href="#subtype"/></tm:type> + <tm:topicRef href="#subjectidentifier-constraint"/> + </tm:role> + tm:role + tm:type<tm:topicRef href="#supertype"/></tm:type> + <tm:topicRef href="#constraint"/> + </tm:role> + </tm:association> + + + <!-- ===================================================================== --> + <!-- === names/occurrences/associations/association roles ================ --> + <!-- ===================================================================== --> + + <!-- topicname-constraint --> + <tm:topic id="topicname-constraint"> + <tm:subjectIdentifier href="http://psi.topicmaps.org/tmcl/topic-name-constraint%22/%3E + </tm:topic> + + tm:association + tm:type<tm:topicRef href="#supertype-subtype"/></tm:type> + tm:role + tm:type<tm:topicRef href="#subtype"/></tm:type> + <tm:topicRef href="#topicname-constraint"/> + </tm:role> + tm:role + tm:type<tm:topicRef href="#supertype"/></tm:type> + <tm:topicRef href="#constraint"/> + </tm:role> + </tm:association> + + <!-- topicoccurrence-constraint --> + <tm:topic id="topicoccurrence-constraint"> + <tm:subjectIdentifier href="http://psi.topicmaps.org/tmcl/topic-occurrence-constraint%22/%3E + </tm:topic> + + tm:association + tm:type<tm:topicRef href="#supertype-subtype"/></tm:type> + tm:role + tm:type<tm:topicRef href="#subtype"/></tm:type> + <tm:topicRef href="#topicoccurrence-constraint"/> + </tm:role> + tm:role + tm:type<tm:topicRef href="#supertype"/></tm:type> + <tm:topicRef href="#constraint"/> + </tm:role> + </tm:association> + + <!-- occurrencedatatype-constraint --> + <tm:topic id="occurrencedatatype-constraint"> + <tm:subjectIdentifier href="http://psi.topicmaps.org/tmcl/occurrence-datatype-constraint%22/%3E + </tm:topic> + + tm:association + tm:type<tm:topicRef href="#supertype-subtype"/></tm:type> + tm:role + tm:type<tm:topicRef href="#subtype"/></tm:type> + <tm:topicRef href="#occurrencedatatype-constraint"/> + </tm:role> + tm:role + tm:type<tm:topicRef href="#supertype"/></tm:type> + <tm:topicRef href="#constraint"/> + </tm:role> + </tm:association> + + <!-- uniqueoccurrence-constraint --> + <tm:topic id="uniqueoccurrence-constraint"> + <tm:subjectIdentifier href="http://psi.topicmaps.org/tmcl/unique-occurrence-constraint%22/%3E + </tm:topic> + + tm:association + tm:type<tm:topicRef href="#supertype-subtype"/></tm:type> + tm:role + tm:type<tm:topicRef href="#subtype"/></tm:type> + <tm:topicRef href="#uniqueoccurrence-constraint"/> + </tm:role> + tm:role + tm:type<tm:topicRef href="#supertype"/></tm:type> + <tm:topicRef href="#constraint"/> + </tm:role> + </tm:association> + + <!-- associationrole-constraint --> + <tm:topic id="associationrole-constraint"> + <tm:subjectIdentifier href="http://psi.topicmaps.org/tmcl/association-role-constraint%22/%3E + </tm:topic> + + tm:association + tm:type<tm:topicRef href="#supertype-subtype"/></tm:type> + tm:role + tm:type<tm:topicRef href="#subtype"/></tm:type> + <tm:topicRef href="#associationrole-constraint"/> + </tm:role> + tm:role + tm:type<tm:topicRef href="#supertype"/></tm:type> + <tm:topicRef href="#constraint"/> + </tm:role> + </tm:association> + + <!-- roleplayer-constraint --> + <tm:topic id="roleplayer-constraint"> + <tm:subjectIdentifier href="http://psi.topicmaps.org/tmcl/role-player-constraint%22/%3E + </tm:topic> + + tm:association + tm:type<tm:topicRef href="#supertype-subtype"/></tm:type> + tm:role + tm:type<tm:topicRef href="#subtype"/></tm:type> + <tm:topicRef href="#roleplayer-constraint"/> + </tm:role> + tm:role + tm:type<tm:topicRef href="#supertype"/></tm:type> + <tm:topicRef href="#constraint"/> + </tm:role> + </tm:association> + + <!-- otherrole-constraint --> + <tm:topic id="otherrole-constraint"> + <tm:subjectIdentifier href="http://psi.topicmaps.org/tmcl/other-role-constraint%22/%3E + </tm:topic> + + tm:association + tm:type<tm:topicRef href="#supertype-subtype"/></tm:type> + tm:role + tm:type<tm:topicRef href="#subtype"/></tm:type> + <tm:topicRef href="#otherrole-constraint"/> + </tm:role> + tm:role + tm:type<tm:topicRef href="#supertype"/></tm:type> + <tm:topicRef href="#constraint"/> + </tm:role> + </tm:association> + + <!-- ===================================================================== --> + <!-- === scopes ========================================================== --> + <!-- ===================================================================== --> + + <!-- nametypescope-constraint --> + <tm:topic id="nametypescope-constraint"> + <tm:subjectIdentifier href="http://psi.topicmaps.org/tmcl/name-type-scope-constraint%22/%3E + </tm:topic> + + tm:association + tm:type<tm:topicRef href="#supertype-subtype"/></tm:type> + tm:role + tm:type<tm:topicRef href="#subtype"/></tm:type> + <tm:topicRef href="#nametypescope-constraint"/> + </tm:role> + tm:role + tm:type<tm:topicRef href="#supertype"/></tm:type> + <tm:topicRef href="#constraint"/> + </tm:role> + </tm:association> + + <!-- occurrencetypescope-constraint --> + <tm:topic id="occurrencetypescope-constraint"> + <tm:subjectIdentifier href="http://psi.topicmaps.org/tmcl/occurrence-type-scope-constraint%22/%3E + </tm:topic> + + tm:association + tm:type<tm:topicRef href="#supertype-subtype"/></tm:type> + tm:role + tm:type<tm:topicRef href="#subtype"/></tm:type> + <tm:topicRef href="#occurrencetypescope-constraint"/> + </tm:role> + tm:role + tm:type<tm:topicRef href="#supertype"/></tm:type> + <tm:topicRef href="#constraint"/> + </tm:role> + </tm:association> + + <!-- associationtypescope-constraint --> + <tm:topic id="associationtypescope-constraint"> + <tm:subjectIdentifier href="http://psi.topicmaps.org/tmcl/association-type-scope-constraint%22/%3E + </tm:topic> + + tm:association + tm:type<tm:topicRef href="#supertype-subtype"/></tm:type> + tm:role + tm:type<tm:topicRef href="#subtype"/></tm:type> + <tm:topicRef href="#associationtypescope-constraint"/> + </tm:role> + tm:role + tm:type<tm:topicRef href="#supertype"/></tm:type> + <tm:topicRef href="#constraint"/> + </tm:role> + </tm:association> + + + <!-- ===================================================================== --> + <!-- === own datamodel: type handling ==================================== --> + <!-- ===================================================================== --> + + <!-- only topics that are instances of topictype are allowed as topic + types --> + <tm:topic id="ttc"> + <tm:subjectIdentifier href="http://some.where/constraint-psis/ttc%22/%3E + tm:instanceOf<tm:topicRef href="#topictype-constraint"/></tm:instanceOf> + </tm:topic> + + <!-- only topics that are instances of associationtype are allowed as + association types --> + <tm:topic id="atc"> + <tm:subjectIdentifier href="http://some.where/constraint-psis/atc%22/%3E + tm:instanceOf<tm:topicRef href="#associationtype-constraint"/></tm:instanceOf> + </tm:topic> + + <!-- only topics that are instances of roletype are allowed as + association role types --> + <tm:topic id="rtc"> + <tm:subjectIdentifier href="http://some.where/constraint-psis/rtc%22/%3E + tm:instanceOf<tm:topicRef href="#roletype-constraint"/></tm:instanceOf> + </tm:topic> + + <!-- only topics that are instances of occurrencetype are allowed as + occurrence types --> + <tm:topic id="otc"> + <tm:subjectIdentifier href="http://some.where/constraint-psis/otc%22/%3E + tm:instanceOf<tm:topicRef href="#occurrencetype-constraint"/></tm:instanceOf> + </tm:topic> + + <!-- only topics that are instances of nametype are allowed as + name types --> + <tm:topic id="ntc"> + <tm:subjectIdentifier href="http://some.where/constraint-psis/ntc%22/%3E + tm:instanceOf<tm:topicRef href="#nametype-constraint"/></tm:instanceOf> + </tm:topic> + + + <!-- ===================================================================== --> + <!-- === own datamodel: base types ======================================= --> + <!-- ===================================================================== --> + + <!-- author --> + <tm:topic id="author"> + <tm:subjectIdentifier href="http://some.where/base-psis/author%22/%3E + tm:instanceOf<tm:topicRef href="#topictype"/></tm:instanceOf> + </tm:topic> + + <tm:topic id="first-name"> + <tm:subjectIdentifier href="http://some.where/base-psis/first-name%22/%3E + tm:instanceOf<tm:topicRef href="#nametype"/></tm:instanceOf> + </tm:topic> + + <tm:topic id="last-name"> + <tm:subjectIdentifier href="http://some.where/base-psis/last-name%22/%3E + tm:instanceOf<tm:topicRef href="#nametype"/></tm:instanceOf> + </tm:topic> + + <tm:topic id="author-info"> + <tm:subjectIdentifier href="http://some.where/base-psis/author-info%22/%3E + tm:instanceOf<tm:topicRef href="#occurrencetype"/></tm:instanceOf> + </tm:topic> + + <!-- poem --> + <tm:topic id="poem"> + <tm:subjectIdentifier href="http://some.where/base-psis/poem%22/%3E + tm:instanceOf<tm:topicRef href="#topictype"/></tm:instanceOf> + </tm:topic> + + <tm:topic id="title"> + <tm:subjectIdentifier href="http://some.where/base-psis/title%22/%3E + tm:instanceOf<tm:topicRef href="#nametype"/></tm:instanceOf> + </tm:topic> + + <tm:topic id="poem-content"> + <tm:subjectIdentifier href="http://some.where/base-psis/poem-content%22/%3E + tm:instanceOf<tm:topicRef href="#occurrencetype"/></tm:instanceOf> + </tm:topic> + + <!-- poem scopes --> + <tm:topic id="de"> + <tm:subjectIdentifier href="http://some.where/base-psis/de%22/%3E + tm:instanceOf<tm:topicRef href="#scopetype"/></tm:instanceOf> + </tm:topic> + + <tm:topic id="en"> + <tm:subjectIdentifier href="http://some.where/base-psis/en%22/%3E + tm:instanceOf<tm:topicRef href="#scopetype"/></tm:instanceOf> + </tm:topic> + + <!-- association author-poem --> + <tm:topic id="written-by"> + <tm:subjectIdentifier href="http://some.where/base-psis/written-by%22/%3E + tm:instanceOf<tm:topicRef href="#associationtype"/></tm:instanceOf> + </tm:topic> + + <tm:topic id="writer"> + <tm:subjectIdentifier href="http://some.where/base-psis/writer%22/%3E + tm:instanceOf<tm:topicRef href="#roletype"/></tm:instanceOf> + </tm:topic> + + <tm:topic id="written"> + <tm:subjectIdentifier href="http://some.where/base-psis/written%22/%3E + tm:instanceOf<tm:topicRef href="#roletype"/></tm:instanceOf> + </tm:topic> + + + <!-- ===================================================================== --> + <!-- === own datamodel: exclusive type constraint ======================== --> + <!-- ===================================================================== --> + <!-- same instances of the type author and title are not allowed --> + <tm:topic id="exc"> + <tm:subjectIdentifier href="http://some.where/constraint-psis/exc%22/%3E + tm:instanceOf<tm:topicRef href="#exclusive-instance"/></tm:instanceOf> + </tm:topic> + + tm:association + tm:type<tm:topicRef href="#applies-to"/></tm:type> + tm:role + tm:type<tm:topicRef href="#constraint-role"/></tm:type> + <tm:topicRef href="#exc"/> + </tm:role> + tm:role + tm:type<tm:topicRef href="#topictype-role"/></tm:type> + <tm:topicRef href="#author"/> + </tm:role> + </tm:association> + + tm:association + tm:type<tm:topicRef href="#applies-to"/></tm:type> + tm:role + tm:type<tm:topicRef href="#constraint-role"/></tm:type> + <tm:topicRef href="#exc"/> + </tm:role> + tm:role + tm:type<tm:topicRef href="#topictype-role"/></tm:type> + <tm:topicRef href="#poem"/> + </tm:role> + </tm:association> + + <!-- ===================================================================== --> + <!-- === own datamodel: subjectIdentifier constraints ==================== --> + <!-- ===================================================================== --> + <!-- a topic of the type author has to have a psi of the form + "^http://some.where/psis/author/.+$" + and a topic of the type poem has to have a psi of the form + "^http://some.where/psis/poem/.+$". + further all topics can have mor psis of the form "^.+$" --> + + <!-- subjectidentifier of author --> + <tm:topic id="sic-author"> + <tm:subjectIdentifier href="http://some.where/constraint-psis/sic-author%22/%3E + tm:instanceOf<tm:topicRef href="#subjectidentifier-constraint"/></tm:instanceOf> + tm:occurrence + tm:type<tm:topicRef href="#card-min"/></tm:type> + <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#unsignedInt%22%3E1</tm:resourceData> + </tm:occurrence> + tm:occurrence + tm:type<tm:topicRef href="#card-max"/></tm:type> + <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#unsignedInt%22%3E1</tm:resourceData> + </tm:occurrence> + tm:occurrence + tm:type<tm:topicRef href="#regexp"/></tm:type> + <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#string%22%3E%5Ehttp://some.where/psis/autho...</tm:resourceData> + </tm:occurrence> + </tm:topic> + + tm:association + tm:type<tm:topicRef href="#applies-to"/></tm:type> + tm:role + tm:type<tm:topicRef href="#constraint-role"/></tm:type> + <tm:topicRef href="#sic-author"/> + </tm:role> + tm:role + tm:type<tm:topicRef href="#topictype-role"/></tm:type> + <tm:topicRef href="#author"/> + </tm:role> + </tm:association> + + <!-- subjectidentifier of poem --> + <tm:topic id="sic-poem"> + <tm:subjectIdentifier href="http://some.where/constraint-psis/sic-poem%22/%3E + tm:instanceOf<tm:topicRef href="#subjectidentifier-constraint"/></tm:instanceOf> + tm:occurrence + tm:type<tm:topicRef href="#card-min"/></tm:type> + <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#unsignedInt%22%3E1</tm:resourceData> + </tm:occurrence> + tm:occurrence + tm:type<tm:topicRef href="#card-max"/></tm:type> + <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#unsignedInt%22%3E1</tm:resourceData> + </tm:occurrence> + tm:occurrence + tm:type<tm:topicRef href="#regexp"/></tm:type> + <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#string%22%3E%5Ehttp://some.where/psis/poem/...</tm:resourceData> + </tm:occurrence> + </tm:topic> + + tm:association + tm:type<tm:topicRef href="#applies-to"/></tm:type> + tm:role + tm:type<tm:topicRef href="#constraint-role"/></tm:type> + <tm:topicRef href="#sic-poem"/> + </tm:role> + tm:role + tm:type<tm:topicRef href="#topictype-role"/></tm:type> + <tm:topicRef href="#poem"/> + </tm:role> + </tm:association> + + <!-- further subjectidentifiers of author and poem --> + <tm:topic id="sic-author-poem"> + <tm:subjectIdentifier href="http://some.where/constraint-psis/sic-author-poem%22/%3E + tm:instanceOf<tm:topicRef href="#subjectidentifier-constraint"/></tm:instanceOf> + tm:occurrence + tm:type<tm:topicRef href="#card-min"/></tm:type> + <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#unsignedInt%22%3E0</tm:resourceData> + </tm:occurrence> + tm:occurrence + tm:type<tm:topicRef href="#card-max"/></tm:type> + <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#unsignedInt%22%3EMAX_INT</tm:resourceData> + </tm:occurrence> + tm:occurrence + tm:type<tm:topicRef href="#regexp"/></tm:type> + <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#string%22%3E%5E.+$</tm:resourceData> + </tm:occurrence> + </tm:topic> + + tm:association + tm:type<tm:topicRef href="#applies-to"/></tm:type> + tm:role + tm:type<tm:topicRef href="#constraint-role"/></tm:type> + <tm:topicRef href="#sic-author-poem"/> + </tm:role> + tm:role + tm:type<tm:topicRef href="#topictype-role"/></tm:type> + <tm:topicRef href="#author"/> + </tm:role> + </tm:association> + + tm:association + tm:type<tm:topicRef href="#applies-to"/></tm:type> + tm:role + tm:type<tm:topicRef href="#constraint-role"/></tm:type> + <tm:topicRef href="#sic-author-poem"/> + </tm:role> + tm:role + tm:type<tm:topicRef href="#topictype-role"/></tm:type> + <tm:topicRef href="#poem"/> + </tm:role> + </tm:association> + + + <!-- ===================================================================== --> + <!-- === own datamodel: subjectIdentifier constraints ==================== --> + <!-- ===================================================================== --> + <!-- all instances of author and poem are not allowed to own a + subjectLocator --> + + <tm:topic id="slc-author-poem"> + <tm:subjectIdentifier href="http://some.where/constraint-psis/slc-author-poem%22/%3E + tm:instanceOf<tm:topicRef href="#subjectlocator-constraint"/></tm:instanceOf> + tm:occurrence + tm:type<tm:topicRef href="#card-min"/></tm:type> + <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#unsignedInt%22%3E0</tm:resourceData> + </tm:occurrence> + tm:occurrence + tm:type<tm:topicRef href="#card-max"/></tm:type> + <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#unsignedInt%22%3E0</tm:resourceData> + </tm:occurrence> + tm:occurrence + tm:type<tm:topicRef href="#regexp"/></tm:type> + <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#string%22%3E%5E.*$</tm:resourceData> + </tm:occurrence> + </tm:topic> + + tm:association + tm:type<tm:topicRef href="#applies-to"/></tm:type> + tm:role + tm:type<tm:topicRef href="#constraint-role"/></tm:type> + <tm:topicRef href="#slc-author-poem"/> + </tm:role> + tm:role + tm:type<tm:topicRef href="#topictype-role"/></tm:type> + <tm:topicRef href="#author"/> + </tm:role> + </tm:association> + + tm:association + tm:type<tm:topicRef href="#applies-to"/></tm:type> + tm:role + tm:type<tm:topicRef href="#constraint-role"/></tm:type> + <tm:topicRef href="#slc-author-poem"/> + </tm:role> + tm:role + tm:type<tm:topicRef href="#topictype-role"/></tm:type> + <tm:topicRef href="#poem"/> + </tm:role> + </tm:association> + + <!-- ===================================================================== --> + <!-- === own datamodel: names constraints ================================ --> + <!-- ===================================================================== --> + <!-- instances of the type author has to own a name of the type first-name + and one of the type last-name. both must be valid to the regular + expression "^.+$". + instances of the type poem has exactly one name of the type title + with the regular expression "^.+$" --> + + <!-- author first name --> + <tm:topic id="author-first-name-constraint"> + <tm:subjectIdentifier href="http://some.where/constraint-psis/author-first-name-constraint%22/%3E + tm:instanceOf<tm:topicRef href="#topicname-constraint"/></tm:instanceOf> + tm:occurrence + tm:type<tm:topicRef href="#card-min"/></tm:type> + <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#unsignedInt%22%3E0</tm:resourceData> + </tm:occurrence> + tm:occurrence + tm:type<tm:topicRef href="#card-max"/></tm:type> + <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#unsignedInt%22%3E1</tm:resourceData> + </tm:occurrence> + tm:occurrence + tm:type<tm:topicRef href="#regexp"/></tm:type> + <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#string%22%3E%5E.+$</tm:resourceData> + </tm:occurrence> + </tm:topic> + + tm:association + tm:type<tm:topicRef href="#applies-to"/></tm:type> + tm:role + tm:type<tm:topicRef href="#constraint-role"/></tm:type> + <tm:topicRef href="#author-first-name-constraint"/> + </tm:role> + tm:role + tm:type<tm:topicRef href="#topictype-role"/></tm:type> + <tm:topicRef href="#author"/> + </tm:role> + </tm:association> + + tm:association + tm:type<tm:topicRef href="#applies-to"/></tm:type> + tm:role + tm:type<tm:topicRef href="#constraint-role"/></tm:type> + <tm:topicRef href="#author-first-name-constraint"/> + </tm:role> + tm:role + tm:type<tm:topicRef href="#nametype-role"/></tm:type> + <tm:topicRef href="#first-name"/> + </tm:role> + </tm:association> + + <!-- author last name --> + <tm:topic id="author-last-name-constraint"> + <tm:subjectIdentifier href="http://some.where/constraint-psis/author-last-name-constraint%22/%3E + tm:instanceOf<tm:topicRef href="#topicname-constraint"/></tm:instanceOf> + tm:occurrence + tm:type<tm:topicRef href="#card-min"/></tm:type> + <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#unsignedInt%22%3E0</tm:resourceData> + </tm:occurrence> + tm:occurrence + tm:type<tm:topicRef href="#card-max"/></tm:type> + <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#unsignedInt%22%3E1</tm:resourceData> + </tm:occurrence> + tm:occurrence + tm:type<tm:topicRef href="#regexp"/></tm:type> + <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#string%22%3E%5E.+$</tm:resourceData> + </tm:occurrence> + </tm:topic> + + tm:association + tm:type<tm:topicRef href="#applies-to"/></tm:type> + tm:role + tm:type<tm:topicRef href="#constraint-role"/></tm:type> + <tm:topicRef href="#author-last-name-constraint"/> + </tm:role> + tm:role + tm:type<tm:topicRef href="#topictype-role"/></tm:type> + <tm:topicRef href="#author"/> + </tm:role> + </tm:association> + + tm:association + tm:type<tm:topicRef href="#applies-to"/></tm:type> + tm:role + tm:type<tm:topicRef href="#constraint-role"/></tm:type> + <tm:topicRef href="#author-last-name-constraint"/> + </tm:role> + tm:role + tm:type<tm:topicRef href="#nametype-role"/></tm:type> + <tm:topicRef href="#last-name"/> + </tm:role> + </tm:association> + + <!-- poem title name --> + <tm:topic id="poem-title-name-constraint"> + <tm:subjectIdentifier href="http://some.where/constraint-psis/poem-title-name-constraint%22/%3E + tm:instanceOf<tm:topicRef href="#topicname-constraint"/></tm:instanceOf> + tm:occurrence + tm:type<tm:topicRef href="#card-min"/></tm:type> + <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#unsignedInt%22%3E0</tm:resourceData> + </tm:occurrence> + tm:occurrence + tm:type<tm:topicRef href="#card-max"/></tm:type> + <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#unsignedInt%22%3E1</tm:resourceData> + </tm:occurrence> + tm:occurrence + tm:type<tm:topicRef href="#regexp"/></tm:type> + <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#string%22%3E%5E.+$</tm:resourceData> + </tm:occurrence> + </tm:topic> + + tm:association + tm:type<tm:topicRef href="#applies-to"/></tm:type> + tm:role + tm:type<tm:topicRef href="#constraint-role"/></tm:type> + <tm:topicRef href="#poem-title-name-constraint"/> + </tm:role> + tm:role + tm:type<tm:topicRef href="#topictype-role"/></tm:type> + <tm:topicRef href="#poem"/> + </tm:role> + </tm:association> + + tm:association + tm:type<tm:topicRef href="#applies-to"/></tm:type> + tm:role + tm:type<tm:topicRef href="#constraint-role"/></tm:type> + <tm:topicRef href="#poem-title-name-constraint"/> + </tm:role> + tm:role + tm:type<tm:topicRef href="#nametype-role"/></tm:type> + <tm:topicRef href="#title"/> + </tm:role> + </tm:association> + + + <!-- ===================================================================== --> + <!-- === own datamodel: occurences constraints =========================== --> + <!-- ===================================================================== --> + <!-- every instance of the topic author can have one occurrence of the type + author-info which contains a resourceRef (= datatype #anyURI) --> + + <!-- author info occurrence --> + <tm:topic id="author-occurrence-constraint"> + <tm:subjectIdentifier href="http://some.where/constraint-psis/author-occurrence-constraint%22/%3E + tm:instanceOf<tm:topicRef href="#topicoccurrence-constraint"/></tm:instanceOf> + tm:occurrence + tm:type<tm:topicRef href="#card-min"/></tm:type> + <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#unsignedInt%22%3E0</tm:resourceData> + </tm:occurrence> + tm:occurrence + tm:type<tm:topicRef href="#card-max"/></tm:type> + <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#unsignedInt%22%3E1</tm:resourceData> + </tm:occurrence> + tm:occurrence + tm:type<tm:topicRef href="#regexp"/></tm:type> + <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#string%22%3E%5E.+$</tm:resourceData> + </tm:occurrence> + </tm:topic> + + tm:association + tm:type<tm:topicRef href="#applies-to"/></tm:type> + tm:role + tm:type<tm:topicRef href="#constraint-role"/></tm:type> + <tm:topicRef href="#author-occurrence-constraint"/> + </tm:role> + tm:role + tm:type<tm:topicRef href="#topictype-role"/></tm:type> + <tm:topicRef href="#author"/> + </tm:role> + </tm:association> + + tm:association + tm:type<tm:topicRef href="#applies-to"/></tm:type> + tm:role + tm:type<tm:topicRef href="#constraint-role"/></tm:type> + <tm:topicRef href="#author-occurrence-constraint"/> + </tm:role> + tm:role + tm:type<tm:topicRef href="#occurrencetype-role"/></tm:type> + <tm:topicRef href="#author-info"/> + </tm:role> + </tm:association> + + <!-- author info occurrence datatype --> + <tm:topic id="author-info-occurrence-datatype-constraint"> + <tm:subjectIdentifier href="http://some.where/constraint-psis/author-poem-occurrence-datatype-constraint... + tm:instanceOf<tm:topicRef href="#occurrencedatatype-constraint"/></tm:instanceOf> + tm:occurrence + tm:type<tm:topicRef href="#datatype"/></tm:type> + <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#string%22%3Ehttp://www.w3.org/2001/XMLSchem...</tm:resourceData> + </tm:occurrence> + </tm:topic> + + tm:association + tm:type<tm:topicRef href="#applies-to"/></tm:type> + tm:role + tm:type<tm:topicRef href="#constraint-role"/></tm:type> + <tm:topicRef href="#author-info-occurrence-datatype-constraint"/> + </tm:role> + tm:role + tm:type<tm:topicRef href="#occurrencetype-role"/></tm:type> + <tm:topicRef href="#author-info"/> + </tm:role> + </tm:association> + + <!-- all instances of the type poem has to have exactly one occurrence + of the type poem-content with the datatype string and the either + the scope en or de--> + <tm:topic id="poem-occurrence-constraint"> + <tm:subjectIdentifier href="http://some.where/constraint-psis/poem-occurrence-constraint%22/%3E + tm:instanceOf<tm:topicRef href="#topicoccurrence-constraint"/></tm:instanceOf> + tm:occurrence + tm:type<tm:topicRef href="#card-min"/></tm:type> + <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#unsignedInt%22%3E1</tm:resourceData> + </tm:occurrence> + tm:occurrence + tm:type<tm:topicRef href="#card-max"/></tm:type> + <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#unsignedInt%22%3E1</tm:resourceData> + </tm:occurrence> + tm:occurrence + tm:type<tm:topicRef href="#regexp"/></tm:type> + <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#string%22%3E%5E.+$</tm:resourceData> + </tm:occurrence> + </tm:topic> + + tm:association + tm:type<tm:topicRef href="#applies-to"/></tm:type> + tm:role + tm:type<tm:topicRef href="#constraint-role"/></tm:type> + <tm:topicRef href="#poem-occurrence-constraint"/> + </tm:role> + tm:role + tm:type<tm:topicRef href="#topictype-role"/></tm:type> + <tm:topicRef href="#poem"/> + </tm:role> + </tm:association> + + tm:association + tm:type<tm:topicRef href="#applies-to"/></tm:type> + tm:role + tm:type<tm:topicRef href="#constraint-role"/></tm:type> + <tm:topicRef href="#poem-occurrence-constraint"/> + </tm:role> + tm:role + tm:type<tm:topicRef href="#occurrencetype-role"/></tm:type> + <tm:topicRef href="#poem-content"/> + </tm:role> + </tm:association> + + <!-- poem content-occurrence datatype --> + <tm:topic id="poem-content-occurrence-datatype-constraint"> + <tm:subjectIdentifier href="http://some.where/constraint-psis/poem-content-occurrence-datatype-constrain... + tm:instanceOf<tm:topicRef href="#occurrencedatatype-constraint"/></tm:instanceOf> + tm:occurrence + tm:type<tm:topicRef href="#datatype"/></tm:type> + <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#string%22%3Ehttp://www.w3.org/2001/XMLSchem...</tm:resourceData> + </tm:occurrence> + </tm:topic> + + tm:association + tm:type<tm:topicRef href="#applies-to"/></tm:type> + tm:role + tm:type<tm:topicRef href="#constraint-role"/></tm:type> + <tm:topicRef href="#poem-content-occurrence-datatype-constraint"/> + </tm:role> + tm:role + tm:type<tm:topicRef href="#occurrencetype-role"/></tm:type> + <tm:topicRef href="#poem-content"/> + </tm:role> + </tm:association> + + <!-- the poem-content-occurrence can only appear once per topictype, + so all topic with this occurrence type must have different + occurrence-values --> + <tm:topic id="unique-poem-occurrence-constraint"> + <tm:subjectIdentifier href="http://some.where/constraint-psis/unique-poem-occurrence-constraint%22/%3E + tm:instanceOf<tm:topicRef href="#uniqueoccurrence-constraint"/></tm:instanceOf> + tm:occurrence + tm:type<tm:topicRef href="#card-min"/></tm:type> + <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#unsignedInt%22%3E1</tm:resourceData> + </tm:occurrence> + tm:occurrence + tm:type<tm:topicRef href="#card-max"/></tm:type> + <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#unsignedInt%22%3E1</tm:resourceData> + </tm:occurrence> + tm:occurrence + tm:type<tm:topicRef href="#regexp"/></tm:type> + <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#string%22%3E%5E.*$</tm:resourceData> + </tm:occurrence> + </tm:topic> + + tm:association + tm:type<tm:topicRef href="#applies-to"/></tm:type> + tm:role + tm:type<tm:topicRef href="#constraint-role"/></tm:type> + <tm:topicRef href="#unique-poem-occurrence-constraint"/> + </tm:role> + tm:role + tm:type<tm:topicRef href="#topictype-role"/></tm:type> + <tm:topicRef href="#poem"/> + </tm:role> + </tm:association> + + tm:association + tm:type<tm:topicRef href="#applies-to"/></tm:type> + tm:role + tm:type<tm:topicRef href="#constraint-role"/></tm:type> + <tm:topicRef href="#unique-poem-occurrence-constraint"/> + </tm:role> + tm:role + tm:type<tm:topicRef href="#occurrencetype-role"/></tm:type> + <tm:topicRef href="#poem-content"/> + </tm:role> + </tm:association> + + <!-- add a scope to the occurrence "poem-content" --> + <tm:topic id="scoped-poem-occurrence-constraint"> + <tm:subjectIdentifier href="http://some.where/constraint-psis/scoped-poem-occurrence-constraint%22/%3E + tm:instanceOf<tm:topicRef href="#occurrencetypescope-constraint"/></tm:instanceOf> + tm:occurrence + tm:type<tm:topicRef href="#card-min"/></tm:type> + <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#unsignedInt%22%3E1</tm:resourceData> + </tm:occurrence> + tm:occurrence + tm:type<tm:topicRef href="#card-max"/></tm:type> + <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#unsignedInt%22%3E2</tm:resourceData> + </tm:occurrence> + </tm:topic> + + tm:association + tm:type<tm:topicRef href="#applies-to"/></tm:type> + tm:role + tm:type<tm:topicRef href="#constraint-role"/></tm:type> + <tm:topicRef href="#scoped-poem-occurrence-constraint"/> + </tm:role> + tm:role + tm:type<tm:topicRef href="#occurrencetype-role"/></tm:type> + <tm:topicRef href="#poem-content"/> + </tm:role> + </tm:association> + + tm:association + tm:type<tm:topicRef href="#applies-to"/></tm:type> + tm:role + tm:type<tm:topicRef href="#constraint-role"/></tm:type> + <tm:topicRef href="#scoped-poem-occurrence-constraint"/> + </tm:role> + tm:role + tm:type<tm:topicRef href="#scopetype-role"/></tm:type> + <tm:topicRef href="#en"/> + </tm:role> + </tm:association> + + tm:association + tm:type<tm:topicRef href="#applies-to"/></tm:type> + tm:role + tm:type<tm:topicRef href="#constraint-role"/></tm:type> + <tm:topicRef href="#scoped-poem-occurrence-constraint"/> + </tm:role> + tm:role + tm:type<tm:topicRef href="#scopetype-role"/></tm:type> + <tm:topicRef href="#de"/> + </tm:role> + </tm:association> + + + <!-- ===================================================================== --> + <!-- === own datamodel: association (-role) constraints ================== --> + <!-- ===================================================================== --> + <!-- there exists one asoociation of the type written-by between the types + author and poem. where one role is of type writer which has a player + of type author and another role of type written which owns a player of + type poem --> + + <!-- the writer role has to appear exactly once in an association of type + written-by --> + <tm:topic id="writer-role-constraint"> + <tm:subjectIdentifier href="http://some.where/constraint-psis/writer-role-constraint%22/%3E + tm:instanceOf<tm:topicRef href="#associationrole-constraint"/></tm:instanceOf> + tm:occurrence + tm:type<tm:topicRef href="#card-min"/></tm:type> + <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#unsignedInt%22%3E1</tm:resourceData> + </tm:occurrence> + tm:occurrence + tm:type<tm:topicRef href="#card-max"/></tm:type> + <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#unsignedInt%22%3E1</tm:resourceData> + </tm:occurrence> + </tm:topic> + + tm:association + tm:type<tm:topicRef href="#applies-to"/></tm:type> + tm:role + tm:type<tm:topicRef href="#constraint-role"/></tm:type> + <tm:topicRef href="#writer-role-constraint"/> + </tm:role> + tm:role + tm:type<tm:topicRef href="#associationtype-role"/></tm:type> + <tm:topicRef href="#written-by"/> + </tm:role> + </tm:association> + + tm:association + tm:type<tm:topicRef href="#applies-to"/></tm:type> + tm:role + tm:type<tm:topicRef href="#constraint-role"/></tm:type> + <tm:topicRef href="#writer-role-constraint"/> + </tm:role> + tm:role + tm:type<tm:topicRef href="#roletype-role"/></tm:type> + <tm:topicRef href="#writer"/> + </tm:role> + </tm:association> + + <!-- the writer role owns a player of the type author --> + <tm:topic id="writer-role-player-constraint"> + <tm:subjectIdentifier href="http://some.where/constraint-psis/writer-role-player-constraint%22/%3E + tm:instanceOf<tm:topicRef href="#roleplayer-constraint"/></tm:instanceOf> + tm:occurrence + tm:type<tm:topicRef href="#card-min"/></tm:type> + <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#unsignedInt%22%3E1</tm:resourceData> + </tm:occurrence> + tm:occurrence + tm:type<tm:topicRef href="#card-max"/></tm:type> + <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#unsignedInt%22%3E1</tm:resourceData> + </tm:occurrence> + </tm:topic> + + tm:association + tm:type<tm:topicRef href="#applies-to"/></tm:type> + tm:role + tm:type<tm:topicRef href="#constraint-role"/></tm:type> + <tm:topicRef href="#writer-role-player-constraint"/> + </tm:role> + tm:role + tm:type<tm:topicRef href="#topictype-role"/></tm:type> + <tm:topicRef href="#author"/> + </tm:role> + </tm:association> + + tm:association + tm:type<tm:topicRef href="#applies-to"/></tm:type> + tm:role + tm:type<tm:topicRef href="#constraint-role"/></tm:type> + <tm:topicRef href="#writer-role-player-constraint"/> + </tm:role> + tm:role + tm:type<tm:topicRef href="#associationtype-role"/></tm:type> + <tm:topicRef href="#written-by"/> + </tm:role> + </tm:association> + + tm:association + tm:type<tm:topicRef href="#applies-to"/></tm:type> + tm:role + tm:type<tm:topicRef href="#constraint-role"/></tm:type> + <tm:topicRef href="#writer-role-player-constraint"/> + </tm:role> + tm:role + tm:type<tm:topicRef href="#roletype-role"/></tm:type> + <tm:topicRef href="#writer"/> + </tm:role> + </tm:association> + + + <!-- the written role has to appear exactly once in an association of type + written-by --> + <tm:topic id="written-role-constraint"> + <tm:subjectIdentifier href="http://some.where/constraint-psis/written-role-constraint%22/%3E + tm:instanceOf<tm:topicRef href="#associationrole-constraint"/></tm:instanceOf> + tm:occurrence + tm:type<tm:topicRef href="#card-min"/></tm:type> + <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#unsignedInt%22%3E1</tm:resourceData> + </tm:occurrence> + tm:occurrence + tm:type<tm:topicRef href="#card-max"/></tm:type> + <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#unsignedInt%22%3E1</tm:resourceData> + </tm:occurrence> + </tm:topic> + + tm:association + tm:type<tm:topicRef href="#applies-to"/></tm:type> + tm:role + tm:type<tm:topicRef href="#constraint-role"/></tm:type> + <tm:topicRef href="#written-role-constraint"/> + </tm:role> + tm:role + tm:type<tm:topicRef href="#associationtype-role"/></tm:type> + <tm:topicRef href="#written-by"/> + </tm:role> + </tm:association> + + tm:association + tm:type<tm:topicRef href="#applies-to"/></tm:type> + tm:role + tm:type<tm:topicRef href="#constraint-role"/></tm:type> + <tm:topicRef href="#written-role-constraint"/> + </tm:role> + tm:role + tm:type<tm:topicRef href="#roletype-role"/></tm:type> + <tm:topicRef href="#written"/> + </tm:role> + </tm:association> + + <!-- the written role owns a player of the type poem --> + <tm:topic id="written-role-player-constraint"> + <tm:subjectIdentifier href="http://some.where/constraint-psis/written-role-player-constraint%22/%3E + tm:instanceOf<tm:topicRef href="#roleplayer-constraint"/></tm:instanceOf> + tm:occurrence + tm:type<tm:topicRef href="#card-min"/></tm:type> + <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#unsignedInt%22%3E1</tm:resourceData> + </tm:occurrence> + tm:occurrence + tm:type<tm:topicRef href="#card-max"/></tm:type> + <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#unsignedInt%22%3E1</tm:resourceData> + </tm:occurrence> + </tm:topic> + + tm:association + tm:type<tm:topicRef href="#applies-to"/></tm:type> + tm:role + tm:type<tm:topicRef href="#constraint-role"/></tm:type> + <tm:topicRef href="#written-role-player-constraint"/> + </tm:role> + tm:role + tm:type<tm:topicRef href="#topictype-role"/></tm:type> + <tm:topicRef href="#poem"/> + </tm:role> + </tm:association> + + tm:association + tm:type<tm:topicRef href="#applies-to"/></tm:type> + tm:role + tm:type<tm:topicRef href="#constraint-role"/></tm:type> + <tm:topicRef href="#written-role-player-constraint"/> + </tm:role> + tm:role + tm:type<tm:topicRef href="#associationtype-role"/></tm:type> + <tm:topicRef href="#written-by"/> + </tm:role> + </tm:association> + + tm:association + tm:type<tm:topicRef href="#applies-to"/></tm:type> + tm:role + tm:type<tm:topicRef href="#constraint-role"/></tm:type> + <tm:topicRef href="#written-role-player-constraint"/> + </tm:role> + tm:role + tm:type<tm:topicRef href="#roletype-role"/></tm:type> + <tm:topicRef href="#written"/> + </tm:role> + </tm:association> + + + <!-- otherrole-constraint: + If there is a role of the type written with a player of the type poem + there must be another role of the type writer with a player of the + type author. + In contrast if there is a role of the type writer with a player of the + type author there must be a role of the type written with a player of + the type poem. + So for this case there are two otherrole-constraints which handle this + both cases. --> + + <tm:topic id="written-by-otherrole-constraint-for-writer"> + <tm:subjectIdentifier href="written-by-otherrole-constraint-for-writer"/> + tm:instanceOf<tm:topicRef href="#otherrole-constraint"/></tm:instanceOf> + tm:occurrence + tm:type + <tm:topicRef href="#card-min"/> + </tm:type> + <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#unsignedInt%22%3E1</tm:resourceData> + </tm:occurrence> + tm:occurrence + tm:type + <tm:topicRef href="#card-max"/> + </tm:type> + <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#unsignedInt%22%3E1</tm:resourceData> + </tm:occurrence> + </tm:topic> + + tm:association + tm:type<tm:topicRef href="#applies-to"/></tm:type> + tm:role + tm:type<tm:topicRef href="#constraint-role"/></tm:type> + <tm:topicRef href="#written-by-otherrole-constraint-for-writer"/> + </tm:role> + tm:role + tm:type<tm:topicRef href="#associationtype-role"/></tm:type> + <tm:topicRef href="#written-by"/> + </tm:role> + </tm:association> + + tm:association + tm:type<tm:topicRef href="#applies-to"/></tm:type> + tm:role + tm:type<tm:topicRef href="#constraint-role"/></tm:type> + <tm:topicRef href="#written-by-otherrole-constraint-for-writer"/> + </tm:role> + tm:role + tm:type<tm:topicRef href="#roletype-role"/></tm:type> + <tm:topicRef href="#writer"/> + </tm:role> + </tm:association> + + tm:association + tm:type<tm:topicRef href="#applies-to"/></tm:type> + tm:role + tm:type<tm:topicRef href="#constraint-role"/></tm:type> + <tm:topicRef href="#written-by-otherrole-constraint-for-writer"/> + </tm:role> + tm:role + tm:type<tm:topicRef href="#topictype-role"/></tm:type> + <tm:topicRef href="#author"/> + </tm:role> + </tm:association> + + tm:association + tm:type<tm:topicRef href="#applies-to"/></tm:type> + tm:role + tm:type<tm:topicRef href="#constraint-role"/></tm:type> + <tm:topicRef href="#written-by-otherrole-constraint-for-writer"/> + </tm:role> + tm:role + tm:type<tm:topicRef href="#otherroletype-role"/></tm:type> + <tm:topicRef href="#written"/> + </tm:role> + </tm:association> + + tm:association + tm:type<tm:topicRef href="#applies-to"/></tm:type> + tm:role + tm:type<tm:topicRef href="#constraint-role"/></tm:type> + <tm:topicRef href="#written-by-otherrole-constraint-for-writer"/> + </tm:role> + tm:role + tm:type<tm:topicRef href="#othertopictype-role"/></tm:type> + <tm:topicRef href="#poem"/> + </tm:role> + </tm:association> + + <tm:topic id="written-by-otherrole-constraint-for-written"> + <tm:subjectIdentifier href="written-by-otherrole-constraint-for-written"/> + tm:instanceOf<tm:topicRef href="#otherrole-constraint"/></tm:instanceOf> + tm:occurrence + tm:type + <tm:topicRef href="#card-min"/> + </tm:type> + <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#unsignedInt%22%3E1</tm:resourceData> + </tm:occurrence> + tm:occurrence + tm:type + <tm:topicRef href="#card-max"/> + </tm:type> + <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#unsignedInt%22%3E1</tm:resourceData> + </tm:occurrence> + </tm:topic> + + tm:association + tm:type<tm:topicRef href="#applies-to"/></tm:type> + tm:role + tm:type<tm:topicRef href="#constraint-role"/></tm:type> + <tm:topicRef href="#written-by-otherrole-constraint-for-written"/> + </tm:role> + tm:role + tm:type<tm:topicRef href="#associationtype-role"/></tm:type> + <tm:topicRef href="#written-by"/> + </tm:role> + </tm:association> + + tm:association + tm:type<tm:topicRef href="#applies-to"/></tm:type> + tm:role + tm:type<tm:topicRef href="#constraint-role"/></tm:type> + <tm:topicRef href="#written-by-otherrole-constraint-for-written"/> + </tm:role> + tm:role + tm:type<tm:topicRef href="#roletype-role"/></tm:type> + <tm:topicRef href="#written"/> + </tm:role> + </tm:association> + + tm:association + tm:type<tm:topicRef href="#applies-to"/></tm:type> + tm:role + tm:type<tm:topicRef href="#constraint-role"/></tm:type> + <tm:topicRef href="#written-by-otherrole-constraint-for-written"/> + </tm:role> + tm:role + tm:type<tm:topicRef href="#topictype-role"/></tm:type> + <tm:topicRef href="#poem"/> + </tm:role> + </tm:association> + + tm:association + tm:type<tm:topicRef href="#applies-to"/></tm:type> + tm:role + tm:type<tm:topicRef href="#constraint-role"/></tm:type> + <tm:topicRef href="#written-by-otherrole-constraint-for-written"/> + </tm:role> + tm:role + tm:type<tm:topicRef href="#otherroletype-role"/></tm:type> + <tm:topicRef href="#writer"/> + </tm:role> + </tm:association> + + tm:association + tm:type<tm:topicRef href="#applies-to"/></tm:type> + tm:role + tm:type<tm:topicRef href="#constraint-role"/></tm:type> + <tm:topicRef href="#written-by-otherrole-constraint-for-written"/> + </tm:role> + tm:role + tm:type<tm:topicRef href="#othertopictype-role"/></tm:type> + <tm:topicRef href="#author"/> + </tm:role> + </tm:association> + + <!-- ===================================================================== --> + <!-- === the "user's" topic map ========================================== --> + <!-- ===================================================================== --> + <tm:topic id="goethe"> + <tm:subjectIdentifier href="http://some.where/psis/author/goethe%22/%3E <!-- must have a psi of this form --> + <tm:subjectIdentifier href="http://some.where/psis/persons/goethe%22/%3E <!-- can own psis of any form --> + tm:instanceOf<tm:topicRef href="#author"/></tm:instanceOf> <!-- must be an instanceOf author --> + tm:name + tm:type<tm:topicRef href="#first-name"/></tm:type> <!-- must contain a name of the type first-name --> + tm:valueJohann Wolfgang</tm:value> + </tm:name> + tm:name + tm:type<tm:topicRef href="#last-name"/></tm:type> <!-- must contain a name of the type last-name --> + tm:valuevon Goethe</tm:value> + </tm:name> + tm:occurrence + tm:type<tm:topicRef href="#author-info"/></tm:type> <!-- can own an occurrence of the type autor-info with the datatype anyURI --> + <tm:resourceRef href="http://de.wikipedia.org/wiki/Johann_Wolfgang_von_Goethe%22/%3E + </tm:occurrence> + </tm:topic> + + <tm:topic id="schiller"> + <tm:subjectIdentifier href="http://some.where/psis/author/schiller%22/%3E <!-- must have a psi of this form --> + tm:instanceOf<tm:topicRef href="#author"/></tm:instanceOf> <!-- must be an instanceOf author --> + tm:name + tm:type<tm:topicRef href="#first-name"/></tm:type> <!-- must contain a name of the type first-name --> + tm:valueJohann Christoph Friedrich</tm:value> + </tm:name> + tm:name + tm:type<tm:topicRef href="#last-name"/></tm:type> <!-- must contain a name of the type last-name --> + tm:valuevon Schiller</tm:value> + </tm:name> + tm:occurrence + tm:type<tm:topicRef href="#author-info"/></tm:type> <!-- can own an occurrence of the type autor-info with the datatype anyURI --> + <tm:resourceRef href="http://de.wikipedia.org/wiki/Schiller%22/%3E + </tm:occurrence> + </tm:topic> + + <tm:topic id="zauberlehrling"> + <tm:subjectIdentifier href="http://some.where/psis/poem/zauberlehrling%22/%3E <!-- must have a psi of this form --> + <tm:subjectIdentifier href="http://some.where/psis/der_zauberlehrling%22/%3E <!-- can own psis of any form --> + tm:instanceOf + <tm:topicRef href="#poem"/><!-- + <tm:topicRef href="#author"/> + <tm:topicRef href="#zauberlehrling"/> + <tm:topicRef href="#topictype-constraint"/>--> + </tm:instanceOf> <!-- must be an instanceOf poem --> + tm:name + tm:type<tm:topicRef href="#title"/></tm:type> <!-- must have a name of the type title --> + tm:valueDer Zauberlehrling</tm:value> + </tm:name> + tm:occurrence + tm:type<tm:topicRef href="#poem-content"/></tm:type> <!-- must have an occurrence of the type poem-content with the scope de or en --> + tm:scope<tm:topicRef href="#de"/></tm:scope> + <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#string%22%3EHat der alte Hexenmeister +sich doch einmal wegbegeben! +Und nun sollen seine Geister +auch nach meinem Willen leben. +Seine Wort und Werke +merkt ich und den Brauch, +und mit Geistesstärke +tu ich Wunder auch. + +Walle! walle +Manche Strecke, +daß, zum Zwecke, +Wasser fließe +und mit reichem, vollem Schwalle +zu dem Bade sich ergieße. + +Und nun komm, du alter Besen! +Nimm die schlechten Lumpenhüllen; +bist schon lange Knecht gewesen: +nun erfülle meinen Willen! +Auf zwei Beinen stehe, +oben sei ein Kopf, +eile nun und gehe +mit dem Wassertopf! + +Walle! walle +manche Strecke, +daß, zum Zwecke, +Wasser fließe +und mit reichem, vollem Schwalle +zu dem Bade sich ergieße. + +Seht, er läuft zum Ufer nieder, +Wahrlich! ist schon an dem Flusse, +und mit Blitzesschnelle wieder +ist er hier mit raschem Gusse. +Schon zum zweiten Male! +Wie das Becken schwillt! +Wie sich jede Schale +voll mit Wasser füllt! + +Stehe! stehe! +denn wir haben +deiner Gaben +vollgemessen! - +Ach, ich merk es! Wehe! wehe! +Hab ich doch das Wort vergessen! + +Ach, das Wort, worauf am Ende +er das wird, was er gewesen. +Ach, er läuft und bringt behende! +Wärst du doch der alte Besen! +Immer neue Güsse +bringt er schnell herein, +Ach! und hundert Flüsse +stürzen auf mich ein. + +Nein, nicht länger +kann ichs lassen; +will ihn fassen. +Das ist Tücke! +Ach! nun wird mir immer bänger! +Welche Mine! welche Blicke! + +O du Ausgeburt der Hölle! +Soll das ganze Haus ersaufen? +Seh ich über jede Schwelle +doch schon Wasserströme laufen. +Ein verruchter Besen, +der nicht hören will! +Stock, der du gewesen, +steh doch wieder still! + +Willst am Ende +gar nicht lassen? +Will dich fassen, +will dich halten +und das alte Holz behende +mit dem scharfen Beile spalten. + +Seht da kommt er schleppend wieder! +Wie ich mich nur auf dich werfe, +gleich, o Kobold, liegst du nieder; +krachend trifft die glatte Schärfe. +Wahrlich, brav getroffen! +Seht, er ist entzwei! +Und nun kann ich hoffen, +und ich atme frei! + +Wehe! wehe! +Beide Teile +stehn in Eile +schon als Knechte +völlig fertig in die Höhe! +Helft mir, ach! ihr hohen Mächte! + +Und sie laufen! Naß und nässer +wirds im Saal und auf den Stufen. +Welch entsetzliches Gewässer! +Herr und Meister! hör mich rufen! - +Ach, da kommt der Meister! +Herr, die Not ist groß! +Die ich rief, die Geister +werd ich nun nicht los. + +"In die Ecke, +Besen, Besen! +Seids gewesen. +Denn als Geister +ruft euch nur zu diesem Zwecke, +erst hervor der alte Meister."</tm:resourceData> + </tm:occurrence> + </tm:topic> + + <tm:topic id="erlkoenig"> + <tm:subjectIdentifier href="http://some.where/psis/poem/erlkoenig%22/%3E <!-- must have a psi of this form --> + tm:instanceOf<tm:topicRef href="#poem"/></tm:instanceOf> <!-- must be an instanceOf poem --> + tm:name + tm:type<tm:topicRef href="#title"/></tm:type> <!-- must have a name of the type title --> + tm:valueDer Erlkönig</tm:value> + </tm:name> + tm:occurrence + tm:type<tm:topicRef href="#poem-content"/></tm:type> <!-- must have an occurrence of the type poem-content with the scope de or en --> + tm:scope<tm:topicRef href="#en"/></tm:scope> + <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#string%22%3EWho rides there so late through the night dark and drear? +The father it is, with his infant so dear; +He holdeth the boy tightly clasp'd in his arm, +He holdeth him safely, he keepeth him warm. + +"My son, wherefore seek'st thou thy face thus to hide?" +"Look, father, the Erl-King is close by our side! +Dost see not the Erl-King, with crown and with train?" +"My son, 'tis the mist rising over the plain." + +"Oh, come, thou dear infant! oh come thou with me! +For many a game I will play there with thee; +On my strand, lovely flowers their blossoms unfold, +My mother shall grace thee with garments of gold." + +"My father, my father, and dost thou not hear +The words that the Erl-King now breathes in mine ear?" +"Be calm, dearest child, 'tis thy fancy deceives; +'Tis the sad wind that sighs through the withering leaves." + +"Wilt go, then, dear infant, wilt go with me there? +My daughters shall tend thee with sisterly care +My daughters by night their glad festival keep, +They'll dance thee, and rock thee, and sing thee to sleep." + +"My father, my father, and dost thou not see, +How the Erl-King his daughters has brought here for me?" +"My darling, my darling, I see it aright, +'Tis the aged grey willows deceiving thy sight." + +"I love thee, I'm charm'd by thy beauty, dear boy! +And if thou'rt unwilling, then force I'll employ." +"My father, my father, he seizes me fast, +For sorely the Erl-King has hurt me at last." + +The father now gallops, with terror half wild, +He grasps in his arms the poor shuddering child; +He reaches his courtyard with toil and with dread,-- +The child in his arms finds he motionless, dead.</tm:resourceData> + </tm:occurrence> + </tm:topic> + + <!-- some assocaitions between goethe and some of his poems, + currently there are no associations between the topic schiller + and any other topic, because there are no topic representing + a poem of schiller --> + tm:association + tm:type<tm:topicRef href="#written-by"/></tm:type> + tm:role + tm:type<tm:topicRef href="#writer"/></tm:type> + <tm:topicRef href="#goethe"/> + </tm:role> + tm:role + tm:type<tm:topicRef href="#written"/></tm:type> + <tm:topicRef href="#zauberlehrling"/> + </tm:role> + </tm:association> + + tm:association + tm:type<tm:topicRef href="#written-by"/></tm:type> + tm:role + tm:type<tm:topicRef href="#writer"/></tm:type> + <tm:topicRef href="#goethe"/> + </tm:role> + tm:role + tm:type<tm:topicRef href="#written"/></tm:type> + <tm:topicRef href="#erlkoenig"/> + </tm:role> + </tm:association> + +</tm:topicMap>