From lgiessmann at common-lisp.net Mon May 4 15:02:45 2009 From: lgiessmann at common-lisp.net (Lukas Giessmann) Date: Mon, 04 May 2009 11:02:45 -0400 Subject: [isidorus-cvs] r28 - in trunk: docs src src/ajax/javascripts src/json src/model src/rest_interface src/unit_tests Message-ID: 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". +//+----------------------------------------------------------------------------- + + + +//+----------------------------------------------------------------------------- +//+ 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". +//+----------------------------------------------------------------------------- + + + +//+----------------------------------------------------------------------------- +//+ 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" : [ , < ... > ], + "scopeConstraints" : { } +} +//+----------------------------------------------------------------------------- +//+ 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. +//+----------------------------------------------------------------------------- + +//+----------------------------------------------------------------------------- +//+ topicOccurrenceConstraint +//+ The topicOccurrenceConstraint describes how the topic's occurrences have +//+ to be defined. +//+ +//+----------------------------------------------------------------------------- +{ + "occurrenceType" : [ "topic-psi-1", "topic-psi-2", "..." ], + "constraints" : [ , < ... > ], + "scopeConstraints" : { }, + "dataConstraint" : "datatype", + "uniqueConstraints" : [ , <...> ] +} +//+----------------------------------------------------------------------------- +//+ 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" : [ , <...> ], + "rolePlayerConstraints" : [ , <...> ], + "otherRoleConstraints" : [ , <...> ], + "scopeConstraints" : { } +} +//+----------------------------------------------------------------------------- +//+ 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" : , + "subjectIdentifierConstraints" : [ , <...> ], + "subjectLocatorConstraints" : [ , <...> ], + "topicNameConstraints" : [ , <...> ], + "topicOccurrenceConstraints" : [ , <...> ], + "abstractConstraint" : +} + + +//+----------------------------------------------------------------------------- +//+ 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" : , + "associationsConstraints" : [ , <...> ] } 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 :player :otherrole :othertopic :card-min :card-max ) <...>) + 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 :player :card-min :card-max ) <...>) + 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 :card-min :card-max ), <...>) + 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 :card-min :card-max )) + 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 :card-min :card-max ) <...>) + 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 + :constraints ( ( :regexp :card-min :card-max ) + <...>) + :scopes ( ( :scope :regexp :card-min :card-max ) + <...>)) + <...>)." + (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 + :constraints ( ( :regexp :card-min :card-max ) + <...>) + :scopes ( ( :scope :regexp :card-min :card-max ) + <...>) + :datatype + :uniqe ( ( :regexp :dard-min :card-max ) ) + <...>)." + (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 + :constraint (:card-min :card-max ))." + (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 :card-min :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 :card-min :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>) + or (list ." + (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 @@ + + + + + + + + + + + + + + + + + + + + + + 1 + + + + + + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1 + + + + 1 + + + + ^http://some.where/psis/author/.+$ + + + + + + + + + + + + + + + + + + + + + + 1 + + + + 1 + + + + ^http://some.where/psis/poem/.+$ + + + + + + + + + + + + + + + + + + + + + + 0 + + + + MAX_INT + + + + ^.+$ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + + + + 0 + + + + ^.*$ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + + + + 1 + + + + ^.+$ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + + + + 1 + + + + ^.+$ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + + + + 1 + + + + ^.+$ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + + + + 1 + + + + ^.+$ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + http://www.w3.org/2001/XMLSchema#anyURI + + + + + + + + + + + + + + + + + + + + + + 1 + + + + 1 + + + + ^.+$ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + http://www.w3.org/2001/XMLSchema#string + + + + + + + + + + + + + + + + + + + + + + 1 + + + + 1 + + + + ^.*$ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1 + + + + 2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1 + + + + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1 + + + + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1 + + + + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1 + + + + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1 + + + + + + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1 + + + + + + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Johann Wolfgang + + + + von Goethe + + + + + + + + + + + + + Johann Christoph Friedrich + + + + von Schiller + + + + + + + + + + + + + + + + Der Zauberlehrling + + + + + 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." + + + + + + + + + Der Erlk?nig + + + + + 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. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From lgiessmann at common-lisp.net Tue May 5 16:28:19 2009 From: lgiessmann at common-lisp.net (Lukas Giessmann) Date: Tue, 05 May 2009 12:28:19 -0400 Subject: [isidorus-cvs] r29 - in trunk: docs src/json src/rest_interface Message-ID: Author: lgiessmann Date: Tue May 5 12:28:18 2009 New Revision: 29 Log: changed the tmcl-json-model and the tmcl-json-exporter. so there will be exported to every constraint the original topictypes e.g. nametypes and all valid subtypes, the second point is that there will be exported all possible player-psis of associationrole, so the user is able to choose a player directly without further communication with the server Modified: trunk/docs/xtm_json.txt trunk/src/json/json_tmcl.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 Tue May 5 12:28:18 2009 @@ -226,7 +226,7 @@ //+ subjectLocator, this member contains an unsigendInt or the string //+ "MAX_INT". //+----------------------------------------------------------------------------- - + //+----------------------------------------------------------------------------- @@ -249,20 +249,18 @@ //+----------------------------------------------------------------------------- //+ 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 . +//+ nametypescope constains the original nametype and all valid subtypes +//+ with the specific scope constraints. +//+ constriants contains the constraints for the owner topic. //+----------------------------------------------------------------------------- { - "nameType" : [ "topic-psi-1", "topic-psi-2", "..." ], - "constraints" : [ , < ... > ], - "scopeConstraints" : { } + "nametypescopes" : [ { + "nametype" : [psi-1, psi-2, "..." ], + "scopeConstraints" : [ ] + }, + <...> + ] + "constraints" : [ , < ... > ] } @@ -282,16 +280,26 @@ //+----------------------------------------------------------------------------- //+ topicOccurrenceConstraint -//+ The topicOccurrenceConstraint describes how the topic's occurrences have -//+ to be defined. -//+ -//+----------------------------------------------------------------------------- -{ - "occurrenceType" : [ "topic-psi-1", "topic-psi-2", "..." ], - "constraints" : [ , < ... > ], - "scopeConstraints" : { }, - "dataConstraint" : "datatype", - "uniqueConstraints" : [ , <...> ] +//+ occurrenceTypes contains a list of a json-sub-object. This sub-object +//+ contains an occurrenceType a specific list of scopeConstraints for +//+ the occurrenceType and a scpecific datatypeConstraint which contains +//+ the datatype for the occurrenceType. +//+ The entire list of occurrenceTypes contains the not only the +//+ original occurrenceType but also the subtypes of this occurrenceType. +//+ constraints is a constraint list of depending to the owner topic. +//+ unqiqueConstraint is a list of uniqeConstraints which also depends on +//+ the owner topic. +//+----------------------------------------------------------------------------- +{ + "occurrenceTypes" : [ { + "occurrenceType" : [ "psi-1", "psi-2", "..." ], + "scopeConstraints" : [ ], + "datatypeConstraint" : "datatype", + }, + <...> + ], + "constraints" : [ , <...>], + "uniqueConstraint" : [ , <...> ] } @@ -303,7 +311,7 @@ //+ in an association of a certain associationtype (the objects owner). //+----------------------------------------------------------------------------- { - "roleType" : [ "topic-psi-1", "topic-psi-2", "..." ], + "roleType" : [ [ "topic-psi-1", "topic-psi-2", "..." ], ["subtype-1-psi-1", "..."], <...> ], "cardMin" : "unsigned integer in string representation", "cardMax" : "unsigend integer in string representation or the string MAX_INT" } @@ -312,17 +320,17 @@ //+----------------------------------------------------------------------------- //+ 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. +//+ of a given type. +//+ palyers is the psi-list representation of a list of all available +//+ players. +//+ roleTypes is a list of topics represented by a list of psi-lists. //+ 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", "..." ], + "players" : [ [ "topic-psi-1", "topic-psi-2", "..." ], [ "topic-2-psi-1", "..."], <...> ] + "roleTypes" : [ [ "topic-psi-1", "topic-psi-2", "..." ], [ "subtype-psi-1", "..." ], <...> ], "cardMin" : "unsigned integer in string representation", "cardMax" : "unsigend integer in string representation or the string MAX_INT" } Modified: trunk/src/json/json_tmcl.lisp ============================================================================== --- trunk/src/json/json_tmcl.lisp (original) +++ trunk/src/json/json_tmcl.lisp Tue May 5 12:28:18 2009 @@ -11,14 +11,15 @@ (:use :cl :datamodel :constants :json-tmcl-constants) (:export :get-constraints-of-fragment :topictype-p - :abstract-p)) + :abstract-p + :list-subtypes)) (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*)) @@ -54,9 +55,9 @@ 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." @@ -94,7 +95,9 @@ (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*))) + (roletype-constraint (get-item-by-psi *roletype-constraint-psi*)) + (topictype (get-item-by-psi *topictype-psi*)) + (topictype-constraint (get-item-by-psi *topictype-constraint-psi*))) (let ((otherrole-constraints (loop for constraint-topic in constraint-topics append (let ((players nil) @@ -177,17 +180,21 @@ (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)))) + (concatenate 'string "\"players\":" + (topics-to-json-list + (list-instances (getf involved-topic-tupple :player) topictype topictype-constraint)))) (json-role - (concatenate 'string "\"roleType\":" - (json-exporter::identifiers-to-json-string (getf involved-topic-tupple :role)))) + (concatenate 'string "\"roleTypes\":" + (topics-to-json-list + (getf (list-subtypes (getf involved-topic-tupple :role) roletype roletype-constraint) :subtypes)))) (json-otherplayer - (concatenate 'string "\"otherPlayerType\":" - (json-exporter::identifiers-to-json-string (getf involved-topic-tupple :player)))) + (concatenate 'string "\"otherPlayers\":" + (topics-to-json-list + (list-instances (getf involved-topic-tupple :otherplayer) topictype topictype-constraint)))) (json-otherrole (concatenate 'string "\"otherRoleType\":" - (json-exporter::identifiers-to-json-string (getf involved-topic-tupple :role)))) + (topics-to-json-list + (getf (list-subtypes (getf involved-topic-tupple :otherrole) roletype roletype-constraint) :subtypes)))) (card-min (concatenate 'string "\"cardMin\":" (getf (first constraint-lists) :card-min))) (card-max @@ -212,7 +219,9 @@ (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*))) + (roletype-constraint (get-item-by-psi *roletype-constraint-psi*)) + (topictype (get-item-by-psi *topictype-psi*)) + (topictype-constraint (get-item-by-psi *topictype-constraint-psi*))) (let ((roleplayer-constraints (loop for constraint-topic in constraint-topics append (let ((constraint-list @@ -251,11 +260,11 @@ (topictype-p current-player) (topictype-p current-role roletype roletype-constraint) (list :player current-player - :role current-role))) + :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 @@ -269,19 +278,21 @@ (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)))) + (let ((json-players + (concatenate 'string "\"players\":" + (topics-to-json-list + (list-instances (getf role-player-tupple :player) topictype topictype-constraint)))) (json-role - (concatenate 'string "\"roleType\":" - (json-exporter::identifiers-to-json-string (getf role-player-tupple :role)))) + (concatenate 'string "\"roleTypes\":" + (topics-to-json-list + (getf (list-subtypes (getf role-player-tupple :role) roletype roletype-constraint) :subtypes)))) (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 "},"))))) + "{" json-players "," json-role "," card-min "," card-max "},"))))) (if (string= cleaned-roleplayer-constraints "[") (setf cleaned-roleplayer-constraints "null") (setf cleaned-roleplayer-constraints @@ -325,12 +336,17 @@ collect (getf associationrole-constraint :constraint))))) (when (> (length constraint-lists) 1) (error "found contrary associationrole-constraints: ~a ~a~%" (uri (first (psis associationroletype-topic))) constraint-lists)) + (let ((roletype-with-subtypes + (json:encode-json-to-string + (map 'list #'(lambda(topic) + (map 'list #'uri (psis topic))) + (getf (list-subtypes associationroletype-topic roletype roletype-constraint) :subtypes))))) (setf cleaned-associationrole-constraints (concatenate 'string cleaned-associationrole-constraints - "{\"roleType\":" (json-exporter::identifiers-to-json-string associationroletype-topic) + "{\"roleType\":" roletype-with-subtypes ",\"cardMin\":" (getf (first constraint-lists) :card-min) - ",\"cardMax\":" (getf (first constraint-lists) :card-max) "},")))) + ",\"cardMax\":" (getf (first constraint-lists) :card-max) "},"))))) (if (string= cleaned-associationrole-constraints "[") (setf cleaned-associationrole-constraints "null") @@ -339,9 +355,9 @@ 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, @@ -425,7 +441,7 @@ "Transforms a list of simple constraint lists of the form ((:regexp :card-min :card-max ) <...>) to a valid json list of the form - [{\"regexp\":\"expr\",\"cardMin\":\"123\",\"cardMax\":\"456\"}, <...>]." + [{regexp: expr, cardMin: 123, cardMax: 456}, <...>]." (let ((constraints "[")) (loop for constraint in simple-constraints do (let ((constraint (concatenate 'string "{\"regexp\":" @@ -446,12 +462,10 @@ (defun get-topicname-constraints(constraint-topics) "Returns all topicname constraints as a list of the following form: - ( ( :type - :constraints ( ( :regexp :card-min :card-max ) - <...>) - :scopes ( ( :scope :regexp :card-min :card-max ) - <...>)) - <...>)." + [{nametypescopes:[{nameType: [psi-1, psi-2], scopeConstraints: []}, + {nameType: [subtype-1-psi-1], scopeConstriants: []}, + constraints: [, <...>]}, + <...>]." (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*)) @@ -466,16 +480,15 @@ 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))) + (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)))) + (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 @@ -487,17 +500,22 @@ (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 "},"))))) + (let ((nametype-with-subtypes + (remove-if #'null (getf (list-subtypes nametype-topic nametype nametype-constraint) :subtypes)))) + (let ((nametypescopes "\"nametypescopes\":[")) + (loop for current-topic in nametype-with-subtypes + do (let ((current-json-string + (concatenate 'string "{\"nameType\":" (json-exporter::identifiers-to-json-string current-topic) + ",\"scopeConstraints\":" (get-typescope-constraints current-topic :what 'topicname) "}"))) + (setf nametypescopes (concatenate 'string nametypescopes current-json-string ",")))) + (if (string= nametypescopes "\"nametypescopes\"[") + (setf nametypescopes "null") + (setf nametypescopes + (concatenate 'string (subseq nametypescopes 0 (- (length nametypescopes) 1)) "]"))) + (let ((json-constraint-lists + (concatenate 'string "\"constraints\":" (simple-constraints-to-json constraint-lists)))) + (setf cleaned-topicname-constraints + (concatenate 'string cleaned-topicname-constraints "{" nametypescopes "," json-constraint-lists "},"))))))) (if (string= cleaned-topicname-constraints "[") (setf cleaned-topicname-constraints "null") (setf cleaned-topicname-constraints @@ -548,24 +566,32 @@ (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 "},"))))) + + + (let ((occurrencetype-with-subtypes + (getf (list-subtypes occurrencetype-topic occurrencetype occurrencetype-constraint) :subtypes))) + + (let ((occurrencetypes-json-string "\"occurrenceTypes\":[")) + (loop for current-topic in occurrencetype-with-subtypes + do (let ((current-json-string + (concatenate 'string "{\"occurrenceType\":" (json-exporter::identifiers-to-json-string current-topic) + ",\"scopeConstraints\":" (get-typescope-constraints current-topic :what 'topicoccurrence) + ",\"datatypeConstraint\":" (get-occurrence-datatype-constraint current-topic) "}"))) + (setf occurrencetypes-json-string (concatenate 'string occurrencetypes-json-string current-json-string ",")))) + + (if (string= occurrencetypes-json-string "\"occurrenceTypes\"[") + (setf occurrencetypes-json-string "null") + (setf occurrencetypes-json-string + (concatenate 'string (subseq occurrencetypes-json-string 0 (- (length occurrencetypes-json-string) 1)) "]"))) + (let ((unique-constraints + (concatenate 'string "\"uniqueConstraints\":" + (get-simple-constraints unique-constraint-topics))) + (json-constraint-lists + (concatenate 'string "\"constraints\":" (simple-constraints-to-json constraint-lists)))) + (let ((current-json-string + (concatenate 'string "{" occurrencetypes-json-string "," json-constraint-lists "," unique-constraints "}"))) + (setf cleaned-topicoccurrence-constraints + (concatenate 'string cleaned-topicoccurrence-constraints current-json-string ",")))))))) (if (string= cleaned-topicoccurrence-constraints "[") (setf cleaned-topicoccurrence-constraints "null") (setf cleaned-topicoccurrence-constraints @@ -609,9 +635,10 @@ 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 - :constraint (:card-min :card-max ))." + The return value is of the form: + [{scopeTypes:[[[psi-1-1, psi-1-2], [subtype-1-psi-1, subtype-1-psi-2]], [[psi-2-1], + [subtype-1-psi-1], [subtype-2-psi-1]]], cardMin: , + cardMax }, <...>]." (let ((element-type-role-and-scope-constraint (cond ((eq what 'topicname) @@ -627,7 +654,8 @@ (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*))) + (applies-to (get-item-by-psi *applies-to-psi*)) + (scopetype (get-item-by-psi *scopetype-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)) @@ -677,13 +705,22 @@ 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 ((json-scopes + (concatenate 'string "\"scopeTypes\":" + + (let ((scopetypes-with-subtypes + (remove-if #'null + (loop for current-scopetype in scopetype-group + collect (getf (list-subtypes current-scopetype scopetype nil) :subtypes))))) + + (json:encode-json-to-string + (map 'list #'(lambda(topic-group) + (map 'list #'(lambda(topic) + (map 'list #'uri (psis topic))) + topic-group)) + scopetypes-with-subtypes)))))) (let ((current-json-string - (concatenate 'string "{" json-scopes "],\"cardMin\":\"" card-min "\",\"cardMax\":\"" card-max "\"}"))) + (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 "[") @@ -693,9 +730,9 @@ 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)" @@ -946,11 +983,14 @@ current-checked-topics)) -(defun topictype-of-p (topic-instance type-instance &optional checked-topics) +(defun topictype-of-p (topic-instance type-instance &optional (topictype (get-item-by-psi *topictype-psi*)) + (topictype-constraint (get-item-by-psi *topictype-constraint-psi*)) + 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" + valid instance-topic of the type-topic called type-instance. TMCL 4.4.2. + When the type-instance is set to nil there will be checked only if the + topic-instance is a valid instance." (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))) @@ -962,7 +1002,7 @@ (return-from topictype-of-p nil)) (loop for isa-of-this in isas-of-this - do (let ((found-topics (topictype-p isa-of-this))) + do (let ((found-topics (topictype-p isa-of-this topictype topictype-constraint))) (when (not found-topics) (return-from topictype-of-p nil)) (dolist (item found-topics) @@ -970,13 +1010,15 @@ (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))) + do (let ((found-topics (topictype-of-p ako-of-this type-instance topictype topictype-constraint 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) + (if type-instance + (when (find type-instance current-checked-topics) + current-checked-topics) current-checked-topics))) @@ -1170,6 +1212,8 @@ (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*)) + (associationtype (get-item-by-psi *associationtype-psi*)) + (associationtype-constraint (get-item-by-psi *associationtype-constraint-psi*)) (roleplayer-constraint (get-item-by-psi *roleplayer-constraint-psi*)) (otherrole-constraint (get-item-by-psi *otherrole-constraint-psi*)) (all-possible-player-topics @@ -1178,9 +1222,6 @@ (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 @@ -1197,5 +1238,81 @@ (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 + append (map 'list #'(lambda(x) + (topictype-p x associationtype associationtype-constraint) + x) + (getf (list-subtypes (player type-role) associationtype associationtype-constraint) :subtypes)))))))))) + all-available-associationtypes))) + + +(defun list-subtypes (topic-instance &optional (topictype (get-item-by-psi *topictype-psi*)) + (topictype-constraint (get-item-by-psi *topictype-constraint-psi*)) + (checked-topics nil) (valid-subtypes nil)) + "Returns all valid subtypes of a topic, e.g.: + nametype-constraint ako constraint . + first-name isa nametype . + first-name-1 ako first-name . + // ... + The return value is a named list of the form (:subtypes ( <...>) :checked-topics ( <...>)" + (let ((current-checked-topics (append checked-topics (list topic-instance)))) + + (handler-case (topictype-p topic-instance topictype topictype-constraint) + (condition () (return-from list-subtypes (list :subtypes nil :checked-topics current-checked-topics)))) + + (let ((subtype (get-item-by-psi *subtype-psi*)) + (supertype (get-item-by-psi *supertype-psi*)) + (supertype-subtype (get-item-by-psi *supertype-subtype-psi*)) + (current-valid-subtypes (append valid-subtypes (list topic-instance)))) + (loop for role in (player-in-roles topic-instance) + when (and (eq supertype (instance-of role)) + (eq supertype-subtype (instance-of (parent role)))) + do (loop for other-role in (roles (parent role)) + do (when (and (eq subtype (instance-of other-role)) + (not (find (player other-role) current-checked-topics))) + (let ((new-values + (list-subtypes (player other-role) topictype topictype-constraint current-checked-topics current-valid-subtypes))) + (dolist (item (getf new-values :subtypes)) + (pushnew item current-valid-subtypes)) + (dolist (item (getf new-values :checked-topics)) + (pushnew item current-checked-topics)))))) + (list :subtypes current-valid-subtypes :checked-topics current-checked-topics)))) + + +(defun list-instances (topic-instance &optional (topictype (get-item-by-psi *topictype-psi*)) + (topictype-constraint (get-item-by-psi *topictype-constraint-psi*))) + "Returns the topic-instance, all subtypes found by the function lis-subtypes and all direct + instances for the found subtypes." + (let ((all-subtypes-of-this + (getf (list-subtypes topic-instance topictype topictype-constraint) :subtypes)) + (type (get-item-by-psi *type-psi*)) + (instance (get-item-by-psi *instance-psi*)) + (type-instance (get-item-by-psi *type-instance-psi*))) + (let ((all-instances-of-this + (remove-duplicates + (loop for subtype-of-this in all-subtypes-of-this + append (loop for role in (player-in-roles subtype-of-this) + when (and (eq type (instance-of role)) + (eq type-instance (instance-of (parent role)))) + append (loop for other-role in (roles (parent role)) + when (eq instance (instance-of other-role)) + collect (player other-role))))))) + (let ((all-subtypes-of-all-instances + (remove-if #'null + (remove-duplicates + (loop for subtype in all-instances-of-this + append (getf (list-subtypes subtype nil nil) :subtypes)))))) + (remove-if #'null + (map 'list #'(lambda(x) + (handler-case (progn + (topictype-of-p x nil) + x) + (condition () nil))) + all-subtypes-of-all-instances)))))) + + +(defun topics-to-json-list (topics) + "Returns a json list of psi-lists." + (json:encode-json-to-string + (map 'list #'(lambda(topic) + (map 'list #'uri (psis topic))) + topics))) \ 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 Tue May 5 12:28:18 2009 @@ -14,7 +14,7 @@ (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-topic-stub-prefix* "/json/topicstubs/(.+)$") ;the json prefix for getting some topic stub information of a topic (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 From lgiessmann at common-lisp.net Tue May 5 19:18:12 2009 From: lgiessmann at common-lisp.net (Lukas Giessmann) Date: Tue, 05 May 2009 15:18:12 -0400 Subject: [isidorus-cvs] r30 - in trunk: docs src src/json Message-ID: Author: lgiessmann Date: Tue May 5 15:18:11 2009 New Revision: 30 Log: some structural improvements in the json module Added: trunk/src/json/json_tmcl_validation.lisp Modified: trunk/docs/xtm_json.txt trunk/src/isidorus.asd trunk/src/json/json_tmcl.lisp Modified: trunk/docs/xtm_json.txt ============================================================================== --- trunk/docs/xtm_json.txt (original) +++ trunk/docs/xtm_json.txt Tue May 5 15:18:11 2009 @@ -294,7 +294,7 @@ "occurrenceTypes" : [ { "occurrenceType" : [ "psi-1", "psi-2", "..." ], "scopeConstraints" : [ ], - "datatypeConstraint" : "datatype", + "datatypeConstraint" : "datatype" }, <...> ], Modified: trunk/src/isidorus.asd ============================================================================== --- trunk/src/isidorus.asd (original) +++ trunk/src/isidorus.asd Tue May 5 15:18:11 2009 @@ -128,9 +128,11 @@ (:module "json" :components ((:file "json_exporter") (:file "json_importer") + (:file "json_tmcl_validation" + :depends-on ("json_tmcl_constants" "json_exporter" )) (:file "json_tmcl_constants") (:file "json_tmcl" - :depends-on ("json_tmcl_constants" "json_exporter"))) + :depends-on ("json_tmcl_validation"))) :depends-on ("model" "xml")) (:module "ajax" :components ((:static-file "isidorus.html") Modified: trunk/src/json/json_tmcl.lisp ============================================================================== --- trunk/src/json/json_tmcl.lisp (original) +++ trunk/src/json/json_tmcl.lisp Tue May 5 15:18:11 2009 @@ -7,13 +7,6 @@ ;;+----------------------------------------------------------------------------- -(defpackage :json-tmcl - (:use :cl :datamodel :constants :json-tmcl-constants) - (:export :get-constraints-of-fragment - :topictype-p - :abstract-p - :list-subtypes)) - (in-package :json-tmcl) @@ -525,14 +518,13 @@ (defun get-topicoccurrence-constraints(constraint-topics unique-constraint-topics) "Returns all topicoccurrence constraints as a list of the following form: - ( ( :type - :constraints ( ( :regexp :card-min :card-max ) - <...>) - :scopes ( ( :scope :regexp :card-min :card-max ) - <...>) - :datatype - :uniqe ( ( :regexp :dard-min :card-max ) ) - <...>)." + [{occurrenceTypes:[{occurrenceType:[psi-1,psi-2], + scopeConstraints:[], + datatypeConstraint:datatype}, + <...>], + constraints:[, <...>], + uniqueConstraint:[, <...> ]} + <...>]." (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*)) @@ -855,173 +847,6 @@ (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 (topictype (get-item-by-psi *topictype-psi*)) - (topictype-constraint (get-item-by-psi *topictype-constraint-psi*)) - 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. - When the type-instance is set to nil there will be checked only if the - topic-instance is a valid instance." - (let ((current-checked-topics (append checked-topics (list topic-instance))) - (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 topictype topictype-constraint))) - (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 topictype topictype-constraint current-checked-topics))) - (when (not found-topics) - (return-from topictype-of-p nil)) - (dolist (item found-topics) - (pushnew item current-checked-topics)))) - - (if type-instance - (when (find type-instance current-checked-topics) - 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" @@ -1129,22 +954,6 @@ :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" @@ -1245,74 +1054,9 @@ all-available-associationtypes))) -(defun list-subtypes (topic-instance &optional (topictype (get-item-by-psi *topictype-psi*)) - (topictype-constraint (get-item-by-psi *topictype-constraint-psi*)) - (checked-topics nil) (valid-subtypes nil)) - "Returns all valid subtypes of a topic, e.g.: - nametype-constraint ako constraint . - first-name isa nametype . - first-name-1 ako first-name . - // ... - The return value is a named list of the form (:subtypes ( <...>) :checked-topics ( <...>)" - (let ((current-checked-topics (append checked-topics (list topic-instance)))) - - (handler-case (topictype-p topic-instance topictype topictype-constraint) - (condition () (return-from list-subtypes (list :subtypes nil :checked-topics current-checked-topics)))) - - (let ((subtype (get-item-by-psi *subtype-psi*)) - (supertype (get-item-by-psi *supertype-psi*)) - (supertype-subtype (get-item-by-psi *supertype-subtype-psi*)) - (current-valid-subtypes (append valid-subtypes (list topic-instance)))) - (loop for role in (player-in-roles topic-instance) - when (and (eq supertype (instance-of role)) - (eq supertype-subtype (instance-of (parent role)))) - do (loop for other-role in (roles (parent role)) - do (when (and (eq subtype (instance-of other-role)) - (not (find (player other-role) current-checked-topics))) - (let ((new-values - (list-subtypes (player other-role) topictype topictype-constraint current-checked-topics current-valid-subtypes))) - (dolist (item (getf new-values :subtypes)) - (pushnew item current-valid-subtypes)) - (dolist (item (getf new-values :checked-topics)) - (pushnew item current-checked-topics)))))) - (list :subtypes current-valid-subtypes :checked-topics current-checked-topics)))) - - -(defun list-instances (topic-instance &optional (topictype (get-item-by-psi *topictype-psi*)) - (topictype-constraint (get-item-by-psi *topictype-constraint-psi*))) - "Returns the topic-instance, all subtypes found by the function lis-subtypes and all direct - instances for the found subtypes." - (let ((all-subtypes-of-this - (getf (list-subtypes topic-instance topictype topictype-constraint) :subtypes)) - (type (get-item-by-psi *type-psi*)) - (instance (get-item-by-psi *instance-psi*)) - (type-instance (get-item-by-psi *type-instance-psi*))) - (let ((all-instances-of-this - (remove-duplicates - (loop for subtype-of-this in all-subtypes-of-this - append (loop for role in (player-in-roles subtype-of-this) - when (and (eq type (instance-of role)) - (eq type-instance (instance-of (parent role)))) - append (loop for other-role in (roles (parent role)) - when (eq instance (instance-of other-role)) - collect (player other-role))))))) - (let ((all-subtypes-of-all-instances - (remove-if #'null - (remove-duplicates - (loop for subtype in all-instances-of-this - append (getf (list-subtypes subtype nil nil) :subtypes)))))) - (remove-if #'null - (map 'list #'(lambda(x) - (handler-case (progn - (topictype-of-p x nil) - x) - (condition () nil))) - all-subtypes-of-all-instances)))))) - - (defun topics-to-json-list (topics) "Returns a json list of psi-lists." (json:encode-json-to-string (map 'list #'(lambda(topic) (map 'list #'uri (psis topic))) - topics))) \ No newline at end of file + topics))) Added: trunk/src/json/json_tmcl_validation.lisp ============================================================================== --- (empty file) +++ trunk/src/json/json_tmcl_validation.lisp Tue May 5 15:18:11 2009 @@ -0,0 +1,271 @@ +;;+----------------------------------------------------------------------------- +;;+ 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 + :list-subtypes)) + + +(in-package :json-tmcl) + + +(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 topictype-of-p (topic-instance type-instance &optional (topictype (get-item-by-psi *topictype-psi*)) + (topictype-constraint (get-item-by-psi *topictype-constraint-psi*)) + 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. + When the type-instance is set to nil there will be checked only if the + topic-instance is a valid instance." + (let ((current-checked-topics (append checked-topics (list topic-instance))) + (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 topictype topictype-constraint))) + (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 topictype topictype-constraint current-checked-topics))) + (when (not found-topics) + (return-from topictype-of-p nil)) + (dolist (item found-topics) + (pushnew item current-checked-topics)))) + + (if type-instance + (when (find type-instance current-checked-topics) + 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 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 a topictype or it is the topictype-topic itself. + This function isn't useable as a standalone function - it's only necessary + for a special case in the function topictype-p." + ;(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 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 + This function was defined for the use in topictype-p and not for a standalone + usage." + (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. + This function was defined for the use in topictype-p and not for a standalone + usage." + (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 list-subtypes (topic-instance &optional (topictype (get-item-by-psi *topictype-psi*)) + (topictype-constraint (get-item-by-psi *topictype-constraint-psi*)) + (checked-topics nil) (valid-subtypes nil)) + "Returns all valid subtypes of a topic, e.g.: + nametype-constraint ako constraint . + first-name isa nametype . + first-name-1 ako first-name . + // ... + The return value is a named list of the form (:subtypes ( <...>) :checked-topics ( <...>)" + (let ((current-checked-topics (append checked-topics (list topic-instance)))) + + (handler-case (topictype-p topic-instance topictype topictype-constraint) + (condition () (return-from list-subtypes (list :subtypes nil :checked-topics current-checked-topics)))) + + (let ((subtype (get-item-by-psi *subtype-psi*)) + (supertype (get-item-by-psi *supertype-psi*)) + (supertype-subtype (get-item-by-psi *supertype-subtype-psi*)) + (current-valid-subtypes (append valid-subtypes (list topic-instance)))) + (loop for role in (player-in-roles topic-instance) + when (and (eq supertype (instance-of role)) + (eq supertype-subtype (instance-of (parent role)))) + do (loop for other-role in (roles (parent role)) + do (when (and (eq subtype (instance-of other-role)) + (not (find (player other-role) current-checked-topics))) + (let ((new-values + (list-subtypes (player other-role) topictype topictype-constraint current-checked-topics current-valid-subtypes))) + (dolist (item (getf new-values :subtypes)) + (pushnew item current-valid-subtypes)) + (dolist (item (getf new-values :checked-topics)) + (pushnew item current-checked-topics)))))) + (list :subtypes current-valid-subtypes :checked-topics current-checked-topics)))) + + +(defun list-instances (topic-instance &optional (topictype (get-item-by-psi *topictype-psi*)) + (topictype-constraint (get-item-by-psi *topictype-constraint-psi*))) + "Returns the topic-instance, all subtypes found by the function lis-subtypes and all direct + instances for the found subtypes." + (let ((all-subtypes-of-this + (getf (list-subtypes topic-instance topictype topictype-constraint) :subtypes)) + (type (get-item-by-psi *type-psi*)) + (instance (get-item-by-psi *instance-psi*)) + (type-instance (get-item-by-psi *type-instance-psi*))) + (let ((all-instances-of-this + (remove-duplicates + (loop for subtype-of-this in all-subtypes-of-this + append (loop for role in (player-in-roles subtype-of-this) + when (and (eq type (instance-of role)) + (eq type-instance (instance-of (parent role)))) + append (loop for other-role in (roles (parent role)) + when (eq instance (instance-of other-role)) + collect (player other-role))))))) + (let ((all-subtypes-of-all-instances + (remove-if #'null + (remove-duplicates + (loop for subtype in all-instances-of-this + append (getf (list-subtypes subtype nil nil) :subtypes)))))) + (remove-if #'null + (map 'list #'(lambda(x) + (handler-case (progn + (topictype-of-p x nil) + x) + (condition () nil))) + all-subtypes-of-all-instances)))))) \ No newline at end of file From lgiessmann at common-lisp.net Tue May 19 09:23:26 2009 From: lgiessmann at common-lisp.net (Lukas Giessmann) Date: Tue, 19 May 2009 05:23:26 -0400 Subject: [isidorus-cvs] r31 - in trunk: docs src/ajax src/ajax/css src/ajax/javascripts src/json src/rest_interface src/unit_tests Message-ID: Author: lgiessmann Date: Tue May 19 05:23:26 2009 New Revision: 31 Log: fixed some problems in the json-tmcl module and started to implement the ajax-client Added: trunk/src/ajax/css/frame.css (contents, props changed) - copied, changed from r26, /trunk/src/ajax/css/home.css trunk/src/ajax/javascripts/create.js trunk/src/ajax/javascripts/datamodel.js trunk/src/ajax/javascripts/edit.js trunk/src/ajax/javascripts/requests.js (contents, props changed) trunk/src/ajax/javascripts/search.js trunk/src/ajax/javascripts/tmcl_tools.js Removed: trunk/src/ajax/css/home.css trunk/src/ajax/javascripts/edit_topic.js trunk/src/ajax/javascripts/make_fragment_node.js Modified: trunk/docs/xtm_json.txt trunk/src/ajax/css/main.css trunk/src/ajax/css/navi.css trunk/src/ajax/isidorus.html trunk/src/ajax/javascripts/constants.js trunk/src/ajax/javascripts/home.js trunk/src/ajax/javascripts/navi.js trunk/src/json/json_tmcl.lisp trunk/src/json/json_tmcl_validation.lisp trunk/src/rest_interface/set-up-json-interface.lisp trunk/src/unit_tests/poems.xtm Modified: trunk/docs/xtm_json.txt ============================================================================== --- trunk/docs/xtm_json.txt (original) +++ trunk/docs/xtm_json.txt Tue May 19 05:23:26 2009 @@ -186,7 +186,10 @@ //+ 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", "..." ], <...> ] +{ + "owner" : ["psi-1", "..."], + "exclusives" : [ [ "topic-1-psi-1", "topic-2-psi-2", "..." ], [ "topic-2-psi", "..." ], <...> ] +} //+----------------------------------------------------------------------------- @@ -234,14 +237,14 @@ //+ 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. +//+ The member availableScopeTypes contains a list of lists of topics in +//+ form of psi-lists. //+ 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", "..." ] <...> ], + "scopeTypes" : [ [ [ "psi-1-1", "psi-1-2", "..." ], [ "subtype-psi-1", "..." ], <...> ], [ "psi-2-1" "..."], <...> ], "cardMin" : "unsigned integer in string representation", "cardMax" : "unsigend integer in string representation or the string MAX_INT" } @@ -255,7 +258,7 @@ //+----------------------------------------------------------------------------- { "nametypescopes" : [ { - "nametype" : [psi-1, psi-2, "..." ], + "nameType" : [psi-1, psi-2, "..." ], "scopeConstraints" : [ ] }, <...> Copied: trunk/src/ajax/css/frame.css (from r26, /trunk/src/ajax/css/home.css) ============================================================================== --- /trunk/src/ajax/css/home.css (original) +++ trunk/src/ajax/css/frame.css Tue May 19 05:23:26 2009 @@ -9,36 +9,19 @@ /* in trunk/src/ajax/javascripts/external/MIT-LICENSE.txt. */ /*----------------------------------------------------------------------------*/ - -.topicSummaryTd { - width: 40px; - border: solid 1px gray; -} - -#topicTable { - width: 80%; - border: solid 1px gray; - margin-left: auto; - margin-right: auto; - margin-top: 10px; - margin-bottom: 10px; -} - -th { - color: red; - border: solid 1px gray; +ul.fragmentFrame { + list-style-type: none; } -ul.topicTable { - list-style: none; +caption { + font-size: 1.5em; + font-weight: bold; } -div.naviTopicTable { - width: 80%; - margin-left: auto; - margin-right: auto; +td.controlColumn { + background-color: #eaeaee; } -select.topicTable { - margin-left: 20px; +tr.showHiddenRows { + background-color: #eaeaee; } \ No newline at end of file Modified: trunk/src/ajax/css/main.css ============================================================================== --- trunk/src/ajax/css/main.css (original) +++ trunk/src/ajax/css/main.css Tue May 19 05:23:26 2009 @@ -10,42 +10,31 @@ /*----------------------------------------------------------------------------*/ -.clickable{ - cursor: pointer; - padding-left: 5px; - padding-right: 5px; -} - -.clickable:hover{ - text-decoration: underline; -} - -.clickable:active{ - color: red; -} - -.headerRow { - background-color: #EEEEFF; -} - - -.topicHeaderRow { - background-color: #CCE5FF; +body { + width: 1024px; + margin-left: auto; + margin-right: auto; } -.topicStubsHeaderRow { - background-color: #CCE5FF; +#subPage { + color: #333377; + min-height: 800px; + border-left: 1px solid #d1d1d3; + border-right: 1px solid #d1d1d3; + border-bottom: 1px solid #d1d1d3; + margin-top: -21px; } -.associationsHeaderRow { - background-color: #CCE5FF; +h1 { + margin-left: 10px; + padding-top: 20px; } -.tmIdsHeaderRow { - background-color: #CCE5FF; +.clickable { + cursor: pointer; } -.frame{ - border: 1px outset black; - margin: 5px; -} +.errorMessage { + color: red; + font-size: 0.85em; +} \ No newline at end of file Modified: trunk/src/ajax/css/navi.css ============================================================================== --- trunk/src/ajax/css/navi.css (original) +++ trunk/src/ajax/css/navi.css Tue May 19 05:23:26 2009 @@ -11,11 +11,55 @@ #navi { - border: solid 1px; - margin-top: 10px; - margin-bottom: 10px; + background-color: #aebae3; + width: 1022px; + margin-left: auto; + margin-right: auto; + padding-top: 10px; + padding-bottom: 5px; + border-left: 1px solid #d1d1d3; + border-top: 1px solid #d1d1d3; + border-right: 1px solid #d1d1d3; } -.naviElem { - background-color: silver; -} \ No newline at end of file +#navi > span { + color: #fbfcff; + cursor: pointer; + border-left: 1px solid #aebae3; + border-top: 1px solid #aebae3; + border-right: 1px solid #aebae3; + padding-left: 3px; + padding-right: 3px; + padding-top: 3px; + padding-bottom: 5px; + font-weight: bold; +} + +#navi > span:first-child { + border-left: none; +} + +#navi > span:first-child:hover { + border-left: none; +} + +#navi > span:hover { + color: #333377; + background-color: #fbfcff; + border-left: 1px solid #d1d1d3; + border-top: 1px solid #d1d1d3; + border-right: 1px solid #d1d1d3; +} + +#navi > .isActive { + color: #333377; + background-color: #fbfcff; + border-left: 1px solid #d1d1d3; + border-top: 1px solid #d1d1d3; + border-right: 1px solid #d1d1d3; +} + +#navi > .isActive:hover { + color: #333377; + background-color: #fbfcff; +} Modified: trunk/src/ajax/isidorus.html ============================================================================== --- trunk/src/ajax/isidorus.html (original) +++ trunk/src/ajax/isidorus.html Tue May 19 05:23:26 2009 @@ -18,7 +18,7 @@ - + @@ -45,21 +45,25 @@ - - + + + + + +
-
+
Modified: trunk/src/ajax/javascripts/constants.js ============================================================================== --- trunk/src/ajax/javascripts/constants.js (original) +++ trunk/src/ajax/javascripts/constants.js Tue May 19 05:23:26 2009 @@ -10,116 +10,86 @@ //+----------------------------------------------------------------------------- -var TIMEOUT = 5000; // const TIMEOUT = 5000 --> "const" doesn't work under IE +// --- Some constants fot the http connections via the XMLHttpRequest-Object +var TIMEOUT = 10000; // const TIMEOUT = 10000 --> "const" doesn't work under IE var HOST_PREF = "http://localhost:8000/"; var GET_PREFIX = HOST_PREF + "json/get/"; +var GET_STUB_PREFIX = HOST_PREF + "json/topicstubs/"; +var TMCL_TYPE_URL = HOST_PREF + "json/tmcl/type/"; +var TMCL_INSTANCE_URL = HOST_PREF + "json/tmcl/instance/"; var COMMIT_URL = HOST_PREF + "json/commit/"; var ALL_PSIS_URL = HOST_PREF + "json/psis/"; +var TYPE_PSIS_URL = HOST_PREF + "json/tmcl/types/"; var OWN_URL = HOST_PREF + "isidorus"; var SUMMARY_URL = HOST_PREF + "json/summary" -// --- a kind of enum for the the different pages with an attribute and a value -var PAGES = {"home" : "home", "search" : "searchTopic", "edit" : "editTopic", "create" : "createTopic"}; -// --- contains most css classes used in this project -var CLASSES = {"__addBtnHeader" : "addButton", - "__associationFrame" : "associationFrame", - "__associationsFrame" : "assocaitionsFrame", - "__associationsHeader" : "associationsHeaderRow", - "__button" : "clickable", - "__fragmentFrame" : "fragmentFrame", - "__frame" : "frame", - "__header" : "headerRow", - "__headerTitle" : "title", - "__hideBtnHeader" : "hideButton", - "__inAssociationFrame" : "inAssociationFrame", - "__inNameFrame" : "inNameFrame", - "__inOccurrenceFrame" : "inOccurrenceFrame", - "__inRoleFrame" : "inRoleFrame", - "__instanceOfFrame" : "instanceOf", - "__inTopicFrame" : "inTopicFrame", - "__inTopicStubFrame" : "inTopicStubFrame", - "__inVariantFrame" : "inVariantFrame", - "__itemIdentityFrame" : "itemIdentity", - "__listFrame" : "listFrame", - "__nameFrame" : "nameFrame", - "__namesFrame" : "namesFrame", - "__occurrenceFrame" : "occurrenceFrame", - "__occurrencesFrame" : "occurrencesFrame", - "__playerFrame" : "playerFrame", - "__removeBtnHeader" : "removeButton", - "__removeBtnRow" : "rowDel", - "__resourceFrame" : "resourceFrame", - "__roleFrame" : "roleFrame", - "__rolesFrame" : "roleFrame", - "__row" : "row", - "__scopeFrame" : "scopeFrame", - "__subjectIdentifierFrame" : "subjectIdentifier", - "__subjectLocatorFrame" : "subjectLocator", - "__textareaRow" : "rowTextArea", - "__textRow" : "rowTextfield", - "__tmIdsFrame" : "tmIdsFrame", - "__tmIdsHeader" : "tmIdsHeaderRow", - "__topicFrame" : "topicFrame", - "__topicHeader" : "topicHeaderRow", - "__topicIdFrame" : "topicId", - "__topicStubFrame" : "topicStubFrame", - "__topicStubsHeader" : "topicStubsHeaderRow", - "__topicStubsFrame" : "topicStubsFrame", - "__typeFrame" : "typeFrame", - "__valueFrame" : "valueFrame", - "__variantFrame" : "variantFrame", - "__variantHeader" : "variantHeaderRow", - "__variantsFrame" : "variantsFrame", - - "addBtnHeader" : function(){ return this.__button + " " + this.__addBtnHeader; }, - "associationFrame" : function(){ return this.__frame + " " + this.__associationFrame; }, - "associationsFrame" : function(){ return this.__frame + " " + this.__associationsFrame; }, - "associationsHeader" : function(){ return this.__associationsHeader; }, - "button" : function(){ this.__button; }, - "fragmentFrame" : function(){ return this.__frame + " " + this.__fragmentFrame; }, - "frame" : function(){ return this.__frame; }, - "header" : function(){ return this.__header; }, - "headerTitle" : function(){ return this.__headerTitle; }, - "hideBtnHeader" : function(){ return this.__button + " " + this.__hideBtnHeader; }, - "inAssociationFrame" : function(){ return this.__inAssociationFrame; }, - "inNameFrame" : function(){ return this.__inNameFrame; }, - "inOccurrenceFrame" : function(){ return this.__inOccurrenceFrame; }, - "inRoleFrame" : function(){ return this.__inRoleFrame; }, - "instanceOfFrame" : function(){ return this.__instanceOfFrame; }, - "inTopicFrame" : function(){ return this.__inTopicFrame; }, - "inTopicStubFrame" : function(){ return this.__inTopicStubFrame; }, - "inVariantFrame" : function(){ return this.__inVariantFrame; }, - "itemIdentityFrame" : function(){ return this.__itemIdentityFrame; }, - "listFrame" : function(){ return this.__frame + " " + this.__listFrame; }, - "nameFrame" : function(){ return this.__frame + " " + this.__nameFrame; }, - "namesFrame" : function(){ return this.__frame + " " + this.__namesFrame; }, - "occurrenceFrame" : function(){ return this.__frame + " " + this.__occurrenceFrame; }, - "occurrencesFrame" : function(){ return this.__frame + " " + this.__occurrencesFrame; }, - "playerFrame" : function(){ return this.__playerFrame; }, - "removeBtnHeader" : function(){ return this.__button + " " + this.__removeBtnHeader; }, - "removeBtnRow" : function(){ return this.__button + " " + this.__removeBtnRow; }, - "roleFrame" : function(){ return this.__frame + " " + this.__roleFrame; }, - "rolesFrame" : function(){ return this.__frame + " " + this.__rolesFrame; }, - "row" : function(){ return this.__row; }, - "scopeFrame" : function(){ return this.__scopeFrame; }, - "resourceFrame" : function(){ return this.__frame + " " + this.__resourceFrame; }, - "subjectIdentifierFrame" : function(){ return this.__subjectIdentifierFrame; }, - "subjectLocatorFrame" : function(){ return this.__subjectLocatorFrame; }, - "textareaRow" : function(){ return this.__textareaRow; }, - "textRow" : function(){ return this.__textRow; }, - "tmIdsFrame" : function(){ return this.__frame + " " + this.__tmIdsFrame; }, - "tmIdsHeader" : function(){ return this.__tmIdsHeader; }, - "topicFrame" : function(){ return this.__frame + " " + this.__topicFrame; }, - "topicHeader" : function(){ return this.__topicHeader; }, - "topicIdFrame" : function(){ return this.__topicIdFrame; }, - "topicStubFrame" : function(){ return this.__frame + " " + this.__topicStubFrame; }, - "topicStubsHeader" : function(){ return this.__topicStubsHeader; }, - "topicStubsFrame" : function(){ return this.__frame + " " + this.__topicStubsFrame; }, - "typeFrame" : function(){ return this.__typeFrame; }, - "valueFrame" : function(){ return this.__valueFrame; }, - "variantFrame" : function(){ return this.__frame + " " + this.__variantFrame; }, - "variantHeader" : function(){ return this.__variantHeader; }, - "variantsFrame" : function(){ return this.__frame + " " + this.__variantsFrame; } +// --- A kind of enum for the the different pages with an attribute and a value +var PAGES = {"home" : "home", "search" : "searchTopic", "edit" : "editTopic", "create" : "createTopic", "current" : ""}; + +var ANY_URI = "http://www.w3.org/2001/XMLSchema#anyURI"; +var STRING = "http://www.w3.org/2001/XMLSchema#string"; + +// --- Contains most css classes used in this project +// --- There should be called only the function to be sure to don't override +// --- the original values. +var CLASSES = {"__divPage__" : "page", + "__divSubPage__" : "subPage", + "__divContent__" : "content", + "__divTextrowWithRemoveButton__" : "textrowWithRemoveButton", + "__divTextrowWithoutRemoveButton__" : "textrowWithoutRemoveButton", + "__divSelectrowWithRemoveButton__" : "selectrowWithRemoveButton", + "__divSelectrowWithoutRemoveButton__" : "selectrowWithoutRemoveButton", + "__spanClickable__" : "clickable", + "__notVisible__" : "notvisible", + "__divError__" : "errorMessage", + "__ulFragmentFrame__" : "fragmentFrame", + "__tableTopicFrame__" : "topicFrame", + "__trTopicIdFrame__" : "topicIdFrame", + "__tdContent__" : "content", + "__tdDescription__" : "description", + "__divInstanceOfFrame__" : "instanceOfFrame", + "__divItemIdentityFrame__" : "itemIdentityFrame", + "__divSubjectLocatorFrame__" : "subjectLocatorFrame", + "__divSubjectIdentifierFrame__" : "subjectIdentifierFrame", + "__divNameContainer__" : "nameContainer", + "__divNameFrame__" : "nameFrame", + "__trControlColumn__" : "controlColumn", + "__trShowHiddenRows__" : "showHiddenRows", + "__trTypeFrame__" : "typeFrame", + "__divScopeFrame__" : "scopeFrame", + "__divValueFrame__" : "valueFrame", + "__divVariantFrame__" : "variantFrame", + "__divVariantContainer__" : "variantContainer", + "__divDatatypeFrame__" : "datatypeFrame", + + "page" : function(){ return this.__divPage__; }, + "subPage" : function(){ return this.__divSubPage__; }, + "content" : function(){ return this.__divContent__; }, + "textrowWithRemoveButton" : function(){ return this.__divTextrowWithRemoveButton__; }, + "textrowWithoutRemoveButton" : function(){ return this.__divTextrowWithoutRemoveButton__; }, + "selectrowWithRemoveButton" : function(){ return this.__divSelectrowWithRemoveButton__; }, + "selectrowWithoutRemoveButton" : function(){ return this.__divSelectrowWithoutRemoveButton__; }, + "clickable" : function(){ return this.__spanClickable__; }, + "notVisible" : function(){ return this.__notVisible__; }, + "error" : function(){ return this.__divError__; }, "fragmentFrame" : function(){ return this.__ulFragmentFrame__; }, + "topicFrame" : function(){ return this.__tableTopicFrame__; }, + "topicIdFrame" : function(){ return this.__trTopicIdFrame__; }, + "content" : function(){ return this.__tdContent__; }, + "description" : function(){ return this.__tdDescription__; }, + "instanceOfFrame" : function(){ return this.__divInstanceOfFrame__; }, + "itemIdentityFrame" : function(){ return this.__divItemIdentityFrame__; }, + "subjectLocatorFrame" : function(){ return this.__divSubjectLocatorFrame__; }, + "subjectIdentifierFrame" : function(){ return this.__divSubjectIdentifierFrame__; }, + "nameContainer" : function(){ return this.__divNameContainer__; }, + "nameFrame" : function(){ return this.__divNameFrame__; }, + "controlColumn" : function(){ return this.__trControlColumn__; }, + "showHiddenRows" : function(){ return this.__trShowHiddenRows__; }, + "typeFrame" : function(){ return this.__trTypeFrame__; }, + "scopeFrame" : function(){ return this.__divScopeFrame__; }, + "valueFrame" : function(){ return this.__divValueFrame__; }, + "variantFrame" : function(){ return this.__divVariantFrame__; }, + "variantContainer" : function(){ return this.__divVariantContainer__; }, + "datatypeFrame" : function(){ return this.__divDatatypeFrame__; } }; \ No newline at end of file Added: trunk/src/ajax/javascripts/create.js ============================================================================== --- (empty file) +++ trunk/src/ajax/javascripts/create.js Tue May 19 05:23:26 2009 @@ -0,0 +1,63 @@ +//+----------------------------------------------------------------------------- +//+ Isidorus +//+ (c) 2008-2009 Marc Kuester, Christoph Ludwig, Lukas Giessmann +//+ +//+ Isidorus is freely distributable under the LGPL license. +//+ This ajax module uses the frameworks PrototypeJs and Scriptaculous, both +//+ are distributed under the MIT license. +//+ You can find a detailed description in trunk/docs/LGPL-LICENSE.txt and +//+ in trunk/src/ajax/javascripts/external/MIT-LICENSE.txt. +//+----------------------------------------------------------------------------- + + +function makeCreate(psi) +{ + var content = new Element("div", {"class" : CLASSES.content()}); + var header = new Element("h1").update("Create a Topic"); + content.insert(header, {"position" : "bottom"}); + $(CLASSES.subPage()).insert(content, {"position" : "bottom"}); + + try{ + var fragmentFrame = new Element("ul", {"class" : CLASSES.fragmentFrame()}); + content.insert({"bottom" : fragmentFrame}); + var liTopicSelect = new Element("li", {"class" : CLASSES.instanceOfFrame()}); + fragmentFrame.insert({"bottom" : liTopicSelect}); + + + function makeInstanceOfFrame(context){ + function makeFragment(psis, constraints){ + var items = $$("li." + CLASSES.topicFrame()); + for(var i = 0; i != items.length; ++i){ + items[i].remove(); + } + + var topic = new TopicC(null, (constraints ? constraints.topicConstraints : null)); + context.insert({"after" : new Element("li", {"class" : CLASSES.topicFrame()}).update(topic.getFrame())}); + } + + function onSuccessHandler(xhr){ + var json = null; + try{ + json = xhr.responseText.evalJSON(); + } + catch(innerErr){ + alert("Got bad JSON data from " + xhr.request.url + "\n\n" + innerErr); + } + var instanceOf = null; + try{ + instanceOf = new InstanceOfC(json.flatten().sort(), makeFragment); + context.insert({"bottom" : instanceOf.getFrame()}); + } + catch(innerErr){ + alert("There occurred an error by creating an InstanceOfC frame, please reload this page!\n\n" + innerErr); + } + } + + getTypePsis(onSuccessHandler, null); + } + + makeInstanceOfFrame(liTopicSelect); + }catch(err){ + alert(err); + } +} \ No newline at end of file Added: trunk/src/ajax/javascripts/datamodel.js ============================================================================== --- (empty file) +++ trunk/src/ajax/javascripts/datamodel.js Tue May 19 05:23:26 2009 @@ -0,0 +1,1158 @@ +//+----------------------------------------------------------------------------- +//+ Isidorus +//+ (c) 2008-2009 Marc Kuester, Christoph Ludwig, Lukas Giessmann +//+ +//+ Isidorus is freely distributable under the LGPL license. +//+ This ajax module uses the frameworks PrototypeJs and Scriptaculous, both +//+ are distributed under the MIT license. +//+ You can find a detailed description in trunk/docs/LGPL-LICENSE.txt and +//+ in trunk/src/ajax/javascripts/external/MIT-LICENSE.txt. +//+----------------------------------------------------------------------------- + +// --- The base class of all Frames defined in this file. +var FrameC = Class.create({"initialize" : function(content, owner, min, max){ + if(!owner) throw "From FrameC(): owner must be set but is null"; + if(max !== -1 && (min > max || max === 0))throw "From FrameC(): min must be > max(" + max + ") and > 0 but is " + min; + if(!owner.__frames__) owner.__frames__ = new Array(); + owner.__frames__.push(this); + + this.__frame__ = new Element("div"); + this.__remove__ = new Element("span", {"class" : CLASSES.clickable()}).update("-"); + this.__add__ = new Element("span", {"class" : CLASSES.clickable()}).update("+"); + + checkRemoveAddButtons(owner, min, max); + + this.__error__ = new Element("div", {"class" : CLASSES.error()}); + this.__error__.hide(); + this.__content__ = new Element("span").update(content); + + this.__frame__.insert({"bottom" : this.__remove__}); + this.__frame__.insert({"bottom" : this.__content__}); + this.__frame__.insert({"bottom" : this.__add__}); + this.__frame__.insert({"bottom" : this.__error__}); + + setRemoveAddHandler(this, owner, min, max, function(){ + return new FrameC("", owner, min, max); + }); + }, + "getFrame" : function(){ + return this.__frame__; + }, + "remove" : function(){ + return this.getFrame().remove(); + }, + "hide" : function(){ + this.getFrame().hide(); + }, + "show" : function(){ + this.getFrame().show(); + }, + "getContent" : function(){ + return this.__content__.textContent; + }, + "toJSON" : function(){ + return this.getContent().toJSON(); + }, + "showError" : function(message){ + this.__error__.update(message); + this.__error__.show(); + }, + "hideError" : function(){ + this.__error__.hide(); + }, + "hideRemoveButton" : function(){ + this.__remove__.hide(); + }, + "showRemoveButton" : function(){ + this.__remove__.show(); + }, + "hideAddButton" : function(){ + this.__add__.hide(); + }, + "showAddButton" : function(){ + this.__add__.show(); + }, + "append" : function(elem){ + return this.getFrame().insert({"after" : elem}); + }}); + + +// --- This class represents a textrow with the functionality of FrameC plus the method isValid +// --- which returns a boolean value depending on the instance's value and the given regular expression. +var TextrowC = Class.create(FrameC, {"initialize" : function($super, content, regexp, owner, min, max, cssTitle){ + $super(content, owner, min, max); + owner.__frames__.pop(); + owner.__frames__.push(this); + + this.__regexp__ = new RegExp(regexp); + this.__frame__.writeAttribute({"class" : CLASSES.textrowWithRemoveButton()}); + this.__content__.remove(); + this.__content__ = new Element("input", {"type" : "text", "value" : content}); + if(cssTitle && cssTitle.length){ + this.__content__.writeAttribute({"title" : cssTitle}); + } + this.__remove__.insert({"after" : this.__content__}); + + checkRemoveAddButtons(owner, min, max); + setRemoveAddHandler(this, owner, min, max, function(){ + return new TextrowC("", regexp, owner, min, max, cssTitle); + }); + }, + "getContent" : function(){ + return this.__content__.value; + }, + "isValid" : function(){ + return this.__regexp__.match(this.getContent()); + }, + "showRemoveButton" : function($super){ + this.__remove__.show(); + this.getFrame().writeAttribute({"class" : CLASSES.textrowWithRemoveButton()}); + }, + "hideRemoveButton" : function(){ + this.__remove__.hide(); + this.getFrame().writeAttribute({"class" : CLASSES.textrowWithoutRemoveButton()}); + }}); + + +// --- This class represents a selectrow with the functionality of FrameC. +var SelectrowC = Class.create(FrameC, {"initialize" : function($super, contents, owner, min, max){ + if(!contents || !contents.length)throw "From SelectrowC(): contents must be an array!"; + $super(contents, owner, min, max); + owner.__frames__.pop(); + owner.__frames__.push(this); + + this.__frame__.writeAttribute({"class" : CLASSES.selectrowWithRemoveButton()}); + this.__content__.remove(); + this.__content__ = new Element("select"); + for(var i = 0; i != contents.length; ++i){ + // --- the attribute value must be set for IE + this.__content__.insert({"bottom" : new Element("option", {"value" : contents[i]}).update(contents[i])}); + } + this.__remove__.insert({"after" : this.__content__}); + + checkRemoveAddButtons(owner, min, max); + setRemoveAddHandler(this, owner, min, max, function(){ + return new SelectrowC(contents, owner, min, max); + }); + }, + "getContent" : function(){ + return this.__content__.value; + }, + "showRemoveButton" : function(){ + this.__remove__.show(); + this.getFrame().writeAttribute({"class" : CLASSES.selectrowWithRemoveButton()}); + }, + "hideRemoveButton" : function(){ + this.__remove__.hide(); + this.getFrame().writeAttribute({"class" : CLASSES.selectrowWithoutRemoveButton()}); + }}); + + +// --- The base Class for alomost all frames which contains other frames like names, occurrences, ... +var ContainerC = Class.create({"initialize" : function(){ + this.__frame__ = new Element("div"); + this.__error__ = new Element("div", {"class" : CLASSES.error()}); + this.__error__.hide(); + this.__frame__.insert({"bottom" : this.__error__}); + }, + "hide" : function(){ + this.__frame__.hide(); + }, + "show" : function(){ + this.__frame__.show(); + }, + "getFrame" : function(){ + return this.__frame__; + }, + "getContent" : function(unique, removeNull){ + return ""; + }, + "toJSON" : function(unique, removeNull){ + return this.getContent(unique, removeNull).toJSON(); + }, + "showError" : function(message){ + this.__error__.update(message); + this.__error__.show(); + }, + "hideError" : function(){ + this.__error__.hide(); + }, + "append" : function(newElem){ + this.getFrame().insert({"after" : newElem}); + }, + "remove" : function(){ + this.getFrame().remove(); + }}); + + +// --- Represents a container for all instanceOf-Psis of a fragment's topic +var InstanceOfC = Class.create(ContainerC, {"initialize" : function($super, contents, successFun){ + $super(); + this.__frame__.writeAttribute({"class" : CLASSES.instanceOfFrame()}); + this.__container__ = new Object(); + try{ + var row = new SelectrowC(contents, this.__container__, 1, -1); + this.__error__.insert({"before" : row.getFrame()}); + } + catch(err){ + throw "From InstanceOfC(): The following exception was thrown:\n" + err; + this.__container__ = null; + } + this.__commit__ = new Element("input", {"type" : "button", "value" : "get constraints"}); + + function setHandler(myself){ + function onSuccessHandler(xhr){ + var json = null; + try{ + json = xhr.responseText.evalJSON(); + } + catch(err){ + alert("Got bad JSON data from " + xhr.request.url + "!\n\n" + err); + } + + var ret = checkExclusiveInstances(json, myself.getContent(true)); + if(ret){ + var str = "Some topics own exclusive-instance-constraints, please deselect the corresponding topics!
"; + for(var i = 0; i != ret.length; ++i){ + for(var j = 0; j != ret[i].length; ++j){ + if(j === 0){ + str += "
" + ret[i][j]; + } + else { + str += "    " + ret[i][j]; + } + str += "
"; + } + } + var items = $$("li." + CLASSES.topicFrame()); + for(var i = 0; i != items.length; ++i){ + items[i].remove(); + } + myself.showError(str); + } + else { + successFun(contents, json); + } + } + + myself.__commit__.observe("click", function(event){ + myself.hideError(); + requestConstraints(myself.toJSON(true), onSuccessHandler, null); + }); + } + setHandler(this); + + this.__error__.insert({"before" : this.__commit__}); + }, + "getContent" : function(unique, removeNull){ + var values = new Array(); + for(var i = 0; i != this.__container__.__frames__.length; ++i){ + if(unique === true && values.indexOf(this.__container__.__frames__[i].getContent()) !== -1) continue; + if(removeNull === true && this.__container__.__frames__[i].getContent().strip().length === 0) continue; + values.push(this.__container__.__frames__[i].getContent().strip()); + } + return values; + }}); + + + +// --- Representation of a itemIdentity frame. +var ItemIdentityC = Class.create(ContainerC, {"initialize" : function($super, contents){ + $super(); + this.__frame__.writeAttribute({"class" : CLASSES.itemIdentityFrame()}); + this.__container__ = new Object(); + + try{ + for(var i = 0; i != contents.length; ++i){ + new TextrowC(contents[i], ".*", this.__container__, 1, -1, null); + this.__error__.insert({"before" : this.__container__.__frames__[i].getFrame()}); + } + } + catch(err){ + this.__container__ = new Object(); + new TextrowC("", ".*", this.__container__, 1, -1, null); + this.__error__.insert({"before" : this.__container__.__frames__[i].getFrame()}); + } + }, + "getContent" : function(unique, removeNull){ + var values = new Array(); + for(var i = 0; i != this.__container__.__frames__.length; ++i){ + if(unique === true && values.indexOf(this.__container__.__frames__[i].getContent()) !== -1) continue; + if(removeNull === true && this.__container__.__frames__[i].getContent().strip().length === 0) continue; + values.push(this.__container__.__frames__[i].getContent().strip()); + } + return values; + }, + "toJSON" : function(unique, removeNull){ + var content = this.getContent(unique, removeNull); + return content.length === 0 ? "null" : content.toJSON(); + }}); + + +// --- Representation of a subjectLocator and subjectIdentifier frames. +var IdentifierC = Class.create(ContainerC, {"initialize" : function($super, contents, constraints, cssClass){ + $super(); + this.__frame__.writeAttribute({"class" : cssClass}); + this.__containers__ = new Array(); + + try{ + if((!contents || contents.length === 0) && constraints && constraints.length > 0){ + for(var i = 0; i != constraints.length; ++i){ + this.__containers__.push(new Object()); + var min = parseInt(constraints[i].cardMin); + var max = constraints[i].cardMax !== "MAX_INT" ? parseInt(constraints[i].cardMax) : "*"; + if(max !== 0){ + var cssTitle = "min: " + min + " max: " + max + " regular expression: " + constraints[i].regexp; + for(var j = 0; j != (min === 0 ? 1 : min); ++j){ + var row = new TextrowC("", constraints[i].regexp, this.__containers__[i], + min === 0 ? 1 : min, max === "*" ? -1 : max, cssTitle); + this.__error__.insert({"before" : row.getFrame()}); + } + } + } + } + else { + // TODO: check already existing contents and order them to the corresponding fields + } + } + catch(err){ + alert("From IdentifierC(): " + err); + } + }, + "getContent" : function(unique, removeNull){ + var values = new Array(); + for(var i = 0; i != this.__containers__.length; ++i){ + for(var j = 0; j != this.__containers__[i].__frames__.length; ++j){ + if(unique === true && values.indexOf(this.__containers__[i].__frames__[j].getContent()) !== -1) continue; + if(removeNull === true && this.__containers__[i].__frames__[j].getContent().strip().length === 0) continue; + values.push(this.__containers__[i].__frames__[j].getContent().strip()); + } + } + return values; + }, + "isValid" : function(){ + // TODO: check the validity of this frame with the passed constraints and return a boolean value + return true; + }}); + + +// --- Represantation of a scope frame, doesn't contain SelectrowCs, because the values must be unique! +// --- So this class uses another implementation. +var ScopeC = Class.create(ContainerC, {"initialize" : function($super, contents, min, max){ + $super(); + this.__frame__.writeAttribute({"class" : CLASSES.scopeFrame()}); + this.__error__ = this.__error__.remove(); + + this.__container__ = null; + this.__contents__ = contents; + this.resetRows(this.__contents__, min, max); + }, + "resetRows" : function(contents, min, max){ + try{ + for(var i = 0; i != this.__container__.__frames__.length; ++i){ + this.__container__.__frames__[i].remove(); + } + this.__container__ = new Object(); + } + catch(err){ + this.__container__ = new Object(); + }; + + this.__contents__ = contents; + if(!contents || contents.length < min) throw "From ScopeC.resetRows(): contents.length (" + + (contents ? contents.length : "null") + ") must be > min (" + min + ")!"; + if(max !== -1 && (min > max || max === 0))throw "From FrameC(): min must be > max(" + max + ") and > 0 but is " + min; + + + var options = new Array(); + for(var i = 0; i != contents.length; ++i){ + var topicPsis = new Array(); + for(var j = 0; j != contents[i].length; ++j){ + for(var k = 0; k != contents[i][j].length; ++k){ + topicPsis.push(contents[i][j][k]); + } + } + options.push(topicPsis); + } + + function checkValues(myself){ + var rows = myself.getFrame().select("div"); + var selectedItems = new Array(); + // --- collects all old selected values and removes the option elements + for(var i = 0; i != rows.length; ++i){ + var selects = rows[i].select("select"); + if(selects[0].value.strip().length !== 0) selectedItems.push(selects[0].value); + selects[0].update(""); + } + + // --- recreates the original values + var values = options.clone(); + for(var i = 0; i != rows.length && i != selectedItems.length; ++i){ + var select = rows[i].select("select")[0]; + var selectedIdx = new Array(); + for(var j = 0; j != values.length; ++j){ + if(values[j].indexOf(selectedItems[i]) !== -1){ + for(var k = 0; k != values[j].length; ++k){ + select.insert({"bottom" : new Element("option", {"value" : values[j][k]}).update(values[j][k])}); + if(values[j][k] === selectedItems[i])select.writeAttribute({"selected" : "selected"}); + //values = values.without(values[j]); + selectedIdx.push(j); + } + break; + } + } + var cleanedValues = new Array(); + for(var k = 0; k != values.length; ++k){ + if(selectedIdx.indexOf(k) === -1){ + cleanedValues.push(values[k]); + } + } + values = cleanedValues; + } + + // --- fills all empty select elements + for(var i = 0; i != rows.length; ++i){ + var select = rows[i].select("select")[0]; + if(select.childElements().length === 0 && values.length !== 0){ + for(var j = 0; j != values[0].length; ++j){ + select.insert({"bottom" : new Element("option", {"value" : values[0][j]}).update(values[0][j])}); + } + values.shift(); + } + } + + // --- adds the values which wasn't distributed + for(var i = 0; i != rows.length; ++i){ + var select = rows[i].select("select")[0]; + for(var j = 0; j != values.length; ++j){ + for(var k = 0; k != values[j].length; ++k){ + select.insert({"bottom" : new Element("option" , {"value" :values[j][k]}).update(values[j][k])}); + } + } + } + }// checkValues + + + function addHandlers(myself){ + var rows = myself.getFrame().select("div"); + checkValues(myself); + + function addHandler(event){ + var div = new Element("div", {"class" : CLASSES.selectrowWithRemoveButton()}); + myself.getFrame().insert({"bottom" : div}); + var select = new Element("select"); + div.insert({"top" : select}); + addHandlers(myself); + } + + function removeHandler(event){ + event.element().up().remove(); + addHandlers(myself); + } + + for(var i = 0; i != rows.length; ++i){ + var spans = rows[i].select("span." + CLASSES.clickable()); + var removeS = null; + var addS = null; + if(spans.length === 0){ + removeS = new Element("span", {"class" : CLASSES.clickable()}).update("-"); + removeS.observe("click", removeHandler); + addS = new Element("span", {"class" : CLASSES.clickable()}).update("+"); + addS.observe("click", addHandler); + rows[i].insert({"top" : removeS}); + rows[i].insert({"bottom" : addS}); + } + else { + removeS = spans[0]; + addS = spans[1]; + } + + if(max === -1 || max > rows.length){ + addS.show() + } + else { + addS.hide(); + } + + if(min !== -1 || min < rows.length){ + removeS.show() + rows[i].writeAttribute({"class" : CLASSES.selectrowWithRemoveButton()}); + } + else { + removeS.hide(); + rows[i].writeAttribute({"class" : CLASSES.selectrowWithoutRemoveButton()}); + } + if(i == 0 && rows.length === 1 && max > 1){ + rows[i].writeAttribute({"class" : CLASSES.selectrowWithoutRemoveButton()}); + removeS.hide(); + } + } + } // addHandlers + + for(var i = 0; i != (min === -1 ? 1 : min); ++i){ + var div = new Element("div", {"class" : CLASSES.selectrowWithoutRemoveButton()}); + var select = new Element("select"); + for(var j = 0; j != options.length; ++j){ + if(j === i || j > min){ + for(var k = 0; k != options[j].length; ++k){ + select.insert({"bottom" : new Element("option", {"value" : options[j][k]}).update(options[j][k])}); + } + } + } + + + div.insert({"top" : select}); + this.getFrame().insert({"bottom" : div}); + addHandlers(this); + } + }, + "getContent" : function(unique, removeNull){ + // --- unique and removeNull aren't be used, they exist only for consistency + var values = new Array(); + var rows = this.getFrame().select("div"); + for(var i = 0; i != rows.length; ++i){ + values.push(new Array(rows[i].select("select")[0].value)); // must be a list of lists + } + return values; + } + }); + + + +// --- Representation of a variant element +var VariantC = Class.create(ContainerC, {"initialize" : function($super, contents, owner){ + $super(); + if(!owner.__frames__) owner.__frames__ = new Array(); + owner.__frames__.push(this); + this.__frame__.writeAttribute({"class" : CLASSES.variantFrame()}); + this.__table__ = new Element("table", {"class" : CLASSES.variantFrame()}); + this.__frame__.insert({"top" : this.__table__}); + + try{ + // --- control row + itemIdentity + makeControlRow(this, 4, contents ? contents.itemIdentities : null); + checkRemoveAddButtons(owner, 1, -1); + setRemoveAddHandler(this, owner, 1, -1, function(){ + return new VariantC(null, owner); + }); + + // --- scopes + this.__scopes__ = null; + //TODO: implement -> also in the server + this.__table__.insert({"bottom" : newRow(CLASSES.scopeFrame(), "Scope", new Element("div"))}); + + // --- resourceValue + var value = ""; + var datatype = ""; + if(contents && contents.resourceRef && contents.resourceRef.length !== 0){ + value = contents.resourceRef; + datatype = ANY_URI; + } + else if(contents && contents.resourceData){ + value = contents.resourceData.value; + datatype = contents.resourceData.datatype; + } + + this.__value__ = new Element("textarea", {"rows" : 3}).update(value); + this.__table__.insert({"bottom" : newRow(CLASSES.valueFrame(), "Resource Value", this.__value__)}); + + // --- datatype + this.__datatype__ = new Object(); + new TextrowC(datatype, ".*", this.__datatype__, 1, 1, null); + this.__table__.insert({"bottom" : newRow(CLASSES.datatypeFrame(), "Datatype", this.__datatype__.__frames__[0].getFrame())}); + + // --- minimize + this.minimize(); + } + catch(err){ + alert("From VariantC(): " + err); + } + }, + "getContent" : function(){ + var resourceRef = null; + var resourceData = null; + if(this.__datatype__.__frames__[0].getContent() === ANY_URI){ + resourceRef = this.__value__.textContent.strip(); + } + else { + var datatype = STRING; + if(this.__datatype__.__frames__[0].getContent().strip() !== "") + datatype = this.__datatype__.__frames__[0].getContent().strip(); + resoureceData = {"datatype" : datatype, "value" : this.__value__.textContent.strip()}; + } + + // TODO: scopes + if(this.__itemIdentity__.getContent(true, true).length === 0 && + resourceRef === null && resourceData === null) return null; + return {"itemIdentities" : this.__itemIdentity__.getContent(true, true), + "scopes" : null, + "resourceRef" : resourceRef, + "resourceData" : resourceData}; + + }, + "toJSON" : function(){ + var resourceRef = null; + var resourceData = null; + if(this.__datatype__.__frames__[0].getContent() === ANY_URI){ + resourceRef = this.__value__.value.strip().toJSON(); + } + else { + var datatype = STRING.toJSON(); + if(this.__datatype__.__frames__[0].getContent().strip() !== "") + datatype = this.__datatype__.__frames__[0].getContent().strip().toJSON(); + resourceData = "{\"datatype\":" + datatype + ",\"value\":" + this.__value__.value.strip().toJSON() + "}"; + } + + // TODO: scopes + return "{\"itemIdentities\":" + this.__itemIdentity__.toJSON(true, true) + + ",\"scopes\":null,\"resourceRef\":" + resourceRef + ",\"resourceData\":" + resourceData + "}"; + + }, + "isValid" : function(){ + return this.__value__.value.strip() !== ""; + }, + "isUsed" : function(){ + return (this.__itemIdentity__.getContent(true, true).length !== 0 || + this.__value__.value.strip() !== "" || this.__datatype__.__frames__[0].getContent().strip() !== ""); + }, + "showRemoveButton" : function(){ + this.__remove__.show(); + }, + "hideRemoveButton" : function(){ + this.__remove__.hide(); + }, + "showAddButton" : function(){ + this.__add__.show(); + }, + "hideAddButton" : function(){ + this.__add__.hide(); + }, + "minimize" : function(){ + var trs = this.__table__.select("tr"); + for(var i = 0; i != trs.length; ++i){ + if(i === 0) trs[i].show(); + else trs[i].hide(); + } + } + }); + + +// --- contains all variants of a name element +var VariantContainerC = Class.create(ContainerC, {"initialize" : function($super, contents){ + $super(); + this.__frame__.writeAttribute({"class" : CLASSES.variantContainer()}); + this.__container__ = new Object(); + + if(contents && contents.length != 0){ + for(var i = 0; i != contents.length; ++i){ + var variant = new VariantC(contents[i], this.__container__); + this.__frame__.insert({"bottom" : variant.getFrame()}); + } + } + else { + var variant = new VariantC(null, this.__container__); + this.__frame__.insert({"bottom" : variant.getFrame()}); + } + }, + "getContent" : function(){ + var values = new Array(); + for(var i = 0; i != this.__container__.__frames__.length; ++i){ + if(this.__container__.__frames__[i].isUsed() === true){ + values.push(this.__container__.__frames__[i].getContent()); + } + } + return values; + }, + "isValid" : function(){ + for(var i = 0; i != this.__container__.__frames__.length; ++i){ + if(this.__container__.__frames__[i].isUsed() === true && + this.__container__.__frames__[i].isValid() === false) return false; + } + return true; + }, + "toJSON" : function(){ + var str = "["; + for(var i = 0; i != this.__container__.__frames__.length; ++i){ + if(this.__container__.__frames__[i].isUsed() === true){ + str += this.__container__.__frames__[i].toJSON(); + } + if(i < this.__container__.__frames__.length - 1){ + str += "," + } + } + str += "]"; + return str === "[]" ? null : str; + }}); + + +// --- representation of a name element +var NameC = Class.create(ContainerC, {"initialize" : function($super, contents, nametypescopes, simpleConstraint, owner, min, max, cssTitle){ + $super(); + if(!owner) throw "From NameC(): owner must be set but is null"; + if(max !== -1 && (min > max || max === 0))throw "From FrameC(): min must be > max(" + max + ") and > 0 but is " + min; + if(!owner.__frames__) owner.__frames__ = new Array(); + owner.__frames__.push(this); + + this.__frame__.writeAttribute({"class" : CLASSES.nameFrame()}); + this.__table__ = new Element("table", {"class" : CLASSES.nameFrame()}); + this.__frame__.insert({"top" : this.__table__}); + + try{ + // --- control row + ItemIdentity + makeControlRow(this, 5, contents ? contents.itemIdentities : null); + checkRemoveAddButtons(owner, min, max); + setRemoveAddHandler(this, owner, min, max, function(){ + return new NameC(null, nametypescopes, simpleConstraint, owner, min, max, cssTitle); + }); + + // --- type + var types = new Array(); + for(var i = 0; nametypescopes && i !== nametypescopes.length; ++i){ + for(j = 0; j != nametypescopes[i].nameType.length; ++j){ + types.push(nametypescopes[i].nameType[j]); + if(contents && contents.type && contents.type[0] === nametypescopes[i].nameType[j]){ + var sslected = nametypescopes[i].nameType[j]; + types[types.length - 1] = types[0]; + types[0] = selected; + } + } + } + this.__type__ = new Object(); + var tr = newRow(CLASSES.typeFrame(), "Type", new SelectrowC(types, this.__type__, 1, 1).getFrame()); + this.__table__.insert({"bottom" : tr}); + + // --- scopes + this.__scopes__ = null; + if(nametypescopes && nametypescopes[0].scopeConstraints){ + // TODO: pass the selected items seperately to the object, so they can be chosen as default + var scopeTypes = nametypescopes[0].scopeConstraints[0].scopeTypes; + var min = parseInt(nametypescopes[0].scopeConstraints[0].cardMin); + var max = nametypescopes[0].scopeConstraints[0].cardMax !== "MAX_INT" ? parseInt(nametypescopes[0].scopeConstraints[0].cardMax) : "*"; + this.__scopes__ = new ScopeC(scopeTypes, min === 0 ? 1 : min, max === "*" ? -1 : max); + tr = newRow(CLASSES.scopeFrame(), "Scope", this.__scopes__.getFrame()); + this.__table__.insert({"bottom" : tr}); + } + else { + var tr = new Element("tr", {"class" : CLASSES.scopeFrame()}); + var tdd = new Element("td", {"class" : CLASSES.description()}).update("Scope"); + var tdc = new Element("td", {"class" : CLASSES.content()}); + tr.insert({"top" : tdd}); + tr.insert({"bottom" : tdc}); + this.__table__.insert({"bottom" : tr}); + } + + // --- value + this.__value__ = new Object(); + var cssTitleV = "min: " + min + " max: " + max + " regular expression: " + (simpleConstraint ? simpleConstraint.regexp : ".*"); + new TextrowC((contents && contents.value ? contents.value : ""), (simpleConstraint ? simpleConstraint.regexp : ".*"), this.__value__, 1, 1, cssTitleV); + this.__table__.insert({"bottom" : newRow(CLASSES.valueFrame(), "Value", this.__value__.__frames__[0].getFrame())}); + + // --- variants + this.__variants__ = new VariantContainerC(contents? contents.variants : null); + this.__table__.insert({"bottom" : newRow(CLASSES.variantContainer(), "Variants", this.__variants__.getFrame())}); + + // --- adds a second show handler, so the variants will be hidden, when the entire + // --- name element will be shown + function addSecondShowHandler(myself){ + myself.__table__.select("tr")[0].observe("click", function(event){ + try{ + for(var i = 0; i != myself.__variants__.__container__.__frames__.length; ++i){ + myself.__variants__.__container__.__frames__[i].minimize(); + } + }catch(tmp){ alert(tmp);} + }); + } + + addSecondShowHandler(this); + } + catch(err){ + alert("From NameC(): " + err); + } + }, + "getContent" : function(){ + if(this.isUsed() === false) return null; + return {"itemIdentities" : this.__itemIdentity__.getContent(true, true), + "scopes" : this.__scopes__.getContent(), + "value" : this.__value__.__frames__[0].getContent(), + "variants" : this.__variants__.getContent()}; + }, + "toJSON" : function(){ + if(this.isUsed() === false) return "null"; + return "{\"itemIdentities\":" + this.__itemIdentity__.toJSON(true, true) + + ",\"type\":[" + this.__type__.__frames__[0].toJSON() + + "],\"scopes\":" + (this.__scopes__ ? this.__scopes__.toJSON() : "null") + + ",\"value\":" + this.__value__.__frames__[0].toJSON() + + ",\"variants\":" + this.__variants__.toJSON() + "}"; + }, + "isUsed" : function(){ + return this.__itemIdentity__.getContent(true, true).length !== 0 || + this.__value__.__frames__[0].getContent().strip().length !== 0 || + this.__variants__.getContent().length !== 0; + }, + "showRemoveButton" : function(){ + this.__remove__.show(); + }, + "hideRemoveButton" : function(){ + this.__remove__.hide(); + }, + "showAddButton" : function(){ + this.__add__.show(); + }, + "hideAddButton" : function(){ + this.__add__.hide(); + }, + "isValid" : function(){ + // TODO: check the content and the constraints + variants.isValid() + return true; + }}); + + + +// --- contains all names of a topic +var NameContainerC = Class.create(ContainerC, {"initialize" : function($super, contents, constraints){ + $super(); + this.__frame__.writeAttribute({"class" : CLASSES.nameContainer()}); + this.__containers__ = new Array(); + + try{ + if((!contents || contents.length === 0) && constraints && constraints.length > 0){ + for(var i = 0; i != constraints.length; ++i){ + this.__containers__.push(new Array()); + for(var j = 0; j != constraints[i].constraints.length; ++j){ + this.__containers__[i].push(new Object()); + var min = parseInt(constraints[i].constraints[j].cardMin); + var max = constraints[i].constraints[j].cardMax !== "MAX_INT" ? parseInt(constraints[i].constraints[j].cardMax) : "*"; + var regexp = constraints[i].constraints[j].regexp; + if(max !== 0){ + var title = "min: " + min + " max: " + max + " regular expression: " + constraints[i].regexp; + var name = new NameC("", constraints[i].nametypescopes, constraints[i].constraints[j], + this.__containers__[i][j], min === 0 ? 1 : min, max === "*" ? -1 : max, title); + this.__error__.insert({"before" : name.getFrame()}); + } + } + } + } + else { + // TODO: check already existing contents and order them to the corresponding fields + } + } + catch(err){ + alert("From NameContainerC(): " + err); + } + }, + "getContent" : function(){ + var values = new Array(); + for(var i = 0; i != this.__containers__.length; ++i){ + for(var j = 0; j != this.__containers__[i].length; ++j){ + for(var k = 0; k != this.__containers__[i][j].__frames__.length; ++k){ + if(this.__containers__[i][j].__frames__[k].isUsed() === true){ + values.push(this.__containers__[i][j].__frames__[k].getContent()); + } + } + } + } + return values; + }, + "toJSON" : function(){ + var str = "["; + for(var i = 0; i != this.__containers__.length; ++i){ + for(var j = 0; j != this.__containers__[i].length; ++j){ + for(var k = 0; k != this.__containers__[i][j].__frames__.length; ++k){ + if(this.__containers__[i][j].__frames__[k].isUsed() === true){ + str += this.__containers__[i][j].__frames__[k].toJSON() + ","; + } + } + } + } + if(str.endsWith(",")) str = str.slice(0, str.length - 1); + str += "]"; + return str === "[]" ? null : str; + }, + "isValid" : function(){ + // TODO: check the validity of this frame with the passed constraints and return a boolean value + isValid() of all names + return true; + }}); + + + +var OccurrenceC = Class.create(ContainerC, {"initialize" : function($super, contents, constraints, owner, min, max, cssTitl){ + +}, + "getContent" : function(){ + // TODO: implement + }, + "toJSON" : function(){ + // TODO: implement + }, + "isUsed" : function(){ + // TODO: implement + }, + "showRemoveButton" : function(){ + this.__remove__.show(); + }, + "hideRemoveButton" : function(){ + this.__remove__.hide(); + }, + "showAddButton" : function(){ + this.__add__.show(); + }, + "hideAddButton" : function(){ + this.__add__.hide(); + }, + "isValid" : function(){ + // TODO: check the content and the constraints + return true; + }}); + + + +var OccurrenceContainerC = Class.create(ContainerC, {"initialize" : function($super, contents, constraints){ + +}, + "isValid" : function(){ + // TODO: implement this method + return true; + }, + "getContent" : function(){ + // TODO: implement this method + }, + "toJSON" : function(){ + // TODO: implement this method + }}); + + + + + +var TopicC = Class.create(ContainerC, {"initialize" : function($super, content, constraints){ + $super(); + try{ + this.__frame__ .writeAttribute({"class" : CLASSES.topicFrame()}); + this.__table__ = new Element("table", {"class" : CLASSES.topicFrame()}); + this.__frame__.insert({"top" : this.__table__}); + this.__caption__ = new Element("caption").update("Topic"); + this.__table__.insert({"top" : this.__caption__}); + + // --- topic id + this.__topicid__ = new Object(); + new TextrowC((content ? content.topicid : null), ".*", this.__topicid__, 1, 1, null); + this.__table__.insert({"bottom" : newRow(CLASSES.topicIdFrame(), "Topic ID", this.__topicid__.__frames__[0].getFrame())}); + + // --- itemIdentity + this.__itemIdentity__ = new ItemIdentityC(content ? content.itemIdentities : null); + this.__table__.insert({"bottom" : newRow(CLASSES.itemIdentityFrame(), "ItemIdentity", this.__itemIdentity__.getFrame())}); + + // --- subjectLocator + var _contents = (content ? content.subjectLocators : null); + var _constraints = (constraints ? constraints.subjectLocatorConstraints : null); + this.__subjectLocator__ = new IdentifierC(_contents, _constraints, CLASSES.subjectLocatorFrame()); + this.__table__.insert({"bottom" : newRow(CLASSES.subjectLocatorFrame(), "SubjectLocator", this.__subjectLocator__.getFrame())}); + + // --- subjectIdentifier + _contents = (content ? content.subjectIdentifiers : null); + _constraints = (constraints ? constraints.subjectIdentifierConstraints : null); + this.__subjectIdentifier__ = new IdentifierC(_contents, _constraints, CLASSES.subjectIdentifierFrame()); + this.__table__.insert({"bottom" : newRow(CLASSES.subjectIdentifierFrame(), "SubjectIdentifier", this.__subjectIdentifier__.getFrame())}); + + // --- names + _contents = (content ? content.names : null); + _constraints = (constraints ? constraints.topicNameConstraints : null); + this.__name__ = new NameContainerC(_contents, _constraints); + this.__table__.insert({"bottom" : newRow(CLASSES.nameContainer(), "Names", this.__name__.getFrame())}); + + + + + + + + + + + var tmp = new Element("input", {"type" : "button", "value" : "test"}); + function tester(myself){ + tmp.observe("click", function(event){ + //alert(myself.__subjectLocator__.getContent() + " -> " + myself.__subjectLocator__.toJSON() + "\n\n" + myself.__subjectLocator__.getContent(true, true) + " -> " + myself.__subjectLocator__.toJSON(true, true)); + + }); + }; + tester(this); + this.__frame__.insert({"bottom" : tmp}); + }catch(err){ + alert("From TopciC(): " + err); + } + }, + "getContent" : function(){ + return {"id" : this.__topicid__.__frames__[0].getContent }; + } + }); + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +// --- helper function to create a dom-fragment of the form +// --- description +//---- content +function newRow(rowClass, description, content){ + var tr = new Element("tr", {"class" : rowClass}); + tr.insert({"top" : new Element("td", {"class" : CLASSES.description()}).update(description)}); + tr.insert({"bottom" : new Element("td", {"class" : CLASSES.content()}).update(content)}); + return tr; +} + + +// --- Helper function for the constructors of all classes +// --- of the type FrameC. +// --- There will be set the remome and add handler. +function setRemoveAddHandler(myself, owner, min, max, call){ + myself.__remove__.stopObserving(); + myself.__add__.stopObserving(); + myself.__remove__.observe("click", function(event){ + myself.remove(); + owner.__frames__ = owner.__frames__.without(myself); + if(min >= owner.__frames__.length){ + for(var i = 0; i != owner.__frames__.length; ++i){ + owner.__frames__[i].hideRemoveButton(); + } + } + if(max > owner.__frames__.length){ + for(var i = 0; i != owner.__frames__.length; ++i){ + owner.__frames__[i].showAddButton(); + } + } + }); + + myself.__add__.observe("click", function(event){ + var newElem = call(); + myself.append(newElem.getFrame()); + if(remove === true && min !== -1 && owner.__frames__.length > min){ + for(var i = 0; i != owner.__frames__.length; ++i){ + owner.__frames__[i].showRemoveButton(); + } + } + if(max > -1 && max <= owner.__frames__.length){ + for(var i = 0; i != owner.__frames__.length; ++i){ + owner.__frames__[i].hideAddButton(); + } + } + }); +} + + +// --- Helper function for the constructors of all classes +// --- of the type FrameC. +// --- There will be checked the visibility of the remove and +// --- add buttons. +function checkRemoveAddButtons(owner, min, max){ + if(min >= owner.__frames__.length){ + for(var i = 0; i != owner.__frames__.length; ++i){ + owner.__frames__[i].hideRemoveButton(); + } + } + + if(min > -1 && min < owner.__frames__.length){ + for(var i = 0; i != owner.__frames__.length; ++i){ + owner.__frames__[i].showRemoveButton(); + } + } + + if(max > -1 && max <= owner.__frames__.length){ + for(var i = 0; i != owner.__frames__.length; ++i){ + owner.__frames__[i].hideAddButton(); + } + } +} + + +// --- creates a control row for NameC, OccurrenceC and VariantC with a nested ItemIdentity frame. +function makeControlRow(myself, rowspan, contents) +{ + var tr = new Element("tr", {"class" : CLASSES.itemIdentityFrame()}); + var tdCtrl = new Element("td", {"class" : CLASSES.controlColumn(), "rowspan" : rowspan}); + tr.insert({"top" : tdCtrl}) + var tdDesc = new Element("td", {"class" : CLASSES.description()}).update("ItemIdentity"); + tr.insert({"bottom" : tdDesc}); + var min = new Element("span", {"class" : CLASSES.clickable()}).update("«"); + myself.__min__ = min; + myself.__remove__ = new Element("span", {"class" : CLASSES.clickable()}).update("-"); + myself.__add__ = new Element("span", {"class" : CLASSES.clickable()}).update("+"); + tdCtrl.insert({"top" : min}); + tdCtrl.insert({"bottom" : "
"}); + tdCtrl.insert({"bottom" : myself.__remove__}); + tdCtrl.insert({"bottom" : "
"}); + tdCtrl.insert({"bottom" : myself.__add__}); + var tdCont = new Element("td", {"class" : CLASSES.content()}); + tr.insert({"bottom" : tdCont}); + myself.__itemIdentity__ = new ItemIdentityC(contents ? contents.itemIdentities : null); + tdCont.insert({"top" : myself.__itemIdentity__.getFrame()}); + myself.__table__.insert({"bottom" : tr}); + + var trCtrl = new Element("tr", {"class" : CLASSES.showHiddenRows()}); + trCtrl.insert({"top" : new Element("td", {"class" : CLASSES.clickable()}).update("»")}); + myself.__table__.insert({"top" : trCtrl}); + trCtrl.hide(); + trCtrl.observe("click", function(){ + var trs = myself.__table__.select("tr"); + for(var i = 0; i != trs.length; ++i) trs[i].show(); + trCtrl.hide(); + }); + + // --- min click-handler + min.observe("click", function(event){ + var trs = myself.__table__.select("tr"); + for(var i = 0; i != trs.length; ++i){ + if(i === 0) trs[i].show(); + else trs[i].hide(); + } + }); +} \ No newline at end of file Added: trunk/src/ajax/javascripts/edit.js ============================================================================== --- (empty file) +++ trunk/src/ajax/javascripts/edit.js Tue May 19 05:23:26 2009 @@ -0,0 +1,18 @@ +//+----------------------------------------------------------------------------- +//+ Isidorus +//+ (c) 2008-2009 Marc Kuester, Christoph Ludwig, Lukas Giessmann +//+ +//+ Isidorus is freely distributable under the LGPL license. +//+ This ajax module uses the frameworks PrototypeJs and Scriptaculous, both +//+ are distributed under the MIT license. +//+ You can find a detailed description in trunk/docs/LGPL-LICENSE.txt and +//+ in trunk/src/ajax/javascripts/external/MIT-LICENSE.txt. +//+----------------------------------------------------------------------------- + + +function makeEdit(psi) +{ + var content = new Element("div", {"class" : CLASSES.content()}); + var header = new Element("h1").update("Edit a Topic"); + $(CLASSES.subPage()).insert((content.insert(header, {"position" : "bottom"})), {"position" : "bottom"}); +} Modified: trunk/src/ajax/javascripts/home.js ============================================================================== --- trunk/src/ajax/javascripts/home.js (original) +++ trunk/src/ajax/javascripts/home.js Tue May 19 05:23:26 2009 @@ -10,265 +10,9 @@ //+----------------------------------------------------------------------------- -// --- with this object there will be set the first and last index of topics to get by the ajax request -// --- further this object handles out of range violations and some other site effects, e.g. -// --- topicsPerPage === -1 -> show all topics, ... -var __idx = {"firstIdx" : 0, "lastIdx" : 10, "lastDirectionForward" : true, "topicsPerPage" : 10, "outOfRange" : false, - "topicPerPageVals" : ["5", "10", "15", "25", "50", "100", "200", "300", "All"], - "getTopicPerPageVals" : function(){ return this.topicPerPageVals; }, - "getFirstIdx" : function(){ return this.firstIdx; }, - "setFirstIdx" : function(x) { if(typeof(x) === "number" && x >= 0) this.firstIdx = x; }, - "getLastIdx" : function(){ return this.lastIdx; }, - "setLastIdx" : function(x) { if(typeof(x) === "number" && x >= 0) this.lastIdx = x; }, - "getLastDirectionForward" : function() { return this.lastDirectionForward; }, - "setLastDirectionForward" : function(x) { if(typeof(x) === "boolean") this.lastDirectionForward = x; }, - "getTopicsPerPage" : function() {return (this.topicsPerPage === -1 ? "nil" : this.topicsPerPage); }, - "getTopicsPerPageAsNumber" : function(){ return this.topicsPerPage; }, - "setTopicsPerPage" : function(x) { - if(typeof(x) === "number" && x > 0){ - this.topicsPerPage = x; - this.lastIdx = this.firstIdx + this.topicsPerPage; - } - else if(typeof(x) === "number" && x === -1){ - this.topicsPerPage = x; - this.lastIdx = "nil"; - } - }, - "getOutOfRange" : function() { return this.outOfRange; }, - "setOutOfRange" : function(x){ if(typeof(x) === "boolean") this.outOfRange = x; }, - "next" : function() { - if(this.outOfRange) return; - this.firstIdx += this.topicsPerPage; - if(this.topicsPerPage !== -1){ this.lastIdx = this.firstIdx + this.topicsPerPage; } - else { this.lastIdx = "nil"; } - this.lastDirectionForward = true; - }, - "prev" : function() { - if(this.topicsPerPage !== -1){ - this.firstIdx -= this.topicsPerPage; - if(this.firstIdx < 0)this.firstIdx = 0; - this.lastIdx = this.firstIdx + this.topicsPerPage; - } - else { - this.firstIdx = 0; - this.lastIdx = "nil"; - } - this.lastDirectionForward = false; - } - }; - - - -// --- creates a html table with the id "tableId" and appends it on the element with the id -// --- "parentId", if the variable next ist set to true there will be shown the next -// --- topics otherwise the previous topics -// --- the table looks like the following schema: -// --- itemIdentity | subjectLocator | subjectIdentifier | instanceOf | name | occurrence -function makeHome(parentId, tableId, next) +function makeHome() { - // --- create the ajax-request handlers ------------------------------------ - function onSuccessHandler(xhr) - { - // --- creates the navigation div-element with a forward-, backward- button and a - // --- selection box where the user can choose the amount of topics per page - function createTableNavi(top) - { - // --- creates the backwards and forwards buttons, if they don't exist - if(($("naviDivTop") === null && top === true) || ($("naviDivBottom") === null && top === false) && $(parentId)){ - var div = new Element("div", {"id" : (top ? "naviDivTop" : "naviDivBottom"), "class" : "naviTopicTable " + PAGES.home}); - var lftBtn = new Element("input", {"type" : "button", "id" : (top ? "topicTableLftBtnTop" : "topicTableLftBtnBottom")}); - var rgtBtn = new Element("input", {"type" : "button", "id" : (top ? "topicTableRgtBtnTop" : "topicTableRgtBtnBottom")}); - lftBtn.value = "<<"; - rgtBtn.value = ">>"; - rgtBtn.setStyle({"float" : "right"}); - lftBtn.setStyle({"float" : "left"}); - div.insert(lftBtn, {"position" : "top"}); - div.insert(rgtBtn, {"position" : "bottom"}); - $("content").insert(div, {"position" : "top"}); - - rgtBtn.observe("click", function(event) - { - __idx.next(); - makeHome(parentId, tableId, true); - }); - lftBtn.observe("click", function(event) - { - __idx.prev(); - makeHome(parentId, tableId, false); - }); - - var select = new Element("select", {"id" : (top === true ? "topicTableSelectTop" : "topicTableSelectBottom"), "class" : "topicTable"}); - var selectValues = __idx.getTopicPerPageVals(); - var selectInnerHTML = ""; - selectValues.each(function(value, idx) - { - var numberValue = value; - numberValue = (numberValue === "All" ? "-1" : numberValue); - if(Number(numberValue) !== __idx.getTopicsPerPageAsNumber()){ - select.insert(new Element("option", {"value" : numberValue}).update(value), {"position" : "bottom"}); - } - else { - select.insert(new Element("option", {"value" : numberValue, "selected" : "selected"}).update(value), {"position" : "bottom"}); - } - }); - div.insert(select, {"position" : "content"}); - - select.observe("change", function(event) - { - __idx.setTopicsPerPage(Number(event.element().value)); - makeHome(parentId, tableId, true); - }); - } - } - - - try { - var topicSummaries = xhr.responseText.evalJSON(); - // --- inserts or updates the topic table if there is some json data or - // --- if there isn't a table yet - if(topicSummaries !== null || $(tableId) === null){ - // --- removes the old table - if there exists an element with the id "tableId" - if($(tableId) !== null)$(tableId).remove(); - if($("naviDivTop") !== null)$("naviDivTop").remove(); - if($("naviDivBottom") !== null)$("naviDivBottom").remove(); - - createTableNavi(true); - - // --- creates the html table - var topicTable = new Element("table", {"id" : "topicTable", "class" : PAGES.home}); - - // --- creates the header row - var header = new Element("tr"); - header.insert(new Element("th", {"id" : "itemIdentityTh"}).update("itemIdentity"), {"position" : "bottom"}); - header.insert(new Element("th", {"id" : "subjectLocatorTh"}).update("subjectLocator"), {"position" : "bottom"}); - header.insert(new Element("th", {"id" : "subjectIdentifierTh"}).update("subjectIdentifier"), {"position" : "bottom"}); - header.insert(new Element("th", {"id" : "instanceOfTh"}).update("instanceOf"), {"position" : "bottom"}); - header.insert(new Element("th", {"id" : "nameTh"}).update("name"), {"position" : "bottom"}); - header.insert(new Element("th", {"id" : "occurrenceTh"}).update("occurrence"), {"position" : "bottom"}); - topicTable.insert(header, {"position" : "top"}); - - // --- creates the topic summary data of the json object - if(topicSummaries !== null){ - topicSummaries.each(function(topicSummary, idx) - { - var tr = new Element("tr"); - - - var itemIdentity = new Element("td", {"class" : "topicSummaryTd"}); - var ul = new Element("ul", {"class" : "topicTable"}); - itemIdentity.insert(ul, {"position" : "top"}); - if(topicSummary.itemIdentities){ - topicSummary.itemIdentities.each(function(itemIdentityJ, innerIdx) - { - ul.insert(new Element("li").update(itemIdentityJ), {"position" : "bottom"}); - }); - } - - var subjectLocator = new Element("td", {"class" : "topicSummaryTd"}); - ul = new Element("ul", {"class" : "topicTable"}); - subjectLocator.insert(ul, {"position" : "top"}); - if(topicSummary.subjectLocators){ - topicSummary.subjectLocators.each(function(subjectLocatorJ, innerIdx) - { - ul.insert(new Element("li").update(subjectLocatorJ), {"position" : "bottom"}); - }); - } - - var subjectIdentifier = new Element("td", {"class" : "topicSummaryTd"}); - ul = new Element("ul", {"class" : "topicTable"}); - subjectIdentifier.insert(ul, {"position" : "top"}); - if(topicSummary.subjectIdentifiers){ - topicSummary.subjectIdentifiers.each(function(subjectIdentifierJ, innerIdx) - { - var li = new Element("li", {"class" : "clickable"}).update(subjectIdentifierJ); - ul.insert(li, {"position" : "bottom"}); - li.observe("click", function(event) - { - var node = event.element(); - makePage(PAGES.edit, node.textContent); - }); - }); - } - - var instanceOf = new Element("td", {"class" : "topicSummaryTd"}); - ul = new Element("ul", {"class" : "topicTable"}); - instanceOf.insert(ul, {"position" : "top"}); - if(topicSummary.instanceOfs){ - topicSummary.instanceOfs.each(function(instanceOfJ, innerIdx) - { - if(instanceOfJ){ - instanceOfJ.each(function(psi, psiIdx) - { - ul.insert(new Element("li").update(psi), {"position" : "top"}); - }); - } - }); - } - - var name = new Element("td", {"class" : "topicSummaryTd"}); - ul = new Element("ul", {"class" : "topicTable"}); - name.insert(ul, {"position" : "top"}); - if(topicSummary.names){ - topicSummary.names.each(function(nameJ, innerIdx) - { - ul.insert(new Element("li").update(nameJ), {"position" : "top"}); - }); - } - - var occurrence = new Element("td", {"class" : "topicSummaryTd"}); - ul = new Element("ul", {"class" : "topicTable"}); - occurrence.insert(ul, {"position" : "top"}); - if(topicSummary.occurrences){ - topicSummary.occurrences.each(function(occurrenceJ, innerIdx) - { - ul.insert(new Element("li").update(occurrenceJ), {"position" : "top"}); - }); - } - - tr.insert(itemIdentity, {"position" : "bottom"}); - tr.insert(subjectLocator, {"position" : "bottom"}); - tr.insert(subjectIdentifier, {"position" : "bottom"}); - tr.insert(instanceOf, {"position" : "bottom"}); - tr.insert(name, {"position" : "bottom"}); - tr.insert(occurrence, {"position" : "bottom"}); - - topicTable.insert(tr, {"position" : "bottom"}); - }); - } - } - - // --- there was no data received or not all requested - // --- so it's not allowed to increment the indices of the requested topics - if(topicSummaries === null || topicSummaries.length != __idx.getTopicsPerPage()){ - __idx.setOutOfRange(true); - } - else { - __idx.setOutOfRange(false); - } - - // --- inserts the table in the parent element - if($(parentId)){ - $(parentId).insert(topicTable, {"position" : "top"}); - } - createTableNavi(false); - } - catch(err){ - window.alert("got bad json data from: " + SUMMARY_URL + "\n\n" + err); - } - } - - - function onFailureHandler(xhr) - { - window.alert("something went wrong ...\n" + xhr.status + ": " + xhr.statusText); - } - - - // --- the real ajax request - new Ajax.Request(SUMMARY_URL, - {"method" : "get", - "onSuccess" : onSuccessHandler, - "onFailure" : onFailureHandler, - "parameters" : {"start" : __idx.getFirstIdx(), "end" : __idx.getLastIdx()} - }); -} \ No newline at end of file + var content = new Element("div", {"class" : CLASSES.content()}); + var header = new Element("h1").update("Topic Map Overview"); + $(CLASSES.subPage()).insert((content.insert(header, {"position" : "bottom"})), {"position" : "bottom"}); +} Modified: trunk/src/ajax/javascripts/navi.js ============================================================================== --- trunk/src/ajax/javascripts/navi.js (original) +++ trunk/src/ajax/javascripts/navi.js Tue May 19 05:23:26 2009 @@ -13,49 +13,55 @@ // --- adds some event handlers to the navigation elements function addHandlersToNavi() { - $(PAGES.home).observe("click", function(){ makePage(PAGES.home, ""); }); - $(PAGES.search).observe("click", function(){ makePage(PAGES.search, ""); }); - $(PAGES.edit).observe("click", function(){ makePage(PAGES.edit, ""); }); - $(PAGES.create).observe("click", function(){ makePage(PAGES.create, ""); }); + $(PAGES.home).observe("click", function(event){ setNaviClasses(event.element()); makePage(PAGES.home, ""); }); + $(PAGES.search).observe("click", function(event){ setNaviClasses(event.element()); makePage(PAGES.search, ""); }); + $(PAGES.edit).observe("click", function(event){ setNaviClasses(event.element()); makePage(PAGES.edit, ""); }); + $(PAGES.create).observe("click", function(event){ setNaviClasses(event.element()); makePage(PAGES.create, ""); }); // --- necessary for the first call of the page - makePage(PAGES.home); + makePage(PAGES.home, ""); +} + + +// --- Sets the classes of all navi-elements to the default class. +// --- The currently clicked element is set to "isActive". +function setNaviClasses(activeNaviElement) +{ + $(PAGES.home).writeAttribute({"class" : "clickableButton"}); + $(PAGES.search).writeAttribute({"class" : "clickableButton"}); + $(PAGES.edit).writeAttribute({"class" : "clickableButton"}); + $(PAGES.create).writeAttribute({"class" : "clickableButton"}); + activeNaviElement.writeAttribute({"class" : "isActive"}); } // --- generates the current page depending on the variable __currentPage function makePage(newPage, psi) { + // --- if there is called the subpage which is already displayed + // --- there will be done nothing! + if(newPage === PAGES.current) return; + PAGES.current = newPage; + // --- removes the old content - cleanPage(newPage); + $(CLASSES.subPage()).update(); // --- creates the new content switch(newPage){ case PAGES.home: - makeHome("content", "topicTable", true); + makeHome(); break; case PAGES.search: + makeSearch(psi); break; case PAGES.edit: - makeEdit(psi); + makeEdit(psi) break; case PAGES.create: + makeCreate(psi); break; } } -// --- removes all old DOM-Elements - if the page to create is not -// --- the old page -function cleanPage(newPage) -{ - $("content").childElements().each(function(nodeToDelete, idx) - { - if(!nodeToDelete.hasClassName(newPage)) - nodeToDelete.remove(); - }); -} - - -document.observe("dom:loaded", addHandlersToNavi); - +document.observe("dom:loaded", addHandlersToNavi); \ No newline at end of file Added: trunk/src/ajax/javascripts/requests.js ============================================================================== --- (empty file) +++ trunk/src/ajax/javascripts/requests.js Tue May 19 05:23:26 2009 @@ -0,0 +1,55 @@ +//+----------------------------------------------------------------------------- +//+ Isidorus +//+ (c) 2008-2009 Marc Kuester, Christoph Ludwig, Lukas Giessmann +//+ +//+ Isidorus is freely distributable under the LGPL license. +//+ This ajax module uses the frameworks PrototypeJs and Scriptaculous, both +//+ are distributed under the MIT license. +//+ You can find a detailed description in trunk/docs/LGPL-LICENSE.txt and +//+ in trunk/src/ajax/javascripts/external/MIT-LICENSE.txt. +//+----------------------------------------------------------------------------- + + +// --- This is the default error handler of the used ajax.requests. +function defaultFailureHandler(xhr) +{ + window.alert("Something went wrong by calling \"" + xhr.request.url + "\"\n" + xhr.status + + ": " + xhr.statusText + "\n" + xhr.responseText); +} + + +// --- Gets all type psis from the server. +function getTypePsis(onSuccessHandler, onFailureHandler) +{ + try{ + var onFailure = onFailureHandler ? onFailureHandler : defaultFailureHandler; + + new Ajax.Request(TYPE_PSIS_URL, { + "method" : "get", + "requestHeaders" : ["If-Modified-Since", "Thu, 1 Jan 1970 00:00:00 GMT"], + "onSuccess" : onSuccessHandler, + "onFailure" : onFailure}); + } + catch(err){ + alert("Could not request all type PSIs, please try again!\n\n" + err); + } +} + + +// --- Sends a post-request to the server with the passed psis as postBody. +// --- Gets a constraint-object. +function requestConstraints(psis, onSuccessHandler, onFailureHandler) +{ + try{ + var onFailure = onFailureHandler ? onFailureHandler : defaultFailureHandler; + + new Ajax.Request(TMCL_TYPE_URL, { + "method" : "post", + "postBody" : psis, + "onSuccess" : onSuccessHandler, + "onFailure" : onFailure}); + } + catch(err){ + alert("Could not request contraints, please try again!\n\n" + err); + } +} \ No newline at end of file Added: trunk/src/ajax/javascripts/search.js ============================================================================== --- (empty file) +++ trunk/src/ajax/javascripts/search.js Tue May 19 05:23:26 2009 @@ -0,0 +1,18 @@ +//+----------------------------------------------------------------------------- +//+ Isidorus +//+ (c) 2008-2009 Marc Kuester, Christoph Ludwig, Lukas Giessmann +//+ +//+ Isidorus is freely distributable under the LGPL license. +//+ This ajax module uses the frameworks PrototypeJs and Scriptaculous, both +//+ are distributed under the MIT license. +//+ You can find a detailed description in trunk/docs/LGPL-LICENSE.txt and +//+ in trunk/src/ajax/javascripts/external/MIT-LICENSE.txt. +//+----------------------------------------------------------------------------- + + +function makeSearch(psi) +{ + var content = new Element("div", {"class" : CLASSES.content()}); + var header = new Element("h1").update("Search a Topic"); + $(CLASSES.subPage()).insert((content.insert(header, {"position" : "bottom"})), {"position" : "bottom"}); +} Added: trunk/src/ajax/javascripts/tmcl_tools.js ============================================================================== --- (empty file) +++ trunk/src/ajax/javascripts/tmcl_tools.js Tue May 19 05:23:26 2009 @@ -0,0 +1,66 @@ +//+----------------------------------------------------------------------------- +//+ Isidorus +//+ (c) 2008-2009 Marc Kuester, Christoph Ludwig, Lukas Giessmann +//+ +//+ Isidorus is freely distributable under the LGPL license. +//+ This ajax module uses the frameworks PrototypeJs and Scriptaculous, both +//+ are distributed under the MIT license. +//+ You can find a detailed description in trunk/docs/LGPL-LICENSE.txt and +//+ in trunk/src/ajax/javascripts/external/MIT-LICENSE.txt. +//+----------------------------------------------------------------------------- + + +// --- Returns an Array of the type [, ]. +// --- If there are exclusive-instance-constraints, the return value is an array +// --- of the form [false, "message"] otherwise [true, ""]. +function checkExclusiveInstances(constraints, psis){ + try{ + var exc = constraints.topicConstraints.exclusiveInstances; + var ret = new Array(); + for(var i = 0; i !== psis.length; ++i){ + var currentArray = new Array(psis[i]); + for(var j = 0; j !== exc.length; ++j){ + for(var k = 0; k !== exc[j].exclusives.length; ++k){ + for(var l = 0; l !== exc[j].exclusives[k].length; ++l){ + if(exc[j].exclusives[k][l] === psis[i]){ + for(var m = 0; m != exc[j].owner.length; ++m){ + currentArray.push(exc[j].owner[m]); + } + break; + } + } + } + } + + if(currentArray.length > 1)ret.push(currentArray); + } + if(ret.length === 0) return null; + return ret; + } + catch(err){ + return null; + } +} + + +// --- checks SubjectLocator and SubjectIdentifier contraints and contents +function checkIdentifierConstraints(contents, constraints) +{ + var innerConstents = (!contents ? new Array() : contents); + if((!constraints || constraints.length === 0) && innerConstraints.length === 0) return false; + + for(var i = 0; i != constraints.length; ++i){ + var regexp = constraints[i].regexp; + var min = constraints[i].cardMin; + var max = constraints[i].cardMax; + + var foundContents = 0; + for(var j = 0; j != innerContents.length; ++j){ + var rex = new RegExp(regexp); + if(rex.match(innerContents[j]) === true) ++foundContents; + } + + if(foundContents < min || foundContents > max) return false; + } + return true; +} \ No newline at end of file Modified: trunk/src/json/json_tmcl.lisp ============================================================================== --- trunk/src/json/json_tmcl.lisp (original) +++ trunk/src/json/json_tmcl.lisp Tue May 19 05:23:26 2009 @@ -13,21 +13,32 @@ ;; ============================================================================= ;; --- all fragment constraints ------------------------------------------------ ;; ============================================================================= -(defun get-constraints-of-fragment(topic-psi &key (treat-as 'type)) +(defun get-constraints-of-fragment(topic-psis &key (treat-as 'type)) + "Returns a json string with all constraints of this topic-psis. + topic-psis must contain one item if it is treated as instance other wiese there can be more psis + then the fragment will be treated as an instanceOf all passed psis." (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 + (topics nil)) + (when (and (not (eql treat-as 'type)) + (> (length topic-psis) 1)) + (error "From get-constraints-of-fragment: when treat-as is set ot instance there must be exactly one item in topic-psis!")) + + (loop for topic-psi in topic-psis + do (let ((psi + (elephant:get-instance-by-value 'PersistentIdC 'uri topic-psi))) + (if psi + (pushnew (identified-construct psi) topics) + (error "Topic \"~a\" not found!" topic-psi)))) + (when topics (let ((topic-constraints (let ((value - (get-constraints-of-topic topic :treat-as treat-as))) + (get-constraints-of-topic topics :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))) + (remove-duplicates + (loop for topic in topics + append (get-available-associations-of-topic topic :treat-as treat-as))))) (dolist (item available-associations) (topictype-p item associationtype associationtype-constraint)) (let ((associations-constraints @@ -46,6 +57,40 @@ (concatenate 'string "{" topic-constraints "," associations-constraints "}"))) json-string))))))) + +;(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))))))) ;; ============================================================================= @@ -351,37 +396,77 @@ ;; ============================================================================= ;; --- 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))) +(defun get-constraints-of-topic (topic-instances &key(treat-as 'type)) + "Returns a constraint list with the constraints: + subjectidentifier-constraints, subjectlocator-constraints, + topicname-constraints, topicoccurrence-constraints and + uniqueoccurrence-constraints. + topic-instances should be a list with exactly one item if trea-as is set to type + otherwise it can constain more items." + (declare (list topic-instances)) + (when (and (> (length topic-instances) 1) + (not (eql treat-as 'type))) + (error "From get-constraints-of-topic: topic-instances must contain exactly one item when treated as instance!")) + (let ((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 topic-instance in topic-instances + do (let ((current-constraints + (get-all-constraint-topics-of-topic topic-instance :treat-as treat-as))) + (dolist (item (getf current-constraints :abstract-topictype-constraints)) + (pushnew item abstract-topictype-constraints)) + (dolist (item (getf current-constraints :exclusive-instance-constraints)) + (let ((current-list + (list topic-instance (list item)))) + (let ((found-item + (find current-list exclusive-instance-constraints :key #'first))) + (if found-item + (dolist (inner-item (second current-list)) + (pushnew inner-item (second found-item))) + (push current-list exclusive-instance-constraints))))) + (dolist (item (getf current-constraints :subjectidentifier-constraints)) + (pushnew item subjectidentifier-constraints)) + (dolist (item (getf current-constraints :subjectlocator-constraints)) + (pushnew item subjectlocator-constraints)) + (dolist (item (getf current-constraints :topicname-constraints)) + (pushnew item topicname-constraints)) + (dolist (item (getf current-constraints :topicoccurrence-constraints)) + (pushnew item topicoccurrence-constraints)) + (dolist (item (getf current-constraints :uniqueoccurrence-constraints)) + (pushnew item uniqueoccurrence-constraints)))) (let ((exclusive-instance-constraints - (let ((value - (get-exclusive-instance-constraints (getf constraint-topics :exclusive-instance-constraints)))) + (let ((value "[")) + (loop for exclusive-instance-constraint in exclusive-instance-constraints + do (setf value (concatenate 'string value + (get-exclusive-instance-constraints (first exclusive-instance-constraint) + (second exclusive-instance-constraint)) ","))) + (if (string= value "[") + (setf value "null") + (setf value (concatenate 'string (subseq value 0 (- (length value) 1)) "]"))) (concatenate 'string "\"exclusiveInstances\":" value))) (subjectidentifier-constraints (let ((value - (get-simple-constraints (getf constraint-topics :subjectidentifier-constraints) :error-msg-constraint-name "subjectidentifier"))) + (get-simple-constraints 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"))) + (get-simple-constraints subjectlocator-constraints :error-msg-constraint-name "subjectlocator"))) (concatenate 'string "\"subjectLocatorConstraints\":" value))) (topicname-constraints (let ((value - (get-topicname-constraints (getf constraint-topics :topicname-constraints)))) + (get-topicname-constraints topicname-constraints))) (concatenate 'string "\"topicNameConstraints\":" value))) (topicoccurrence-constraints (let ((value - (get-topicoccurrence-constraints (getf constraint-topics :topicoccurrence-constraints) - (getf constraint-topics :uniqueoccurrence-constraints)))) + (get-topicoccurrence-constraints topicoccurrence-constraints uniqueoccurrence-constraints))) (concatenate 'string "\"topicOccurrenceConstraints\":" value))) (abstract-constraint (concatenate 'string "\"abstractConstraint\":" - (if (getf constraint-topics :abstract-constraint) + (if abstract-topictype-constraints "true" "false")))) (let ((json-string @@ -390,12 +475,50 @@ topicoccurrence-constraints "," abstract-constraint "}"))) json-string)))) - -(defun get-exclusive-instance-constraints(exclusive-instances-lists) - "Returns a list of psis which represents some topics." +;(defun get-constraints-of-topic (topic-instances &key(treat-as 'type)) +; (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-topictype-constraints) +; "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(owner exclusive-instances-lists) + "Returns a JSON-obejct of the following form: + {owner: [psi-1, psi-2], exclusives: [[psi-1-1, psi-1-2], [psi-2-1, <...>], <...>]}." (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*))) + (topictype-role (get-item-by-psi *topictype-role-psi*)) + (topictype (get-item-by-psi *topictype-psi*)) + (topictype-constraint (get-item-by-psi *topictype-constraint-psi*))) (let ((topics (remove-duplicates (loop for exclusive-instances-list in exclusive-instances-lists @@ -408,10 +531,13 @@ 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)))))) + ;collect (player other-role))))))))) + append (getf (list-subtypes (player other-role) topictype topictype-constraint) :subtypes))))))))) + (concatenate 'string "{\"owner\":" (json-exporter::identifiers-to-json-string owner) + ",\"exclusives\":" + (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")) @@ -456,7 +582,7 @@ (defun get-topicname-constraints(constraint-topics) "Returns all topicname constraints as a list of the following form: [{nametypescopes:[{nameType: [psi-1, psi-2], scopeConstraints: []}, - {nameType: [subtype-1-psi-1], scopeConstriants: []}, + {nameType: [subtype-1-psi-1], scopeConstraints: []}, constraints: [, <...>]}, <...>]." (let ((constraint-role (get-item-by-psi *constraint-role-psi*)) @@ -742,7 +868,7 @@ (defun get-constraint-occurrence-value(topic &key (what 'regexp)) "Checks the occurrence-value of a regexp, card-min or card-max - constriant-occurrence. + constraint-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 @@ -905,7 +1031,7 @@ :uniqueoccurrence-constraints uniqueoccurrence-constraints))) -(defmethod get-all-constraint-topics-of-topic (topic-instance &key (treat-as 'type)) +(defun 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. Modified: trunk/src/json/json_tmcl_validation.lisp ============================================================================== --- trunk/src/json/json_tmcl_validation.lisp (original) +++ trunk/src/json/json_tmcl_validation.lisp Tue May 19 05:23:26 2009 @@ -30,7 +30,7 @@ (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))) + (topictype-of-p (player other-role) abstract-topictype-constraint)) return t)))) 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 Tue May 19 05:23:26 2009 @@ -15,8 +15,8 @@ (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/topicstubs/(.+)$") ;the json prefix for getting some topic stub information of a topic -(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 *json-get-type-tmcl-url* "/json/tmcl/type/?$") ;the json url for getting some tmcl information of a topic treated as a type +(defparameter *json-get-instance-tmcl-url* "/json/tmcl/instance/?$") ;the json url 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 @@ -30,8 +30,8 @@ (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*) + (json-get-type-tmcl-url *json-get-type-tmcl-url*) + (json-get-instance-tmcl-url *json-get-instance-tmcl-url*) (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*) @@ -84,12 +84,14 @@ (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))) + (create-regex-dispatcher json-get-type-tmcl-url #'(lambda(&optional param) + (declare (ignorable param)) + (return-tmcl-info-of-psis 'json-tmcl::type))) hunchentoot:*dispatch-table*) (push - (create-regex-dispatcher json-get-instance-tmcl-prefix #'(lambda(&optional psi) - (return-tmcl-info-of-psi 'json-tmcl::instance psi))) + (create-regex-dispatcher json-get-instance-tmcl-url #'(lambda(&optional param) + (declare (ignorable param)) + (return-tmcl-info-of-psis 'json-tmcl::instance))) hunchentoot:*dispatch-table*) (push (create-regex-dispatcher json-commit-url #'json-commit) @@ -102,6 +104,8 @@ ;; --- some handlers for the json-rest-interface ------------------------------- ;; ============================================================================= (defun return-all-tmcl-types(&optional param) + "Returns all topics that are valid types -> so they have to be valid to the + topictype-constraint (if it exists) and the can't be abstract." (declare (ignorable param)) (handler-case (let ((all-topics (elephant:get-instances-by-class 'd:TopicC)) @@ -150,29 +154,55 @@ (format nil "Condition: Topic \"~a\" not found" psi))))) -(defun return-tmcl-info-of-psi(treat-as &optional psi) +(defun return-tmcl-info-of-psis(treat-as) "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)))) + (let ((http-method (hunchentoot:request-method*))) + (if (or (eq http-method :POST) + (eq http-method :PUT)) + (let ((external-format (flexi-streams:make-external-format :UTF-8 :eol-style :LF))) + (let ((json-data (hunchentoot:raw-post-data :external-format external-format :force-text t))) + (handler-case (let ((psis + (json:decode-json-from-string json-data))) + (let ((tmcl + (json-tmcl:get-constraints-of-fragment psis :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." psis))))) (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+)))) + (format nil "Condition: \"~a\"" err)))))) + (setf (hunchentoot:return-code*) hunchentoot:+http-bad-request+)))) + +;(defun return-tmcl-info-of-psis(treat-as &otptional psi) +; "Returns a json string which represents the defined tmcl-constraints of the +; topic and the associations where this topic can be a player." +; (alert 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." psis)))) +; (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) Modified: trunk/src/unit_tests/poems.xtm ============================================================================== --- trunk/src/unit_tests/poems.xtm (original) +++ trunk/src/unit_tests/poems.xtm Tue May 19 05:23:26 2009 @@ -1,90 +1,5 @@ - - - - - - - - - - - - - - - - - - - - 1 - - - - - - 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -678,6 +593,84 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -694,6 +687,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -728,6 +749,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + @@ -797,9 +842,69 @@ - - - + + + + + + + 1 + + + + 1 + + + + ^http://some.where/psis/region/.+$ + + + + + + + + + + + + + + + + + + + + + + 1 + + + + 1 + + + + ^http://some.where/psis/country/.+$ + + + + + + + + + + + + + + + + + + @@ -819,7 +924,7 @@ - + @@ -831,7 +936,7 @@ - + @@ -839,15 +944,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + - + - - - + + @@ -867,7 +996,7 @@ - + @@ -879,7 +1008,7 @@ - + @@ -887,8 +1016,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + - + - - - - - - - - + + + + - 0 + 1 @@ -1051,11 +1197,11 @@ - + - + @@ -1063,7 +1209,150 @@ - + + + + + + + + + + + + + + + 1 + + + + 2 + + + + ^.+$ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1 + + + + 2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + + + + 1 + + + + ^.+$ + + + + + + + + + + + + + + + + + + + + @@ -1137,57 +1426,824 @@ - - - - - - - http://www.w3.org/2001/XMLSchema#string - - - + + + + + + + http://www.w3.org/2001/XMLSchema#string + + + + + + + + + + + + + + + + + + + + + + 1 + + + + 1 + + + + ^.*$ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1 + + + + 2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1 + + + + 1 + + + + ^.+$ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + http://www.w3.org/2001/XMLSchema#unsignedLong + + + + + + + + + + + + + + + + + + + + + + + + + + + 1 + + + + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1 + + + + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1 + + + + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1 + + + + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1 + + + + + + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1 + + + + + + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1 + + + + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1 + + + + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1 + + + + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1 + + + + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1 + + + + + + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - + + - - - - + + + - + + + 1 - + + + 1 - - - ^.*$ - - + - - + + @@ -1195,37 +2251,23 @@ - + - - + + - - - - - - - - 1 - - - - 2 - - - + - - + + @@ -1233,11 +2275,11 @@ - + - - + + @@ -1245,27 +2287,20 @@ - + - - + + - - - - - - - - - + + + + @@ -1281,11 +2316,11 @@ - + - + @@ -1293,17 +2328,17 @@ - + - + - - - + + + @@ -1319,11 +2354,11 @@ - + - + @@ -1331,11 +2366,11 @@ - + - + @@ -1343,19 +2378,17 @@ - + - + - - - - + + + @@ -1371,11 +2404,11 @@ - + - + @@ -1383,17 +2416,17 @@ - + - + - - - + + + @@ -1409,11 +2442,11 @@ - + - + @@ -1421,11 +2454,11 @@ - + - + @@ -1433,27 +2466,20 @@ - + - + - - - - - + + + @@ -1473,11 +2499,11 @@ - + - + @@ -1485,11 +2511,11 @@ - + - + @@ -1497,11 +2523,11 @@ - + - + @@ -1509,11 +2535,11 @@ - + - + @@ -1521,16 +2547,16 @@ - + - + - - + + @@ -1550,11 +2576,11 @@ - + - + @@ -1562,11 +2588,11 @@ - + - + @@ -1574,11 +2600,11 @@ - + - + @@ -1586,11 +2612,11 @@ - + - + @@ -1598,17 +2624,131 @@ - + - + + + + + + + Deutschland + + + + Germany + + + + + + + + + Polen + + + + Poland + + + + + + + + + Frankfurt am Main + + + + 659021 + + + + + + + + + + + + + + + + + + + + + Marbach am Neckar + + + + 15601 + + + + + + + + + + + + + + + + + + + + + Lubowitz + + + + 365 + + + + + + + + + + + + + + + + + + + + + Joseph Karl Benedikt + + + + von Eichendorff + + + @@ -1627,6 +2767,18 @@ + + + + + + + + + + + + @@ -1644,15 +2796,23 @@ + + + + + + + + + + + + - - + Der Zauberlehrling @@ -1826,10 +2986,6 @@ - @@ -1854,4 +3010,187 @@ + + + + + + Resignation - Eine Phantasie + + + + + Auch ich war in Arkadien geboren, +Auch mir hat die Natur +An meiner Wiege Freude zugeschworen, +Auch ich war in Arkadien geboren, +Doch Tr?nen gab der kurze Lenz mir nur. + +Des Lebens Mai bl?ht einmal und nicht wieder, +Mir hat er abgebl?ht. +Der stille Gott - o weinet, meine Br?der - +Der stille Gott taucht meine Fackel nieder, +Und die Erscheinung flieht. + +Da steh ich schon auf deiner Schauerbr?cke, +Ehrw?rdge Geistermutter - Ewigkeit. +Empfange meinen Vollmachtbrief zum Gl?cke, +Ich bring ihn unerbrochen dir zur?cke, +Mein Lauf ist aus. Ich wei? von keiner Seligkeit. + +Vor deinem Thron erheb ich meine Klage, +Verh?llte Richterin. +Auf jenem Stern ging eine frohe Sage, +Du thronest hier mit des Gerichtes Waage +Und nennest dich Vergelterin. + +Hier - spricht man - warten Schrecken auf den B?sen, +Und Freuden auf den Redlichen. +Des Herzens Kr?mmen werdest du entbl??en, +Der Vorsicht R?tsel werdest du mir l?sen +Und Rechnung halten mit dem Leidenden. + +Hier ?ffne sich die Heimat dem Verbannten, +Hier endige des Dulders Dornenbahn. +Ein G?tterkind, das sie mir Wahrheit nannten, +Die meisten flohen, wenige nur kannten, +Hielt meines Lebens raschen Z?gel an. + +?Ich zahle dir in einem andern Leben, +Gib deine Jugend mir! +Nichts kann ich dir als diese Weisung geben.? +Ich nahm die Weisung auf das andre Leben, +Und meiner Jugend Freuden gab ich ihr. + +?Gib mir das Weib, so teuer deinem Herzen, +Gib deine Laura mir. +Jenseits der Gr?ber wuchern deine Schmerzen.? - +Ich ri? sie blutend aus dem wunden Herzen +Und weinte laut und gab sie ihr. + +?Du siehst die Zeit nach jenen Ufern fliegen, +Die bl?hende Natur +Bleibt hinter ihr - ein welker Leichnam - liegen. +Wenn Erd und Himmel tr?mmernd auseinanderfliegen, +Daran erkenne den erf?llten Schwur.? + +?Die Schuldverschreibung lautet an die Toten?, +Hohnl?chelte die Welt, +?Die L?gnerin, gedungen von Despoten, +Hat f?r die Wahrheit Schatten dir geboten, +Du bist nicht mehr, wenn dieser Schein verf?llt.? + +Frech witzelte das Schlangenheer der Sp?tter: +?Vor einem Wahn, den nur Verj?hrung weiht, +Erzitterst du? Was sollen deine G?tter, +Des kranken Weltplans schlau erdachte Retter, +Die Menschenwitz des Menschen Notdurft leiht? + +Ein Gaukelspiel, ohnm?chtigen Gew?rmen +Vom M?chtigen geg?nnt, +Schreckfeuer, angesteckt auf hohen T?rmen, +Die Phantasie des Tr?umers zu best?rmen, +Wo des Gesetzes Fackel dunkel brennt. + +Was hei?t die Zukunft, die uns Gr?ber decken? +Die Ewigkeit, mit der du eitel prangst? +Ehrw?rdig nur, weil schlaue H?llen sie verstecken, +Der Riesenschatten unsrer eignen Schrecken +Im hohlen Spiegel der Gewissensangst; + +Ein L?genbild lebendiger Gestalten, +Die Mumie der Zeit, +Vom Balsamgeist der Hoffnung in den kalten +Behausungen des Grabes hingehalten, +Das nennt dein Fieberwahn - Unsterblichkeit? + +F?r Hoffnungen - Verwesung straft sie L?gen - +Gabst du gewisse G?ter hin? +Sechstausend Jahre hat der Tod geschwiegen, +Kam je ein Leichnam aus der Gruft gestiegen, +Der Meldung tat von der Vergelterin?" - + +Ich sah die Zeit nach deinen Ufern fliegen, +Die bl?hende Natur +Blieb hinter ihr, ein welker Leichnam, liegen, +Kein Toter kam aus seiner Gruft gestiegen, +Und fest vertraut ich auf den G?tterschwur. + +All meine Freuden hab ich dir geschlachtet, +Jetzt werf ich mich vor deinen Richterthron. +Der Menge Spott hab ich beherzt verachtet, +Nur deine G?ter hab ich gro? geachtet, +Vergelterin, ich fodre meinen Lohn. + +"Mit gleicher Liebe lieb ich meine Kinder!" +Rief unsichtbar ein Genius. +"Zwei Blumen", rief er, "- h?rt es, Menschenkinder - +Zwei Blumen bl?hen f?r den weisen Finder, +Sie hei?en Hoffnung und Genu?. + +Wer dieser Blumen eine brach, begehre +Die andre Schwester nicht. +Genie?e, wer nicht glauben kann. Die Lehre +Ist ewig wie die Welt. Wer glauben kann, entbehre. +Die Weltgeschichte ist das Weltgericht. + +Du hast gehofft, dein Lohn ist abgetragen, +Dein Glaube war dein zugewognes Gl?ck. +Du konntest deine Weisen fragen, +Was man von der Minute ausgeschlagen, +Gibt keine Ewigkeit zur?ck." + + + + + + + + + + + + + + + + + + + + + Mondnacht + + + + + Es war, als h?tt' der Himmel +Die Erde still gek?sst, +Dass sie im Bl?tenschimmer +Von ihm nun tr?umen m?sst'. + +Die Luft ging durch die Felder, +Die ?hren wogten sacht, +Es rauschten leis' die W?lder, +So sternklar war die Nacht. + +Und meine Seele spannte +Weit ihre Fl?gel aus, +Flog durch die stillen Lande, +Als fl?ge sie nach Haus. + + + + + + + + + + + + + + + From lgiessmann at common-lisp.net Sun May 31 13:08:01 2009 From: lgiessmann at common-lisp.net (Lukas Giessmann) Date: Sun, 31 May 2009 09:08:01 -0400 Subject: [isidorus-cvs] r32 - in trunk: docs src/ajax/javascripts src/json src/rest_interface src/unit_tests src/xml Message-ID: Author: lgiessmann Date: Sun May 31 09:08:00 2009 New Revision: 32 Log: some fixes in the json-tmcl module and the json-data-model, some new developments in the ajax module Added: trunk/docs/JSON_model.pdf (contents, props changed) Modified: trunk/docs/xtm_json.txt trunk/src/ajax/javascripts/constants.js trunk/src/ajax/javascripts/create.js trunk/src/ajax/javascripts/datamodel.js trunk/src/json/json_tmcl.lisp trunk/src/json/json_tmcl_validation.lisp trunk/src/rest_interface/set-up-json-interface.lisp trunk/src/unit_tests/poems.xtm trunk/src/xml/setup.lisp Added: trunk/docs/JSON_model.pdf ============================================================================== Binary file. No diff available. Modified: trunk/docs/xtm_json.txt ============================================================================== --- trunk/docs/xtm_json.txt (original) +++ trunk/docs/xtm_json.txt Sun May 31 09:08:00 2009 @@ -1,4 +1,4 @@ -//+----------------------------------------------------------------------------- +?//+----------------------------------------------------------------------------- //+ Overview: //+ *Part 1: XTM - data model //+ *Part 2: Object summaries @@ -6,8 +6,6 @@ //+----------------------------------------------------------------------------- - - //+----------------------------------------------------------------------------- //+ Part 1: XTM - data model: //+ The first part describes the xtm's data model, here will be all elements @@ -112,7 +110,6 @@ "roles" : [ { }, { <...> } ] } - //+----------------------------------------------------------------------------- //+ topicStub //+----------------------------------------------------------------------------- @@ -173,7 +170,6 @@ } - //+----------------------------------------------------------------------------- //+ Part 3: TMCL - data model //+ This part explains how the tmcl-rules/suggestions of isidorus are @@ -198,13 +194,13 @@ //+ 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 +//+ element, this member contains an unsignedInt 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" + "cardMax" : "unsigned integer in string representation or the string MAX_INT" } @@ -214,7 +210,7 @@ //+ 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 +//+ subjectIdentifier, this member contains an unsignedInt or the string //+ "MAX_INT". //+----------------------------------------------------------------------------- @@ -226,7 +222,7 @@ //+ 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 +//+ subjectLocator, this member contains an unsignedInt or the string //+ "MAX_INT". //+----------------------------------------------------------------------------- @@ -246,7 +242,7 @@ { "scopeTypes" : [ [ [ "psi-1-1", "psi-1-2", "..." ], [ "subtype-psi-1", "..." ], <...> ], [ "psi-2-1" "..."], <...> ], "cardMin" : "unsigned integer in string representation", - "cardMax" : "unsigend integer in string representation or the string MAX_INT" + "cardMax" : "unsigned integer in string representation or the string MAX_INT" } @@ -254,13 +250,20 @@ //+ topicNameConstraint //+ nametypescope constains the original nametype and all valid subtypes //+ with the specific scope constraints. -//+ constriants contains the constraints for the owner topic. +//+ constraints contains the constraints for the owner topic. +//+ Note scopeConstraints is a list, because, the can be more scope +//+ constriants, e.g. one constraints wants 2 scopes of the type "en", and +//+ "de", and another, wants 3 scopes of the type "fr", "pl" and "sp". //+----------------------------------------------------------------------------- { "nametypescopes" : [ { "nameType" : [psi-1, psi-2, "..." ], "scopeConstraints" : [ ] }, + { + "nameType" : [subtype-1-psi-1, subtype-1-psi-2, "..." ], + "scopeConstraints" : [ ] + }, <...> ] "constraints" : [ , < ... > ] @@ -299,10 +302,15 @@ "scopeConstraints" : [ ], "datatypeConstraint" : "datatype" }, + { + "occurrenceType" : [ "subtype-1-psi-1", "subtype-1-psi-2", "..." ], + "scopeConstraints" : [ ], + "datatypeConstraint" : "datatype" + }, <...> ], "constraints" : [ , <...>], - "uniqueConstraint" : [ , <...> ] + "uniqueConstraints" : [ , <...> ] } @@ -316,7 +324,7 @@ { "roleType" : [ [ "topic-psi-1", "topic-psi-2", "..." ], ["subtype-1-psi-1", "..."], <...> ], "cardMin" : "unsigned integer in string representation", - "cardMax" : "unsigend integer in string representation or the string MAX_INT" + "cardMax" : "unsigned integer in string representation or the string MAX_INT" } @@ -335,7 +343,7 @@ "players" : [ [ "topic-psi-1", "topic-psi-2", "..." ], [ "topic-2-psi-1", "..."], <...> ] "roleTypes" : [ [ "topic-psi-1", "topic-psi-2", "..." ], [ "subtype-psi-1", "..." ], <...> ], "cardMin" : "unsigned integer in string representation", - "cardMax" : "unsigend integer in string representation or the string MAX_INT" + "cardMax" : "unsigned integer in string representation or the string MAX_INT" } @@ -353,7 +361,7 @@ "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" + "cardMax" : "unsigned integer in string representation or the string MAX_INT" } @@ -368,6 +376,7 @@ //+ associationTypeScopes contains all available scopes for this association. //+----------------------------------------------------------------------------- { + "associationType" : [ "topic-psi-1", "topic-psi-2" ], "associationRoleConstraints" : [ , <...> ], "rolePlayerConstraints" : [ , <...> ], "otherRoleConstraints" : [ , <...> ], @@ -378,6 +387,8 @@ //+----------------------------------------------------------------------------- //+ topicConstraint //+ The topicConstraint contains the members: +//+ *exclusiveInstances which contains a topic-list of topic-psis depending +//+ on the users exclusive-instance-constraints //+ *subjectIdentifierConstraints which defines the subjectIdentifiers //+ *subjectLocatorConstraints which defines the subjectLocators //+ *topicNameConstraints which defines the topic names @@ -398,9 +409,7 @@ //+----------------------------------------------------------------------------- //+ 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. +//+ fragment. //+ topicConstraint contains an object with all constraints of all baseTypes //+ of the mainTopic. //+ associationConstraints contains a list of all association constraints Modified: trunk/src/ajax/javascripts/constants.js ============================================================================== --- trunk/src/ajax/javascripts/constants.js (original) +++ trunk/src/ajax/javascripts/constants.js Sun May 31 09:08:00 2009 @@ -59,10 +59,18 @@ "__trShowHiddenRows__" : "showHiddenRows", "__trTypeFrame__" : "typeFrame", "__divScopeFrame__" : "scopeFrame", + "__divScopeContainer__" : "scopeContainer", "__divValueFrame__" : "valueFrame", "__divVariantFrame__" : "variantFrame", "__divVariantContainer__" : "variantContainer", "__divDatatypeFrame__" : "datatypeFrame", + "__divOccurrenceContainer__" : "occurrenceContainer", + "__divOccurrenceFrame__" : "occurrenceFrame", + "__divAssociationContainer__" : "associationContainer", + "__divAssociationFrame__" : "associationFrame", + "__divRoleContainer__" : "roleContainer", + "__divRoleFrame__" : "roleFrame", + "__divPlayerFrame__" : "playerFrame", "page" : function(){ return this.__divPage__; }, "subPage" : function(){ return this.__divSubPage__; }, @@ -88,8 +96,16 @@ "showHiddenRows" : function(){ return this.__trShowHiddenRows__; }, "typeFrame" : function(){ return this.__trTypeFrame__; }, "scopeFrame" : function(){ return this.__divScopeFrame__; }, + "scopeContainer" : function(){ return this.__divScopeContainer__; }, "valueFrame" : function(){ return this.__divValueFrame__; }, "variantFrame" : function(){ return this.__divVariantFrame__; }, "variantContainer" : function(){ return this.__divVariantContainer__; }, - "datatypeFrame" : function(){ return this.__divDatatypeFrame__; } + "datatypeFrame" : function(){ return this.__divDatatypeFrame__; }, + "occurrenceContainer" : function(){ return this.__divOccurrenceContainer__; }, + "occurrenceFrame" : function(){ return this.__divOccurrenceFrame__; }, + "associationContainer" : function(){ return this.__divAssociationContainer__; }, + "associationFrame" : function(){ return this.__divAssociationFrame__; }, + "roleContainer" : function(){ return this.__divRoleContainer__; }, + "roleFrame" : function(){ return this.__divRoleFrame__; }, + "playerFrame" : function(){ return this.__divPlayerFrame__; } }; \ No newline at end of file Modified: trunk/src/ajax/javascripts/create.js ============================================================================== --- trunk/src/ajax/javascripts/create.js (original) +++ trunk/src/ajax/javascripts/create.js Sun May 31 09:08:00 2009 @@ -31,8 +31,18 @@ items[i].remove(); } + items = $$("li." + CLASSES.associationContainer()); + for(var i = 0; i != items.length; ++i){ + items[i].remove(); + } + var topic = new TopicC(null, (constraints ? constraints.topicConstraints : null)); - context.insert({"after" : new Element("li", {"class" : CLASSES.topicFrame()}).update(topic.getFrame())}); + var liT = new Element("li", {"class" : CLASSES.topicFrame()}).update(topic.getFrame()); + context.insert({"after" : liT}); + + var associations = new AssociationContainerC(null, (constraints ? constraints.associationsConstraints : null)); + var liA = new Element("li", {"class" : CLASSES.associationContainer()}).update(associations.getFrame()); + liT.insert({"after" : liA}); } function onSuccessHandler(xhr){ Modified: trunk/src/ajax/javascripts/datamodel.js ============================================================================== --- trunk/src/ajax/javascripts/datamodel.js (original) +++ trunk/src/ajax/javascripts/datamodel.js Sun May 31 09:08:00 2009 @@ -182,6 +182,18 @@ }, "remove" : function(){ this.getFrame().remove(); + }, + "showRemoveButton" : function(){ + try{ this.__remove__.show(); } catch(err) {} + }, + "hideRemoveButton" : function(){ + try{ this.__remove__.hide(); } catch(err) {} + }, + "showAddButton" : function(){ + try{ this.__add__.show(); } catch(err) {} + }, + "hideAddButton" : function(){ + try{ this.__add__.hide(); } catch(err) {} }}); @@ -291,36 +303,37 @@ // --- Representation of a subjectLocator and subjectIdentifier frames. var IdentifierC = Class.create(ContainerC, {"initialize" : function($super, contents, constraints, cssClass){ - $super(); - this.__frame__.writeAttribute({"class" : cssClass}); - this.__containers__ = new Array(); - - try{ - if((!contents || contents.length === 0) && constraints && constraints.length > 0){ - for(var i = 0; i != constraints.length; ++i){ - this.__containers__.push(new Object()); - var min = parseInt(constraints[i].cardMin); - var max = constraints[i].cardMax !== "MAX_INT" ? parseInt(constraints[i].cardMax) : "*"; - if(max !== 0){ - var cssTitle = "min: " + min + " max: " + max + " regular expression: " + constraints[i].regexp; - for(var j = 0; j != (min === 0 ? 1 : min); ++j){ - var row = new TextrowC("", constraints[i].regexp, this.__containers__[i], - min === 0 ? 1 : min, max === "*" ? -1 : max, cssTitle); - this.__error__.insert({"before" : row.getFrame()}); - } + $super(); + this.__frame__.writeAttribute({"class" : cssClass}); + this.__containers__ = new Array(); + + try{ + if((!contents || contents.length === 0) && constraints && constraints.length > 0){ + for(var i = 0; i != constraints.length; ++i){ + this.__containers__.push(new Object()); + var min = parseInt(constraints[i].cardMin); + var max = constraints[i].cardMax !== "MAX_INT" ? parseInt(constraints[i].cardMax) : "*"; + if(max !== 0){ + var cssTitle = "min: " + min + " max: " + max + " regular expression: " + constraints[i].regexp; + for(var j = 0; j != (min === 0 ? 1 : min); ++j){ + var row = new TextrowC("", constraints[i].regexp, this.__containers__[i], + min === 0 ? 1 : min, max === "*" ? -1 : max, cssTitle); + this.__error__.insert({"before" : row.getFrame()}); } } } - else { - // TODO: check already existing contents and order them to the corresponding fields - } } - catch(err){ - alert("From IdentifierC(): " + err); + else { + // TODO: check already existing contents and order them to the corresponding fields } - }, - "getContent" : function(unique, removeNull){ - var values = new Array(); + } + catch(err){ + alert("From IdentifierC(): " + err); + } + }, + "getContent" : function(unique, removeNull){ + var values = new Array(); + try{ for(var i = 0; i != this.__containers__.length; ++i){ for(var j = 0; j != this.__containers__[i].__frames__.length; ++j){ if(unique === true && values.indexOf(this.__containers__[i].__frames__[j].getContent()) !== -1) continue; @@ -328,12 +341,20 @@ values.push(this.__containers__[i].__frames__[j].getContent().strip()); } } + } + catch(err){ return values; - }, - "isValid" : function(){ - // TODO: check the validity of this frame with the passed constraints and return a boolean value - return true; - }}); + } + return values; + }, + "toJSON" : function(unique, removeNull){ + var content = this.getContent(unique, removeNull); + return content.length === 0 ? "null" : content.toJSON(); + }, + "isValid" : function(){ + // TODO: check the validity of this frame with the passed constraints and return a boolean value + return true; + }}); // --- Represantation of a scope frame, doesn't contain SelectrowCs, because the values must be unique! @@ -361,9 +382,18 @@ this.__contents__ = contents; if(!contents || contents.length < min) throw "From ScopeC.resetRows(): contents.length (" + (contents ? contents.length : "null") + ") must be > min (" + min + ")!"; - if(max !== -1 && (min > max || max === 0))throw "From FrameC(): min must be > max(" + max + ") and > 0 but is " + min; - + if(max !== -1 && min > max)throw "From FrameC(): min must be > max(" + max + ") and > 0 but is " + min; + // --- creates an empty div element + if(max === 0){ + this.getFrame().update(""); + var div = new Element("div", {"class" : CLASSES.selectrowWithoutRemoveButton()}); + div.insert({"top" : select}); + this.getFrame().insert({"bottom" : div}); + return; + } + + // --- creates an array with all available psis var options = new Array(); for(var i = 0; i != contents.length; ++i){ var topicPsis = new Array(); @@ -378,7 +408,7 @@ function checkValues(myself){ var rows = myself.getFrame().select("div"); var selectedItems = new Array(); - // --- collects all old selected values and removes the option elements + // --- collects all old selected values and removes the elements for(var i = 0; i != rows.length; ++i){ var selects = rows[i].select("select"); if(selects[0].value.strip().length !== 0) selectedItems.push(selects[0].value); @@ -410,6 +440,23 @@ values = cleanedValues; } + // --- if there is an empty value "" (if cardMin == 0), this value should be the last + // --- in the array (only when there is another value selected) + for(var h = 0; h != rows.length; ++h){ + var select = rows[h].select("select")[0].value; + if(select !== ""){ + for(var i = 0; i != values.length; ++i){ + for(var j = 0; j != values[i].length; ++j){ + if(values[i][j].length === 0){ + values[i] = values[values.length - 1]; + values[values.length - 1] = new Array(""); + } + } + } + break; + } + } + // --- fills all empty select elements for(var i = 0; i != rows.length; ++i){ var select = rows[i].select("select")[0]; @@ -506,17 +553,98 @@ addHandlers(this); } }, + "isUsed" : function(){ + return this.getContent(true, true).length !== 0; + }, "getContent" : function(unique, removeNull){ - // --- unique and removeNull aren't be used, they exist only for consistency var values = new Array(); - var rows = this.getFrame().select("div"); - for(var i = 0; i != rows.length; ++i){ - values.push(new Array(rows[i].select("select")[0].value)); // must be a list of lists + try{ + var rows = this.getFrame().select("div"); + for(var i = 0; i != rows.length; ++i){ + var select = rows[i].select("select")[0].value; + if(unique === true && values.indexOf(select) !== -1) continue; + if(removeNull === true && select.length === 0) continue; + values.push(select); + } + } + catch(err){ + return new Array(); } return values; - } - }); + }}); + + + +// --- Contains all scope frames of an element (there can be more than one scope constraint) +var ScopeContainerC = Class.create(ContainerC, {"initialize" : function($super, contents, constraints){ + $super(); + this.__frame__.writeAttribute({"class" : CLASSES.scopeContainer()}); + this.__container__ = new Array(); + this.resetValues(contents, constraints); + }, + "resetValues" : function(contents, constraints){ + try{ + for(var i = 0; i != this.__container__.length; ++i){ + this.__container__[i].remove(); + } + this.__container__ = new Array(); + } + catch(err){ + this.__container__ = new Array(); + } + // --- sets contents corresponding to the passed constraints + if(constraints && constraints.length){ + for(var i = 0; i != constraints.length; ++i){ + var scopeTypes = constraints[i].scopeTypes; + var min = parseInt(constraints[i].cardMin); + var max = constraints[i].cardMax !== "MAX_INT" ? parseInt(constraints[i].cardMax) : "*"; + + // TODO: check and adds contents to the types + + // --- if min === 0 && there is no content, adds an empty option + if(min === 0){ // TODO: check contents of this type + scopeTypes.unshift(new Array(new Array(""))); // [[""]] + } + this.__container__.push(new ScopeC(scopeTypes, min === 0 ? 1 : min, max === "*" ? -1 : max)); + this.__error__.insert({"before" : this.__container__[this.__container__.length - 1].getFrame()}); + } + } + else { + this.getFrame().insert({"top" : new Element("div", {"class" : CLASSES.selectrowWithoutRemoveButton()})}); + } + }, + "isUsed" : function(){ + for(var i = 0; i != this.__container__.length; ++i){ + if(this.__container__[i].isUsed() === true) return true; + } + return false; + }, + "isValid" : function(){ + for(var i = 0; i != this.__container__.length; ++i){ + if(this.__container__[i].isUsed() === true) return true; + } + return false; + }, + "getContent" : function(){ + var values = new Array(); + try{ + for(var i = 0; i != this.__container__.length; ++i){ + var cValues = this.__container__[i].getContent(true, true); + for(var j = 0; j != cValues.length; ++j){ + if(values.indexOf(cValues[j]) !== -1) continue; + values.push(cValues[j]); + } + } + }catch(err){ + return new Array(); + } + return values; + }, + "toJSON" : function(){ + if(this.getContent().length === 0) return "null"; + return this.getContent().toJSON(); + }}); // --- Representation of a variant element @@ -539,27 +667,10 @@ // --- scopes this.__scopes__ = null; //TODO: implement -> also in the server - this.__table__.insert({"bottom" : newRow(CLASSES.scopeFrame(), "Scope", new Element("div"))}); - - // --- resourceValue - var value = ""; - var datatype = ""; - if(contents && contents.resourceRef && contents.resourceRef.length !== 0){ - value = contents.resourceRef; - datatype = ANY_URI; - } - else if(contents && contents.resourceData){ - value = contents.resourceData.value; - datatype = contents.resourceData.datatype; - } - - this.__value__ = new Element("textarea", {"rows" : 3}).update(value); - this.__table__.insert({"bottom" : newRow(CLASSES.valueFrame(), "Resource Value", this.__value__)}); + this.__table__.insert({"bottom" : newRow(CLASSES.scopeContainer(), "Scope", new Element("div"))}); - // --- datatype - this.__datatype__ = new Object(); - new TextrowC(datatype, ".*", this.__datatype__, 1, 1, null); - this.__table__.insert({"bottom" : newRow(CLASSES.datatypeFrame(), "Datatype", this.__datatype__.__frames__[0].getFrame())}); + // --- resource value and datatype + makeResource(this, contents, null, null, null); // --- minimize this.minimize(); @@ -633,8 +744,7 @@ if(i === 0) trs[i].show(); else trs[i].hide(); } - } - }); + }}); // --- contains all variants of a name element @@ -708,10 +818,10 @@ // --- type var types = new Array(); for(var i = 0; nametypescopes && i !== nametypescopes.length; ++i){ - for(j = 0; j != nametypescopes[i].nameType.length; ++j){ + for(var j = 0; j != nametypescopes[i].nameType.length; ++j){ types.push(nametypescopes[i].nameType[j]); if(contents && contents.type && contents.type[0] === nametypescopes[i].nameType[j]){ - var sslected = nametypescopes[i].nameType[j]; + var selected = nametypescopes[i].nameType[j]; types[types.length - 1] = types[0]; types[0] = selected; } @@ -722,29 +832,16 @@ this.__table__.insert({"bottom" : tr}); // --- scopes - this.__scopes__ = null; - if(nametypescopes && nametypescopes[0].scopeConstraints){ - // TODO: pass the selected items seperately to the object, so they can be chosen as default - var scopeTypes = nametypescopes[0].scopeConstraints[0].scopeTypes; - var min = parseInt(nametypescopes[0].scopeConstraints[0].cardMin); - var max = nametypescopes[0].scopeConstraints[0].cardMax !== "MAX_INT" ? parseInt(nametypescopes[0].scopeConstraints[0].cardMax) : "*"; - this.__scopes__ = new ScopeC(scopeTypes, min === 0 ? 1 : min, max === "*" ? -1 : max); - tr = newRow(CLASSES.scopeFrame(), "Scope", this.__scopes__.getFrame()); - this.__table__.insert({"bottom" : tr}); - } - else { - var tr = new Element("tr", {"class" : CLASSES.scopeFrame()}); - var tdd = new Element("td", {"class" : CLASSES.description()}).update("Scope"); - var tdc = new Element("td", {"class" : CLASSES.content()}); - tr.insert({"top" : tdd}); - tr.insert({"bottom" : tdc}); - this.__table__.insert({"bottom" : tr}); - } - + this.__scope__ = new ScopeContainerC(contents && contents.scopes ? scopes : null, nametypescopes && nametypescopes[0].scopeConstraints ? nametypescopes[0].scopeConstraints : null); + this.__table__.insert({"bottom" : newRow(CLASSES.scopeContainer(), "Scope", this.__scope__.getFrame())}); + onTypeChangeScope(this, contents ? contents.scopes : null, nametypescopes, "name"); + // --- value this.__value__ = new Object(); - var cssTitleV = "min: " + min + " max: " + max + " regular expression: " + (simpleConstraint ? simpleConstraint.regexp : ".*"); - new TextrowC((contents && contents.value ? contents.value : ""), (simpleConstraint ? simpleConstraint.regexp : ".*"), this.__value__, 1, 1, cssTitleV); + var _min = parseInt(simpleConstraint.cardMin); + var _max = simpleConstraint.cardMax !== "MAX_INT" ? parseInt(simpleConstraint.cardMax) : "*"; + var cssTitleV = "min: " + _min + " max: " + _max + " regular expression: " + (simpleConstraint ? simpleConstraint.regexp : ".*"); + new TextrowC((contents ? contents.value : ""), (simpleConstraint ? simpleConstraint.regexp : ".*"), this.__value__, 1, 1, cssTitleV); this.__table__.insert({"bottom" : newRow(CLASSES.valueFrame(), "Value", this.__value__.__frames__[0].getFrame())}); // --- variants @@ -772,7 +869,7 @@ "getContent" : function(){ if(this.isUsed() === false) return null; return {"itemIdentities" : this.__itemIdentity__.getContent(true, true), - "scopes" : this.__scopes__.getContent(), + "scopes" : this.__scope__.getContent(), "value" : this.__value__.__frames__[0].getContent(), "variants" : this.__variants__.getContent()}; }, @@ -780,7 +877,7 @@ if(this.isUsed() === false) return "null"; return "{\"itemIdentities\":" + this.__itemIdentity__.toJSON(true, true) + ",\"type\":[" + this.__type__.__frames__[0].toJSON() + - "],\"scopes\":" + (this.__scopes__ ? this.__scopes__.toJSON() : "null") + + "],\"scopes\":" + this.__scope__.toJSON() + ",\"value\":" + this.__value__.__frames__[0].toJSON() + ",\"variants\":" + this.__variants__.toJSON() + "}"; }, @@ -789,21 +886,16 @@ this.__value__.__frames__[0].getContent().strip().length !== 0 || this.__variants__.getContent().length !== 0; }, - "showRemoveButton" : function(){ - this.__remove__.show(); - }, - "hideRemoveButton" : function(){ - this.__remove__.hide(); - }, - "showAddButton" : function(){ - this.__add__.show(); - }, - "hideAddButton" : function(){ - this.__add__.hide(); - }, "isValid" : function(){ // TODO: check the content and the constraints + variants.isValid() return true; + }, + "minimize" : function(){ + var trs = this.__table__.select("tr"); + for(var i = 0; i != trs.length; ++i){ + if(i === 0) trs[i].show(); + else trs[i].hide(); + } }}); @@ -824,10 +916,11 @@ var max = constraints[i].constraints[j].cardMax !== "MAX_INT" ? parseInt(constraints[i].constraints[j].cardMax) : "*"; var regexp = constraints[i].constraints[j].regexp; if(max !== 0){ - var title = "min: " + min + " max: " + max + " regular expression: " + constraints[i].regexp; + var title = "min: " + min + " max: " + max + " regular expression: " + regexp; var name = new NameC("", constraints[i].nametypescopes, constraints[i].constraints[j], this.__containers__[i][j], min === 0 ? 1 : min, max === "*" ? -1 : max, title); this.__error__.insert({"before" : name.getFrame()}); + if(min === 0)name.minimize(); } } } @@ -842,31 +935,41 @@ }, "getContent" : function(){ var values = new Array(); - for(var i = 0; i != this.__containers__.length; ++i){ - for(var j = 0; j != this.__containers__[i].length; ++j){ - for(var k = 0; k != this.__containers__[i][j].__frames__.length; ++k){ - if(this.__containers__[i][j].__frames__[k].isUsed() === true){ - values.push(this.__containers__[i][j].__frames__[k].getContent()); + try{ + for(var i = 0; i != this.__containers__.length; ++i){ + for(var j = 0; j != this.__containers__[i].length; ++j){ + for(var k = 0; k != this.__containers__[i][j].__frames__.length; ++k){ + if(this.__containers__[i][j].__frames__[k].isUsed() === true){ + values.push(this.__containers__[i][j].__frames__[k].getContent()); + } } } } + return values; + } + catch(err){ + return values; } - return values; }, "toJSON" : function(){ - var str = "["; - for(var i = 0; i != this.__containers__.length; ++i){ - for(var j = 0; j != this.__containers__[i].length; ++j){ - for(var k = 0; k != this.__containers__[i][j].__frames__.length; ++k){ - if(this.__containers__[i][j].__frames__[k].isUsed() === true){ - str += this.__containers__[i][j].__frames__[k].toJSON() + ","; + try{ + var str = "["; + for(var i = 0; i != this.__containers__.length; ++i){ + for(var j = 0; j != this.__containers__[i].length; ++j){ + for(var k = 0; k != this.__containers__[i][j].__frames__.length; ++k){ + if(this.__containers__[i][j].__frames__[k].isUsed() === true){ + str += this.__containers__[i][j].__frames__[k].toJSON() + ","; + } } } } + if(str.endsWith(",")) str = str.slice(0, str.length - 1); + str += "]"; + return str === "[]" ? null : str; + } + catch(err){ + return "null"; } - if(str.endsWith(",")) str = str.slice(0, str.length - 1); - str += "]"; - return str === "[]" ? null : str; }, "isValid" : function(){ // TODO: check the validity of this frame with the passed constraints and return a boolean value + isValid() of all names @@ -874,64 +977,208 @@ }}); +// --- represenation of an occurrence element +var OccurrenceC = Class.create(ContainerC, {"initialize" : function($super, contents, occurrenceTypes, constraint, uniqueConstraints, owner, min, max, cssTitle){ + $super(); + if(!owner.__frames__) owner.__frames__ = new Array(); + owner.__frames__.push(this); + this.__frame__.writeAttribute({"class" : CLASSES.occurrenceFrame()}); + this.__table__ = new Element("table", {"class" : CLASSES.occurrenceFrame()}); + this.__frame__.insert({"top" : this.__table__}); -var OccurrenceC = Class.create(ContainerC, {"initialize" : function($super, contents, constraints, owner, min, max, cssTitl){ - -}, + try{ + // --- control row + itemIdentity + makeControlRow(this, 5, contents ? contents.itemIdentities : null); + checkRemoveAddButtons(owner, 1, max); + setRemoveAddHandler(this, owner, 1, max, function(){ + return new OccurrenceC(null, occurrenceTypes, constraint, uniqueConstraints, owner, min, max, cssTitle); + }); + + // --- type + var types = new Array(); + for(var i = 0; occurrenceTypes && i !== occurrenceTypes.length; ++i){ + for(var j = 0; j != occurrenceTypes[i].occurrenceType.length; ++j){ + types.push(occurrenceTypes[i].occurrenceType[j]); + if(contents && contents.type && contents.type[0] === ooccurrenceTypes[i].occurrenceType[j]){ + var selected = occurrenceTypes[i].occurrenceType[j]; + types[types.length - 1] = types[0]; + types[0] = selected; + } + } + } + this.__type__ = new Object(); + var tr = newRow(CLASSES.typeFrame(), "Type", new SelectrowC(types, this.__type__, 1, 1).getFrame()); + this.__table__.insert({"bottom" : tr}); + + // --- scopes + this.__scope__ = new ScopeContainerC(contents && contents.scopes ? contents.scopes : null, occurrenceTypes && occurrenceTypes[0].scopeConstraints ? occurrenceTypes[0].scopeConstraints : null); + this.__table__.insert({"bottom" : newRow(CLASSES.scopeContainer(), "Scope", this.__scope__.getFrame())}); + onTypeChangeScope(this, contents.scopes, occurrenceTypes, "occurrence"); + + // --- resource value and datatype + var _min = parseInt(constraint.cardMin); + var _max = constraint.cardMax !== "MAX_INT" ? parseInt(constraint.cardMax) : "*"; + var cssTitle = "min: " + _min + " max: " + _max + " regular expression: " + constraint.regexp; + makeResource(this, contents, constraint, (occurrenceTypes ? occurrenceTypes[0].datatypeConstraint : null), cssTitle); + } + catch(err){ + alert("From OccurrenceC(): " + err); + } + }, "getContent" : function(){ - // TODO: implement + if(this.isUsed() === true){ + var resourceRef = null; + var resourceData = null; + if(this.__datatype__.__frames__[0].getContent() === ANY_URI){ + resourceRef = this.__value__.value; + } + else { + resourceData = {"datatype" : this.__datatype__.__frames__[0].getContent(), + "value" : this.__value__.value}; + } + return {"itemIdentities" : this.__itemIdentity__.getContent(true, true), + "type" : [this.__type__.__frames__[0].getContent()], + "scopes" : this.__scope__.getContent(), + "resourceRef" : resourceRef, + "resourceData" : resourceData}; + } + else { + return null; + } }, "toJSON" : function(){ - // TODO: implement + if(this.isUsed() === true){ + var resourceRef = "null"; + var resourceData = "null"; + if(this.__datatype__.__frames__[0].getContent() === ANY_URI){ + resourceRef = this.__value__.value.toJSON(); + } + else { + resourceData = "{\"datatype\":" + this.__datatype__.__frames__[0].toJSON() + + ",\"value\":" + this.__value__.value.toJSON() + "}"; + } + return "{\"itemIdentities\":" + this.__itemIdentity__.toJSON(true, true) + + ",\"type\":[" + this.__type__.__frames__[0].toJSON() + + "],\"scopes\":" + this.__scope__.toJSON() + + ",\"resourceRef\":" + resourceRef + + ",\"resourceData\":" + resourceData + "}"; + } + else { + return "null"; + } }, "isUsed" : function(){ - // TODO: implement - }, - "showRemoveButton" : function(){ - this.__remove__.show(); - }, - "hideRemoveButton" : function(){ - this.__remove__.hide(); - }, - "showAddButton" : function(){ - this.__add__.show(); - }, - "hideAddButton" : function(){ - this.__add__.hide(); + return this.__itemIdentity__.getContent(true, true).length !== 0 || + this.__value__.value.strip().length !== 0; }, "isValid" : function(){ // TODO: check the content and the constraints return true; + }, + "minimize" : function(){ + var trs = this.__table__.select("tr"); + for(var i = 0; i != trs.length; ++i){ + if(i === 0) trs[i].show(); + else trs[i].hide(); + } }}); + - - +// --- contains all occurrences of an topic element var OccurrenceContainerC = Class.create(ContainerC, {"initialize" : function($super, contents, constraints){ - -}, + $super(); + this.__containers__ = new Array(); + this.__frame__.writeAttribute({"class" : CLASSES.occurrenceContainer()}); + + try{ + if((!contents || contents.length === 0) && constraints && constraints.length > 0){ + for(var i = 0; i != constraints.length; ++i){ + this.__containers__.push(new Array()); + for(var j = 0; j != constraints[i].constraints.length; ++j){ + this.__containers__[i].push(new Object()); + var min = parseInt(constraints[i].constraints[j].cardMin); + var max = constraints[i].constraints[j].cardMax !== "MAX_INT" ? parseInt(constraints[i].constraints[j].cardMax) : "*"; + var regexp = constraints[i].constraints[j].regexp; + if(max !== 0){ + var title = "min: " + min + " max: " + max + " regular expression: " + regexp; + var occurrence = new OccurrenceC("", constraints[i].occurrenceTypes, constraints[i].constraints[j], + constraints[i].uniqueConstraints, this.__containers__[i][j], + min === 0 ? 1 : min, max === "*" ? -1 : max, title); + this.__error__.insert({"before" : occurrence.getFrame()}); + if(min === 0)occurrence.minimize(); + } + } + } + } + else { + // TODO: check already existing contents and order them to the corresponding fields + } + } + catch(err){ + alert("From OccurrenceContainerC(): " + err); + } + }, "isValid" : function(){ // TODO: implement this method return true; }, "getContent" : function(){ - // TODO: implement this method + var values = new Array(); + try{ + for(var i = 0; i != this.__containers__.length; ++i){ + for(var j = 0; j != this.__containers__[i].length; ++j){ + for(var k = 0; k != this.__containers__[i][j].__frames__.length; ++k){ + if(this.__containers__[i][j].__frames__[k].isUsed() === true){ + values.push(this.__containers__[i][j].__frames__[k].getContent()); + } + } + } + } + return values; + } + catch(err){ + return values; + } }, - "toJSON" : function(){ - // TODO: implement this method + "toJSON" : function(){ + try{ + var str = "["; + for(var i = 0; i != this.__containers__.length; ++i){ + for(var j = 0; j != this.__containers__[i].length; ++j){ + for(var k = 0; k != this.__containers__[i][j].__frames__.length; ++k){ + if(this.__containers__[i][j].__frames__[k].isUsed() === true){ + str += this.__containers__[i][j].__frames__[k].toJSON() + ","; + } + } + } + } + if(str.endsWith(",")) str = str.slice(0, str.length - 1); + str += "]"; + return str === "[]" ? null : str; + } + catch(err){ + return "null"; + } }}); - - - +// --- representation of a topic element. var TopicC = Class.create(ContainerC, {"initialize" : function($super, content, constraints){ $super(); + this.__minimized__ = false; try{ this.__frame__ .writeAttribute({"class" : CLASSES.topicFrame()}); this.__table__ = new Element("table", {"class" : CLASSES.topicFrame()}); this.__frame__.insert({"top" : this.__table__}); - this.__caption__ = new Element("caption").update("Topic"); + this.__caption__ = new Element("caption", {"class" : CLASSES.clickable()}).update("Topic"); this.__table__.insert({"top" : this.__caption__}); + + function setMinimizeHandler(myself){ + myself.__caption__.observe("click", function(event){ + myself.minimize(); + }); + } + setMinimizeHandler(this); // --- topic id this.__topicid__ = new Object(); @@ -960,32 +1207,328 @@ this.__name__ = new NameContainerC(_contents, _constraints); this.__table__.insert({"bottom" : newRow(CLASSES.nameContainer(), "Names", this.__name__.getFrame())}); - - - - + // --- occurrences + _contents = (content ? content.occurrences : null); + _constraints = (constraints ? constraints.topicOccurrenceConstraints : null); + this.__occurrence__ = new OccurrenceContainerC(_contents, _constraints); + this.__table__.insert({"bottom" : newRow(CLASSES.occurrenceContainer(), "Occurrences", this.__occurrence__.getFrame())}); - var tmp = new Element("input", {"type" : "button", "value" : "test"}); - function tester(myself){ - tmp.observe("click", function(event){ - //alert(myself.__subjectLocator__.getContent() + " -> " + myself.__subjectLocator__.toJSON() + "\n\n" + myself.__subjectLocator__.getContent(true, true) + " -> " + myself.__subjectLocator__.toJSON(true, true)); - - }); - }; - tester(this); - this.__frame__.insert({"bottom" : tmp}); + var btn = new Element("input", {"value" : "topic.toJSON()", "type" : "button"}); + function addBtnHandler(myself){ + btn.observe("click", function(event){ + alert(myself.toJSON()); + }) + } + addBtnHandler(this); + this.__frame__.insert({"bottom" : btn}); }catch(err){ alert("From TopciC(): " + err); } }, + "isValid" : function(){ + // TODO: implement + return true; + }, "getContent" : function(){ - return {"id" : this.__topicid__.__frames__[0].getContent }; - } - }); + try{ + return {"id" : this.__topicid__.__frames__[0].getContent().strip(), + "itemIdentities" : this.__itemIdentity__.getContent(true, true), + "subjectLocators" : this.__subjectLocator__.getContent(true, true), + "subjectIdentifiers" : this.__subjectIdentifier__.getContent(true, true), + "names" : this.__name__.getContent(), + "occurrences" : this.__occurrence__.getContent()}; + } + catch(err){ + return null; + } + }, + "toJSON" : function(){ + try{ + return "{\"id\":" + this.__topicid__.__frames__[0].getContent().strip().toJSON() + + ",\"itemIdentities\":" + this.__itemIdentity__.toJSON(true, true) + + ",\"subjectLocators\":" + this.__subjectLocator__.toJSON(true, true) + + ",\"subjectIdentifiers\":" + this.__subjectIdentifier__.toJSON(true, true) + + ",\"names\":" + this.__name__.toJSON() + + ",\"occurrences\":" + this.__occurrence__.toJSON() + "}"; + } + catch(err){ + return "null"; + } + }, + "minimize" : function(){ + var rows = new Array(); + rows.push(this.getFrame().select("tr." + CLASSES.topicIdFrame())[0], + this.getFrame().select("tr." + CLASSES.itemIdentityFrame())[0], + this.getFrame().select("tr." + CLASSES.subjectLocatorFrame())[0], + this.getFrame().select("tr." + CLASSES.subjectIdentifierFrame())[0], + this.getFrame().select("tr." + CLASSES.nameContainer())[0], + this.getFrame().select("tr." + CLASSES.occurrenceContainer())[0]); + for(var i = 0; i != rows.length; ++i){ + if(this.__minimized__ === false) rows[i].hide(); + else rows[i].show(); + } + this.__minimized__ = !this.__minimized__; + }}); + + +// --- representation of a role element. +var RoleC = Class.create(ContainerC, {"initialize" : function($super, itemIdentities, roleTypes, rolePlayers, owner, min, max){ + $super(); + if(!owner.__frames__) owner.__frames__ = new Array(); + if(!roleTypes || roleTypes.length === 0) throw "From RoleC(): roleTypes must be set!"; + if(!rolePlayers || rolePlayers.length === 0) throw "From RoleC(): rolePalyers must be set"; + owner.__frames__.push(this); + this.__frame__.writeAttribute({"class" : CLASSES.roleFrame()}); + this.__table__ = new Element("table", {"class" : CLASSES.roleFrame()}); + this.__frame__.insert({"top" : this.__table__}); + this.__roleTypes__ = roleTypes; + this.__rolePlayers__ = rolePlayers; + + try{ + // --- control row + itemIdentity + makeControlRow(this, 3, itemIdentities); // make control row have to be changed to a separate control row for roles + checkRemoveAddButtons(owner, 1, max); + setRemoveAddHandler(this, owner, 1, max, function(){ + return new RoleC(null, roleTypes, rolePlayers, owner, min, max); + }); + + // --- type + var types = this.__roleTypes__.flatten(); + this.__type__ = new Object(); + var tr = newRow(CLASSES.typeFrame(), "Type", new SelectrowC(types, this.__type__, 1, 1).getFrame()); + this.__table__.insert({"bottom" : tr}); + + // --- player + var players = this.__rolePlayers__.flatten(); + this.__player__ = new Object(); + tr = newRow(CLASSES.playerFrame(), "Player", new SelectrowC(players, this.__player__, 1, 1).getFrame()); + this.__table__.insert({"bottom" : tr}); + } + catch(err){ + alert("From RoleC(): " + err); + } + }, + "getType" : function(){ + return this.__type__.__frames__[0].getContent(); + }, + "getPlayer" : function(){ + return this.__player__.__frames__[0].getContent(); + }, + "getContent" : function(){ + if(this.isUsed()){ + return {"itemIdentities" : this.__itemIdentity__.getContent(true, true), + "type" : new Array(this.getType()), + "topicRef" : new Array(this.getPlayer())}; + } + + return null; + }, + "toJSON" : function(){ + if(this.isUsed()){ + return "{\"itemIdentities\":" + this.__itemIdentity__.toJSON(true, true) + + ",\"type\":[" + this.getType().toJSON() + "]" + + ",\"topicRef\":[" + this.getPlayer().toJSON() + "]}"; + } + + return "null"; + }, + "isValid" : function(){ + return this.getType().length !== 0 && this.getPlayer().length !== 0; + }, + "isUsed" : function(){ + return this.getType().length !== 0 || this.getPlayer().length !== 0 || this.__itemIdentity__.getContent(true, true).length !== 0; + }}); + + +// --- contains all roles of an association +var RoleContainerC = Class.create(ContainerC, {"initialize" : function($super, contents, roleConstraints, playerConstraints, otherRoleConstraints){ + $super(); + this.__frame__.writeAttribute({"class" : CLASSES.roleContainer()}); + this.__container__ = new Object(); + + try{ + if((!contents || contents.length === 0) && roleConstraints && playerConstraints){ + for(var i = 0; playerConstraints && i !== playerConstraints.length; ++i){ + //new RoleC(new Array("itemIdentity " + i), playerConstraints[i].roleTypes, playerConstraints[i].players, this.__container__, 1, 4); + //this.__error__.insert({"before" : this.__container__.__frames__[i].getFrame()}); + } + } + else { + // TODO: check already existing contents and order them to the corresponding fields + } + + + + } + catch(err){ + alert("From RoleContainerC(): " + err); + } + }, + "resetValues" : function(roleConstraints, playerConstraints, otherRoleConstraints){ + + // TODO: implement + }, + "getContent" : function(){ + // TODO: implement + }, + "toJSON" : function(){ + // TODO: implement + }, + "isValid" : function(){ + // TODO: implement + }, + "isUsed" : function(){ + // TODO: implement + }}); + + +// --- representation of an association element +var AssociationC = Class.create(ContainerC, {"initialize" : function($super, contents, constraints, owner){ + $super(); + if(!owner) throw "From NameC(): owner must be set but is null"; + if(!owner.__frames__) owner.__frames__ = new Array(); + owner.__frames__.push(this); + + this.__frame__.writeAttribute({"class" : CLASSES.associationFrame()}); + this.__table__ = new Element("table", {"class" : CLASSES.associationFrame()}); + this.__frame__.insert({"top" : this.__table__}); + this.__constraints__ = constraints; + this.__contents__ = contents; + + try{ + // --- control row + ItemIdentity + makeControlRow(this, 4, contents ? contents.itemIdentities : null); + checkRemoveAddButtons(owner, 1, -1); + setRemoveAddHandler(this, owner, 1, -1, function(){ + return new AssociationC(null, constraints, owner); + }); + + // --- type + var types = new Array(); + for(var i = 0; constraints && i !== constraints.length; ++i){ + for(var j = 0; j != constraints[i].associationType.length; ++j){ + types.push(constraints[i].associationType[j]); + if(contents && contents.type && contents.type[0] === constraints[i].associationType[j]){ + var selected = constraints[i].associationType[j]; + types[types.length - 1] = types[0]; + types[0] = selected; + } + } + } + this.__type__ = new Object(); + var tr = newRow(CLASSES.typeFrame(), "Type", new SelectrowC(types, this.__type__, 1, 1).getFrame()); + this.__table__.insert({"bottom" : tr}); + + // --- scopes + this.__scope__ = new ScopeContainerC(this.__contents__ && this.__contents__.scopes ? this.__contents__.scopes : null, this.__constraints__ && this.__constraints__[0].scopeConstraints ? this.__constraints__[0].scopeConstraints : null); + this.__table__.insert({"bottom" : newRow(CLASSES.scopeContainer(), "Scope", this.__scope__.getFrame())}); + + // --- roles + var _roleConstraints = _playerConstraints = _otherRoleConstraints = null; + if(this.__constraints__){ + _roleConstraints = this.__constraints__[0].associationRoleConstraints; + _playerConstraints = this.__constraints__[0].rolePlayerConstraints; + _otherRoleConstraints = this.__constraints__[0].otherRoleConstraints; + } + + this.__roles__ = new RoleContainerC(this.__contents__ ? this.__contents__.roles : null, _roleConstraints, _playerConstraints, _otherRoleConstraints); + this.__table__.insert({"bottom" : newRow(CLASSES.roleContainer(), "Roles", this.__roles__.getFrame())}); + + // --- registers the onChangeHandler of the Type-selectrow + onTypeChangeScope(this, null, null, "association"); + } + catch(err){ + alert("From AssociationC(): " + err); + } + }, + "resetValues" : function(){ + // --- scope, depends only to the associationtype, roles can be ignored + // --- finds the scopes depending to the selected type + var foundIdx = -1; + for(var i = 0; this.__constraints__ && i != this.__constraints__.length; ++i) + { + if(foundIdx !== -1) break; + for(var j = 0; j != this.__constraints__[i].associationType.length; ++j){ + if(this.__type__.__frames__[0].getContent() === this.__constraints__[i].associationType[j]){ + foundIdx = i; + break; + } + } + } + this.__scope__.resetValues(null, (foundIdx === -1 ? null : this.__constraints__[foundIdx].scopeConstraints)); + + var _roleConstraints = _playerConstraints = _otherRoleConstraints = null; + if(foundIdx !== -1){ + _roleConstraints = this.__constraints__[foundIdx].associationRoleConstraints; + _playerConstraints = this.__constraints__[foundIdx].rolePlayerConstraints; + _otherRoleConstraints = this.__constraints__[foundIdx].otherRoleConstraints; + } + this.__roles__.resetValues(_roleConstraints, _playerConstraints, _otherRoleConstraints); + }, + "getContent" : function(){ + // TODO: implement + }, + "toJSON" : function(){ + // TODO: implement + }, + "isValid" : function(){ + // TODO: implement + }, + "isUsed" : function(){ + // TODO: implement + }}); + + +var AssociationContainerC = Class.create(ContainerC, {"initialize" : function($super, contents, constraints){ + $super(); + this.__minimized__ = false; + try{ + this.__frame__ .writeAttribute({"class" : CLASSES.associationContainer()}); + this.__table__ = new Element("table", {"class" : CLASSES.associationContainer()}); + this.__frame__.insert({"top" : this.__table__}); + this.__caption__ = new Element("caption", {"class" : CLASSES.clickable()}).update("Associations"); + this.__table__.insert({"top" : this.__caption__}) + + this.__container__ = new Object(); + + for(var i = 0; contents && i != contents.length; ++i){ + var association = new AssociationC(contents[i], constraints, this.__container__); + var tr = new Element("tr", {"class" : CLASSES.associationFrame()}); + var td = new Element("td", {"class" : CLASSES.content()}); + td.update(association.getFrame()); + tr.update(td); + this.__table__.insert({"bottom" : tr}); + } + + if(!this.__container__.__frames__ && constraints && constraints.length !== 0){ + var association = new AssociationC(null, constraints, this.__container__); + var tr = new Element("tr", {"class" : CLASSES.associationFrame()}); + var td = new Element("td", {"class" : CLASSES.content()}); + td.update(association.getFrame()); + tr.update(td); + this.__table__.insert({"bottom" : tr}); + } + } + catch(err){ + alert("From AssociationContainerC(): " + err); + } + }, + "getContent" : function(){ + // TODO: implement + }, + "toJSON" : function(){ + // TODO: implement + }, + "isValid" : function(){ + // TODO: implement + }, + "minimize" : function(){ + // TODO: implement + }}); @@ -1155,4 +1698,101 @@ else trs[i].hide(); } }); +} + + +// --- This function adds a onchange handler to the type-selct-element +// --- of the instance passed through the variable myself. +// --- On changing there will be reset the scope frame to the corresponding +// --- type and when what is set to "occurrence" there will be set a corresponding +// --- datatype-value. +function onTypeChangeScope(myself, contents, constraints, what){ + try{ + var select = myself.__table__.select("tr." + CLASSES.typeFrame())[0].select("td." + CLASSES.content())[0].select("select")[0]; + select.observe("change", function(event){ + var type = event.element().value; + + var foundIdx = -1; + if(what === "name"){ + for(var i = 0; constraints && i !== constraints.length; ++i){ + if(foundIdx !== -1) break; + for(var j = 0; j !== constraints[i].nameType.length; ++j){ + if(foundIdx !== -1) break; + if(constraints[i].nameType[j] === type){ + foundIdx = i; + break; + } + } + } + myself.__scope__.resetValues(contents, (foundIdx === -1 ? null : constraints[foundIdx].scopeConstraints)); + } + else if(what === "occurrence"){ + for(var i = 0; constraints && i !== constraints.length; ++i){ + if(foundIdx !== -1) break; + for(var j = 0; j !== constraints[i].occurrenceType.length; ++j){ + if(foundIdx !== -1) break; + if(constraints[i].occurrenceType[j] === type){ + foundIdx = i; + break; + } + } + } + if(foundIdx !== -1 && constraints[foundIdx].datatypeConstraint){ + var dc = constraints[foundIdx].datatypeConstraint; + myself.__datatype__.__frames__[0].getFrame().select("input")[0].writeAttribute({"readonly" : "readonly", "value" : dc}); + } + else { + myself.__datatype__.__frames__[0].getFrame().select("input")[0].writeAttribute({"value" : ""}); + myself.__datatype__.__frames__[0].getFrame().select("input")[0].removeAttribute("readonly"); + } + myself.__scope__.resetValues(contents, (foundIdx === -1 ? null : constraints[foundIdx].scopeConstraints)); + } + else if(what === "variant"){ + // do nothing all values will be stored + } + else if(what === "association"){ + myself.resetValues(); + } + }); + } + catch(err){} +} + + +// --- sets the resource value and datatype of names and occurrences +function makeResource(myself, content, constraints, datatypeConstraint, cssTitle){ + var value = ""; + var datatype = ""; + if(content && content.resourceRef && content.resourceRef.length !== 0){ + value = content.resourceRef; + datatype = ANY_URI; + } + else if(content && content.resourceData){ + value = content.resourceData.value; + datatype = contents.resourceData.datatype; + } + + try{ + this.__value__.remove(); + this.__value__ = null; + }catch(err){} + try{ + this.__datatype__.__frames__[0].remove(); + this.__datytype__ = new Object(); + }catch(err){} + + myself.__value__ = new Element("textarea", {"rows" : 3}).update(value); + myself.__table__.insert({"bottom" : newRow(CLASSES.valueFrame(), "Resource Value", myself.__value__)}); + if(cssTitle && cssTitle.length !== 0) myself.__value__.writeAttribute({"title" : cssTitle}); + + // --- datatype + myself.__datatype__ = new Object(); + if(datatypeConstraint && datatypeConstraint.length !== 0){ + new TextrowC(datatypeConstraint, datatypeConstraint, myself.__datatype__, 1, 1, null); + myself.__datatype__.__frames__[0].getFrame().select("input")[0].writeAttribute({"readonly" : "readonly"}); + } + else { + new TextrowC(datatype, ".*", myself.__datatype__, 1, 1, null); + } + myself.__table__.insert({"bottom" : newRow(CLASSES.datatypeFrame(), "Datatype", myself.__datatype__.__frames__[0].getFrame())}); } \ No newline at end of file Modified: trunk/src/json/json_tmcl.lisp ============================================================================== --- trunk/src/json/json_tmcl.lisp (original) +++ trunk/src/json/json_tmcl.lisp Sun May 31 09:08:00 2009 @@ -35,7 +35,7 @@ (let ((value (get-constraints-of-topic topics :treat-as treat-as))) (concatenate 'string "\"topicConstraints\":" value)))) - (let ((available-associations ;what's with association which have only a associationrole-constraint? + (let ((available-associations ;what's with association which have only a associationrole-constraints? (remove-duplicates (loop for topic in topics append (get-available-associations-of-topic topic :treat-as treat-as))))) @@ -58,40 +58,6 @@ "{" topic-constraints "," associations-constraints "}"))) json-string))))))) -;(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 --------------------------------------------- @@ -101,7 +67,10 @@ passed associationtype-topic." (let ((constraint-topics (get-all-constraint-topics-of-association associationtype-topic))) - (let ((associationtypescope-constraints + (let ((associationtype + (concatenate 'string "\"associationType\":" + (json-exporter::identifiers-to-json-string associationtype-topic))) + (associationtypescope-constraints (let ((value (get-typescope-constraints associationtype-topic :what 'association))) (concatenate 'string "\"scopeConstraints\":" value))) (associationrole-constraints @@ -117,7 +86,7 @@ (get-otherrole-constraints (getf constraint-topics :otherrole-constraints)))) (concatenate 'string "\"otherRoleConstraints\":" value)))) (let ((json-string - (concatenate 'string "{" associationrole-constraints "," roleplayer-constraints "," + (concatenate 'string "{" associationtype "," associationrole-constraints "," roleplayer-constraints "," otherrole-constraints "," associationtypescope-constraints "}"))) json-string)))) @@ -217,6 +186,7 @@ (uri (first (psis (getf involved-topic-tupple :otherplayer)))) (uri (first (psis (getf involved-topic-tupple :otherrole)))) constraint-lists)) + (let ((json-player (concatenate 'string "\"players\":" (topics-to-json-list @@ -342,7 +312,9 @@ "Returns a list of the form ((:associationroletype :card-min :card-max ), <...>) which describes all associationrole-constraints of the passed - constraint-topics." + constraint-topics. + If as-json is set to t the return value of this function is a json-string otherwise a + list of lists of the following form (:roletype :cardMin :cardMax )" (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*)) @@ -366,6 +338,7 @@ associationroletype)) associationrole-constraints)))) (let ((cleaned-associationrole-constraints "[")) + ;(raw-constraints nil)) (loop for associationroletype-topic in associationroletype-topics do (let ((constraint-lists (remove-duplicate-constraints @@ -385,6 +358,7 @@ "{\"roleType\":" roletype-with-subtypes ",\"cardMin\":" (getf (first constraint-lists) :card-min) ",\"cardMax\":" (getf (first constraint-lists) :card-max) "},"))))) + (if (string= cleaned-associationrole-constraints "[") (setf cleaned-associationrole-constraints "null") @@ -475,41 +449,6 @@ topicoccurrence-constraints "," abstract-constraint "}"))) json-string)))) -;(defun get-constraints-of-topic (topic-instances &key(treat-as 'type)) -; (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-topictype-constraints) -; "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(owner exclusive-instances-lists) "Returns a JSON-obejct of the following form: @@ -745,7 +684,7 @@ (error "found contrary occurrence-datatype-constraints: ~a~%" datatype-constraints)) (if datatype-constraint (json:encode-json-to-string (first datatype-constraint)) - nil))))) + "null"))))) (defun get-typescope-constraints(element-type-topic &key(what 'topicname)) Modified: trunk/src/json/json_tmcl_validation.lisp ============================================================================== --- trunk/src/json/json_tmcl_validation.lisp (original) +++ trunk/src/json/json_tmcl_validation.lisp Sun May 31 09:08:00 2009 @@ -241,7 +241,7 @@ (defun list-instances (topic-instance &optional (topictype (get-item-by-psi *topictype-psi*)) (topictype-constraint (get-item-by-psi *topictype-constraint-psi*))) - "Returns the topic-instance, all subtypes found by the function lis-subtypes and all direct + "Returns the topic-instance, all subtypes found by the function list-subtypes and all direct instances for the found subtypes." (let ((all-subtypes-of-this (getf (list-subtypes topic-instance topictype topictype-constraint) :subtypes)) @@ -262,10 +262,11 @@ (remove-duplicates (loop for subtype in all-instances-of-this append (getf (list-subtypes subtype nil nil) :subtypes)))))) - (remove-if #'null - (map 'list #'(lambda(x) - (handler-case (progn - (topictype-of-p x nil) - x) - (condition () nil))) - all-subtypes-of-all-instances)))))) \ No newline at end of file + (union all-instances-of-this + (remove-if #'null + (map 'list #'(lambda(x) + (handler-case (progn + (topictype-of-p x nil) + x) + (condition () nil))) + all-subtypes-of-all-instances))))))) \ 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 Sun May 31 09:08:00 2009 @@ -12,7 +12,7 @@ (defparameter *json-get-prefix* "/json/get/(.+)$") ;the prefix to get a fragment by the psis -> localhost:8000/json/get/ (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-summary-url* "/json/summary/?$") ;the url to get a summary of 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/topicstubs/(.+)$") ;the json prefix for getting some topic stub information of a topic (defparameter *json-get-type-tmcl-url* "/json/tmcl/type/?$") ;the json url for getting some tmcl information of a topic treated as a type Modified: trunk/src/unit_tests/poems.xtm ============================================================================== --- trunk/src/unit_tests/poems.xtm (original) +++ trunk/src/unit_tests/poems.xtm Sun May 31 09:08:00 2009 @@ -582,7 +582,7 @@ - + @@ -593,6 +593,26 @@ + + + + + + + + + + + + + + + + + + + + @@ -1059,7 +1079,7 @@ - 3 + 1 @@ -1262,8 +1282,9 @@ - - + + + @@ -1279,7 +1300,7 @@ - + @@ -1291,7 +1312,7 @@ - + @@ -1303,14 +1324,111 @@ - + + + + + + + + + 0 + + + + 6 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Modified: trunk/src/xml/setup.lisp ============================================================================== --- trunk/src/xml/setup.lisp (original) +++ trunk/src/xml/setup.lisp Sun May 31 09:08:00 2009 @@ -33,7 +33,10 @@ (if (eq xtm-format '2.0) (importer xtm-dom :tm-id tm-id :xtm-id xtm-id) (importer-xtm1.0 xtm-dom :tm-id tm-id :xtm-id xtm-id)) - (format t "#Topics in the store: ~a~%" (length (elephant:get-instances-by-class 'TopicC))))) + (format t "#Objects in the store: Topics: ~a, Associations: ~a~%" + (length (elephant:get-instances-by-class 'TopicC)) + (length (elephant:get-instances-by-class 'AssociationC))))) + ;(format t "#Topics in the store: ~a~%" (length (elephant:get-instances-by-class 'TopicC))))) (defun setup-repository (xtm-path repository-path &key