[isidorus-cvs] r28 - in trunk: docs src src/ajax/javascripts src/json src/model src/rest_interface src/unit_tests
Lukas Giessmann
lgiessmann at common-lisp.net
Mon May 4 15:02:45 UTC 2009
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/">
+
+ <!-- === 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">1</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">1</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"/> <!-- 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"/>
+ <tm:instanceOf><tm:topicRef href="#topictype"/></tm:instanceOf>
+ </tm:topic>
+
+ <tm:topic id="associationtype">
+ <tm:subjectIdentifier href="http://psi.topicmaps.org/tmcl/association-type"/>
+ <tm:instanceOf><tm:topicRef href="#topictype"/></tm:instanceOf>
+ </tm:topic>
+
+ <tm:topic id="roletype">
+ <tm:subjectIdentifier href="http://psi.topicmaps.org/tmcl/role-type"/>
+ <tm:instanceOf><tm:topicRef href="#topictype"/></tm:instanceOf>
+ </tm:topic>
+
+ <tm:topic id="nametype">
+ <tm:subjectIdentifier href="http://psi.topicmaps.org/tmcl/name-type"/>
+ <tm:instanceOf><tm:topicRef href="#topictype"/></tm:instanceOf>
+ </tm:topic>
+
+ <tm:topic id="scopetype">
+ <tm:subjectIdentifier href="http://psi.topicmaps.org/tmcl/scope-type"/>
+ <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"/>
+ <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"/>
+ <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"/>
+ <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"/>
+ <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"/>
+ <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"/>
+ <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"/>
+ <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"/>
+ <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"/>
+ <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"/>
+ <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"/>
+ <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"/>
+ <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"/>
+ <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"/>
+ <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"/>
+ <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"/>
+ <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"/>
+ </tm:topic>
+
+ <tm:topic id="supertype">
+ <tm:subjectIdentifier href="http://psi.topicmaps.org/iso13250/model/supertype"/>
+ </tm:topic>
+
+ <tm:topic id="subtype">
+ <tm:subjectIdentifier href="http://psi.topicmaps.org/iso13250/model/subtype"/>
+ </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"/>
+ <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"/>
+ </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"/>
+ </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"/>
+ </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"/>
+ </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"/>
+ </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"/>
+ </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"/>
+ </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"/>
+ </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"/>
+ </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"/>
+ </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"/>
+ </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"/>
+ </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"/>
+ </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"/>
+ </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"/>
+ </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"/>
+ </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"/>
+ </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"/>
+ </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"/>
+ </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"/>
+ <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"/>
+ <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"/>
+ <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"/>
+ <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"/>
+ <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"/>
+ <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"/>
+ <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"/>
+ <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"/>
+ <tm:instanceOf><tm:topicRef href="#occurrencetype"/></tm:instanceOf>
+ </tm:topic>
+
+ <!-- poem -->
+ <tm:topic id="poem">
+ <tm:subjectIdentifier href="http://some.where/base-psis/poem"/>
+ <tm:instanceOf><tm:topicRef href="#topictype"/></tm:instanceOf>
+ </tm:topic>
+
+ <tm:topic id="title">
+ <tm:subjectIdentifier href="http://some.where/base-psis/title"/>
+ <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"/>
+ <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"/>
+ <tm:instanceOf><tm:topicRef href="#scopetype"/></tm:instanceOf>
+ </tm:topic>
+
+ <tm:topic id="en">
+ <tm:subjectIdentifier href="http://some.where/base-psis/en"/>
+ <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"/>
+ <tm:instanceOf><tm:topicRef href="#associationtype"/></tm:instanceOf>
+ </tm:topic>
+
+ <tm:topic id="writer">
+ <tm:subjectIdentifier href="http://some.where/base-psis/writer"/>
+ <tm:instanceOf><tm:topicRef href="#roletype"/></tm:instanceOf>
+ </tm:topic>
+
+ <tm:topic id="written">
+ <tm:subjectIdentifier href="http://some.where/base-psis/written"/>
+ <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"/>
+ <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"/>
+ <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">1</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">1</tm:resourceData>
+ </tm:occurrence>
+ <tm:occurrence>
+ <tm:type><tm:topicRef href="#regexp"/></tm:type>
+ <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#string">^http://some.where/psis/author/.+$</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"/>
+ <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">1</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">1</tm:resourceData>
+ </tm:occurrence>
+ <tm:occurrence>
+ <tm:type><tm:topicRef href="#regexp"/></tm:type>
+ <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#string">^http://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"/>
+ <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">0</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">MAX_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">^.+$</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"/>
+ <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">0</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">0</tm:resourceData>
+ </tm:occurrence>
+ <tm:occurrence>
+ <tm:type><tm:topicRef href="#regexp"/></tm:type>
+ <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#string">^.*$</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"/>
+ <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">0</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">1</tm:resourceData>
+ </tm:occurrence>
+ <tm:occurrence>
+ <tm:type><tm:topicRef href="#regexp"/></tm:type>
+ <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#string">^.+$</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"/>
+ <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">0</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">1</tm:resourceData>
+ </tm:occurrence>
+ <tm:occurrence>
+ <tm:type><tm:topicRef href="#regexp"/></tm:type>
+ <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#string">^.+$</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"/>
+ <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">0</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">1</tm:resourceData>
+ </tm:occurrence>
+ <tm:occurrence>
+ <tm:type><tm:topicRef href="#regexp"/></tm:type>
+ <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#string">^.+$</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"/>
+ <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">0</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">1</tm:resourceData>
+ </tm:occurrence>
+ <tm:occurrence>
+ <tm:type><tm:topicRef href="#regexp"/></tm:type>
+ <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#string">^.+$</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">http://www.w3.org/2001/XMLSchema#anyURI</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"/>
+ <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">1</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">1</tm:resourceData>
+ </tm:occurrence>
+ <tm:occurrence>
+ <tm:type><tm:topicRef href="#regexp"/></tm:type>
+ <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#string">^.+$</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-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">http://www.w3.org/2001/XMLSchema#string</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"/>
+ <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">1</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">1</tm:resourceData>
+ </tm:occurrence>
+ <tm:occurrence>
+ <tm:type><tm:topicRef href="#regexp"/></tm:type>
+ <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#string">^.*$</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"/>
+ <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">1</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">2</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"/>
+ <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">1</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">1</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"/>
+ <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">1</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">1</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"/>
+ <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">1</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">1</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"/>
+ <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">1</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">1</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">1</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">1</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">1</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">1</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"/> <!-- must have a psi of this form -->
+ <tm:subjectIdentifier href="http://some.where/psis/persons/goethe"/> <!-- 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:value>Johann 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:value>von 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"/>
+ </tm:occurrence>
+ </tm:topic>
+
+ <tm:topic id="schiller">
+ <tm:subjectIdentifier href="http://some.where/psis/author/schiller"/> <!-- 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:value>Johann 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:value>von 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"/>
+ </tm:occurrence>
+ </tm:topic>
+
+ <tm:topic id="zauberlehrling">
+ <tm:subjectIdentifier href="http://some.where/psis/poem/zauberlehrling"/> <!-- must have a psi of this form -->
+ <tm:subjectIdentifier href="http://some.where/psis/der_zauberlehrling"/> <!-- 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:value>Der 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">Hat 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"/> <!-- 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:value>Der 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">Who 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>
More information about the Isidorus-cvs
mailing list