isidorus-cvs
Threads by month
- ----- 2025 -----
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- 1037 discussions
Author: lgiessmann
Date: Sun Jun 7 14:29:14 2009
New Revision: 34
Log:
added the otherroleplayer-constraint and a player-type-change-handler to the ajax-client; currently there is missing a remove- and add- handler for roles and the possibility to set the new created topic as a roleplyer
Modified:
trunk/src/ajax/javascripts/datamodel.js
Modified: trunk/src/ajax/javascripts/datamodel.js
==============================================================================
--- trunk/src/ajax/javascripts/datamodel.js (original)
+++ trunk/src/ajax/javascripts/datamodel.js Sun Jun 7 14:29:14 2009
@@ -1037,7 +1037,7 @@
"value" : this.__value__.value};
}
return {"itemIdentities" : this.__itemIdentity__.getContent(true, true),
- "type" : [this.__type__.__frames__[0].getContent()],
+ "type" : new Array(this.__type__.__frames__[0].getContent()),
"scopes" : this.__scope__.getContent(),
"resourceRef" : resourceRef,
"resourceData" : resourceData};
@@ -1212,19 +1212,6 @@
_constraints = (constraints ? constraints.topicOccurrenceConstraints : null);
this.__occurrence__ = new OccurrenceContainerC(_contents, _constraints);
this.__table__.insert({"bottom" : newRow(CLASSES.occurrenceContainer(), "Occurrences", this.__occurrence__.getFrame())});
-
-
-
-
-
- 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);
}
@@ -1336,7 +1323,6 @@
}
if(j !== this.__rolePlayers__.length){
this.__rolePlayers__[j] = player;
- alert("test");
break;
}
}
@@ -1421,9 +1407,7 @@
this.__frame__.writeAttribute({"class" : CLASSES.roleContainer()});
this.__arContainer__ = new Object();
this.__orContainer__ = new Object();
-
/*
-
*associationrole-constraints: A association role constraint defines how many and of what type the roles in associations of given a type must be.
*min: card-min indicating the minimum number of times the role can appear in the association
*max: card-max indicating the maximum number of times the role can appear in the association
@@ -1437,22 +1421,7 @@
player type in an association.
*min: card-min indicating the minimum number of times the other role can occur
*max: card-max indicating the maximum number of times the other role can occur
-
-
-algorithmus:
-OK *alle rollen aus associationroleconstraints erstellen in einem __arContainer__
-OK *überprüfen, ob die kardinalitäten der roleplayer mit den kardinalitäten der associationrole übereinstimmen
-OK *card-min rp < card-min ar -> fehler
-OK *card-max rp > card-max ar -> fehler
-OK *card-min rp > card-max ar -> fehler
-OK *card-max rp < card-min ar -> fehler
-OK *zu allen gefundenen roles vorhandene roleplayer-constraints suchen
-OK *alle roleplayer sammeln und an eine leere option anhängen, anschließend in RoleC anhängen
-*__orContainer__ für otherrole-constraints initialisieren
-*handler hinzufügen
*/
-
-
try{
if((!contents || contents.length === 0) && associationRoleConstraints){
this.resetValues(associationRoleConstraints, rolePlayerConstraints, otherRoleConstraints);
@@ -1489,7 +1458,6 @@
this.__orContainer__ = new Object();
}
-
// --- creates all roles from existing associationroleconstraints and roleplayerConstraints
// TODO: insert existing contents to the corresponding constraints
for(var i = 0; this.__associationRoleConstraints__ && i !== this.__associationRoleConstraints__.length; ++i){
@@ -1497,6 +1465,10 @@
var foundRpcs = getRolePlayerConstraintsForRole(arc.roleType, this.__rolePlayerConstraints__);
this.__makeRolesFromARC__(arc, foundRpcs);
}
+ // --- creates roles from otherrole-constraints
+ for(var i = 0; i !== this.__arContainer__.__frames__.length; ++i){
+ this.__makeRolesFromORC__(this.__arContainer__.__frames__[i].getType(), this.__arContainer__.__frames__[i].getPlayer());
+ }
},
"__makeRolesFromARC__" : function(associationRoleConstraint, rolePlayerConstraints){
if(!associationRoleConstraint || !rolePlayerConstraints || rolePlayerConstraints.length === 0) return;
@@ -1522,7 +1494,7 @@
var _players = cleanedPlayers;
_players.unshift(selectedPlayer);
var role = new RoleC(null, roleType, _players, this.__arContainer__, removeFunction, addFunction);
- this.__setRoleChangePlayerHandler__(role);
+ this.__setRoleChangePlayerHandler__(role, this.__arContainer__.__frames__, rolePlayerConstraints, null);
this.__error__.insert({"before" : role.getFrame()});
++rolesCreated;
}
@@ -1552,7 +1524,7 @@
}
var role = new RoleC(null, roleType, cleanedPlayers, this.__arContainer__, removeFunction, addFunction);
- this.__setRoleChangePlayerHandler__(role);
+ this.__setRoleChangePlayerHandler__(role, this.__arContainer__.__frames__, rolePlayerConstraints, null);
this.__error__.insert({"before" : role.getFrame()});
++rolesCreated;
++currentlyCreated;
@@ -1562,7 +1534,38 @@
}
},
"__makeRolesFromORC__" : function(roleType, player){
+ var orpcs = getOtherRoleConstraintsForRole(new Array(roleType), new Array(player), this.__otherRoleConstraints__);
+ var removeFunction = function(event){ alert("removeFunction"); };
+ var addFunction = function(event){ alert("addFunction"); };
+ for(var i = 0; i !== orpcs.length; ++i){
+ var cPlayers = orpcs[i].players;
+ var cRoleType = orpcs[i].roleType;
+ var cOtherPlayers = orpcs[i].otherPlayers;
+ var cOtherRoleType = orpcs[i].otherRoleType;
+ var cMin = parseInt(orpcs[i].cardMin);
+ if(!cOtherPlayers || cOtherPlayers.length < cMin) throw "from __makeRolesFromORC__(): not enough players(=" + cOtherPlayers.length + ") for roletype + \"" + cOtherRoleType.flatten()[0] + "\"!";
+ var existingRoles = this.getExistingRoles(cOtherRoleType, cOtherPlayers, this.__orContainer__.__frames__);
+ for(var j = 0; j < cMin - existingRoles.length; ++j){
+ // --- removes all players that are already selected from the
+ // --- current players list
+ var cleanedPlayers = new Array();
+ for(var k = 0; k !== cOtherPlayers.length; ++k){
+ if(this.getExistingRoles(cOtherRoleType, cOtherPlayers[k], this.__orContainer__.__frames__).length === 0){
+ cleanedPlayers.push(cOtherPlayers[k]);
+ }
+ }
+ // --- removes the player that will be selected in this role
+ // --- from all existing roles
+ for(var j = 0; this.__orContainer__.__frames__ && j !== this.__orContainer__.__frames__.length; ++j){
+ this.__orContainer__.__frames__[j].removePlayer(cleanedPlayers[0]);
+ }
+
+ var role = new RoleC(null, cOtherRoleType, cleanedPlayers, this.__orContainer__, removeFunction, addFunction);
+ this.__setRoleChangePlayerHandler__(role, this.__orContainer__.__frames__, null, orpcs);
+ this.__error__.insert({"before" : role.getFrame()});
+ }
+ }
},
"getExistingRoles" : function(roleType, players, roles){
var rolesFound = new Array();
@@ -1576,19 +1579,90 @@
return rolesFound;
},
- "__setRoleChangePlayerHandler__" : function(role){
+ "__setRoleChangePlayerHandler__" : function(role, roleContainer, arConstraints, orConstraints){
+ var constraints = null;
+ if(arConstraints && arConstraints.length !== 0) constraints = arConstraints;
+ else if(orConstraints && orConstraints.length !== 0) constraints = orConstraints;
+ else if(arConstraints && orConstraints && arConstraints.length !== 0 && orConstraints.length !== 0) throw "From __setRoleChangePlayerHandler__(): one of the parameters arConstraints or orConstraints must be set to null";
+ role.__lastPlayer__ = new Array(role.getPlayer());
var select = role.__table__.select("tr." + CLASSES.playerFrame())[0].select("td." + CLASSES.content())[0].select("select")[0];
- select.observe("change", function(event){ alert("changed!"); });
-
+ function setEvent(myself){
+ select.observe("change", function(event){
+ role.__lastPlayer__.push(role.getPlayer());
+ if(role.__lastPlayer__.length > 2) role.__lastPlayer__.shift();
+ if(!roleContainer || roleContainer.length < 2 || ! constraints || constraints.length === 0) return;
+ role.getLastPlayer = function(){
+ return role.__lastPlayer__[role.__lastPlayer__.length - 2];
+ }
+ // --- selects the players which have to be removed or added to
+ // --- the found roles
+ var playerToAdd = new Array(role.getLastPlayer());
+ var playerToRemove = new Array(role.getPlayer());
+
+ // --- collects all roles depending on the same constraint as the passed role
+ var existingRoles = new Array();
+ for(var i = 0; constraints && i !== constraints.length; ++i){
+ var roleType = orConstraints ? constraints[i].otherRoleType : constraints[i].roleType;
+ var players = orConstraints ? constraints[i].otherPlayers : constraints[i].players;
+
+ // --- adds new psi of the roles have to be added
+ for(var j = 0; j !== players.length; ++j){
+ if(players[j].indexOf(playerToRemove[0]) !== -1){
+ for(var l = 0; l !== players[j].length; ++l){
+ if(players[j][l] !== playerToRemove[0]) playerToRemove.push(players[j][l]);
+ }
+ }
+ if(players[j].indexOf(playerToAdd[0]) !== -1){
+ for(var l = 0; l !== players[j].length; ++l){
+ if(players[j][l] !== playerToAdd[0]) playerToAdd.push(players[j][l]);
+ }
+ }
+ }
+
+ var foundRoles = myself.getExistingRoles(roleType, players, roleContainer);
+ for(var j = 0; j !== foundRoles.length; ++j){
+ existingRoles.push(foundRoles[j]);
+ }
+ }
+ existingRoles = existingRoles.without(role);
+
+ // --- removes and adds the new selected psi-value
+ // --- and the old deselected psi if the player is another one
+ if(playerToRemove.indexOf(role.getLastPlayer()) === -1){
+ for(var i = 0; i !== existingRoles.length; ++i){
+ existingRoles[i].addPlayer(playerToAdd);
+ existingRoles[i].removePlayer(playerToRemove);
+ }
+ }
+ });
+ }
+ setEvent(this);
},
"getContent" : function(){
- // TODO: implement
+ if((!this.__orContainer__.__frames__ && this.__orContainer__.frames__.length === 0) || (!this.__arContainer__.__frames__ && this.__arContainer__.__frames__.length === 0)) return null;
+ var roles = new Array();
+ for(var i = 0; this.__arContainer__.__frames__ && i !== this.__arContainer__.__frames__.length; ++i){
+ roles.push(this.__arContainer__.__frames__[i].getContent());
+ }
+ for(var i = 0; this.__orContainer__.__frames__ && i !== this.__orContainer__.__frames__.length; ++i){
+ roles.push(this.__orContainer__.__frames__[i].getContent());
+ }
+ return roles;
},
"toJSON" : function(){
- // TODO: implement
+ if((!this.__orContainer__.__frames__ && this.__orContainer__.frames__.length === 0) || (!this.__arContainer__.__frames__ && this.__arContainer__.__frames__.length === 0)) return "null";
+ var roles = "[";
+ for(var i = 0; this.__arContainer__.__frames__ && i !== this.__arContainer__.__frames__.length; ++i){
+ roles += this.__arContainer__.__frames__[i].toJSON() + ",";
+ }
+ for(var i = 0; this.__orContainer__.__frames__ && i !== this.__orContainer__.__frames__.length; ++i){
+ roles += this.__orContainer__.__frames__[i].toJSON() + ",";
+ }
+ return roles.substring(0, roles.length - 1) + "]";
},
"isValid" : function(){
// TODO: implement
+ return true;
}});
@@ -1676,16 +1750,26 @@
this.__roles__.resetValues(_roleConstraints, _playerConstraints, _otherRoleConstraints);
},
"getContent" : function(){
- // TODO: implement
+ if(!this.isUsed()) return null;
+ return {"itemIdentities" : this.__itemIdentity__.getContent(true, true),
+ "type" : new Array(this.__type__.__frames__[0].getContent()),
+ "scopes" : this.__scope__.getContent(),
+ "roles" : this.__roles__.getContent()};
},
"toJSON" : function(){
- // TODO: implement
+ if(!this.isUsed()) return "null";
+ return "{\"itemIdentities\":" + this.__itemIdentity__.toJSON(true, true) +
+ ",\"type\":[" + this.__type__.__frames__[0].toJSON() + "]" +
+ ",\"scopes\":" + this.__scope__.toJSON() +
+ ",\"roles\":" + this.__roles__.toJSON() + "}";
},
"isValid" : function(){
// TODO: implement
+ return true;
},
"isUsed" : function(){
- // TODO: implement
+ // TODO: implement (activate button)
+ return true;
}});
@@ -1718,22 +1802,56 @@
tr.update(td);
this.__table__.insert({"bottom" : tr});
}
+ function setMinimizeHandler(myself){
+ myself.__caption__.observe("click", function(event){
+ myself.minimize();
+ });
+ }
+ setMinimizeHandler(this);
+/*
+ var button = new Element("input", {"type" : "button", "value" : "toJSON()"});
+ function test(myself){
+ button.observe("click", function(event){
+ alert("content:\n\n" + myself.getContent());
+ alert("JSON:\n\n" + myself.toJSON());
+ });
+ }
+ test(this);
+ this.getFrame().insert({"bottom" : button});
+*/
}
catch(err){
alert("From AssociationContainerC(): " + err);
}
},
"getContent" : function(){
- // TODO: implement
+ var associations = new Array();
+ for(var i = 0; this.__container__.__frames__ && i !== this.__container__.__frames__.length; ++i){
+ if(this.__container__.__frames__[i].isUsed() === true) associations.push(this.__container__.__frames__[i].getContent());
+ }
+ if(associations.length === 0) return null;
+ return associations;
},
"toJSON" : function(){
- // TODO: implement
+ var associations = "[";
+ for(var i = 0; this.__container__.__frames__ && i !== this.__container__.__frames__.length; ++i){
+ if(this.__container__.__frames__[i].isUsed() === true) associations += this.__container__.__frames__[i].toJSON() +",";
+ }
+
+ if(associations === "[") return "null";
+ return associations.substring(0, associations.length - 1) + "]";
},
"isValid" : function(){
// TODO: implement
+ return true;
},
"minimize" : function(){
- // TODO: implement
+ var rows = this.__table__.select("tr." + CLASSES.associationFrame());
+ for(var i = 0; i != rows.length; ++i){
+ if(this.__minimized__ === false) rows[i].hide();
+ else rows[i].show();
+ }
+ this.__minimized__ = !this.__minimized__;
}});
1
0

[isidorus-cvs] r33 - in trunk: docs src/ajax/javascripts src/json src/unit_tests
by Lukas Giessmann 05 Jun '09
by Lukas Giessmann 05 Jun '09
05 Jun '09
Author: lgiessmann
Date: Fri Jun 5 06:42:59 2009
New Revision: 33
Log:
client ajax: added the basic handling for roleplayer-constraints and associationrole-constraints
Modified:
trunk/docs/xtm_json.txt
trunk/src/ajax/javascripts/datamodel.js
trunk/src/ajax/javascripts/tmcl_tools.js
trunk/src/json/json_tmcl.lisp
trunk/src/unit_tests/poems.xtm
Modified: trunk/docs/xtm_json.txt
==============================================================================
--- trunk/docs/xtm_json.txt (original)
+++ trunk/docs/xtm_json.txt Fri Jun 5 06:42:59 2009
@@ -341,7 +341,7 @@
//+-----------------------------------------------------------------------------
{
"players" : [ [ "topic-psi-1", "topic-psi-2", "..." ], [ "topic-2-psi-1", "..."], <...> ]
- "roleTypes" : [ [ "topic-psi-1", "topic-psi-2", "..." ], [ "subtype-psi-1", "..." ], <...> ],
+ "roleType" : [ [ "topic-psi-1", "topic-psi-2", "..." ], [ "subtype-psi-1", "..." ], <...> ],
"cardMin" : "unsigned integer in string representation",
"cardMax" : "unsigned integer in string representation or the string MAX_INT"
}
@@ -356,10 +356,10 @@
//+ 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", "..." ],
+ "players" : [ [ "topic-psi-1", "topic-psi-2", "..." ], [ "topic-2-psi-1", "..."], <...> ] ],
+ "roleType" : [ [ "topic-psi-1", "topic-psi-2", "..." ], [ "subtype-psi-1", "..." ], <...> ],
+ "otherPlayers" : [ "topic-psi-1", "topic-psi-2", "..." ], [ "topic-2-psi-1", "..."], <...> ] ],
+ "otherRoleType" : [ "topic-psi-1", "topic-psi-2", "..." ], [ "subtype-psi-1", "..." ], <...> ],
"cardMin" : "unsigned integer in string representation",
"cardMax" : "unsigned integer in string representation or the string MAX_INT"
}
Modified: trunk/src/ajax/javascripts/datamodel.js
==============================================================================
--- trunk/src/ajax/javascripts/datamodel.js (original)
+++ trunk/src/ajax/javascripts/datamodel.js Fri Jun 5 06:42:59 2009
@@ -1276,11 +1276,12 @@
// --- representation of a role element.
-var RoleC = Class.create(ContainerC, {"initialize" : function($super, itemIdentities, roleTypes, rolePlayers, owner, min, max){
+var RoleC = Class.create(ContainerC, {"initialize" : function($super, itemIdentities, roleTypes, rolePlayers, owner, removeFunction, addFunction){
$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";
+ if(!rolePlayers || rolePlayers.length === 0) throw "From RoleC(): rolePlayers must be set";
+ if(!removeFunction || !addFunction) throw "From RoleC(): removeFunction and addFunction must be set!";
owner.__frames__.push(this);
this.__frame__.writeAttribute({"class" : CLASSES.roleFrame()});
this.__table__ = new Element("table", {"class" : CLASSES.roleFrame()});
@@ -1291,16 +1292,25 @@
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);
- });
+ checkRemoveAddButtons(owner, 1, -1);
+ setRemoveAddHandler(this, owner, 1, -1, function(){ /*do nothing*/ });
+ // --- resets the add and remove handlers
+ var cTd = this.__table__.select("tr." + CLASSES.itemIdentityFrame())[0].select("td." + CLASSES.controlColumn())[0].select("span." + CLASSES.clickable());
+ var removeButton = cTd[1];
+ var addButton = cTd[2];
+ removeButton.show();
+ addButton.show();
+ removeButton.stopObserving();
+ addButton.stopObserving();
+ removeButton.observe("click", removeFunction);
+ addButton.observe("click", addFunction);
// --- 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});
+ // TODO: implement a onTypeChangeHandler
// --- player
var players = this.__rolePlayers__.flatten();
@@ -1312,6 +1322,67 @@
alert("From RoleC(): " + err);
}
},
+ "addPlayer" : function(player){
+ if(!player || player.length === 0) return;
+ var selected = this.__player__.__frames__[0].getContent();
+ var select = this.__player__.__frames__[0].getFrame().select("select")[0];
+ select.update("");
+ if(this.__rolePlayers__){
+ var j = 0;
+ for(var i = 0; i !== player.length; ++i){
+ j = 0;
+ for( ; j !== this.__rolePlayers__.length; ++j){
+ if(this.__rolePlayers__[j].indexOf(player[i]) !== -1) break;
+ }
+ if(j !== this.__rolePlayers__.length){
+ this.__rolePlayers__[j] = player;
+ alert("test");
+ break;
+ }
+ }
+ if(j === this.__rolePlayers__.length)this.__rolePlayers__.push(player);
+ }
+ else {
+ this.__rolePlayers__ = new Array(player);
+ }
+ for(var i = 0; i !== this.__rolePlayers__.length; ++i){
+ for(var j = 0; j !== this.__rolePlayers__[i].length; ++j){
+ var opt = new Element("option", {"value" : this.__rolePlayers__[i][j]}).update(this.__rolePlayers__[i][j]);
+ if(this.__rolePlayers__[i][j] !== selected){
+ select.insert({"bottom" : opt});
+ }
+ else {
+ select.insert({"top" : opt});
+ }
+ }
+ }
+ },
+ "removePlayer" : function(player){
+ if(!player || player.length === 0 || !this.__rolePlayers__ || this.__rolePlayers__.length === 0) return;
+ var selected = this.__player__.__frames__[0].getContent();
+ var select = this.__player__.__frames__[0].getFrame().select("select")[0];
+ select.update("");
+ var j = 0;
+ for(var i = 0; i !== player.length; ++i){
+ j = 0;
+ for( ; j !== this.__rolePlayers__.length; ++j){
+ if(this.__rolePlayers__[j].indexOf(player[i]) !== -1) break;
+ }
+ if(j !== this.__rolePlayers__.length) break;
+ }
+ this.__rolePlayers__ = this.__rolePlayers__.slice(0, j).concat(this.__rolePlayers__.slice(j + 1, this.__rolePlayers__.length));
+ for(var i = 0; i !== this.__rolePlayers__.length; ++i){
+ for(var j = 0; j !== this.__rolePlayers__[i].length; ++j){
+ var opt = new Element("option", {"value" : this.__rolePlayers__[i][j]}).update(this.__rolePlayers__[i][j]);
+ if(this.__rolePlayers__[i][j] !== selected){
+ select.insert({"bottom" : opt});
+ }
+ else {
+ select.insert({"top" : opt});
+ }
+ }
+ }
+ },
"getType" : function(){
return this.__type__.__frames__[0].getContent();
},
@@ -1345,32 +1416,170 @@
// --- contains all roles of an association
-var RoleContainerC = Class.create(ContainerC, {"initialize" : function($super, contents, roleConstraints, playerConstraints, otherRoleConstraints){
+var RoleContainerC = Class.create(ContainerC, {"initialize" : function($super, contents, associationRoleConstraints, rolePlayerConstraints, otherRoleConstraints){
$super();
this.__frame__.writeAttribute({"class" : CLASSES.roleContainer()});
- this.__container__ = new Object();
+ this.__arContainer__ = new Object();
+ this.__orContainer__ = new Object();
+
+ /*
+
+ *associationrole-constraints: A association role constraint defines how many and of what type the roles in associations of given a type must be.
+ *min: card-min indicating the minimum number of times the role can appear in the association
+ *max: card-max indicating the maximum number of times the role can appear in the association
+ *roleplayer-constraints: A role player constraint defines a way to constrain the type of allowed role players of a given role with a given type
+ in an association of a given type.
+ *min: card-min indicating the minimum number of times a topic can play the role with the given type in the given
+ association of the given type
+ *max: card-max indicating the maximum number of times a topic can play the role with the given type in the given
+ association of the given type
+ *otherrole-constraints: A other role constraint defines a way to constrain the allowed type of role player given the existence of another role
+ player type in an association.
+ *min: card-min indicating the minimum number of times the other role can occur
+ *max: card-max indicating the maximum number of times the other role can occur
+
+
+algorithmus:
+OK *alle rollen aus associationroleconstraints erstellen in einem __arContainer__
+OK *überprüfen, ob die kardinalitäten der roleplayer mit den kardinalitäten der associationrole übereinstimmen
+OK *card-min rp < card-min ar -> fehler
+OK *card-max rp > card-max ar -> fehler
+OK *card-min rp > card-max ar -> fehler
+OK *card-max rp < card-min ar -> fehler
+OK *zu allen gefundenen roles vorhandene roleplayer-constraints suchen
+OK *alle roleplayer sammeln und an eine leere option anhängen, anschließend in RoleC anhängen
+*__orContainer__ für otherrole-constraints initialisieren
+*handler hinzufügen
+ */
+
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()});
- }
+ if((!contents || contents.length === 0) && associationRoleConstraints){
+ this.resetValues(associationRoleConstraints, rolePlayerConstraints, otherRoleConstraints);
}
else {
// TODO: check already existing contents and order them to the corresponding fields
}
-
-
-
}
catch(err){
alert("From RoleContainerC(): " + err);
}
},
- "resetValues" : function(roleConstraints, playerConstraints, otherRoleConstraints){
+ "resetValues" : function(associationRoleConstraints, rolePlayerConstraints, otherRoleConstraints){
+ this.__associationRoleConstraints__ = associationRoleConstraints;
+ this.__rolePlayerConstraints__ = rolePlayerConstraints;
+ this.__otherRoleConstraints__ = otherRoleConstraints;
+
+ try{
+ for(var i = 0; this.__arContainer__.__frames__ && i !== this.__arContainer__.__frames__.length; ++i){
+ this.__arContainer__.__frames__[i].remove();
+ }
+ this.__arContainer__ = new Object();
+ }
+ catch(err){
+ this.__arContainer__ = new Object();
+ }
+ try{
+ for(var i = 0; this.__orContainer__.__frames__ && i !== this.__orContainer__.__frames__.length; ++i){
+ this.__orContainer__.__frames__[i].remove();
+ }
+ this.__orContainer__ = new Object();
+ }
+ catch(err){
+ this.__orContainer__ = new Object();
+ }
+
+
+ // --- creates all roles from existing associationroleconstraints and roleplayerConstraints
+ // TODO: insert existing contents to the corresponding constraints
+ for(var i = 0; this.__associationRoleConstraints__ && i !== this.__associationRoleConstraints__.length; ++i){
+ var arc = this.__associationRoleConstraints__[i];
+ var foundRpcs = getRolePlayerConstraintsForRole(arc.roleType, this.__rolePlayerConstraints__);
+ this.__makeRolesFromARC__(arc, foundRpcs);
+ }
+ },
+ "__makeRolesFromARC__" : function(associationRoleConstraint, rolePlayerConstraints){
+ if(!associationRoleConstraint || !rolePlayerConstraints || rolePlayerConstraints.length === 0) return;
+ checkCardinalitiesARC_RPC(associationRoleConstraint, rolePlayerConstraints);
+
+ // --- creates all roles with all needed players
+ var rolesCreated = 0;
+ var allAvailablePlayers = extractPlayersOfConstraints(rolePlayerConstraints);
+ var roleType = associationRoleConstraint.roleType;
+ var roleMin = associationRoleConstraint.cardMin;
+ for(var i = 0; i !== rolePlayerConstraints.length; ++i){
+ var playerMin = rolePlayerConstraints[i].cardMin;
+ var currentAvailablePlayers = rolePlayerConstraints[i].players;
+ var cleanedPlayers = cleanPlayers(allAvailablePlayers, currentAvailablePlayers);
+ for(var j = playerMin; j < currentAvailablePlayers.length; ++j){
+ cleanedPlayers.push(currentAvailablePlayers[j]);
+ }
+ if(currentAvailablePlayers.length < playerMin) throw "From __makeRolesFromARC__(): not enough players(=" + currentAvailablePlayers.length + ") to reach card-min(=" + playerMin + ") of roletype\"" + roleType.flatten()[0] + "\"!";
+ for(var j = 0; j !== playerMin; ++j){
+ var removeFunction = function(event){ alert("removeFunction"); };
+ var addFunction = function(event){ alert("addFunction"); };
+ var selectedPlayer = currentAvailablePlayers[j];
+ var _players = cleanedPlayers;
+ _players.unshift(selectedPlayer);
+ var role = new RoleC(null, roleType, _players, this.__arContainer__, removeFunction, addFunction);
+ this.__setRoleChangePlayerHandler__(role);
+ this.__error__.insert({"before" : role.getFrame()});
+ ++rolesCreated;
+ }
+ }
+
+ // --- creates all further needed roles with players that owns a card-max > existing players
+ while(rolesCreated < roleMin){
+ var currentlyCreated = 0;
+ for(var i= 0; i !== rolePlayerConstraints.length; ++i){
+ // existing roles --> all roles that owns a player which is selected of those listed in the roleplayer-constraint
+ var existingRoles = this.getExistingRoles(roleType, rolePlayerConstraints[i].players, this.__arContainer__.__frames__);
+ var availablePlayers = rolePlayerConstraints[i].players;
+ if(existingRoles.length < rolePlayerConstraints[i].cardMax && availablePlayers.length > existingRoles.length){
+ var currentAvailablePlayers = rolePlayerConstraints[i].players;
+ var cleanedPlayers = cleanPlayers(allAvailablePlayers, currentAvailablePlayers);
+
+ // --- adds players that are not selected yet
+ for(var j = 0; j !== currentAvailablePlayers.length; ++j){
+ if(this.getExistingRoles(roleType, currentAvailablePlayers[j], this.__arContainer__.__frames__).length === 0){
+ cleanedPlayers.push(currentAvailablePlayers[j]);
+ }
+ }
+
+ // --- removes the player which will be seleted by the new created role of all other select-elements
+ for(var j = 0; j !== this.__arContainer__.__frames__.length; ++j){
+ this.__arContainer__.__frames__[j].removePlayer(cleanedPlayers[0]);
+ }
+
+ var role = new RoleC(null, roleType, cleanedPlayers, this.__arContainer__, removeFunction, addFunction);
+ this.__setRoleChangePlayerHandler__(role);
+ this.__error__.insert({"before" : role.getFrame()});
+ ++rolesCreated;
+ ++currentlyCreated;
+ }
+ }
+ if(currentlyCreated === 0) throw "Not enough players to create all needed roles of the type \"" + roleType.flatten()[0] + "\"!";
+ }
+ },
+ "__makeRolesFromORC__" : function(roleType, player){
+
+ },
+ "getExistingRoles" : function(roleType, players, roles){
+ var rolesFound = new Array();
+ if(!roles || roles.length === 0) return rolesFound;
- // TODO: implement
+ var allTypes = roleType && roleType.length !== 0 ? roleType.flatten() : new Array();
+ var allPlayers = players && players.length !== 0 ? players.flatten() : new Array();
+ for(var i = 0; i !== roles.length; ++i){
+ if(allTypes.indexOf(roles[i].getType()) !== -1 && allPlayers.indexOf(roles[i].getPlayer()) !== -1) rolesFound.push(roles[i]);
+ }
+
+ return rolesFound;
+ },
+ "__setRoleChangePlayerHandler__" : function(role){
+ var select = role.__table__.select("tr." + CLASSES.playerFrame())[0].select("td." + CLASSES.content())[0].select("select")[0];
+ select.observe("change", function(event){ alert("changed!"); });
+
},
"getContent" : function(){
// TODO: implement
@@ -1380,9 +1589,6 @@
},
"isValid" : function(){
// TODO: implement
- },
- "isUsed" : function(){
- // TODO: implement
}});
Modified: trunk/src/ajax/javascripts/tmcl_tools.js
==============================================================================
--- trunk/src/ajax/javascripts/tmcl_tools.js (original)
+++ trunk/src/ajax/javascripts/tmcl_tools.js Fri Jun 5 06:42:59 2009
@@ -63,4 +63,140 @@
if(foundContents < min || foundContents > max) return false;
}
return true;
+}
+
+
+// --- Returns an array of rolePlayerConstraints belonging to the given type in roleType.
+// --- roleType is of the form [["psi-1", "psi-2", "..."], ["sub-psi-1", "..."], <...>]
+function getRolePlayerConstraintsForRole(roleType, rolePlayerConstraints){
+ if(!roleType || roleType.length === 0 || !rolePlayerConstraints || rolePlayerConstraints.length === 0) return new Array();
+
+ var foundConstraints = new Array();
+ var allRoleTypes = roleType.flatten();
+ for(var i = 0; i !== rolePlayerConstraints.length; ++i){
+ var allCRoleTypes = rolePlayerConstraints[i].roleType.flatten();
+ for(var j = 0; j !== allRoleTypes.length; ++j){
+ if(allCRoleTypes.indexOf(allRoleTypes[j]) !== -1){
+ foundConstraints.push(rolePlayerConstraints[i]);
+ break;
+ }
+ }
+ }
+ return foundConstraints;
+}
+
+
+// --- Returns an array of otherRoleConstraints belonging to the given roleType and players.
+// --- roleType is of the form [["psi-1", "psi-2", "..."], ["sub-psi-1", "..."], <...>]
+// --- players is of the form [["t1-psi-1", "t1-psi-2", "..."], ["t2-psi-1", "..."], <...>]
+function getOtherRoleConstraintsForRole(roleType, players, otherRoleConstraints){
+ if(!roleType || roleType.length === 0 || !players || players.length === 0 || !otherRoleConstraints || otherRoleConstraints.length === 0) return new Array();
+
+ var foundConstraints = new Array();
+ var allRoleTypes = roleType.flatten();
+ var allPlayers = players.flatten();
+ for(var i = 0; i !== otherRoleConstraints.length; ++i){
+ var roleTypeMatches = false;
+ var allCRoleTypes = otherRoleConstraints[i].roleType.flatten();
+ for(var j = 0; j !== allPlayers.length; ++j){
+ if(allCRoleTypes.indexOf(allRoleTypes[j]) !== -1){
+ var allCPlayers = otherRoleConstraints[i].players.flatten();
+ for(var k = 0; k !== allPlayers.length; ++k){
+ if(allCPlayers.indexOf(allPlayers[k]) !== -1){
+ foundConstraints.push(otherRoleConstraints[i]);
+ break;
+ }
+ }
+ break;
+ }
+ }
+ }
+ return foundConstraints;
+}
+
+
+// --- Returns the sum of all cardMin values of all rolePlayerConstraints.
+function getRolePlayerMinForRole(anyRoleConstraints){
+ if(!anyRoleConstraints || anyRoleConstraints === 0) return 0;
+ var min = 0;
+ for(var i = 0; i !== anyRoleConstraints.length; ++i){
+ min += parseInt(anyRoleConstraints[i].cardMin);
+ }
+ return min;
+}
+
+
+// --- Returns the sum of all cardMax values of all rolePlayerConstraints.
+function getRolePlayerMaxForRole(anyRoleConstraints){
+ if(!anyRoleConstraints || anyRoleConstraints === 0) return 0;
+ var max = 0;
+ for(var i = 0; i !== anyRoleConstraints.length; ++i){
+ if(anyRoleConstraints[i].cardMax === "MAX_INT") return "*";
+ else max += parseInt(anyRoleConstraints[i].cardMax);
+ }
+ return max;
+}
+
+
+// --- checks the cardinalities of all rolePlayerconstraints depending on a
+// --- given associationRoleConstraint
+function checkCardinalitiesARC_RPC(associationRoleConstraint, rolePlayerConstraints){
+ if(!associationRoleConstraint) throw "From checkCardinalitiesARC(): associationRoleConstraint is not set!";
+ if(!rolePlayerConstraints || rolePlayerConstraints.length === 0) throw "From checkCardinalitiesARC(): rolePlayerConstraints is not set!";
+ var arMin = parseInt(associationRoleConstraint.cardMin);
+ var arMax = associationRoleConstraint.cardMax === "MAX_INT" ? "*" : parseInt(associationRoleConstraint.cardMax);
+ var rpcs = getRolePlayerConstraintsForRole(associationRoleConstraint.roleType, rolePlayerConstraints);
+ var rpMin = getRolePlayerMinForRole(rpcs);
+ var rpMax = getRolePlayerMaxForRole(rpcs);
+ var type = associationRoleConstraint.roleType.flatten()[0];
+
+ if(rpMax !== "*" && rpMax < arMin) throw "Not enough players available for roletype \"" + type + "\" (rpMax=" + rpMax + ", arMin=" + arMin + ")";
+ if(arMax !== "*" && rpMin > arMax) throw "Too much players for the roletype \"" + type + "\" (rpMin=" + rpMin + ", arMax=" + arMax + ")";
+ /*
+ if(rpMin < arMin) throw "sum of card-min(=" + rpMin + ") of all roleplayer-constraints < card-min(=" + arMin + ") of associationrole-constraint for the role \"" + type + "\"! not enough players";
+ if(arMax !== "*" && (rpMax === "*" || rpMax > arMax)) throw "sum of card-max(=" + rpMax + ") of all roleplayer-constraints > card-max(=" + arMax + ") of associationrole-constraint for the role \"" + type + "\"! too much players"
+ if(arMax !== "*" && rpMin > arMax) throw "sum of card-min(=" + rpMin + ") of all roleplayer-constraints > card-max(=" + arMax + ") of associationrole-constraint for the role \"" + type + "\"! too much players";
+ if(rpMax !== "*" && rpMax < arMin) throw "sum of card-max(=" + rpMax + ") of all roleplayer-constraints > card-min(=" + arMin + ") of associationrole-constraint for the role \"" + type + "\"! not enough players";
+ */
+}
+
+
+// --- Returns all listed players of a constraint of the type
+// --- roleplayer-constraint or otherrole-constraint and returns them
+// --- as an array.
+function extractPlayersOfConstraints(anyConstraints){
+ var players = new Array();
+ if(!anyConstraints || anyConstraints.length === 0) return players;
+
+ for(var i = 0; i !== anyConstraints.length; ++i){
+ for(var j = 0; j !== anyConstraints[i].players.length; ++j){
+ players.push(anyConstraints[i].players[j])
+ }
+ }
+
+ return players;
+}
+
+
+// --- Returns an array of players where the players from playersToClean will
+// --- be deleted from allPlayers.
+function cleanPlayers(allPlayers, playersToClean){
+ var cleanedPlayers = new Array();
+ if(!allPlayers) return cleanedPlayers;
+ if(!playersToClean) return allPlayers;
+
+ for(var i = 0; i !== allPlayers.length; ++i){
+ var toDel = false;
+ for(var j = 0; j !== allPlayers[i].length; ++j){
+ for(var k = 0; k !== playersToClean.length; ++k){
+ if(playersToClean[k].indexOf(allPlayers[i][j]) !== -1){
+ toDel = true;
+ break;
+ }
+ }
+ if(toDel === true) break;
+ }
+ if(toDel === false) cleanedPlayers.push(allPlayers[i]);
+ }
+ return cleanedPlayers;
}
\ 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 Fri Jun 5 06:42:59 2009
@@ -192,7 +192,7 @@
(topics-to-json-list
(list-instances (getf involved-topic-tupple :player) topictype topictype-constraint))))
(json-role
- (concatenate 'string "\"roleTypes\":"
+ (concatenate 'string "\"roleType\":"
(topics-to-json-list
(getf (list-subtypes (getf involved-topic-tupple :role) roletype roletype-constraint) :subtypes))))
(json-otherplayer
@@ -291,7 +291,7 @@
(topics-to-json-list
(list-instances (getf role-player-tupple :player) topictype topictype-constraint))))
(json-role
- (concatenate 'string "\"roleTypes\":"
+ (concatenate 'string "\"roleType\":"
(topics-to-json-list
(getf (list-subtypes (getf role-player-tupple :role) roletype roletype-constraint) :subtypes))))
(card-min
Modified: trunk/src/unit_tests/poems.xtm
==============================================================================
--- trunk/src/unit_tests/poems.xtm (original)
+++ trunk/src/unit_tests/poems.xtm Fri Jun 5 06:42:59 2009
@@ -1,5 +1,57 @@
<?xml version="1.0" encoding="UTF-8"?>
<tm:topicMap version="2.0" xmlns:tm="http://www.topicmaps.org/xtm/">
+ <!-- test: defines some scopse constraints for associations of the type "born-in" -->
+ <tm:topic id="scoped-born-in-constraint-1">
+ <tm:subjectIdentifier href="http://some.where/constraint-psis/scoped-born-in-constraint-1"/>
+ <tm:instanceOf><tm:topicRef href="#associationtypescope-constraint"/></tm:instanceOf>
+ <tm:occurrence>
+ <tm:type><tm:topicRef href="#card-min"/></tm:type>
+ <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#unsignedInt">1</tm:resourceData>
+ </tm:occurrence>
+ <tm:occurrence>
+ <tm:type><tm:topicRef href="#card-max"/></tm:type>
+ <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#unsignedInt">2</tm:resourceData>
+ </tm:occurrence>
+ </tm:topic>
+
+ <tm:association>
+ <tm:type><tm:topicRef href="#applies-to"/></tm:type>
+ <tm:role>
+ <tm:type><tm:topicRef href="#constraint-role"/></tm:type>
+ <tm:topicRef href="#scoped-born-in-constraint-1"/>
+ </tm:role>
+ <tm:role>
+ <tm:type><tm:topicRef href="#associationtype-role"/></tm:type>
+ <tm:topicRef href="#written-by"/>
+ </tm:role>
+ </tm:association>
+
+ <tm:association>
+ <tm:type><tm:topicRef href="#applies-to"/></tm:type>
+ <tm:role>
+ <tm:type><tm:topicRef href="#constraint-role"/></tm:type>
+ <tm:topicRef href="#scoped-born-in-constraint-1"/>
+ </tm:role>
+ <tm:role>
+ <tm:type><tm:topicRef href="#scopetype-role"/></tm:type>
+ <tm:topicRef href="#en"/>
+ </tm:role>
+ </tm:association>
+
+ <tm:association>
+ <tm:type><tm:topicRef href="#applies-to"/></tm:type>
+ <tm:role>
+ <tm:type><tm:topicRef href="#constraint-role"/></tm:type>
+ <tm:topicRef href="#scoped-born-in-constraint-1"/>
+ </tm:role>
+ <tm:role>
+ <tm:type><tm:topicRef href="#scopetype-role"/></tm:type>
+ <tm:topicRef href="#de"/>
+ </tm:role>
+ </tm:association>
+ <!-- end test -->
+
+
<!-- ===================================================================== -->
<!-- === TMCL meta-model topics ========================================== -->
<!-- ===================================================================== -->
@@ -1566,6 +1618,46 @@
</tm:role>
</tm:association>
+
+ <!-- a subtype of poem-content with another datatype as the original type -->
+ <tm:topic id="sub-poem-content">
+ <tm:subjectIdentifier href="http://some.where/base-psis/sub-poem-content"/>
+ </tm:topic>
+
+ <tm:association>
+ <tm:type><tm:topicRef href="#supertype-subtype"/></tm:type>
+ <tm:role>
+ <tm:type><tm:topicRef href="#subtype"/></tm:type>
+ <tm:topicRef href="#sub-poem-content"/>
+ </tm:role>
+ <tm:role>
+ <tm:type><tm:topicRef href="#supertype"/></tm:type>
+ <tm:topicRef href="#poem-content"/>
+ </tm:role>
+ </tm:association>
+
+ <tm:topic id="sub-poem-content-occurrence-datatype-constraint">
+ <tm:subjectIdentifier href="http://some.where/constraint-psis/sub-poem-content-occurrence-datatype-cons…"/>
+ <tm:instanceOf><tm:topicRef href="#occurrencedatatype-constraint"/></tm:instanceOf>
+ <tm:occurrence>
+ <tm:type><tm:topicRef href="#datatype"/></tm:type>
+ <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#string">http://www.w3.org/2001/XMLSchema#float</tm:resourceData>
+ </tm:occurrence>
+ </tm:topic>
+
+ <tm:association>
+ <tm:type><tm:topicRef href="#applies-to"/></tm:type>
+ <tm:role>
+ <tm:type><tm:topicRef href="#constraint-role"/></tm:type>
+ <tm:topicRef href="#sub-poem-content-occurrence-datatype-constraint"/>
+ </tm:role>
+ <tm:role>
+ <tm:type><tm:topicRef href="#occurrencetype-role"/></tm:type>
+ <tm:topicRef href="#sub-poem-content"/>
+ </tm:role>
+ </tm:association>
+
+
<!-- the poem-content-occurrence can only appear once per topictype,
so all topic with this occurrence type must have different
occurrence-values -->
@@ -1732,10 +1824,10 @@
of type author and another role of type written which owns a player of
type poem -->
- <!-- the writer role has to appear exactly once in an association of type
+ <!-- the written role has to appear exactly once in an association of type
written-by -->
- <tm:topic id="written-by-writer-role-constraint">
- <tm:subjectIdentifier href="http://some.where/constraint-psis/written-by-writer-role-constraint"/>
+ <tm:topic id="written-role-constraint">
+ <tm:subjectIdentifier href="http://some.where/constraint-psis/written-role-constraint"/>
<tm:instanceOf><tm:topicRef href="#associationrole-constraint"/></tm:instanceOf>
<tm:occurrence>
<tm:type><tm:topicRef href="#card-min"/></tm:type>
@@ -1751,7 +1843,7 @@
<tm:type><tm:topicRef href="#applies-to"/></tm:type>
<tm:role>
<tm:type><tm:topicRef href="#constraint-role"/></tm:type>
- <tm:topicRef href="#written-by-writer-role-constraint"/>
+ <tm:topicRef href="#written-role-constraint"/>
</tm:role>
<tm:role>
<tm:type><tm:topicRef href="#associationtype-role"/></tm:type>
@@ -1763,17 +1855,17 @@
<tm:type><tm:topicRef href="#applies-to"/></tm:type>
<tm:role>
<tm:type><tm:topicRef href="#constraint-role"/></tm:type>
- <tm:topicRef href="#written-by-writer-role-constraint"/>
+ <tm:topicRef href="#written-role-constraint"/>
</tm:role>
<tm:role>
<tm:type><tm:topicRef href="#roletype-role"/></tm:type>
- <tm:topicRef href="#writer"/>
+ <tm:topicRef href="#written"/>
</tm:role>
</tm:association>
- <!-- the writer role owns a player of the type author -->
- <tm:topic id="written-by-writer-role-player-constraint">
- <tm:subjectIdentifier href="http://some.where/constraint-psis/written-by-writer-role-player-constraint"/>
+ <!-- the written role owns a player of the type poem -->
+ <tm:topic id="written-role-player-constraint">
+ <tm:subjectIdentifier href="http://some.where/constraint-psis/written-role-player-constraint"/>
<tm:instanceOf><tm:topicRef href="#roleplayer-constraint"/></tm:instanceOf>
<tm:occurrence>
<tm:type><tm:topicRef href="#card-min"/></tm:type>
@@ -1789,11 +1881,11 @@
<tm:type><tm:topicRef href="#applies-to"/></tm:type>
<tm:role>
<tm:type><tm:topicRef href="#constraint-role"/></tm:type>
- <tm:topicRef href="#written-by-writer-role-player-constraint"/>
+ <tm:topicRef href="#written-role-player-constraint"/>
</tm:role>
<tm:role>
<tm:type><tm:topicRef href="#topictype-role"/></tm:type>
- <tm:topicRef href="#author"/>
+ <tm:topicRef href="#poem"/>
</tm:role>
</tm:association>
@@ -1801,7 +1893,7 @@
<tm:type><tm:topicRef href="#applies-to"/></tm:type>
<tm:role>
<tm:type><tm:topicRef href="#constraint-role"/></tm:type>
- <tm:topicRef href="#written-by-writer-role-player-constraint"/>
+ <tm:topicRef href="#written-role-player-constraint"/>
</tm:role>
<tm:role>
<tm:type><tm:topicRef href="#associationtype-role"/></tm:type>
@@ -1813,26 +1905,32 @@
<tm:type><tm:topicRef href="#applies-to"/></tm:type>
<tm:role>
<tm:type><tm:topicRef href="#constraint-role"/></tm:type>
- <tm:topicRef href="#written-by-writer-role-player-constraint"/>
+ <tm:topicRef href="#written-role-player-constraint"/>
</tm:role>
<tm:role>
<tm:type><tm:topicRef href="#roletype-role"/></tm:type>
- <tm:topicRef href="#writer"/>
+ <tm:topicRef href="#written"/>
</tm:role>
</tm:association>
- <!-- the written role has to appear exactly once in an association of type
- written-by -->
- <tm:topic id="written-role-constraint">
- <tm:subjectIdentifier href="http://some.where/constraint-psis/written-role-constraint"/>
- <tm:instanceOf><tm:topicRef href="#associationrole-constraint"/></tm:instanceOf>
+ <!-- otherrole-constraint:
+ If there is a role of the type written with a player of the type poem
+ there must be another role of the type writer with a player of the
+ type author. -->
+ <tm:topic id="written-by-otherrole-constraint-for-written">
+ <tm:subjectIdentifier href="http://some.where/contraint-psis/written-by-otherrole-constraint-for-written"/>
+ <tm:instanceOf><tm:topicRef href="#otherrole-constraint"/></tm:instanceOf>
<tm:occurrence>
- <tm:type><tm:topicRef href="#card-min"/></tm:type>
+ <tm:type>
+ <tm:topicRef href="#card-min"/>
+ </tm:type>
<tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#unsignedInt">1</tm:resourceData>
</tm:occurrence>
<tm:occurrence>
- <tm:type><tm:topicRef href="#card-max"/></tm:type>
+ <tm:type>
+ <tm:topicRef href="#card-max"/>
+ </tm:type>
<tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#unsignedInt">1</tm:resourceData>
</tm:occurrence>
</tm:topic>
@@ -1841,7 +1939,7 @@
<tm:type><tm:topicRef href="#applies-to"/></tm:type>
<tm:role>
<tm:type><tm:topicRef href="#constraint-role"/></tm:type>
- <tm:topicRef href="#written-role-constraint"/>
+ <tm:topicRef href="#written-by-otherrole-constraint-for-written"/>
</tm:role>
<tm:role>
<tm:type><tm:topicRef href="#associationtype-role"/></tm:type>
@@ -1853,7 +1951,7 @@
<tm:type><tm:topicRef href="#applies-to"/></tm:type>
<tm:role>
<tm:type><tm:topicRef href="#constraint-role"/></tm:type>
- <tm:topicRef href="#written-role-constraint"/>
+ <tm:topicRef href="#written-by-otherrole-constraint-for-written"/>
</tm:role>
<tm:role>
<tm:type><tm:topicRef href="#roletype-role"/></tm:type>
@@ -1861,25 +1959,11 @@
</tm:role>
</tm:association>
- <!-- the written role owns a player of the type poem -->
- <tm:topic id="written-role-player-constraint">
- <tm:subjectIdentifier href="http://some.where/constraint-psis/written-role-player-constraint"/>
- <tm:instanceOf><tm:topicRef href="#roleplayer-constraint"/></tm:instanceOf>
- <tm:occurrence>
- <tm:type><tm:topicRef href="#card-min"/></tm:type>
- <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#unsignedInt">1</tm:resourceData>
- </tm:occurrence>
- <tm:occurrence>
- <tm:type><tm:topicRef href="#card-max"/></tm:type>
- <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#unsignedInt">1</tm:resourceData>
- </tm:occurrence>
- </tm:topic>
-
<tm:association>
<tm:type><tm:topicRef href="#applies-to"/></tm:type>
<tm:role>
<tm:type><tm:topicRef href="#constraint-role"/></tm:type>
- <tm:topicRef href="#written-role-player-constraint"/>
+ <tm:topicRef href="#written-by-otherrole-constraint-for-written"/>
</tm:role>
<tm:role>
<tm:type><tm:topicRef href="#topictype-role"/></tm:type>
@@ -1891,11 +1975,11 @@
<tm:type><tm:topicRef href="#applies-to"/></tm:type>
<tm:role>
<tm:type><tm:topicRef href="#constraint-role"/></tm:type>
- <tm:topicRef href="#written-role-player-constraint"/>
+ <tm:topicRef href="#written-by-otherrole-constraint-for-written"/>
</tm:role>
<tm:role>
- <tm:type><tm:topicRef href="#associationtype-role"/></tm:type>
- <tm:topicRef href="#written-by"/>
+ <tm:type><tm:topicRef href="#otherroletype-role"/></tm:type>
+ <tm:topicRef href="#writer"/>
</tm:role>
</tm:association>
@@ -1903,38 +1987,29 @@
<tm:type><tm:topicRef href="#applies-to"/></tm:type>
<tm:role>
<tm:type><tm:topicRef href="#constraint-role"/></tm:type>
- <tm:topicRef href="#written-role-player-constraint"/>
+ <tm:topicRef href="#written-by-otherrole-constraint-for-written"/>
</tm:role>
<tm:role>
- <tm:type><tm:topicRef href="#roletype-role"/></tm:type>
- <tm:topicRef href="#written"/>
+ <tm:type><tm:topicRef href="#othertopictype-role"/></tm:type>
+ <tm:topicRef href="#author"/>
</tm:role>
</tm:association>
+ <!-- born-in associations have to have one role of the type writer with a
+ player of the type author. The other role is of type place with the
+ player of the type region. -->
+ <!-- place associationrole-constraint -->
- <!-- otherrole-constraint:
- If there is a role of the type written with a player of the type poem
- there must be another role of the type writer with a player of the
- type author.
- In contrast if there is a role of the type writer with a player of the
- type author there must be a role of the type written with a player of
- the type poem.
- So for this case there are two otherrole-constraints which handle this
- both cases. -->
-
- <tm:topic id="written-by-otherrole-constraint-for-writer">
- <tm:subjectIdentifier href="http://some.where/contraint-psis/written-by-otherrole-constraint-for-writer"/>
- <tm:instanceOf><tm:topicRef href="#otherrole-constraint"/></tm:instanceOf>
+ <!-- writer associationrole-constraint -->
+ <tm:topic id="born-in-writer-role-constraint">
+ <tm:subjectIdentifier href="http://some.where/constraint-psis/born-in-writer-role-constraint"/>
+ <tm:instanceOf><tm:topicRef href="#associationrole-constraint"/></tm:instanceOf>
<tm:occurrence>
- <tm:type>
- <tm:topicRef href="#card-min"/>
- </tm:type>
+ <tm:type><tm:topicRef href="#card-min"/></tm:type>
<tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#unsignedInt">1</tm:resourceData>
</tm:occurrence>
<tm:occurrence>
- <tm:type>
- <tm:topicRef href="#card-max"/>
- </tm:type>
+ <tm:type><tm:topicRef href="#card-max"/></tm:type>
<tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#unsignedInt">1</tm:resourceData>
</tm:occurrence>
</tm:topic>
@@ -1943,11 +2018,11 @@
<tm:type><tm:topicRef href="#applies-to"/></tm:type>
<tm:role>
<tm:type><tm:topicRef href="#constraint-role"/></tm:type>
- <tm:topicRef href="#written-by-otherrole-constraint-for-writer"/>
+ <tm:topicRef href="#born-in-writer-role-constraint"/>
</tm:role>
<tm:role>
<tm:type><tm:topicRef href="#associationtype-role"/></tm:type>
- <tm:topicRef href="#written-by"/>
+ <tm:topicRef href="#born-in"/>
</tm:role>
</tm:association>
@@ -1955,7 +2030,7 @@
<tm:type><tm:topicRef href="#applies-to"/></tm:type>
<tm:role>
<tm:type><tm:topicRef href="#constraint-role"/></tm:type>
- <tm:topicRef href="#written-by-otherrole-constraint-for-writer"/>
+ <tm:topicRef href="#born-in-writer-role-constraint"/>
</tm:role>
<tm:role>
<tm:type><tm:topicRef href="#roletype-role"/></tm:type>
@@ -1963,11 +2038,25 @@
</tm:role>
</tm:association>
+ <!-- place-role roleplayer-constraint -->
+ <tm:topic id="born-in-writer-role-player-constraint">
+ <tm:subjectIdentifier href="http://some.where/constraint-psis/born-in-writer-role-player-constraint"/>
+ <tm:instanceOf><tm:topicRef href="#roleplayer-constraint"/></tm:instanceOf>
+ <tm:occurrence>
+ <tm:type><tm:topicRef href="#card-min"/></tm:type>
+ <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#unsignedInt">1</tm:resourceData>
+ </tm:occurrence>
+ <tm:occurrence>
+ <tm:type><tm:topicRef href="#card-max"/></tm:type>
+ <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#unsignedInt">1</tm:resourceData>
+ </tm:occurrence>
+ </tm:topic>
+
<tm:association>
<tm:type><tm:topicRef href="#applies-to"/></tm:type>
<tm:role>
<tm:type><tm:topicRef href="#constraint-role"/></tm:type>
- <tm:topicRef href="#written-by-otherrole-constraint-for-writer"/>
+ <tm:topicRef href="#born-in-writer-role-player-constraint"/>
</tm:role>
<tm:role>
<tm:type><tm:topicRef href="#topictype-role"/></tm:type>
@@ -1979,11 +2068,11 @@
<tm:type><tm:topicRef href="#applies-to"/></tm:type>
<tm:role>
<tm:type><tm:topicRef href="#constraint-role"/></tm:type>
- <tm:topicRef href="#written-by-otherrole-constraint-for-writer"/>
+ <tm:topicRef href="#born-in-writer-role-player-constraint"/>
</tm:role>
<tm:role>
- <tm:type><tm:topicRef href="#otherroletype-role"/></tm:type>
- <tm:topicRef href="#written"/>
+ <tm:type><tm:topicRef href="#associationtype-role"/></tm:type>
+ <tm:topicRef href="#born-in"/>
</tm:role>
</tm:association>
@@ -1991,16 +2080,20 @@
<tm:type><tm:topicRef href="#applies-to"/></tm:type>
<tm:role>
<tm:type><tm:topicRef href="#constraint-role"/></tm:type>
- <tm:topicRef href="#written-by-otherrole-constraint-for-writer"/>
+ <tm:topicRef href="#born-in-writer-role-player-constraint"/>
</tm:role>
<tm:role>
- <tm:type><tm:topicRef href="#othertopictype-role"/></tm:type>
- <tm:topicRef href="#poem"/>
+ <tm:type><tm:topicRef href="#roletype-role"/></tm:type>
+ <tm:topicRef href="#writer"/>
</tm:role>
</tm:association>
- <tm:topic id="written-by-otherrole-constraint-for-written">
- <tm:subjectIdentifier href="http://some.where/contraint-psis/written-by-otherrole-constraint-for-written"/>
+ <!-- otherplayer-constraints:
+ A "born-in" association must have exactly one writer-role with a
+ player of the type author and one place-role with a player of the
+ type city. -->
+ <tm:topic id="born-in-otherrole-constraint-for-writer">
+ <tm:subjectIdentifier href="http://some.where/contraint-psis/born-in-otherrole-constraint-for-writer"/>
<tm:instanceOf><tm:topicRef href="#otherrole-constraint"/></tm:instanceOf>
<tm:occurrence>
<tm:type>
@@ -2020,11 +2113,11 @@
<tm:type><tm:topicRef href="#applies-to"/></tm:type>
<tm:role>
<tm:type><tm:topicRef href="#constraint-role"/></tm:type>
- <tm:topicRef href="#written-by-otherrole-constraint-for-written"/>
+ <tm:topicRef href="#born-in-otherrole-constraint-for-writer"/>
</tm:role>
<tm:role>
<tm:type><tm:topicRef href="#associationtype-role"/></tm:type>
- <tm:topicRef href="#written-by"/>
+ <tm:topicRef href="#born-in"/>
</tm:role>
</tm:association>
@@ -2032,11 +2125,11 @@
<tm:type><tm:topicRef href="#applies-to"/></tm:type>
<tm:role>
<tm:type><tm:topicRef href="#constraint-role"/></tm:type>
- <tm:topicRef href="#written-by-otherrole-constraint-for-written"/>
+ <tm:topicRef href="#born-in-otherrole-constraint-for-writer"/>
</tm:role>
<tm:role>
<tm:type><tm:topicRef href="#roletype-role"/></tm:type>
- <tm:topicRef href="#written"/>
+ <tm:topicRef href="#writer"/>
</tm:role>
</tm:association>
@@ -2044,11 +2137,11 @@
<tm:type><tm:topicRef href="#applies-to"/></tm:type>
<tm:role>
<tm:type><tm:topicRef href="#constraint-role"/></tm:type>
- <tm:topicRef href="#written-by-otherrole-constraint-for-written"/>
+ <tm:topicRef href="#born-in-otherrole-constraint-for-writer"/>
</tm:role>
<tm:role>
<tm:type><tm:topicRef href="#topictype-role"/></tm:type>
- <tm:topicRef href="#poem"/>
+ <tm:topicRef href="#author"/>
</tm:role>
</tm:association>
@@ -2056,11 +2149,11 @@
<tm:type><tm:topicRef href="#applies-to"/></tm:type>
<tm:role>
<tm:type><tm:topicRef href="#constraint-role"/></tm:type>
- <tm:topicRef href="#written-by-otherrole-constraint-for-written"/>
+ <tm:topicRef href="#born-in-otherrole-constraint-for-writer"/>
</tm:role>
<tm:role>
<tm:type><tm:topicRef href="#otherroletype-role"/></tm:type>
- <tm:topicRef href="#writer"/>
+ <tm:topicRef href="#place"/>
</tm:role>
</tm:association>
@@ -2068,20 +2161,21 @@
<tm:type><tm:topicRef href="#applies-to"/></tm:type>
<tm:role>
<tm:type><tm:topicRef href="#constraint-role"/></tm:type>
- <tm:topicRef href="#written-by-otherrole-constraint-for-written"/>
+ <tm:topicRef href="#born-in-otherrole-constraint-for-writer"/>
</tm:role>
<tm:role>
<tm:type><tm:topicRef href="#othertopictype-role"/></tm:type>
- <tm:topicRef href="#author"/>
+ <tm:topicRef href="#region"/>
</tm:role>
</tm:association>
- <!-- born-in associations have to have one role of the type writer with a
- player of the type author. The other role is of type place with the
- player of the type city. -->
+
+ <!-- located-in associations have to have one role of the type container with
+ a player of the type country. The other role is of type containee with
+ a player of the type city. -->
<!-- place associationrole-constraint -->
- <tm:topic id="born-in-place-role-constraint">
- <tm:subjectIdentifier href="http://some.where/constraint-psis/born-in-place-role-constraint"/>
+ <tm:topic id="located-in-container-role-constraint">
+ <tm:subjectIdentifier href="http://some.where/constraint-psis/located-in-container-role-constraint"/>
<tm:instanceOf><tm:topicRef href="#associationrole-constraint"/></tm:instanceOf>
<tm:occurrence>
<tm:type><tm:topicRef href="#card-min"/></tm:type>
@@ -2097,11 +2191,11 @@
<tm:type><tm:topicRef href="#applies-to"/></tm:type>
<tm:role>
<tm:type><tm:topicRef href="#constraint-role"/></tm:type>
- <tm:topicRef href="#born-in-place-role-constraint"/>
+ <tm:topicRef href="#located-in-container-role-constraint"/>
</tm:role>
<tm:role>
<tm:type><tm:topicRef href="#associationtype-role"/></tm:type>
- <tm:topicRef href="#born-in"/>
+ <tm:topicRef href="#located-in"/>
</tm:role>
</tm:association>
@@ -2109,17 +2203,17 @@
<tm:type><tm:topicRef href="#applies-to"/></tm:type>
<tm:role>
<tm:type><tm:topicRef href="#constraint-role"/></tm:type>
- <tm:topicRef href="#born-in-place-role-constraint"/>
+ <tm:topicRef href="#located-in-container-role-constraint"/>
</tm:role>
<tm:role>
<tm:type><tm:topicRef href="#roletype-role"/></tm:type>
- <tm:topicRef href="#place"/>
+ <tm:topicRef href="#container"/>
</tm:role>
</tm:association>
<!-- place-role roleplayer-constraint -->
- <tm:topic id="born-in-place-role-player-constraint">
- <tm:subjectIdentifier href="http://some.where/constraint-psis/born-in-place-role-player-constraint"/>
+ <tm:topic id="located-in-container-role-player-constraint">
+ <tm:subjectIdentifier href="http://some.where/constraint-psis/located-in-container-role-player-constrai…"/>
<tm:instanceOf><tm:topicRef href="#roleplayer-constraint"/></tm:instanceOf>
<tm:occurrence>
<tm:type><tm:topicRef href="#card-min"/></tm:type>
@@ -2135,11 +2229,11 @@
<tm:type><tm:topicRef href="#applies-to"/></tm:type>
<tm:role>
<tm:type><tm:topicRef href="#constraint-role"/></tm:type>
- <tm:topicRef href="#born-in-place-role-player-constraint"/>
+ <tm:topicRef href="#located-in-container-role-player-constraint"/>
</tm:role>
<tm:role>
<tm:type><tm:topicRef href="#topictype-role"/></tm:type>
- <tm:topicRef href="#region"/>
+ <tm:topicRef href="#country"/>
</tm:role>
</tm:association>
@@ -2147,11 +2241,11 @@
<tm:type><tm:topicRef href="#applies-to"/></tm:type>
<tm:role>
<tm:type><tm:topicRef href="#constraint-role"/></tm:type>
- <tm:topicRef href="#born-in-place-role-player-constraint"/>
+ <tm:topicRef href="#located-in-container-role-player-constraint"/>
</tm:role>
<tm:role>
<tm:type><tm:topicRef href="#associationtype-role"/></tm:type>
- <tm:topicRef href="#born-in"/>
+ <tm:topicRef href="#located-in"/>
</tm:role>
</tm:association>
@@ -2159,446 +2253,22 @@
<tm:type><tm:topicRef href="#applies-to"/></tm:type>
<tm:role>
<tm:type><tm:topicRef href="#constraint-role"/></tm:type>
- <tm:topicRef href="#born-in-place-role-player-constraint"/>
+ <tm:topicRef href="#located-in-container-role-player-constraint"/>
</tm:role>
<tm:role>
<tm:type><tm:topicRef href="#roletype-role"/></tm:type>
- <tm:topicRef href="#place"/>
+ <tm:topicRef href="#container"/>
</tm:role>
</tm:association>
- <!-- writer associationrole-constraint -->
- <tm:topic id="born-in-writer-role-constraint">
- <tm:subjectIdentifier href="http://some.where/constraint-psis/born-in-writer-role-constraint"/>
- <tm:instanceOf><tm:topicRef href="#associationrole-constraint"/></tm:instanceOf>
- <tm:occurrence>
- <tm:type><tm:topicRef href="#card-min"/></tm:type>
- <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#unsignedInt">1</tm:resourceData>
- </tm:occurrence>
- <tm:occurrence>
- <tm:type><tm:topicRef href="#card-max"/></tm:type>
- <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#unsignedInt">1</tm:resourceData>
- </tm:occurrence>
- </tm:topic>
-
- <tm:association>
- <tm:type><tm:topicRef href="#applies-to"/></tm:type>
- <tm:role>
- <tm:type><tm:topicRef href="#constraint-role"/></tm:type>
- <tm:topicRef href="#born-in-writer-role-constraint"/>
- </tm:role>
- <tm:role>
- <tm:type><tm:topicRef href="#associationtype-role"/></tm:type>
- <tm:topicRef href="#born-in"/>
- </tm:role>
- </tm:association>
-
- <tm:association>
- <tm:type><tm:topicRef href="#applies-to"/></tm:type>
- <tm:role>
- <tm:type><tm:topicRef href="#constraint-role"/></tm:type>
- <tm:topicRef href="#born-in-writer-role-constraint"/>
- </tm:role>
- <tm:role>
- <tm:type><tm:topicRef href="#roletype-role"/></tm:type>
- <tm:topicRef href="#writer"/>
- </tm:role>
- </tm:association>
-
- <!-- place-role roleplayer-constraint -->
- <tm:topic id="born-in-writer-role-player-constraint">
- <tm:subjectIdentifier href="http://some.where/constraint-psis/born-in-writer-role-player-constraint"/>
- <tm:instanceOf><tm:topicRef href="#roleplayer-constraint"/></tm:instanceOf>
- <tm:occurrence>
- <tm:type><tm:topicRef href="#card-min"/></tm:type>
- <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#unsignedInt">1</tm:resourceData>
- </tm:occurrence>
- <tm:occurrence>
- <tm:type><tm:topicRef href="#card-max"/></tm:type>
- <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#unsignedInt">1</tm:resourceData>
- </tm:occurrence>
- </tm:topic>
-
- <tm:association>
- <tm:type><tm:topicRef href="#applies-to"/></tm:type>
- <tm:role>
- <tm:type><tm:topicRef href="#constraint-role"/></tm:type>
- <tm:topicRef href="#born-in-writer-role-player-constraint"/>
- </tm:role>
- <tm:role>
- <tm:type><tm:topicRef href="#topictype-role"/></tm:type>
- <tm:topicRef href="#author"/>
- </tm:role>
- </tm:association>
-
- <tm:association>
- <tm:type><tm:topicRef href="#applies-to"/></tm:type>
- <tm:role>
- <tm:type><tm:topicRef href="#constraint-role"/></tm:type>
- <tm:topicRef href="#born-in-writer-role-player-constraint"/>
- </tm:role>
- <tm:role>
- <tm:type><tm:topicRef href="#associationtype-role"/></tm:type>
- <tm:topicRef href="#born-in"/>
- </tm:role>
- </tm:association>
-
- <tm:association>
- <tm:type><tm:topicRef href="#applies-to"/></tm:type>
- <tm:role>
- <tm:type><tm:topicRef href="#constraint-role"/></tm:type>
- <tm:topicRef href="#born-in-writer-role-player-constraint"/>
- </tm:role>
- <tm:role>
- <tm:type><tm:topicRef href="#roletype-role"/></tm:type>
- <tm:topicRef href="#writer"/>
- </tm:role>
- </tm:association>
-
- <!-- otherplayer-constraints:
- A "born-in" association must have exactly one writer-role with a
- player of the type author and one place-role with a player of the
- type city. -->
- <tm:topic id="born-in-otherrole-constraint-for-writer">
- <tm:subjectIdentifier href="http://some.where/contraint-psis/born-in-otherrole-constraint-for-writer"/>
- <tm:instanceOf><tm:topicRef href="#otherrole-constraint"/></tm:instanceOf>
- <tm:occurrence>
- <tm:type>
- <tm:topicRef href="#card-min"/>
- </tm:type>
- <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#unsignedInt">1</tm:resourceData>
- </tm:occurrence>
- <tm:occurrence>
- <tm:type>
- <tm:topicRef href="#card-max"/>
- </tm:type>
- <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#unsignedInt">1</tm:resourceData>
- </tm:occurrence>
- </tm:topic>
-
- <tm:association>
- <tm:type><tm:topicRef href="#applies-to"/></tm:type>
- <tm:role>
- <tm:type><tm:topicRef href="#constraint-role"/></tm:type>
- <tm:topicRef href="#born-in-otherrole-constraint-for-writer"/>
- </tm:role>
- <tm:role>
- <tm:type><tm:topicRef href="#associationtype-role"/></tm:type>
- <tm:topicRef href="#born-in"/>
- </tm:role>
- </tm:association>
-
- <tm:association>
- <tm:type><tm:topicRef href="#applies-to"/></tm:type>
- <tm:role>
- <tm:type><tm:topicRef href="#constraint-role"/></tm:type>
- <tm:topicRef href="#born-in-otherrole-constraint-for-writer"/>
- </tm:role>
- <tm:role>
- <tm:type><tm:topicRef href="#roletype-role"/></tm:type>
- <tm:topicRef href="#writer"/>
- </tm:role>
- </tm:association>
-
- <tm:association>
- <tm:type><tm:topicRef href="#applies-to"/></tm:type>
- <tm:role>
- <tm:type><tm:topicRef href="#constraint-role"/></tm:type>
- <tm:topicRef href="#born-in-otherrole-constraint-for-writer"/>
- </tm:role>
- <tm:role>
- <tm:type><tm:topicRef href="#topictype-role"/></tm:type>
- <tm:topicRef href="#author"/>
- </tm:role>
- </tm:association>
-
- <tm:association>
- <tm:type><tm:topicRef href="#applies-to"/></tm:type>
- <tm:role>
- <tm:type><tm:topicRef href="#constraint-role"/></tm:type>
- <tm:topicRef href="#born-in-otherrole-constraint-for-writer"/>
- </tm:role>
- <tm:role>
- <tm:type><tm:topicRef href="#otherroletype-role"/></tm:type>
- <tm:topicRef href="#place"/>
- </tm:role>
- </tm:association>
-
- <tm:association>
- <tm:type><tm:topicRef href="#applies-to"/></tm:type>
- <tm:role>
- <tm:type><tm:topicRef href="#constraint-role"/></tm:type>
- <tm:topicRef href="#born-in-otherrole-constraint-for-writer"/>
- </tm:role>
- <tm:role>
- <tm:type><tm:topicRef href="#othertopictype-role"/></tm:type>
- <tm:topicRef href="#region"/>
- </tm:role>
- </tm:association>
-
- <tm:topic id="born-in-otherrole-constraint-for-place">
- <tm:subjectIdentifier href="http://some.where/contraint-psis/born-in-otherrole-constraint-for-place"/>
- <tm:instanceOf><tm:topicRef href="#otherrole-constraint"/></tm:instanceOf>
- <tm:occurrence>
- <tm:type>
- <tm:topicRef href="#card-min"/>
- </tm:type>
- <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#unsignedInt">1</tm:resourceData>
- </tm:occurrence>
- <tm:occurrence>
- <tm:type>
- <tm:topicRef href="#card-max"/>
- </tm:type>
- <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#unsignedInt">1</tm:resourceData>
- </tm:occurrence>
- </tm:topic>
-
- <tm:association>
- <tm:type><tm:topicRef href="#applies-to"/></tm:type>
- <tm:role>
- <tm:type><tm:topicRef href="#constraint-role"/></tm:type>
- <tm:topicRef href="#born-in-otherrole-constraint-for-place"/>
- </tm:role>
- <tm:role>
- <tm:type><tm:topicRef href="#associationtype-role"/></tm:type>
- <tm:topicRef href="#born-in"/>
- </tm:role>
- </tm:association>
-
- <tm:association>
- <tm:type><tm:topicRef href="#applies-to"/></tm:type>
- <tm:role>
- <tm:type><tm:topicRef href="#constraint-role"/></tm:type>
- <tm:topicRef href="#born-in-otherrole-constraint-for-place"/>
- </tm:role>
- <tm:role>
- <tm:type><tm:topicRef href="#roletype-role"/></tm:type>
- <tm:topicRef href="#place"/>
- </tm:role>
- </tm:association>
-
- <tm:association>
- <tm:type><tm:topicRef href="#applies-to"/></tm:type>
- <tm:role>
- <tm:type><tm:topicRef href="#constraint-role"/></tm:type>
- <tm:topicRef href="#born-in-otherrole-constraint-for-place"/>
- </tm:role>
- <tm:role>
- <tm:type><tm:topicRef href="#topictype-role"/></tm:type>
- <tm:topicRef href="#region"/>
- </tm:role>
- </tm:association>
-
- <tm:association>
- <tm:type><tm:topicRef href="#applies-to"/></tm:type>
- <tm:role>
- <tm:type><tm:topicRef href="#constraint-role"/></tm:type>
- <tm:topicRef href="#born-in-otherrole-constraint-for-place"/>
- </tm:role>
- <tm:role>
- <tm:type><tm:topicRef href="#otherroletype-role"/></tm:type>
- <tm:topicRef href="#writer"/>
- </tm:role>
- </tm:association>
-
- <tm:association>
- <tm:type><tm:topicRef href="#applies-to"/></tm:type>
- <tm:role>
- <tm:type><tm:topicRef href="#constraint-role"/></tm:type>
- <tm:topicRef href="#born-in-otherrole-constraint-for-place"/>
- </tm:role>
- <tm:role>
- <tm:type><tm:topicRef href="#othertopictype-role"/></tm:type>
- <tm:topicRef href="#author"/>
- </tm:role>
- </tm:association>
-
- <!-- located-in associations have to have one role of the type container with
- a player of the type country. The other role is of type containee with
- a player of the type city. -->
- <!-- place associationrole-constraint -->
- <tm:topic id="located-in-container-role-constraint">
- <tm:subjectIdentifier href="http://some.where/constraint-psis/located-in-container-role-constraint"/>
- <tm:instanceOf><tm:topicRef href="#associationrole-constraint"/></tm:instanceOf>
- <tm:occurrence>
- <tm:type><tm:topicRef href="#card-min"/></tm:type>
- <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#unsignedInt">1</tm:resourceData>
- </tm:occurrence>
- <tm:occurrence>
- <tm:type><tm:topicRef href="#card-max"/></tm:type>
- <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#unsignedInt">1</tm:resourceData>
- </tm:occurrence>
- </tm:topic>
-
- <tm:association>
- <tm:type><tm:topicRef href="#applies-to"/></tm:type>
- <tm:role>
- <tm:type><tm:topicRef href="#constraint-role"/></tm:type>
- <tm:topicRef href="#located-in-container-role-constraint"/>
- </tm:role>
- <tm:role>
- <tm:type><tm:topicRef href="#associationtype-role"/></tm:type>
- <tm:topicRef href="#located-in"/>
- </tm:role>
- </tm:association>
-
- <tm:association>
- <tm:type><tm:topicRef href="#applies-to"/></tm:type>
- <tm:role>
- <tm:type><tm:topicRef href="#constraint-role"/></tm:type>
- <tm:topicRef href="#located-in-container-role-constraint"/>
- </tm:role>
- <tm:role>
- <tm:type><tm:topicRef href="#roletype-role"/></tm:type>
- <tm:topicRef href="#container"/>
- </tm:role>
- </tm:association>
-
- <!-- place-role roleplayer-constraint -->
- <tm:topic id="located-in-container-role-player-constraint">
- <tm:subjectIdentifier href="http://some.where/constraint-psis/located-in-container-role-player-constrai…"/>
- <tm:instanceOf><tm:topicRef href="#roleplayer-constraint"/></tm:instanceOf>
- <tm:occurrence>
- <tm:type><tm:topicRef href="#card-min"/></tm:type>
- <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#unsignedInt">1</tm:resourceData>
- </tm:occurrence>
- <tm:occurrence>
- <tm:type><tm:topicRef href="#card-max"/></tm:type>
- <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#unsignedInt">1</tm:resourceData>
- </tm:occurrence>
- </tm:topic>
-
- <tm:association>
- <tm:type><tm:topicRef href="#applies-to"/></tm:type>
- <tm:role>
- <tm:type><tm:topicRef href="#constraint-role"/></tm:type>
- <tm:topicRef href="#located-in-container-role-player-constraint"/>
- </tm:role>
- <tm:role>
- <tm:type><tm:topicRef href="#topictype-role"/></tm:type>
- <tm:topicRef href="#region"/>
- </tm:role>
- </tm:association>
-
- <tm:association>
- <tm:type><tm:topicRef href="#applies-to"/></tm:type>
- <tm:role>
- <tm:type><tm:topicRef href="#constraint-role"/></tm:type>
- <tm:topicRef href="#located-in-container-role-player-constraint"/>
- </tm:role>
- <tm:role>
- <tm:type><tm:topicRef href="#associationtype-role"/></tm:type>
- <tm:topicRef href="#located-in"/>
- </tm:role>
- </tm:association>
-
- <tm:association>
- <tm:type><tm:topicRef href="#applies-to"/></tm:type>
- <tm:role>
- <tm:type><tm:topicRef href="#constraint-role"/></tm:type>
- <tm:topicRef href="#located-in-container-role-player-constraint"/>
- </tm:role>
- <tm:role>
- <tm:type><tm:topicRef href="#roletype-role"/></tm:type>
- <tm:topicRef href="#container"/>
- </tm:role>
- </tm:association>
-
- <!-- writer associationrole-constraint -->
- <tm:topic id="located-in-containee-role-constraint">
- <tm:subjectIdentifier href="http://some.where/constraint-psis/located-in-containee-role-constraint"/>
- <tm:instanceOf><tm:topicRef href="#associationrole-constraint"/></tm:instanceOf>
- <tm:occurrence>
- <tm:type><tm:topicRef href="#card-min"/></tm:type>
- <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#unsignedInt">1</tm:resourceData>
- </tm:occurrence>
- <tm:occurrence>
- <tm:type><tm:topicRef href="#card-max"/></tm:type>
- <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#unsignedInt">1</tm:resourceData>
- </tm:occurrence>
- </tm:topic>
-
- <tm:association>
- <tm:type><tm:topicRef href="#applies-to"/></tm:type>
- <tm:role>
- <tm:type><tm:topicRef href="#constraint-role"/></tm:type>
- <tm:topicRef href="#located-in-containee-role-constraint"/>
- </tm:role>
- <tm:role>
- <tm:type><tm:topicRef href="#associationtype-role"/></tm:type>
- <tm:topicRef href="#located-in"/>
- </tm:role>
- </tm:association>
-
- <tm:association>
- <tm:type><tm:topicRef href="#applies-to"/></tm:type>
- <tm:role>
- <tm:type><tm:topicRef href="#constraint-role"/></tm:type>
- <tm:topicRef href="#located-in-containee-role-constraint"/>
- </tm:role>
- <tm:role>
- <tm:type><tm:topicRef href="#roletype-role"/></tm:type>
- <tm:topicRef href="#containee"/>
- </tm:role>
- </tm:association>
-
- <!-- place-role roleplayer-constraint -->
- <tm:topic id="located-in-containee-role-player-constraint">
- <tm:subjectIdentifier href="http://some.where/constraint-psis/located-in-containee-role-player-constrai…"/>
- <tm:instanceOf><tm:topicRef href="#roleplayer-constraint"/></tm:instanceOf>
- <tm:occurrence>
- <tm:type><tm:topicRef href="#card-min"/></tm:type>
- <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#unsignedInt">1</tm:resourceData>
- </tm:occurrence>
- <tm:occurrence>
- <tm:type><tm:topicRef href="#card-max"/></tm:type>
- <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#unsignedInt">1</tm:resourceData>
- </tm:occurrence>
- </tm:topic>
-
- <tm:association>
- <tm:type><tm:topicRef href="#applies-to"/></tm:type>
- <tm:role>
- <tm:type><tm:topicRef href="#constraint-role"/></tm:type>
- <tm:topicRef href="#located-in-containee-role-player-constraint"/>
- </tm:role>
- <tm:role>
- <tm:type><tm:topicRef href="#topictype-role"/></tm:type>
- <tm:topicRef href="#region"/>
- </tm:role>
- </tm:association>
-
- <tm:association>
- <tm:type><tm:topicRef href="#applies-to"/></tm:type>
- <tm:role>
- <tm:type><tm:topicRef href="#constraint-role"/></tm:type>
- <tm:topicRef href="#located-in-containee-role-player-constraint"/>
- </tm:role>
- <tm:role>
- <tm:type><tm:topicRef href="#associationtype-role"/></tm:type>
- <tm:topicRef href="#located-in"/>
- </tm:role>
- </tm:association>
-
- <tm:association>
- <tm:type><tm:topicRef href="#applies-to"/></tm:type>
- <tm:role>
- <tm:type><tm:topicRef href="#constraint-role"/></tm:type>
- <tm:topicRef href="#located-in-containee-role-player-constraint"/>
- </tm:role>
- <tm:role>
- <tm:type><tm:topicRef href="#roletype-role"/></tm:type>
- <tm:topicRef href="#containee"/>
- </tm:role>
- </tm:association>
-
- <!-- otherplayer-constraints:
- A "born-in" association must have exactly one writer-role with a
- player of the type author and one place-role with a player of the
- type city. -->
- <tm:topic id="located-in-otherrole-constraint-for-container">
- <tm:subjectIdentifier href="http://some.where/contraint-psis/located-in-otherrole-constraint-for-contai…"/>
- <tm:instanceOf><tm:topicRef href="#otherrole-constraint"/></tm:instanceOf>
+
+ <!-- otherplayer-constraints:
+ A "located-in" association must have exactly one container-role with a
+ player of the type country and one containee-role with a player of the
+ type region. -->
+ <tm:topic id="located-in-otherrole-constraint-for-container">
+ <tm:subjectIdentifier href="http://some.where/contraint-psis/located-in-otherrole-constraint-for-contai…"/>
+ <tm:instanceOf><tm:topicRef href="#otherrole-constraint"/></tm:instanceOf>
<tm:occurrence>
<tm:type>
<tm:topicRef href="#card-min"/>
@@ -2673,82 +2343,6 @@
</tm:role>
</tm:association>
- <tm:topic id="located-in-otherrole-constraint-for-containee">
- <tm:subjectIdentifier href="http://some.where/contraint-psis/located-in-otherrole-constraint-for-contai…"/>
- <tm:instanceOf><tm:topicRef href="#otherrole-constraint"/></tm:instanceOf>
- <tm:occurrence>
- <tm:type>
- <tm:topicRef href="#card-min"/>
- </tm:type>
- <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#unsignedInt">1</tm:resourceData>
- </tm:occurrence>
- <tm:occurrence>
- <tm:type>
- <tm:topicRef href="#card-max"/>
- </tm:type>
- <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#unsignedInt">1</tm:resourceData>
- </tm:occurrence>
- </tm:topic>
-
- <tm:association>
- <tm:type><tm:topicRef href="#applies-to"/></tm:type>
- <tm:role>
- <tm:type><tm:topicRef href="#constraint-role"/></tm:type>
- <tm:topicRef href="#located-in-otherrole-constraint-for-containee"/>
- </tm:role>
- <tm:role>
- <tm:type><tm:topicRef href="#associationtype-role"/></tm:type>
- <tm:topicRef href="#born-in"/>
- </tm:role>
- </tm:association>
-
- <tm:association>
- <tm:type><tm:topicRef href="#applies-to"/></tm:type>
- <tm:role>
- <tm:type><tm:topicRef href="#constraint-role"/></tm:type>
- <tm:topicRef href="#located-in-otherrole-constraint-for-containee"/>
- </tm:role>
- <tm:role>
- <tm:type><tm:topicRef href="#roletype-role"/></tm:type>
- <tm:topicRef href="#containee"/>
- </tm:role>
- </tm:association>
-
- <tm:association>
- <tm:type><tm:topicRef href="#applies-to"/></tm:type>
- <tm:role>
- <tm:type><tm:topicRef href="#constraint-role"/></tm:type>
- <tm:topicRef href="#located-in-otherrole-constraint-for-containee"/>
- </tm:role>
- <tm:role>
- <tm:type><tm:topicRef href="#topictype-role"/></tm:type>
- <tm:topicRef href="#region"/>
- </tm:role>
- </tm:association>
-
- <tm:association>
- <tm:type><tm:topicRef href="#applies-to"/></tm:type>
- <tm:role>
- <tm:type><tm:topicRef href="#constraint-role"/></tm:type>
- <tm:topicRef href="#located-in-otherrole-constraint-for-containee"/>
- </tm:role>
- <tm:role>
- <tm:type><tm:topicRef href="#otherroletype-role"/></tm:type>
- <tm:topicRef href="#container"/>
- </tm:role>
- </tm:association>
-
- <tm:association>
- <tm:type><tm:topicRef href="#applies-to"/></tm:type>
- <tm:role>
- <tm:type><tm:topicRef href="#constraint-role"/></tm:type>
- <tm:topicRef href="#located-in-otherrole-constraint-for-containee"/>
- </tm:role>
- <tm:role>
- <tm:type><tm:topicRef href="#othertopictype-role"/></tm:type>
- <tm:topicRef href="#country"/>
- </tm:role>
- </tm:association>
<!-- ===================================================================== -->
<!-- === the "user's" topic map ========================================== -->
1
0

[isidorus-cvs] r32 - in trunk: docs src/ajax/javascripts src/json src/rest_interface src/unit_tests src/xml
by Lukas Giessmann 31 May '09
by Lukas Giessmann 31 May '09
31 May '09
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" : [ { <role> }, { <...> } ]
}
-
//+-----------------------------------------------------------------------------
//+ 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".
//+-----------------------------------------------------------------------------
<simpleConstraint>
@@ -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".
//+-----------------------------------------------------------------------------
<simpleConstraint>
@@ -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" : [ <scopeConstraints> ]
},
+ {
+ "nameType" : [subtype-1-psi-1, subtype-1-psi-2, "..." ],
+ "scopeConstraints" : [ <scopeConstraints> ]
+ },
<...>
]
"constraints" : [ <simpleConstraint>, < ... > ]
@@ -299,10 +302,15 @@
"scopeConstraints" : [ <scopeConstraints> ],
"datatypeConstraint" : "datatype"
},
+ {
+ "occurrenceType" : [ "subtype-1-psi-1", "subtype-1-psi-2", "..." ],
+ "scopeConstraints" : [ <scopeConstraints> ],
+ "datatypeConstraint" : "datatype"
+ },
<...>
],
"constraints" : [ <simpleConstraints>, <...>],
- "uniqueConstraint" : [ <uniqueConstraints>, <...> ]
+ "uniqueConstraints" : [ <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" : [ <associationRoleConstraint>, <...> ],
"rolePlayerConstraints" : [ <rolePlayerConstraints>, <...> ],
"otherRoleConstraints" : [ <otherRoleConstraint>, <...> ],
@@ -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 <topic> :card-min <string> :card-max <string>), <...>)
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 <topic, topic, ...> :cardMin <min> :cardMax <max>)"
(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/<fragment-psi>
(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 @@
<tm:instanceOf><tm:topicRef href="#occurrencetype"/></tm:instanceOf>
</tm:topic>
- <!-- poem scopes -->
+ <!-- available scopes -->
<tm:topic id="de">
<tm:subjectIdentifier href="http://some.where/base-psis/de"/>
<tm:instanceOf><tm:topicRef href="#scopetype"/></tm:instanceOf>
@@ -593,6 +593,26 @@
<tm:instanceOf><tm:topicRef href="#scopetype"/></tm:instanceOf>
</tm:topic>
+ <tm:topic id="fr">
+ <tm:subjectIdentifier href="http://some.where/base-psis/fr"/>
+ <tm:instanceOf><tm:topicRef href="#scopetype"/></tm:instanceOf>
+ </tm:topic>
+
+ <tm:topic id="fin">
+ <tm:subjectIdentifier href="http://some.where/base-psis/fin"/>
+ <tm:instanceOf><tm:topicRef href="#scopetype"/></tm:instanceOf>
+ </tm:topic>
+
+ <tm:topic id="rus">
+ <tm:subjectIdentifier href="http://some.where/base-psis/rus"/>
+ <tm:instanceOf><tm:topicRef href="#scopetype"/></tm:instanceOf>
+ </tm:topic>
+
+ <tm:topic id="pl">
+ <tm:subjectIdentifier href="http://some.where/base-psis/pl"/>
+ <tm:instanceOf><tm:topicRef href="#scopetype"/></tm:instanceOf>
+ </tm:topic>
+
<!-- region -->
<tm:topic id="region">
<tm:subjectIdentifier href="http://some.where/base-psis/region"/>
@@ -1059,7 +1079,7 @@
</tm:occurrence>
<tm:occurrence>
<tm:type><tm:topicRef href="#card-max"/></tm:type>
- <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#unsignedInt">3</tm:resourceData>
+ <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#unsignedInt">1</tm:resourceData>
</tm:occurrence>
<tm:occurrence>
<tm:type><tm:topicRef href="#regexp"/></tm:type>
@@ -1262,8 +1282,9 @@
</tm:association>
<!-- country-name scopes -->
- <tm:topic id="scoped-country-name-constraint">
- <tm:subjectIdentifier href="http://some.where/constraint-psis/scoped-country-name-constraint"/>
+ <!-- scope constraint 1: there must be either the scope en or de -->
+ <tm:topic id="scoped-country-name-constraint-1">
+ <tm:subjectIdentifier href="http://some.where/constraint-psis/scoped-country-name-constraint-1"/>
<tm:instanceOf><tm:topicRef href="#nametypescope-constraint"/></tm:instanceOf>
<tm:occurrence>
<tm:type><tm:topicRef href="#card-min"/></tm:type>
@@ -1279,7 +1300,7 @@
<tm:type><tm:topicRef href="#applies-to"/></tm:type>
<tm:role>
<tm:type><tm:topicRef href="#constraint-role"/></tm:type>
- <tm:topicRef href="#scoped-country-name-constraint"/>
+ <tm:topicRef href="#scoped-country-name-constraint-1"/>
</tm:role>
<tm:role>
<tm:type><tm:topicRef href="#nametype-role"/></tm:type>
@@ -1291,7 +1312,7 @@
<tm:type><tm:topicRef href="#applies-to"/></tm:type>
<tm:role>
<tm:type><tm:topicRef href="#constraint-role"/></tm:type>
- <tm:topicRef href="#scoped-country-name-constraint"/>
+ <tm:topicRef href="#scoped-country-name-constraint-1"/>
</tm:role>
<tm:role>
<tm:type><tm:topicRef href="#scopetype-role"/></tm:type>
@@ -1303,14 +1324,111 @@
<tm:type><tm:topicRef href="#applies-to"/></tm:type>
<tm:role>
<tm:type><tm:topicRef href="#constraint-role"/></tm:type>
- <tm:topicRef href="#scoped-country-name-constraint"/>
+ <tm:topicRef href="#scoped-country-name-constraint-1"/>
</tm:role>
<tm:role>
<tm:type><tm:topicRef href="#scopetype-role"/></tm:type>
<tm:topicRef href="#de"/>
</tm:role>
</tm:association>
+
+ <!-- scope constraint 2: there can exist the scopes de, en, pl, fr, fin or rus -->
+ <tm:topic id="scoped-country-name-constraint-2">
+ <tm:subjectIdentifier href="http://some.where/constraint-psis/scoped-country-name-constraint-2"/>
+ <tm:instanceOf><tm:topicRef href="#nametypescope-constraint"/></tm:instanceOf>
+ <tm:occurrence>
+ <tm:type><tm:topicRef href="#card-min"/></tm:type>
+ <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#unsignedInt">0</tm:resourceData>
+ </tm:occurrence>
+ <tm:occurrence>
+ <tm:type><tm:topicRef href="#card-max"/></tm:type>
+ <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#unsignedInt">6</tm:resourceData>
+ </tm:occurrence>
+ </tm:topic>
+
+ <tm:association>
+ <tm:type><tm:topicRef href="#applies-to"/></tm:type>
+ <tm:role>
+ <tm:type><tm:topicRef href="#constraint-role"/></tm:type>
+ <tm:topicRef href="#scoped-country-name-constraint-2"/>
+ </tm:role>
+ <tm:role>
+ <tm:type><tm:topicRef href="#nametype-role"/></tm:type>
+ <tm:topicRef href="#country-name"/>
+ </tm:role>
+ </tm:association>
+
+ <tm:association>
+ <tm:type><tm:topicRef href="#applies-to"/></tm:type>
+ <tm:role>
+ <tm:type><tm:topicRef href="#constraint-role"/></tm:type>
+ <tm:topicRef href="#scoped-country-name-constraint-2"/>
+ </tm:role>
+ <tm:role>
+ <tm:type><tm:topicRef href="#scopetype-role"/></tm:type>
+ <tm:topicRef href="#en"/>
+ </tm:role>
+ </tm:association>
+ <tm:association>
+ <tm:type><tm:topicRef href="#applies-to"/></tm:type>
+ <tm:role>
+ <tm:type><tm:topicRef href="#constraint-role"/></tm:type>
+ <tm:topicRef href="#scoped-country-name-constraint-2"/>
+ </tm:role>
+ <tm:role>
+ <tm:type><tm:topicRef href="#scopetype-role"/></tm:type>
+ <tm:topicRef href="#pl"/>
+ </tm:role>
+ </tm:association>
+
+ <tm:association>
+ <tm:type><tm:topicRef href="#applies-to"/></tm:type>
+ <tm:role>
+ <tm:type><tm:topicRef href="#constraint-role"/></tm:type>
+ <tm:topicRef href="#scoped-country-name-constraint-2"/>
+ </tm:role>
+ <tm:role>
+ <tm:type><tm:topicRef href="#scopetype-role"/></tm:type>
+ <tm:topicRef href="#fr"/>
+ </tm:role>
+ </tm:association>
+
+ <tm:association>
+ <tm:type><tm:topicRef href="#applies-to"/></tm:type>
+ <tm:role>
+ <tm:type><tm:topicRef href="#constraint-role"/></tm:type>
+ <tm:topicRef href="#scoped-country-name-constraint-2"/>
+ </tm:role>
+ <tm:role>
+ <tm:type><tm:topicRef href="#scopetype-role"/></tm:type>
+ <tm:topicRef href="#fin"/>
+ </tm:role>
+ </tm:association>
+
+ <tm:association>
+ <tm:type><tm:topicRef href="#applies-to"/></tm:type>
+ <tm:role>
+ <tm:type><tm:topicRef href="#constraint-role"/></tm:type>
+ <tm:topicRef href="#scoped-country-name-constraint-2"/>
+ </tm:role>
+ <tm:role>
+ <tm:type><tm:topicRef href="#scopetype-role"/></tm:type>
+ <tm:topicRef href="#rus"/>
+ </tm:role>
+ </tm:association>
+
+ <tm:association>
+ <tm:type><tm:topicRef href="#applies-to"/></tm:type>
+ <tm:role>
+ <tm:type><tm:topicRef href="#constraint-role"/></tm:type>
+ <tm:topicRef href="#scoped-country-name-constraint-2"/>
+ </tm:role>
+ <tm:role>
+ <tm:type><tm:topicRef href="#scopetype-role"/></tm:type>
+ <tm:topicRef href="#de"/>
+ </tm:role>
+ </tm:association>
<!-- ===================================================================== -->
<!-- === own datamodel: occurence constraints ============================ -->
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
1
0

[isidorus-cvs] r31 - in trunk: docs src/ajax src/ajax/css src/ajax/javascripts src/json src/rest_interface src/unit_tests
by Lukas Giessmann 19 May '09
by Lukas Giessmann 19 May '09
19 May '09
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" : [ <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 @@
<!-- includes all necessary css-files -->
<link rel="stylesheet" type="text/css" href="css/main.css"/>
- <link rel="stylesheet" type="text/css" href="css/home.css"/>
+ <link rel="stylesheet" type="text/css" href="css/frame.css"/>
<link rel="stylesheet" type="text/css" href="css/navi.css"/>
<!-- error handling for javascript code -->
@@ -45,21 +45,25 @@
<!-- includes own javascript files -->
<script language="JavaScript" type="text/javascript" src="javascripts/constants.js"></script>
- <script language="JavaScript" type="text/javascript" src="javascripts/make_fragment_node.js"></script>
- <script language="JavaScript" type="text/javascript" src="javascripts/edit_topic.js"></script>
+ <script language="JavaScript" type="text/javascript" src="javascripts/tmcl_tools.js"></script>
+ <script language="JavaScript" type="text/javascript" src="javascripts/requests.js"></script>
+ <script language="JavaScript" type="text/javascript" src="javascripts/datamodel.js"></script>
<script language="JavaScript" type="text/javascript" src="javascripts/home.js"></script>
+ <script language="JavaScript" type="text/javascript" src="javascripts/search.js"></script>
+ <script language="JavaScript" type="text/javascript" src="javascripts/edit.js"></script>
+ <script language="JavaScript" type="text/javascript" src="javascripts/create.js"></script>
<script language="JavaScript" type="text/javascript" src="javascripts/navi.js"></script>
</head>
<body>
<div id="page">
<div id="navi">
- <span id="home" class="naviElem clickable">home</span>
- <span id="searchTopic" class="naviElem clickable">search topic</span>
- <span id="editTopic" class="naviElem clickable">edit topic</span>
- <span id="createTopic" class="naviElem clickable">create topic</span>
+ <span id="home" class="isActive">Home</span>
+ <span id="searchTopic" class="clickableButton">Search Topics</span>
+ <span id="editTopic" class="clickableButton">Edit Topics</span>
+ <span id="createTopic" class="clickableButton">Create Topics</span>
</div>
- <div id="content" style="border: red solid 1px;">
+ <div id="subPage">
</div>
</div>
</body>
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!<br/>";
+ for(var i = 0; i != ret.length; ++i){
+ for(var j = 0; j != ret[i].length; ++j){
+ if(j === 0){
+ str += "<br/>" + ret[i][j];
+ }
+ else {
+ str += " " + ret[i][j];
+ }
+ str += "<br/>";
+ }
+ }
+ 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
+// --- <tr class="rowClass"><td class="description">description</td>
+//---- <td class="content">content</td></tr>
+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" : "<br/>"});
+ tdCtrl.insert({"bottom" : myself.__remove__});
+ tdCtrl.insert({"bottom" : "<br/>"});
+ 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 [<boolean>, <string>].
+// --- 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: [<scopeConstraint>]},
- {nameType: [subtype-1-psi-1], scopeConstriants: [<scopeConstraints>]},
+ {nameType: [subtype-1-psi-1], scopeConstraints: [<scopeConstraints>]},
constraints: [<simpleConstraint>, <...>]},
<...>]."
(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 @@
<?xml version="1.0" encoding="UTF-8"?>
<tm:topicMap version="2.0" xmlns:tm="http://www.topicmaps.org/xtm/">
-
- <!-- === association-test ================================================ -->
- <tm:topic id="test-scope-1">
- <tm:subjectIdentifier href="test-scope-1"/>
- <tm:instanceOf><tm:topicRef href="#scopetype"/></tm:instanceOf>
- </tm:topic>
-
- <tm:topic id="test-scope-2">
- <tm:subjectIdentifier href="test-scope-2"/>
- <tm:instanceOf><tm:topicRef href="#scopetype"/></tm:instanceOf>
- </tm:topic>
-
- <tm:topic id="written-by-test-scope-constraint">
- <tm:subjectIdentifier href="written-by-test-scope-constraint"/>
- <tm:instanceOf><tm:topicRef href="#associationtypescope-constraint"/></tm:instanceOf>
- <tm:occurrence>
- <tm:type>
- <tm:topicRef href="#card-min"/>
- </tm:type>
- <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#unsignedInt">1</tm:resourceData>
- </tm:occurrence>
- <tm:occurrence>
- <tm:type>
- <tm:topicRef href="#card-max"/>
- </tm:type>
- <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#unsignedInt">1</tm:resourceData>
- </tm:occurrence>
- </tm:topic>
-
- <tm:association>
- <tm:type>
- <tm:topicRef href="#applies-to"/>
- </tm:type>
- <tm:role>
- <tm:type>
- <tm:topicRef href="#constraint-role"/>
- </tm:type>
- <tm:topicRef href="#written-by-test-scope-constraint"/>
- </tm:role>
- <tm:role>
- <tm:type>
- <tm:topicRef href="#associationtype-role"/>
- </tm:type>
- <tm:topicRef href="#written-by"/>
- </tm:role>
- </tm:association>
-
- <tm:association>
- <tm:type>
- <tm:topicRef href="#applies-to"/>
- </tm:type>
- <tm:role>
- <tm:type>
- <tm:topicRef href="#constraint-role"/>
- </tm:type>
- <tm:topicRef href="#written-by-test-scope-constraint"/>
- </tm:role>
- <tm:role>
- <tm:type>
- <tm:topicRef href="#scopetype-role"/>
- </tm:type>
- <tm:topicRef href="#test-scope-1"/>
- </tm:role>
- </tm:association>
-
- <tm:association>
- <tm:type>
- <tm:topicRef href="#applies-to"/>
- </tm:type>
- <tm:role>
- <tm:type>
- <tm:topicRef href="#constraint-role"/>
- </tm:type>
- <tm:topicRef href="#written-by-test-scope-constraint"/>
- </tm:role>
- <tm:role>
- <tm:type>
- <tm:topicRef href="#scopetype-role"/>
- </tm:type>
- <tm:topicRef href="#test-scope-2"/>
- </tm:role>
- </tm:association>
- <!-- === end association-test ============================================ -->
-
-
<!-- ===================================================================== -->
<!-- === TMCL meta-model topics ========================================== -->
<!-- ===================================================================== -->
@@ -678,6 +593,84 @@
<tm:instanceOf><tm:topicRef href="#scopetype"/></tm:instanceOf>
</tm:topic>
+ <!-- region -->
+ <tm:topic id="region">
+ <tm:subjectIdentifier href="http://some.where/base-psis/region"/>
+ <tm:instanceOf><tm:topicRef href="#topictype"/></tm:instanceOf>
+ </tm:topic>
+
+ <tm:topic id="abstract-constraint-for-region">
+ <tm:subjectIdentifier href="http://some.where/constraint-psis/abstract-constraint-for-region"/>
+ <tm:instanceOf><tm:topicRef href="#abstract-topictype-constraint"/></tm:instanceOf>
+ </tm:topic>
+
+ <tm:association>
+ <tm:type><tm:topicRef href="#applies-to"/></tm:type>
+ <tm:role>
+ <tm:type><tm:topicRef href="#constraint-role"/></tm:type>
+ <tm:topicRef href="#abstract-constraint-for-region"/>
+ </tm:role>
+ <tm:role>
+ <tm:type><tm:topicRef href="#topictype-role"/></tm:type>
+ <tm:topicRef href="#region"/>
+ </tm:role>
+ </tm:association>
+
+ <tm:topic id="region-name">
+ <tm:subjectIdentifier href="http://some.where/base-psis/region-name"/>
+ <tm:instanceOf><tm:topicRef href="#nametype"/></tm:instanceOf>
+ </tm:topic>
+
+ <tm:topic id="region-population">
+ <tm:subjectIdentifier href="http://some.where/base-psis/region-population"/>
+ <tm:instanceOf><tm:topicRef href="#occurrencetype"/></tm:instanceOf>
+ </tm:topic>
+
+ <!-- city -->
+ <tm:topic id="city">
+ <tm:subjectIdentifier href="http://some.where/base-psis/city"/>
+ </tm:topic>
+
+ <tm:association>
+ <tm:type><tm:topicRef href="#supertype-subtype"/></tm:type>
+ <tm:role>
+ <tm:type><tm:topicRef href="#supertype"/></tm:type>
+ <tm:topicRef href="#region"/>
+ </tm:role>
+ <tm:role>
+ <tm:type><tm:topicRef href="#subtype"/></tm:type>
+ <tm:topicRef href="#city"/>
+ </tm:role>
+ </tm:association>
+
+ <!-- metropolis -->
+ <tm:topic id="metropolis">
+ <tm:subjectIdentifier href="http://some.where/base-psis/metropolis"/>
+ </tm:topic>
+
+ <tm:association>
+ <tm:type><tm:topicRef href="#supertype-subtype"/></tm:type>
+ <tm:role>
+ <tm:type><tm:topicRef href="#supertype"/></tm:type>
+ <tm:topicRef href="#region"/>
+ </tm:role>
+ <tm:role>
+ <tm:type><tm:topicRef href="#subtype"/></tm:type>
+ <tm:topicRef href="#metropolis"/>
+ </tm:role>
+ </tm:association>
+
+ <!-- country -->
+ <tm:topic id="country">
+ <tm:subjectIdentifier href="http://some.where/base-psis/country"/>
+ <tm:instanceOf><tm:topicRef href="#topictype"/></tm:instanceOf>
+ </tm:topic>
+
+ <tm:topic id="country-name">
+ <tm:subjectIdentifier href="http://some.where/base-psis/country-name"/>
+ <tm:instanceOf><tm:topicRef href="#nametype"/></tm:instanceOf>
+ </tm:topic>
+
<!-- association author-poem -->
<tm:topic id="written-by">
<tm:subjectIdentifier href="http://some.where/base-psis/written-by"/>
@@ -694,6 +687,34 @@
<tm:instanceOf><tm:topicRef href="#roletype"/></tm:instanceOf>
</tm:topic>
+ <!-- association country-city -->
+ <tm:topic id="located-in">
+ <tm:subjectIdentifier href="http://some.where/base-psis/located-in"/>
+ <tm:instanceOf><tm:topicRef href="#associationtype"/></tm:instanceOf>
+ </tm:topic>
+
+ <tm:topic id="container">
+ <tm:subjectIdentifier href="http://some.where/base-psis/container"/>
+ <tm:instanceOf><tm:topicRef href="#roletype"/></tm:instanceOf>
+ </tm:topic>
+
+ <tm:topic id="containee">
+ <tm:subjectIdentifier href="http://some.where/base-psis/containee"/>
+ <tm:instanceOf><tm:topicRef href="#roletype"/></tm:instanceOf>
+ </tm:topic>
+
+ <!-- association author-city -->
+ <tm:topic id="born-in">
+ <tm:subjectIdentifier href="http://some.where/base-psis/born-in"/>
+ <tm:instanceOf><tm:topicRef href="#associationtype"/></tm:instanceOf>
+ </tm:topic>
+
+ <!-- writer already defined for written-by -->
+
+ <tm:topic id="place">
+ <tm:subjectIdentifier href="http://some.where/base-psis/place"/>
+ <tm:instanceOf><tm:topicRef href="#roletype"/></tm:instanceOf>
+ </tm:topic>
<!-- ===================================================================== -->
<!-- === own datamodel: exclusive type constraint ======================== -->
@@ -728,6 +749,30 @@
</tm:role>
</tm:association>
+ <tm:association>
+ <tm:type><tm:topicRef href="#applies-to"/></tm:type>
+ <tm:role>
+ <tm:type><tm:topicRef href="#constraint-role"/></tm:type>
+ <tm:topicRef href="#exc"/>
+ </tm:role>
+ <tm:role>
+ <tm:type><tm:topicRef href="#topictype-role"/></tm:type>
+ <tm:topicRef href="#region"/>
+ </tm:role>
+ </tm:association>
+
+ <tm:association>
+ <tm:type><tm:topicRef href="#applies-to"/></tm:type>
+ <tm:role>
+ <tm:type><tm:topicRef href="#constraint-role"/></tm:type>
+ <tm:topicRef href="#exc"/>
+ </tm:role>
+ <tm:role>
+ <tm:type><tm:topicRef href="#topictype-role"/></tm:type>
+ <tm:topicRef href="#country"/>
+ </tm:role>
+ </tm:association>
+
<!-- ===================================================================== -->
<!-- === own datamodel: subjectIdentifier constraints ==================== -->
<!-- ===================================================================== -->
@@ -797,9 +842,69 @@
</tm:role>
</tm:association>
- <!-- further subjectidentifiers of author and poem -->
- <tm:topic id="sic-author-poem">
- <tm:subjectIdentifier href="http://some.where/constraint-psis/sic-author-poem"/>
+ <!-- subjectidentifier of region -->
+ <tm:topic id="sic-region">
+ <tm:subjectIdentifier href="http://some.where/constraint-psis/sic-region"/>
+ <tm:instanceOf><tm:topicRef href="#subjectidentifier-constraint"/></tm:instanceOf>
+ <tm:occurrence>
+ <tm:type><tm:topicRef href="#card-min"/></tm:type>
+ <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#unsignedInt">1</tm:resourceData>
+ </tm:occurrence>
+ <tm:occurrence>
+ <tm:type><tm:topicRef href="#card-max"/></tm:type>
+ <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#unsignedInt">1</tm:resourceData>
+ </tm:occurrence>
+ <tm:occurrence>
+ <tm:type><tm:topicRef href="#regexp"/></tm:type>
+ <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#string">^http://some.where/psis/region/.+$</tm:resourceData>
+ </tm:occurrence>
+ </tm:topic>
+
+ <tm:association>
+ <tm:type><tm:topicRef href="#applies-to"/></tm:type>
+ <tm:role>
+ <tm:type><tm:topicRef href="#constraint-role"/></tm:type>
+ <tm:topicRef href="#sic-region"/>
+ </tm:role>
+ <tm:role>
+ <tm:type><tm:topicRef href="#topictype-role"/></tm:type>
+ <tm:topicRef href="#region"/>
+ </tm:role>
+ </tm:association>
+
+ <!-- subjectidentifier of country -->
+ <tm:topic id="sic-country">
+ <tm:subjectIdentifier href="http://some.where/constraint-psis/sic-country"/>
+ <tm:instanceOf><tm:topicRef href="#subjectidentifier-constraint"/></tm:instanceOf>
+ <tm:occurrence>
+ <tm:type><tm:topicRef href="#card-min"/></tm:type>
+ <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#unsignedInt">1</tm:resourceData>
+ </tm:occurrence>
+ <tm:occurrence>
+ <tm:type><tm:topicRef href="#card-max"/></tm:type>
+ <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#unsignedInt">1</tm:resourceData>
+ </tm:occurrence>
+ <tm:occurrence>
+ <tm:type><tm:topicRef href="#regexp"/></tm:type>
+ <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#string">^http://some.where/psis/country/.+$</tm:resourceData>
+ </tm:occurrence>
+ </tm:topic>
+
+ <tm:association>
+ <tm:type><tm:topicRef href="#applies-to"/></tm:type>
+ <tm:role>
+ <tm:type><tm:topicRef href="#constraint-role"/></tm:type>
+ <tm:topicRef href="#sic-country"/>
+ </tm:role>
+ <tm:role>
+ <tm:type><tm:topicRef href="#topictype-role"/></tm:type>
+ <tm:topicRef href="#country"/>
+ </tm:role>
+ </tm:association>
+
+ <!-- further subjectidentifiers of all topics -->
+ <tm:topic id="sic-all">
+ <tm:subjectIdentifier href="http://some.where/constraint-psis/all"/>
<tm:instanceOf><tm:topicRef href="#subjectidentifier-constraint"/></tm:instanceOf>
<tm:occurrence>
<tm:type><tm:topicRef href="#card-min"/></tm:type>
@@ -819,7 +924,7 @@
<tm:type><tm:topicRef href="#applies-to"/></tm:type>
<tm:role>
<tm:type><tm:topicRef href="#constraint-role"/></tm:type>
- <tm:topicRef href="#sic-author-poem"/>
+ <tm:topicRef href="#sic-all"/>
</tm:role>
<tm:role>
<tm:type><tm:topicRef href="#topictype-role"/></tm:type>
@@ -831,7 +936,7 @@
<tm:type><tm:topicRef href="#applies-to"/></tm:type>
<tm:role>
<tm:type><tm:topicRef href="#constraint-role"/></tm:type>
- <tm:topicRef href="#sic-author-poem"/>
+ <tm:topicRef href="#sic-all"/>
</tm:role>
<tm:role>
<tm:type><tm:topicRef href="#topictype-role"/></tm:type>
@@ -839,15 +944,39 @@
</tm:role>
</tm:association>
+ <tm:association>
+ <tm:type><tm:topicRef href="#applies-to"/></tm:type>
+ <tm:role>
+ <tm:type><tm:topicRef href="#constraint-role"/></tm:type>
+ <tm:topicRef href="#sic-all"/>
+ </tm:role>
+ <tm:role>
+ <tm:type><tm:topicRef href="#topictype-role"/></tm:type>
+ <tm:topicRef href="#region"/>
+ </tm:role>
+ </tm:association>
+
+ <tm:association>
+ <tm:type><tm:topicRef href="#applies-to"/></tm:type>
+ <tm:role>
+ <tm:type><tm:topicRef href="#constraint-role"/></tm:type>
+ <tm:topicRef href="#sic-all"/>
+ </tm:role>
+ <tm:role>
+ <tm:type><tm:topicRef href="#topictype-role"/></tm:type>
+ <tm:topicRef href="#country"/>
+ </tm:role>
+ </tm:association>
+
<!-- ===================================================================== -->
- <!-- === own datamodel: subjectIdentifier constraints ==================== -->
+ <!-- === own datamodel: subjectLocator constraints ======================= -->
<!-- ===================================================================== -->
- <!-- all instances of author and poem are not allowed to own a
+ <!-- all instances of author, poem, city and country are not allowed to own a
subjectLocator -->
- <tm:topic id="slc-author-poem">
- <tm:subjectIdentifier href="http://some.where/constraint-psis/slc-author-poem"/>
+ <tm:topic id="slc-author-poem-city-country">
+ <tm:subjectIdentifier href="http://some.where/constraint-psis/slc-author-poem-city-country"/>
<tm:instanceOf><tm:topicRef href="#subjectlocator-constraint"/></tm:instanceOf>
<tm:occurrence>
<tm:type><tm:topicRef href="#card-min"/></tm:type>
@@ -867,7 +996,7 @@
<tm:type><tm:topicRef href="#applies-to"/></tm:type>
<tm:role>
<tm:type><tm:topicRef href="#constraint-role"/></tm:type>
- <tm:topicRef href="#slc-author-poem"/>
+ <tm:topicRef href="#slc-author-poem-city-country"/>
</tm:role>
<tm:role>
<tm:type><tm:topicRef href="#topictype-role"/></tm:type>
@@ -879,7 +1008,7 @@
<tm:type><tm:topicRef href="#applies-to"/></tm:type>
<tm:role>
<tm:type><tm:topicRef href="#constraint-role"/></tm:type>
- <tm:topicRef href="#slc-author-poem"/>
+ <tm:topicRef href="#slc-author-poem-city-country"/>
</tm:role>
<tm:role>
<tm:type><tm:topicRef href="#topictype-role"/></tm:type>
@@ -887,8 +1016,32 @@
</tm:role>
</tm:association>
+ <tm:association>
+ <tm:type><tm:topicRef href="#applies-to"/></tm:type>
+ <tm:role>
+ <tm:type><tm:topicRef href="#constraint-role"/></tm:type>
+ <tm:topicRef href="#slc-author-poem-city-country"/>
+ </tm:role>
+ <tm:role>
+ <tm:type><tm:topicRef href="#topictype-role"/></tm:type>
+ <tm:topicRef href="#region"/>
+ </tm:role>
+ </tm:association>
+
+ <tm:association>
+ <tm:type><tm:topicRef href="#applies-to"/></tm:type>
+ <tm:role>
+ <tm:type><tm:topicRef href="#constraint-role"/></tm:type>
+ <tm:topicRef href="#slc-author-poem-city-country"/>
+ </tm:role>
+ <tm:role>
+ <tm:type><tm:topicRef href="#topictype-role"/></tm:type>
+ <tm:topicRef href="#country"/>
+ </tm:role>
+ </tm:association>
+
<!-- ===================================================================== -->
- <!-- === own datamodel: names constraints ================================ -->
+ <!-- === own datamodel: name constraints ================================= -->
<!-- ===================================================================== -->
<!-- instances of the type author has to own a name of the type first-name
and one of the type last-name. both must be valid to the regular
@@ -902,11 +1055,11 @@
<tm:instanceOf><tm:topicRef href="#topicname-constraint"/></tm:instanceOf>
<tm:occurrence>
<tm:type><tm:topicRef href="#card-min"/></tm:type>
- <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#unsignedInt">0</tm:resourceData>
+ <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#unsignedInt">1</tm:resourceData>
</tm:occurrence>
<tm:occurrence>
<tm:type><tm:topicRef href="#card-max"/></tm:type>
- <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#unsignedInt">1</tm:resourceData>
+ <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#unsignedInt">3</tm:resourceData>
</tm:occurrence>
<tm:occurrence>
<tm:type><tm:topicRef href="#regexp"/></tm:type>
@@ -944,7 +1097,7 @@
<tm:instanceOf><tm:topicRef href="#topicname-constraint"/></tm:instanceOf>
<tm:occurrence>
<tm:type><tm:topicRef href="#card-min"/></tm:type>
- <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#unsignedInt">0</tm:resourceData>
+ <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#unsignedInt">1</tm:resourceData>
</tm:occurrence>
<tm:occurrence>
<tm:type><tm:topicRef href="#card-max"/></tm:type>
@@ -986,7 +1139,7 @@
<tm:instanceOf><tm:topicRef href="#topicname-constraint"/></tm:instanceOf>
<tm:occurrence>
<tm:type><tm:topicRef href="#card-min"/></tm:type>
- <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#unsignedInt">0</tm:resourceData>
+ <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#unsignedInt">1</tm:resourceData>
</tm:occurrence>
<tm:occurrence>
<tm:type><tm:topicRef href="#card-max"/></tm:type>
@@ -1022,20 +1175,13 @@
</tm:role>
</tm:association>
-
- <!-- ===================================================================== -->
- <!-- === own datamodel: occurences constraints =========================== -->
- <!-- ===================================================================== -->
- <!-- every instance of the topic author can have one occurrence of the type
- author-info which contains a resourceRef (= datatype #anyURI) -->
-
- <!-- author info occurrence -->
- <tm:topic id="author-occurrence-constraint">
- <tm:subjectIdentifier href="http://some.where/constraint-psis/author-occurrence-constraint"/>
- <tm:instanceOf><tm:topicRef href="#topicoccurrence-constraint"/></tm:instanceOf>
+ <!-- region: region-name -->
+ <tm:topic id="region-name-constraint">
+ <tm:subjectIdentifier href="http://some.where/constraint-psis/region-name-constraint"/>
+ <tm:instanceOf><tm:topicRef href="#topicname-constraint"/></tm:instanceOf>
<tm:occurrence>
<tm:type><tm:topicRef href="#card-min"/></tm:type>
- <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#unsignedInt">0</tm:resourceData>
+ <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#unsignedInt">1</tm:resourceData>
</tm:occurrence>
<tm:occurrence>
<tm:type><tm:topicRef href="#card-max"/></tm:type>
@@ -1051,11 +1197,11 @@
<tm:type><tm:topicRef href="#applies-to"/></tm:type>
<tm:role>
<tm:type><tm:topicRef href="#constraint-role"/></tm:type>
- <tm:topicRef href="#author-occurrence-constraint"/>
+ <tm:topicRef href="#region-name-constraint"/>
</tm:role>
<tm:role>
<tm:type><tm:topicRef href="#topictype-role"/></tm:type>
- <tm:topicRef href="#author"/>
+ <tm:topicRef href="#region"/>
</tm:role>
</tm:association>
@@ -1063,7 +1209,150 @@
<tm:type><tm:topicRef href="#applies-to"/></tm:type>
<tm:role>
<tm:type><tm:topicRef href="#constraint-role"/></tm:type>
- <tm:topicRef href="#author-occurrence-constraint"/>
+ <tm:topicRef href="#region-name-constraint"/>
+ </tm:role>
+ <tm:role>
+ <tm:type><tm:topicRef href="#nametype-role"/></tm:type>
+ <tm:topicRef href="#region-name"/>
+ </tm:role>
+ </tm:association>
+
+ <!-- country: country-name
+ A country hast to have at least one name with the scope "en" or "de".
+ There can exist both names with the scopes "en" and "de". -->
+ <tm:topic id="country-name-constraint">
+ <tm:subjectIdentifier href="http://some.where/constraint-psis/country-name-constraint"/>
+ <tm:instanceOf><tm:topicRef href="#topicname-constraint"/></tm:instanceOf>
+ <tm:occurrence>
+ <tm:type><tm:topicRef href="#card-min"/></tm:type>
+ <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#unsignedInt">1</tm:resourceData>
+ </tm:occurrence>
+ <tm:occurrence>
+ <tm:type><tm:topicRef href="#card-max"/></tm:type>
+ <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#unsignedInt">2</tm:resourceData>
+ </tm:occurrence>
+ <tm:occurrence>
+ <tm:type><tm:topicRef href="#regexp"/></tm:type>
+ <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#string">^.+$</tm:resourceData>
+ </tm:occurrence>
+ </tm:topic>
+
+ <tm:association>
+ <tm:type><tm:topicRef href="#applies-to"/></tm:type>
+ <tm:role>
+ <tm:type><tm:topicRef href="#constraint-role"/></tm:type>
+ <tm:topicRef href="#country-name-constraint"/>
+ </tm:role>
+ <tm:role>
+ <tm:type><tm:topicRef href="#topictype-role"/></tm:type>
+ <tm:topicRef href="#country"/>
+ </tm:role>
+ </tm:association>
+
+ <tm:association>
+ <tm:type><tm:topicRef href="#applies-to"/></tm:type>
+ <tm:role>
+ <tm:type><tm:topicRef href="#constraint-role"/></tm:type>
+ <tm:topicRef href="#country-name-constraint"/>
+ </tm:role>
+ <tm:role>
+ <tm:type><tm:topicRef href="#nametype-role"/></tm:type>
+ <tm:topicRef href="#country-name"/>
+ </tm:role>
+ </tm:association>
+
+ <!-- country-name scopes -->
+ <tm:topic id="scoped-country-name-constraint">
+ <tm:subjectIdentifier href="http://some.where/constraint-psis/scoped-country-name-constraint"/>
+ <tm:instanceOf><tm:topicRef href="#nametypescope-constraint"/></tm:instanceOf>
+ <tm:occurrence>
+ <tm:type><tm:topicRef href="#card-min"/></tm:type>
+ <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#unsignedInt">1</tm:resourceData>
+ </tm:occurrence>
+ <tm:occurrence>
+ <tm:type><tm:topicRef href="#card-max"/></tm:type>
+ <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#unsignedInt">2</tm:resourceData>
+ </tm:occurrence>
+ </tm:topic>
+
+ <tm:association>
+ <tm:type><tm:topicRef href="#applies-to"/></tm:type>
+ <tm:role>
+ <tm:type><tm:topicRef href="#constraint-role"/></tm:type>
+ <tm:topicRef href="#scoped-country-name-constraint"/>
+ </tm:role>
+ <tm:role>
+ <tm:type><tm:topicRef href="#nametype-role"/></tm:type>
+ <tm:topicRef href="#country-name"/>
+ </tm:role>
+ </tm:association>
+
+ <tm:association>
+ <tm:type><tm:topicRef href="#applies-to"/></tm:type>
+ <tm:role>
+ <tm:type><tm:topicRef href="#constraint-role"/></tm:type>
+ <tm:topicRef href="#scoped-country-name-constraint"/>
+ </tm:role>
+ <tm:role>
+ <tm:type><tm:topicRef href="#scopetype-role"/></tm:type>
+ <tm:topicRef href="#en"/>
+ </tm:role>
+ </tm:association>
+
+ <tm:association>
+ <tm:type><tm:topicRef href="#applies-to"/></tm:type>
+ <tm:role>
+ <tm:type><tm:topicRef href="#constraint-role"/></tm:type>
+ <tm:topicRef href="#scoped-country-name-constraint"/>
+ </tm:role>
+ <tm:role>
+ <tm:type><tm:topicRef href="#scopetype-role"/></tm:type>
+ <tm:topicRef href="#de"/>
+ </tm:role>
+ </tm:association>
+
+
+ <!-- ===================================================================== -->
+ <!-- === own datamodel: occurence constraints ============================ -->
+ <!-- ===================================================================== -->
+ <!-- every instance of the topic author can have one occurrence of the type
+ author-info which contains a resourceRef (= datatype #anyURI) -->
+
+ <!-- author info occurrence -->
+ <tm:topic id="author-occurrence-constraint">
+ <tm:subjectIdentifier href="http://some.where/constraint-psis/author-occurrence-constraint"/>
+ <tm:instanceOf><tm:topicRef href="#topicoccurrence-constraint"/></tm:instanceOf>
+ <tm:occurrence>
+ <tm:type><tm:topicRef href="#card-min"/></tm:type>
+ <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#unsignedInt">0</tm:resourceData>
+ </tm:occurrence>
+ <tm:occurrence>
+ <tm:type><tm:topicRef href="#card-max"/></tm:type>
+ <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#unsignedInt">1</tm:resourceData>
+ </tm:occurrence>
+ <tm:occurrence>
+ <tm:type><tm:topicRef href="#regexp"/></tm:type>
+ <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#string">^.+$</tm:resourceData>
+ </tm:occurrence>
+ </tm:topic>
+
+ <tm:association>
+ <tm:type><tm:topicRef href="#applies-to"/></tm:type>
+ <tm:role>
+ <tm:type><tm:topicRef href="#constraint-role"/></tm:type>
+ <tm:topicRef href="#author-occurrence-constraint"/>
+ </tm:role>
+ <tm:role>
+ <tm:type><tm:topicRef href="#topictype-role"/></tm:type>
+ <tm:topicRef href="#author"/>
+ </tm:role>
+ </tm:association>
+
+ <tm:association>
+ <tm:type><tm:topicRef href="#applies-to"/></tm:type>
+ <tm:role>
+ <tm:type><tm:topicRef href="#constraint-role"/></tm:type>
+ <tm:topicRef href="#author-occurrence-constraint"/>
</tm:role>
<tm:role>
<tm:type><tm:topicRef href="#occurrencetype-role"/></tm:type>
@@ -1137,57 +1426,824 @@
</tm:role>
</tm:association>
- <!-- poem content-occurrence datatype -->
- <tm:topic id="poem-content-occurrence-datatype-constraint">
- <tm:subjectIdentifier href="http://some.where/constraint-psis/poem-content-occurrence-datatype-constrai…"/>
- <tm:instanceOf><tm:topicRef href="#occurrencedatatype-constraint"/></tm:instanceOf>
- <tm:occurrence>
- <tm:type><tm:topicRef href="#datatype"/></tm:type>
- <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#string">http://www.w3.org/2001/XMLSchema#string</tm:resourceData>
- </tm:occurrence>
- </tm:topic>
-
+ <!-- poem content-occurrence datatype -->
+ <tm:topic id="poem-content-occurrence-datatype-constraint">
+ <tm:subjectIdentifier href="http://some.where/constraint-psis/poem-content-occurrence-datatype-constrai…"/>
+ <tm:instanceOf><tm:topicRef href="#occurrencedatatype-constraint"/></tm:instanceOf>
+ <tm:occurrence>
+ <tm:type><tm:topicRef href="#datatype"/></tm:type>
+ <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#string">http://www.w3.org/2001/XMLSchema#string</tm:resourceData>
+ </tm:occurrence>
+ </tm:topic>
+
+ <tm:association>
+ <tm:type><tm:topicRef href="#applies-to"/></tm:type>
+ <tm:role>
+ <tm:type><tm:topicRef href="#constraint-role"/></tm:type>
+ <tm:topicRef href="#poem-content-occurrence-datatype-constraint"/>
+ </tm:role>
+ <tm:role>
+ <tm:type><tm:topicRef href="#occurrencetype-role"/></tm:type>
+ <tm:topicRef href="#poem-content"/>
+ </tm:role>
+ </tm:association>
+
+ <!-- the poem-content-occurrence can only appear once per topictype,
+ so all topic with this occurrence type must have different
+ occurrence-values -->
+ <tm:topic id="unique-poem-occurrence-constraint">
+ <tm:subjectIdentifier href="http://some.where/constraint-psis/unique-poem-occurrence-constraint"/>
+ <tm:instanceOf><tm:topicRef href="#uniqueoccurrence-constraint"/></tm:instanceOf>
+ <tm:occurrence>
+ <tm:type><tm:topicRef href="#card-min"/></tm:type>
+ <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#unsignedInt">1</tm:resourceData>
+ </tm:occurrence>
+ <tm:occurrence>
+ <tm:type><tm:topicRef href="#card-max"/></tm:type>
+ <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#unsignedInt">1</tm:resourceData>
+ </tm:occurrence>
+ <tm:occurrence>
+ <tm:type><tm:topicRef href="#regexp"/></tm:type>
+ <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#string">^.*$</tm:resourceData>
+ </tm:occurrence>
+ </tm:topic>
+
+ <tm:association>
+ <tm:type><tm:topicRef href="#applies-to"/></tm:type>
+ <tm:role>
+ <tm:type><tm:topicRef href="#constraint-role"/></tm:type>
+ <tm:topicRef href="#unique-poem-occurrence-constraint"/>
+ </tm:role>
+ <tm:role>
+ <tm:type><tm:topicRef href="#topictype-role"/></tm:type>
+ <tm:topicRef href="#poem"/>
+ </tm:role>
+ </tm:association>
+
+ <tm:association>
+ <tm:type><tm:topicRef href="#applies-to"/></tm:type>
+ <tm:role>
+ <tm:type><tm:topicRef href="#constraint-role"/></tm:type>
+ <tm:topicRef href="#unique-poem-occurrence-constraint"/>
+ </tm:role>
+ <tm:role>
+ <tm:type><tm:topicRef href="#occurrencetype-role"/></tm:type>
+ <tm:topicRef href="#poem-content"/>
+ </tm:role>
+ </tm:association>
+
+ <!-- add a scope to the occurrence "poem-content" -->
+ <tm:topic id="scoped-poem-occurrence-constraint">
+ <tm:subjectIdentifier href="http://some.where/constraint-psis/scoped-poem-occurrence-constraint"/>
+ <tm:instanceOf><tm:topicRef href="#occurrencetypescope-constraint"/></tm:instanceOf>
+ <tm:occurrence>
+ <tm:type><tm:topicRef href="#card-min"/></tm:type>
+ <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#unsignedInt">1</tm:resourceData>
+ </tm:occurrence>
+ <tm:occurrence>
+ <tm:type><tm:topicRef href="#card-max"/></tm:type>
+ <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#unsignedInt">2</tm:resourceData>
+ </tm:occurrence>
+ </tm:topic>
+
+ <tm:association>
+ <tm:type><tm:topicRef href="#applies-to"/></tm:type>
+ <tm:role>
+ <tm:type><tm:topicRef href="#constraint-role"/></tm:type>
+ <tm:topicRef href="#scoped-poem-occurrence-constraint"/>
+ </tm:role>
+ <tm:role>
+ <tm:type><tm:topicRef href="#occurrencetype-role"/></tm:type>
+ <tm:topicRef href="#poem-content"/>
+ </tm:role>
+ </tm:association>
+
+ <tm:association>
+ <tm:type><tm:topicRef href="#applies-to"/></tm:type>
+ <tm:role>
+ <tm:type><tm:topicRef href="#constraint-role"/></tm:type>
+ <tm:topicRef href="#scoped-poem-occurrence-constraint"/>
+ </tm:role>
+ <tm:role>
+ <tm:type><tm:topicRef href="#scopetype-role"/></tm:type>
+ <tm:topicRef href="#en"/>
+ </tm:role>
+ </tm:association>
+
+ <tm:association>
+ <tm:type><tm:topicRef href="#applies-to"/></tm:type>
+ <tm:role>
+ <tm:type><tm:topicRef href="#constraint-role"/></tm:type>
+ <tm:topicRef href="#scoped-poem-occurrence-constraint"/>
+ </tm:role>
+ <tm:role>
+ <tm:type><tm:topicRef href="#scopetype-role"/></tm:type>
+ <tm:topicRef href="#de"/>
+ </tm:role>
+ </tm:association>
+
+ <!-- city population-occurrence -->
+ <tm:topic id="region-population-occurrence-constraint">
+ <tm:subjectIdentifier href="http://some.where/constraint-psis/region-population-occurrence-constraint"/>
+ <tm:instanceOf><tm:topicRef href="#topicoccurrence-constraint"/></tm:instanceOf>
+ <tm:occurrence>
+ <tm:type><tm:topicRef href="#card-min"/></tm:type>
+ <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#unsignedInt">1</tm:resourceData>
+ </tm:occurrence>
+ <tm:occurrence>
+ <tm:type><tm:topicRef href="#card-max"/></tm:type>
+ <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#unsignedInt">1</tm:resourceData>
+ </tm:occurrence>
+ <tm:occurrence>
+ <tm:type><tm:topicRef href="#regexp"/></tm:type>
+ <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#string">^.+$</tm:resourceData>
+ </tm:occurrence>
+ </tm:topic>
+
+ <tm:association>
+ <tm:type><tm:topicRef href="#applies-to"/></tm:type>
+ <tm:role>
+ <tm:type><tm:topicRef href="#constraint-role"/></tm:type>
+ <tm:topicRef href="#region-population-occurrence-constraint"/>
+ </tm:role>
+ <tm:role>
+ <tm:type><tm:topicRef href="#topictype-role"/></tm:type>
+ <tm:topicRef href="#region"/>
+ </tm:role>
+ </tm:association>
+
+ <tm:association>
+ <tm:type><tm:topicRef href="#applies-to"/></tm:type>
+ <tm:role>
+ <tm:type><tm:topicRef href="#constraint-role"/></tm:type>
+ <tm:topicRef href="#region-population-occurrence-constraint"/>
+ </tm:role>
+ <tm:role>
+ <tm:type><tm:topicRef href="#occurrencetype-role"/></tm:type>
+ <tm:topicRef href="#region-population"/>
+ </tm:role>
+ </tm:association>
+
+ <!-- city population-occurrence datatype -->
+ <tm:topic id="region-population-occurrence-datatype-constraint">
+ <tm:subjectIdentifier href="http://some.where/constraint-psis/region-population-occurrence-datatype-con…"/>
+ <tm:instanceOf><tm:topicRef href="#occurrencedatatype-constraint"/></tm:instanceOf>
+ <tm:occurrence>
+ <tm:type><tm:topicRef href="#datatype"/></tm:type>
+ <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#string">http://www.w3.org/2001/XMLSchema#unsignedLong</tm:resourceData>
+ </tm:occurrence>
+ </tm:topic>
+
+ <tm:association>
+ <tm:type><tm:topicRef href="#applies-to"/></tm:type>
+ <tm:role>
+ <tm:type><tm:topicRef href="#constraint-role"/></tm:type>
+ <tm:topicRef href="#region-population-occurrence-datatype-constraint"/>
+ </tm:role>
+ <tm:role>
+ <tm:type><tm:topicRef href="#occurrencetype-role"/></tm:type>
+ <tm:topicRef href="#region-population"/>
+ </tm:role>
+ </tm:association>
+
+ <!-- ===================================================================== -->
+ <!-- === own datamodel: association (-role) constraints ================== -->
+ <!-- ===================================================================== -->
+ <!-- there exists one asoociation of the type written-by between the types
+ author and poem. where one role is of type writer which has a player
+ of type author and another role of type written which owns a player of
+ type poem -->
+
+ <!-- the writer role has to appear exactly once in an association of type
+ written-by -->
+ <tm:topic id="written-by-writer-role-constraint">
+ <tm:subjectIdentifier href="http://some.where/constraint-psis/written-by-writer-role-constraint"/>
+ <tm:instanceOf><tm:topicRef href="#associationrole-constraint"/></tm:instanceOf>
+ <tm:occurrence>
+ <tm:type><tm:topicRef href="#card-min"/></tm:type>
+ <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#unsignedInt">1</tm:resourceData>
+ </tm:occurrence>
+ <tm:occurrence>
+ <tm:type><tm:topicRef href="#card-max"/></tm:type>
+ <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#unsignedInt">1</tm:resourceData>
+ </tm:occurrence>
+ </tm:topic>
+
+ <tm:association>
+ <tm:type><tm:topicRef href="#applies-to"/></tm:type>
+ <tm:role>
+ <tm:type><tm:topicRef href="#constraint-role"/></tm:type>
+ <tm:topicRef href="#written-by-writer-role-constraint"/>
+ </tm:role>
+ <tm:role>
+ <tm:type><tm:topicRef href="#associationtype-role"/></tm:type>
+ <tm:topicRef href="#written-by"/>
+ </tm:role>
+ </tm:association>
+
+ <tm:association>
+ <tm:type><tm:topicRef href="#applies-to"/></tm:type>
+ <tm:role>
+ <tm:type><tm:topicRef href="#constraint-role"/></tm:type>
+ <tm:topicRef href="#written-by-writer-role-constraint"/>
+ </tm:role>
+ <tm:role>
+ <tm:type><tm:topicRef href="#roletype-role"/></tm:type>
+ <tm:topicRef href="#writer"/>
+ </tm:role>
+ </tm:association>
+
+ <!-- the writer role owns a player of the type author -->
+ <tm:topic id="written-by-writer-role-player-constraint">
+ <tm:subjectIdentifier href="http://some.where/constraint-psis/written-by-writer-role-player-constraint"/>
+ <tm:instanceOf><tm:topicRef href="#roleplayer-constraint"/></tm:instanceOf>
+ <tm:occurrence>
+ <tm:type><tm:topicRef href="#card-min"/></tm:type>
+ <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#unsignedInt">1</tm:resourceData>
+ </tm:occurrence>
+ <tm:occurrence>
+ <tm:type><tm:topicRef href="#card-max"/></tm:type>
+ <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#unsignedInt">1</tm:resourceData>
+ </tm:occurrence>
+ </tm:topic>
+
+ <tm:association>
+ <tm:type><tm:topicRef href="#applies-to"/></tm:type>
+ <tm:role>
+ <tm:type><tm:topicRef href="#constraint-role"/></tm:type>
+ <tm:topicRef href="#written-by-writer-role-player-constraint"/>
+ </tm:role>
+ <tm:role>
+ <tm:type><tm:topicRef href="#topictype-role"/></tm:type>
+ <tm:topicRef href="#author"/>
+ </tm:role>
+ </tm:association>
+
+ <tm:association>
+ <tm:type><tm:topicRef href="#applies-to"/></tm:type>
+ <tm:role>
+ <tm:type><tm:topicRef href="#constraint-role"/></tm:type>
+ <tm:topicRef href="#written-by-writer-role-player-constraint"/>
+ </tm:role>
+ <tm:role>
+ <tm:type><tm:topicRef href="#associationtype-role"/></tm:type>
+ <tm:topicRef href="#written-by"/>
+ </tm:role>
+ </tm:association>
+
+ <tm:association>
+ <tm:type><tm:topicRef href="#applies-to"/></tm:type>
+ <tm:role>
+ <tm:type><tm:topicRef href="#constraint-role"/></tm:type>
+ <tm:topicRef href="#written-by-writer-role-player-constraint"/>
+ </tm:role>
+ <tm:role>
+ <tm:type><tm:topicRef href="#roletype-role"/></tm:type>
+ <tm:topicRef href="#writer"/>
+ </tm:role>
+ </tm:association>
+
+
+ <!-- the written role has to appear exactly once in an association of type
+ written-by -->
+ <tm:topic id="written-role-constraint">
+ <tm:subjectIdentifier href="http://some.where/constraint-psis/written-role-constraint"/>
+ <tm:instanceOf><tm:topicRef href="#associationrole-constraint"/></tm:instanceOf>
+ <tm:occurrence>
+ <tm:type><tm:topicRef href="#card-min"/></tm:type>
+ <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#unsignedInt">1</tm:resourceData>
+ </tm:occurrence>
+ <tm:occurrence>
+ <tm:type><tm:topicRef href="#card-max"/></tm:type>
+ <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#unsignedInt">1</tm:resourceData>
+ </tm:occurrence>
+ </tm:topic>
+
+ <tm:association>
+ <tm:type><tm:topicRef href="#applies-to"/></tm:type>
+ <tm:role>
+ <tm:type><tm:topicRef href="#constraint-role"/></tm:type>
+ <tm:topicRef href="#written-role-constraint"/>
+ </tm:role>
+ <tm:role>
+ <tm:type><tm:topicRef href="#associationtype-role"/></tm:type>
+ <tm:topicRef href="#written-by"/>
+ </tm:role>
+ </tm:association>
+
+ <tm:association>
+ <tm:type><tm:topicRef href="#applies-to"/></tm:type>
+ <tm:role>
+ <tm:type><tm:topicRef href="#constraint-role"/></tm:type>
+ <tm:topicRef href="#written-role-constraint"/>
+ </tm:role>
+ <tm:role>
+ <tm:type><tm:topicRef href="#roletype-role"/></tm:type>
+ <tm:topicRef href="#written"/>
+ </tm:role>
+ </tm:association>
+
+ <!-- the written role owns a player of the type poem -->
+ <tm:topic id="written-role-player-constraint">
+ <tm:subjectIdentifier href="http://some.where/constraint-psis/written-role-player-constraint"/>
+ <tm:instanceOf><tm:topicRef href="#roleplayer-constraint"/></tm:instanceOf>
+ <tm:occurrence>
+ <tm:type><tm:topicRef href="#card-min"/></tm:type>
+ <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#unsignedInt">1</tm:resourceData>
+ </tm:occurrence>
+ <tm:occurrence>
+ <tm:type><tm:topicRef href="#card-max"/></tm:type>
+ <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#unsignedInt">1</tm:resourceData>
+ </tm:occurrence>
+ </tm:topic>
+
+ <tm:association>
+ <tm:type><tm:topicRef href="#applies-to"/></tm:type>
+ <tm:role>
+ <tm:type><tm:topicRef href="#constraint-role"/></tm:type>
+ <tm:topicRef href="#written-role-player-constraint"/>
+ </tm:role>
+ <tm:role>
+ <tm:type><tm:topicRef href="#topictype-role"/></tm:type>
+ <tm:topicRef href="#poem"/>
+ </tm:role>
+ </tm:association>
+
+ <tm:association>
+ <tm:type><tm:topicRef href="#applies-to"/></tm:type>
+ <tm:role>
+ <tm:type><tm:topicRef href="#constraint-role"/></tm:type>
+ <tm:topicRef href="#written-role-player-constraint"/>
+ </tm:role>
+ <tm:role>
+ <tm:type><tm:topicRef href="#associationtype-role"/></tm:type>
+ <tm:topicRef href="#written-by"/>
+ </tm:role>
+ </tm:association>
+
+ <tm:association>
+ <tm:type><tm:topicRef href="#applies-to"/></tm:type>
+ <tm:role>
+ <tm:type><tm:topicRef href="#constraint-role"/></tm:type>
+ <tm:topicRef href="#written-role-player-constraint"/>
+ </tm:role>
+ <tm:role>
+ <tm:type><tm:topicRef href="#roletype-role"/></tm:type>
+ <tm:topicRef href="#written"/>
+ </tm:role>
+ </tm:association>
+
+
+ <!-- otherrole-constraint:
+ If there is a role of the type written with a player of the type poem
+ there must be another role of the type writer with a player of the
+ type author.
+ In contrast if there is a role of the type writer with a player of the
+ type author there must be a role of the type written with a player of
+ the type poem.
+ So for this case there are two otherrole-constraints which handle this
+ both cases. -->
+
+ <tm:topic id="written-by-otherrole-constraint-for-writer">
+ <tm:subjectIdentifier href="http://some.where/contraint-psis/written-by-otherrole-constraint-for-writer"/>
+ <tm:instanceOf><tm:topicRef href="#otherrole-constraint"/></tm:instanceOf>
+ <tm:occurrence>
+ <tm:type>
+ <tm:topicRef href="#card-min"/>
+ </tm:type>
+ <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#unsignedInt">1</tm:resourceData>
+ </tm:occurrence>
+ <tm:occurrence>
+ <tm:type>
+ <tm:topicRef href="#card-max"/>
+ </tm:type>
+ <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#unsignedInt">1</tm:resourceData>
+ </tm:occurrence>
+ </tm:topic>
+
+ <tm:association>
+ <tm:type><tm:topicRef href="#applies-to"/></tm:type>
+ <tm:role>
+ <tm:type><tm:topicRef href="#constraint-role"/></tm:type>
+ <tm:topicRef href="#written-by-otherrole-constraint-for-writer"/>
+ </tm:role>
+ <tm:role>
+ <tm:type><tm:topicRef href="#associationtype-role"/></tm:type>
+ <tm:topicRef href="#written-by"/>
+ </tm:role>
+ </tm:association>
+
+ <tm:association>
+ <tm:type><tm:topicRef href="#applies-to"/></tm:type>
+ <tm:role>
+ <tm:type><tm:topicRef href="#constraint-role"/></tm:type>
+ <tm:topicRef href="#written-by-otherrole-constraint-for-writer"/>
+ </tm:role>
+ <tm:role>
+ <tm:type><tm:topicRef href="#roletype-role"/></tm:type>
+ <tm:topicRef href="#writer"/>
+ </tm:role>
+ </tm:association>
+
+ <tm:association>
+ <tm:type><tm:topicRef href="#applies-to"/></tm:type>
+ <tm:role>
+ <tm:type><tm:topicRef href="#constraint-role"/></tm:type>
+ <tm:topicRef href="#written-by-otherrole-constraint-for-writer"/>
+ </tm:role>
+ <tm:role>
+ <tm:type><tm:topicRef href="#topictype-role"/></tm:type>
+ <tm:topicRef href="#author"/>
+ </tm:role>
+ </tm:association>
+
+ <tm:association>
+ <tm:type><tm:topicRef href="#applies-to"/></tm:type>
+ <tm:role>
+ <tm:type><tm:topicRef href="#constraint-role"/></tm:type>
+ <tm:topicRef href="#written-by-otherrole-constraint-for-writer"/>
+ </tm:role>
+ <tm:role>
+ <tm:type><tm:topicRef href="#otherroletype-role"/></tm:type>
+ <tm:topicRef href="#written"/>
+ </tm:role>
+ </tm:association>
+
+ <tm:association>
+ <tm:type><tm:topicRef href="#applies-to"/></tm:type>
+ <tm:role>
+ <tm:type><tm:topicRef href="#constraint-role"/></tm:type>
+ <tm:topicRef href="#written-by-otherrole-constraint-for-writer"/>
+ </tm:role>
+ <tm:role>
+ <tm:type><tm:topicRef href="#othertopictype-role"/></tm:type>
+ <tm:topicRef href="#poem"/>
+ </tm:role>
+ </tm:association>
+
+ <tm:topic id="written-by-otherrole-constraint-for-written">
+ <tm:subjectIdentifier href="http://some.where/contraint-psis/written-by-otherrole-constraint-for-written"/>
+ <tm:instanceOf><tm:topicRef href="#otherrole-constraint"/></tm:instanceOf>
+ <tm:occurrence>
+ <tm:type>
+ <tm:topicRef href="#card-min"/>
+ </tm:type>
+ <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#unsignedInt">1</tm:resourceData>
+ </tm:occurrence>
+ <tm:occurrence>
+ <tm:type>
+ <tm:topicRef href="#card-max"/>
+ </tm:type>
+ <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#unsignedInt">1</tm:resourceData>
+ </tm:occurrence>
+ </tm:topic>
+
+ <tm:association>
+ <tm:type><tm:topicRef href="#applies-to"/></tm:type>
+ <tm:role>
+ <tm:type><tm:topicRef href="#constraint-role"/></tm:type>
+ <tm:topicRef href="#written-by-otherrole-constraint-for-written"/>
+ </tm:role>
+ <tm:role>
+ <tm:type><tm:topicRef href="#associationtype-role"/></tm:type>
+ <tm:topicRef href="#written-by"/>
+ </tm:role>
+ </tm:association>
+
+ <tm:association>
+ <tm:type><tm:topicRef href="#applies-to"/></tm:type>
+ <tm:role>
+ <tm:type><tm:topicRef href="#constraint-role"/></tm:type>
+ <tm:topicRef href="#written-by-otherrole-constraint-for-written"/>
+ </tm:role>
+ <tm:role>
+ <tm:type><tm:topicRef href="#roletype-role"/></tm:type>
+ <tm:topicRef href="#written"/>
+ </tm:role>
+ </tm:association>
+
+ <tm:association>
+ <tm:type><tm:topicRef href="#applies-to"/></tm:type>
+ <tm:role>
+ <tm:type><tm:topicRef href="#constraint-role"/></tm:type>
+ <tm:topicRef href="#written-by-otherrole-constraint-for-written"/>
+ </tm:role>
+ <tm:role>
+ <tm:type><tm:topicRef href="#topictype-role"/></tm:type>
+ <tm:topicRef href="#poem"/>
+ </tm:role>
+ </tm:association>
+
+ <tm:association>
+ <tm:type><tm:topicRef href="#applies-to"/></tm:type>
+ <tm:role>
+ <tm:type><tm:topicRef href="#constraint-role"/></tm:type>
+ <tm:topicRef href="#written-by-otherrole-constraint-for-written"/>
+ </tm:role>
+ <tm:role>
+ <tm:type><tm:topicRef href="#otherroletype-role"/></tm:type>
+ <tm:topicRef href="#writer"/>
+ </tm:role>
+ </tm:association>
+
+ <tm:association>
+ <tm:type><tm:topicRef href="#applies-to"/></tm:type>
+ <tm:role>
+ <tm:type><tm:topicRef href="#constraint-role"/></tm:type>
+ <tm:topicRef href="#written-by-otherrole-constraint-for-written"/>
+ </tm:role>
+ <tm:role>
+ <tm:type><tm:topicRef href="#othertopictype-role"/></tm:type>
+ <tm:topicRef href="#author"/>
+ </tm:role>
+ </tm:association>
+
+ <!-- born-in associations have to have one role of the type writer with a
+ player of the type author. The other role is of type place with the
+ player of the type city. -->
+ <!-- place associationrole-constraint -->
+ <tm:topic id="born-in-place-role-constraint">
+ <tm:subjectIdentifier href="http://some.where/constraint-psis/born-in-place-role-constraint"/>
+ <tm:instanceOf><tm:topicRef href="#associationrole-constraint"/></tm:instanceOf>
+ <tm:occurrence>
+ <tm:type><tm:topicRef href="#card-min"/></tm:type>
+ <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#unsignedInt">1</tm:resourceData>
+ </tm:occurrence>
+ <tm:occurrence>
+ <tm:type><tm:topicRef href="#card-max"/></tm:type>
+ <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#unsignedInt">1</tm:resourceData>
+ </tm:occurrence>
+ </tm:topic>
+
+ <tm:association>
+ <tm:type><tm:topicRef href="#applies-to"/></tm:type>
+ <tm:role>
+ <tm:type><tm:topicRef href="#constraint-role"/></tm:type>
+ <tm:topicRef href="#born-in-place-role-constraint"/>
+ </tm:role>
+ <tm:role>
+ <tm:type><tm:topicRef href="#associationtype-role"/></tm:type>
+ <tm:topicRef href="#born-in"/>
+ </tm:role>
+ </tm:association>
+
+ <tm:association>
+ <tm:type><tm:topicRef href="#applies-to"/></tm:type>
+ <tm:role>
+ <tm:type><tm:topicRef href="#constraint-role"/></tm:type>
+ <tm:topicRef href="#born-in-place-role-constraint"/>
+ </tm:role>
+ <tm:role>
+ <tm:type><tm:topicRef href="#roletype-role"/></tm:type>
+ <tm:topicRef href="#place"/>
+ </tm:role>
+ </tm:association>
+
+ <!-- place-role roleplayer-constraint -->
+ <tm:topic id="born-in-place-role-player-constraint">
+ <tm:subjectIdentifier href="http://some.where/constraint-psis/born-in-place-role-player-constraint"/>
+ <tm:instanceOf><tm:topicRef href="#roleplayer-constraint"/></tm:instanceOf>
+ <tm:occurrence>
+ <tm:type><tm:topicRef href="#card-min"/></tm:type>
+ <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#unsignedInt">1</tm:resourceData>
+ </tm:occurrence>
+ <tm:occurrence>
+ <tm:type><tm:topicRef href="#card-max"/></tm:type>
+ <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#unsignedInt">1</tm:resourceData>
+ </tm:occurrence>
+ </tm:topic>
+
+ <tm:association>
+ <tm:type><tm:topicRef href="#applies-to"/></tm:type>
+ <tm:role>
+ <tm:type><tm:topicRef href="#constraint-role"/></tm:type>
+ <tm:topicRef href="#born-in-place-role-player-constraint"/>
+ </tm:role>
+ <tm:role>
+ <tm:type><tm:topicRef href="#topictype-role"/></tm:type>
+ <tm:topicRef href="#region"/>
+ </tm:role>
+ </tm:association>
+
+ <tm:association>
+ <tm:type><tm:topicRef href="#applies-to"/></tm:type>
+ <tm:role>
+ <tm:type><tm:topicRef href="#constraint-role"/></tm:type>
+ <tm:topicRef href="#born-in-place-role-player-constraint"/>
+ </tm:role>
+ <tm:role>
+ <tm:type><tm:topicRef href="#associationtype-role"/></tm:type>
+ <tm:topicRef href="#born-in"/>
+ </tm:role>
+ </tm:association>
+
+ <tm:association>
+ <tm:type><tm:topicRef href="#applies-to"/></tm:type>
+ <tm:role>
+ <tm:type><tm:topicRef href="#constraint-role"/></tm:type>
+ <tm:topicRef href="#born-in-place-role-player-constraint"/>
+ </tm:role>
+ <tm:role>
+ <tm:type><tm:topicRef href="#roletype-role"/></tm:type>
+ <tm:topicRef href="#place"/>
+ </tm:role>
+ </tm:association>
+
+ <!-- writer associationrole-constraint -->
+ <tm:topic id="born-in-writer-role-constraint">
+ <tm:subjectIdentifier href="http://some.where/constraint-psis/born-in-writer-role-constraint"/>
+ <tm:instanceOf><tm:topicRef href="#associationrole-constraint"/></tm:instanceOf>
+ <tm:occurrence>
+ <tm:type><tm:topicRef href="#card-min"/></tm:type>
+ <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#unsignedInt">1</tm:resourceData>
+ </tm:occurrence>
+ <tm:occurrence>
+ <tm:type><tm:topicRef href="#card-max"/></tm:type>
+ <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#unsignedInt">1</tm:resourceData>
+ </tm:occurrence>
+ </tm:topic>
+
+ <tm:association>
+ <tm:type><tm:topicRef href="#applies-to"/></tm:type>
+ <tm:role>
+ <tm:type><tm:topicRef href="#constraint-role"/></tm:type>
+ <tm:topicRef href="#born-in-writer-role-constraint"/>
+ </tm:role>
+ <tm:role>
+ <tm:type><tm:topicRef href="#associationtype-role"/></tm:type>
+ <tm:topicRef href="#born-in"/>
+ </tm:role>
+ </tm:association>
+
+ <tm:association>
+ <tm:type><tm:topicRef href="#applies-to"/></tm:type>
+ <tm:role>
+ <tm:type><tm:topicRef href="#constraint-role"/></tm:type>
+ <tm:topicRef href="#born-in-writer-role-constraint"/>
+ </tm:role>
+ <tm:role>
+ <tm:type><tm:topicRef href="#roletype-role"/></tm:type>
+ <tm:topicRef href="#writer"/>
+ </tm:role>
+ </tm:association>
+
+ <!-- place-role roleplayer-constraint -->
+ <tm:topic id="born-in-writer-role-player-constraint">
+ <tm:subjectIdentifier href="http://some.where/constraint-psis/born-in-writer-role-player-constraint"/>
+ <tm:instanceOf><tm:topicRef href="#roleplayer-constraint"/></tm:instanceOf>
+ <tm:occurrence>
+ <tm:type><tm:topicRef href="#card-min"/></tm:type>
+ <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#unsignedInt">1</tm:resourceData>
+ </tm:occurrence>
+ <tm:occurrence>
+ <tm:type><tm:topicRef href="#card-max"/></tm:type>
+ <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#unsignedInt">1</tm:resourceData>
+ </tm:occurrence>
+ </tm:topic>
+
+ <tm:association>
+ <tm:type><tm:topicRef href="#applies-to"/></tm:type>
+ <tm:role>
+ <tm:type><tm:topicRef href="#constraint-role"/></tm:type>
+ <tm:topicRef href="#born-in-writer-role-player-constraint"/>
+ </tm:role>
+ <tm:role>
+ <tm:type><tm:topicRef href="#topictype-role"/></tm:type>
+ <tm:topicRef href="#author"/>
+ </tm:role>
+ </tm:association>
+
+ <tm:association>
+ <tm:type><tm:topicRef href="#applies-to"/></tm:type>
+ <tm:role>
+ <tm:type><tm:topicRef href="#constraint-role"/></tm:type>
+ <tm:topicRef href="#born-in-writer-role-player-constraint"/>
+ </tm:role>
+ <tm:role>
+ <tm:type><tm:topicRef href="#associationtype-role"/></tm:type>
+ <tm:topicRef href="#born-in"/>
+ </tm:role>
+ </tm:association>
+
+ <tm:association>
+ <tm:type><tm:topicRef href="#applies-to"/></tm:type>
+ <tm:role>
+ <tm:type><tm:topicRef href="#constraint-role"/></tm:type>
+ <tm:topicRef href="#born-in-writer-role-player-constraint"/>
+ </tm:role>
+ <tm:role>
+ <tm:type><tm:topicRef href="#roletype-role"/></tm:type>
+ <tm:topicRef href="#writer"/>
+ </tm:role>
+ </tm:association>
+
+ <!-- otherplayer-constraints:
+ A "born-in" association must have exactly one writer-role with a
+ player of the type author and one place-role with a player of the
+ type city. -->
+ <tm:topic id="born-in-otherrole-constraint-for-writer">
+ <tm:subjectIdentifier href="http://some.where/contraint-psis/born-in-otherrole-constraint-for-writer"/>
+ <tm:instanceOf><tm:topicRef href="#otherrole-constraint"/></tm:instanceOf>
+ <tm:occurrence>
+ <tm:type>
+ <tm:topicRef href="#card-min"/>
+ </tm:type>
+ <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#unsignedInt">1</tm:resourceData>
+ </tm:occurrence>
+ <tm:occurrence>
+ <tm:type>
+ <tm:topicRef href="#card-max"/>
+ </tm:type>
+ <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#unsignedInt">1</tm:resourceData>
+ </tm:occurrence>
+ </tm:topic>
+
+ <tm:association>
+ <tm:type><tm:topicRef href="#applies-to"/></tm:type>
+ <tm:role>
+ <tm:type><tm:topicRef href="#constraint-role"/></tm:type>
+ <tm:topicRef href="#born-in-otherrole-constraint-for-writer"/>
+ </tm:role>
+ <tm:role>
+ <tm:type><tm:topicRef href="#associationtype-role"/></tm:type>
+ <tm:topicRef href="#born-in"/>
+ </tm:role>
+ </tm:association>
+
+ <tm:association>
+ <tm:type><tm:topicRef href="#applies-to"/></tm:type>
+ <tm:role>
+ <tm:type><tm:topicRef href="#constraint-role"/></tm:type>
+ <tm:topicRef href="#born-in-otherrole-constraint-for-writer"/>
+ </tm:role>
+ <tm:role>
+ <tm:type><tm:topicRef href="#roletype-role"/></tm:type>
+ <tm:topicRef href="#writer"/>
+ </tm:role>
+ </tm:association>
+
+ <tm:association>
+ <tm:type><tm:topicRef href="#applies-to"/></tm:type>
+ <tm:role>
+ <tm:type><tm:topicRef href="#constraint-role"/></tm:type>
+ <tm:topicRef href="#born-in-otherrole-constraint-for-writer"/>
+ </tm:role>
+ <tm:role>
+ <tm:type><tm:topicRef href="#topictype-role"/></tm:type>
+ <tm:topicRef href="#author"/>
+ </tm:role>
+ </tm:association>
+
+ <tm:association>
+ <tm:type><tm:topicRef href="#applies-to"/></tm:type>
+ <tm:role>
+ <tm:type><tm:topicRef href="#constraint-role"/></tm:type>
+ <tm:topicRef href="#born-in-otherrole-constraint-for-writer"/>
+ </tm:role>
+ <tm:role>
+ <tm:type><tm:topicRef href="#otherroletype-role"/></tm:type>
+ <tm:topicRef href="#place"/>
+ </tm:role>
+ </tm:association>
+
<tm:association>
<tm:type><tm:topicRef href="#applies-to"/></tm:type>
<tm:role>
<tm:type><tm:topicRef href="#constraint-role"/></tm:type>
- <tm:topicRef href="#poem-content-occurrence-datatype-constraint"/>
+ <tm:topicRef href="#born-in-otherrole-constraint-for-writer"/>
</tm:role>
<tm:role>
- <tm:type><tm:topicRef href="#occurrencetype-role"/></tm:type>
- <tm:topicRef href="#poem-content"/>
+ <tm:type><tm:topicRef href="#othertopictype-role"/></tm:type>
+ <tm:topicRef href="#region"/>
</tm:role>
</tm:association>
- <!-- the poem-content-occurrence can only appear once per topictype,
- so all topic with this occurrence type must have different
- occurrence-values -->
- <tm:topic id="unique-poem-occurrence-constraint">
- <tm:subjectIdentifier href="http://some.where/constraint-psis/unique-poem-occurrence-constraint"/>
- <tm:instanceOf><tm:topicRef href="#uniqueoccurrence-constraint"/></tm:instanceOf>
+ <tm:topic id="born-in-otherrole-constraint-for-place">
+ <tm:subjectIdentifier href="http://some.where/contraint-psis/born-in-otherrole-constraint-for-place"/>
+ <tm:instanceOf><tm:topicRef href="#otherrole-constraint"/></tm:instanceOf>
<tm:occurrence>
- <tm:type><tm:topicRef href="#card-min"/></tm:type>
+ <tm:type>
+ <tm:topicRef href="#card-min"/>
+ </tm:type>
<tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#unsignedInt">1</tm:resourceData>
</tm:occurrence>
<tm:occurrence>
- <tm:type><tm:topicRef href="#card-max"/></tm:type>
+ <tm:type>
+ <tm:topicRef href="#card-max"/>
+ </tm:type>
<tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#unsignedInt">1</tm:resourceData>
</tm:occurrence>
- <tm:occurrence>
- <tm:type><tm:topicRef href="#regexp"/></tm:type>
- <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#string">^.*$</tm:resourceData>
- </tm:occurrence>
</tm:topic>
<tm:association>
<tm:type><tm:topicRef href="#applies-to"/></tm:type>
<tm:role>
<tm:type><tm:topicRef href="#constraint-role"/></tm:type>
- <tm:topicRef href="#unique-poem-occurrence-constraint"/>
+ <tm:topicRef href="#born-in-otherrole-constraint-for-place"/>
</tm:role>
<tm:role>
- <tm:type><tm:topicRef href="#topictype-role"/></tm:type>
- <tm:topicRef href="#poem"/>
+ <tm:type><tm:topicRef href="#associationtype-role"/></tm:type>
+ <tm:topicRef href="#born-in"/>
</tm:role>
</tm:association>
@@ -1195,37 +2251,23 @@
<tm:type><tm:topicRef href="#applies-to"/></tm:type>
<tm:role>
<tm:type><tm:topicRef href="#constraint-role"/></tm:type>
- <tm:topicRef href="#unique-poem-occurrence-constraint"/>
+ <tm:topicRef href="#born-in-otherrole-constraint-for-place"/>
</tm:role>
<tm:role>
- <tm:type><tm:topicRef href="#occurrencetype-role"/></tm:type>
- <tm:topicRef href="#poem-content"/>
+ <tm:type><tm:topicRef href="#roletype-role"/></tm:type>
+ <tm:topicRef href="#place"/>
</tm:role>
</tm:association>
-
- <!-- add a scope to the occurrence "poem-content" -->
- <tm:topic id="scoped-poem-occurrence-constraint">
- <tm:subjectIdentifier href="http://some.where/constraint-psis/scoped-poem-occurrence-constraint"/>
- <tm:instanceOf><tm:topicRef href="#occurrencetypescope-constraint"/></tm:instanceOf>
- <tm:occurrence>
- <tm:type><tm:topicRef href="#card-min"/></tm:type>
- <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#unsignedInt">1</tm:resourceData>
- </tm:occurrence>
- <tm:occurrence>
- <tm:type><tm:topicRef href="#card-max"/></tm:type>
- <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#unsignedInt">2</tm:resourceData>
- </tm:occurrence>
- </tm:topic>
<tm:association>
<tm:type><tm:topicRef href="#applies-to"/></tm:type>
<tm:role>
<tm:type><tm:topicRef href="#constraint-role"/></tm:type>
- <tm:topicRef href="#scoped-poem-occurrence-constraint"/>
+ <tm:topicRef href="#born-in-otherrole-constraint-for-place"/>
</tm:role>
<tm:role>
- <tm:type><tm:topicRef href="#occurrencetype-role"/></tm:type>
- <tm:topicRef href="#poem-content"/>
+ <tm:type><tm:topicRef href="#topictype-role"/></tm:type>
+ <tm:topicRef href="#region"/>
</tm:role>
</tm:association>
@@ -1233,11 +2275,11 @@
<tm:type><tm:topicRef href="#applies-to"/></tm:type>
<tm:role>
<tm:type><tm:topicRef href="#constraint-role"/></tm:type>
- <tm:topicRef href="#scoped-poem-occurrence-constraint"/>
+ <tm:topicRef href="#born-in-otherrole-constraint-for-place"/>
</tm:role>
<tm:role>
- <tm:type><tm:topicRef href="#scopetype-role"/></tm:type>
- <tm:topicRef href="#en"/>
+ <tm:type><tm:topicRef href="#otherroletype-role"/></tm:type>
+ <tm:topicRef href="#writer"/>
</tm:role>
</tm:association>
@@ -1245,27 +2287,20 @@
<tm:type><tm:topicRef href="#applies-to"/></tm:type>
<tm:role>
<tm:type><tm:topicRef href="#constraint-role"/></tm:type>
- <tm:topicRef href="#scoped-poem-occurrence-constraint"/>
+ <tm:topicRef href="#born-in-otherrole-constraint-for-place"/>
</tm:role>
<tm:role>
- <tm:type><tm:topicRef href="#scopetype-role"/></tm:type>
- <tm:topicRef href="#de"/>
+ <tm:type><tm:topicRef href="#othertopictype-role"/></tm:type>
+ <tm:topicRef href="#author"/>
</tm:role>
</tm:association>
-
- <!-- ===================================================================== -->
- <!-- === own datamodel: association (-role) constraints ================== -->
- <!-- ===================================================================== -->
- <!-- there exists one asoociation of the type written-by between the types
- author and poem. where one role is of type writer which has a player
- of type author and another role of type written which owns a player of
- type poem -->
-
- <!-- the writer role has to appear exactly once in an association of type
- written-by -->
- <tm:topic id="writer-role-constraint">
- <tm:subjectIdentifier href="http://some.where/constraint-psis/writer-role-constraint"/>
+ <!-- located-in associations have to have one role of the type container with
+ a player of the type country. The other role is of type containee with
+ a player of the type city. -->
+ <!-- place associationrole-constraint -->
+ <tm:topic id="located-in-container-role-constraint">
+ <tm:subjectIdentifier href="http://some.where/constraint-psis/located-in-container-role-constraint"/>
<tm:instanceOf><tm:topicRef href="#associationrole-constraint"/></tm:instanceOf>
<tm:occurrence>
<tm:type><tm:topicRef href="#card-min"/></tm:type>
@@ -1281,11 +2316,11 @@
<tm:type><tm:topicRef href="#applies-to"/></tm:type>
<tm:role>
<tm:type><tm:topicRef href="#constraint-role"/></tm:type>
- <tm:topicRef href="#writer-role-constraint"/>
+ <tm:topicRef href="#located-in-container-role-constraint"/>
</tm:role>
<tm:role>
<tm:type><tm:topicRef href="#associationtype-role"/></tm:type>
- <tm:topicRef href="#written-by"/>
+ <tm:topicRef href="#located-in"/>
</tm:role>
</tm:association>
@@ -1293,17 +2328,17 @@
<tm:type><tm:topicRef href="#applies-to"/></tm:type>
<tm:role>
<tm:type><tm:topicRef href="#constraint-role"/></tm:type>
- <tm:topicRef href="#writer-role-constraint"/>
+ <tm:topicRef href="#located-in-container-role-constraint"/>
</tm:role>
<tm:role>
<tm:type><tm:topicRef href="#roletype-role"/></tm:type>
- <tm:topicRef href="#writer"/>
+ <tm:topicRef href="#container"/>
</tm:role>
</tm:association>
- <!-- the writer role owns a player of the type author -->
- <tm:topic id="writer-role-player-constraint">
- <tm:subjectIdentifier href="http://some.where/constraint-psis/writer-role-player-constraint"/>
+ <!-- place-role roleplayer-constraint -->
+ <tm:topic id="located-in-container-role-player-constraint">
+ <tm:subjectIdentifier href="http://some.where/constraint-psis/located-in-container-role-player-constrai…"/>
<tm:instanceOf><tm:topicRef href="#roleplayer-constraint"/></tm:instanceOf>
<tm:occurrence>
<tm:type><tm:topicRef href="#card-min"/></tm:type>
@@ -1319,11 +2354,11 @@
<tm:type><tm:topicRef href="#applies-to"/></tm:type>
<tm:role>
<tm:type><tm:topicRef href="#constraint-role"/></tm:type>
- <tm:topicRef href="#writer-role-player-constraint"/>
+ <tm:topicRef href="#located-in-container-role-player-constraint"/>
</tm:role>
<tm:role>
<tm:type><tm:topicRef href="#topictype-role"/></tm:type>
- <tm:topicRef href="#author"/>
+ <tm:topicRef href="#region"/>
</tm:role>
</tm:association>
@@ -1331,11 +2366,11 @@
<tm:type><tm:topicRef href="#applies-to"/></tm:type>
<tm:role>
<tm:type><tm:topicRef href="#constraint-role"/></tm:type>
- <tm:topicRef href="#writer-role-player-constraint"/>
+ <tm:topicRef href="#located-in-container-role-player-constraint"/>
</tm:role>
<tm:role>
<tm:type><tm:topicRef href="#associationtype-role"/></tm:type>
- <tm:topicRef href="#written-by"/>
+ <tm:topicRef href="#located-in"/>
</tm:role>
</tm:association>
@@ -1343,19 +2378,17 @@
<tm:type><tm:topicRef href="#applies-to"/></tm:type>
<tm:role>
<tm:type><tm:topicRef href="#constraint-role"/></tm:type>
- <tm:topicRef href="#writer-role-player-constraint"/>
+ <tm:topicRef href="#located-in-container-role-player-constraint"/>
</tm:role>
<tm:role>
<tm:type><tm:topicRef href="#roletype-role"/></tm:type>
- <tm:topicRef href="#writer"/>
+ <tm:topicRef href="#container"/>
</tm:role>
</tm:association>
-
- <!-- the written role has to appear exactly once in an association of type
- written-by -->
- <tm:topic id="written-role-constraint">
- <tm:subjectIdentifier href="http://some.where/constraint-psis/written-role-constraint"/>
+ <!-- writer associationrole-constraint -->
+ <tm:topic id="located-in-containee-role-constraint">
+ <tm:subjectIdentifier href="http://some.where/constraint-psis/located-in-containee-role-constraint"/>
<tm:instanceOf><tm:topicRef href="#associationrole-constraint"/></tm:instanceOf>
<tm:occurrence>
<tm:type><tm:topicRef href="#card-min"/></tm:type>
@@ -1371,11 +2404,11 @@
<tm:type><tm:topicRef href="#applies-to"/></tm:type>
<tm:role>
<tm:type><tm:topicRef href="#constraint-role"/></tm:type>
- <tm:topicRef href="#written-role-constraint"/>
+ <tm:topicRef href="#located-in-containee-role-constraint"/>
</tm:role>
<tm:role>
<tm:type><tm:topicRef href="#associationtype-role"/></tm:type>
- <tm:topicRef href="#written-by"/>
+ <tm:topicRef href="#located-in"/>
</tm:role>
</tm:association>
@@ -1383,17 +2416,17 @@
<tm:type><tm:topicRef href="#applies-to"/></tm:type>
<tm:role>
<tm:type><tm:topicRef href="#constraint-role"/></tm:type>
- <tm:topicRef href="#written-role-constraint"/>
+ <tm:topicRef href="#located-in-containee-role-constraint"/>
</tm:role>
<tm:role>
<tm:type><tm:topicRef href="#roletype-role"/></tm:type>
- <tm:topicRef href="#written"/>
+ <tm:topicRef href="#containee"/>
</tm:role>
</tm:association>
- <!-- the written role owns a player of the type poem -->
- <tm:topic id="written-role-player-constraint">
- <tm:subjectIdentifier href="http://some.where/constraint-psis/written-role-player-constraint"/>
+ <!-- place-role roleplayer-constraint -->
+ <tm:topic id="located-in-containee-role-player-constraint">
+ <tm:subjectIdentifier href="http://some.where/constraint-psis/located-in-containee-role-player-constrai…"/>
<tm:instanceOf><tm:topicRef href="#roleplayer-constraint"/></tm:instanceOf>
<tm:occurrence>
<tm:type><tm:topicRef href="#card-min"/></tm:type>
@@ -1409,11 +2442,11 @@
<tm:type><tm:topicRef href="#applies-to"/></tm:type>
<tm:role>
<tm:type><tm:topicRef href="#constraint-role"/></tm:type>
- <tm:topicRef href="#written-role-player-constraint"/>
+ <tm:topicRef href="#located-in-containee-role-player-constraint"/>
</tm:role>
<tm:role>
<tm:type><tm:topicRef href="#topictype-role"/></tm:type>
- <tm:topicRef href="#poem"/>
+ <tm:topicRef href="#region"/>
</tm:role>
</tm:association>
@@ -1421,11 +2454,11 @@
<tm:type><tm:topicRef href="#applies-to"/></tm:type>
<tm:role>
<tm:type><tm:topicRef href="#constraint-role"/></tm:type>
- <tm:topicRef href="#written-role-player-constraint"/>
+ <tm:topicRef href="#located-in-containee-role-player-constraint"/>
</tm:role>
<tm:role>
<tm:type><tm:topicRef href="#associationtype-role"/></tm:type>
- <tm:topicRef href="#written-by"/>
+ <tm:topicRef href="#located-in"/>
</tm:role>
</tm:association>
@@ -1433,27 +2466,20 @@
<tm:type><tm:topicRef href="#applies-to"/></tm:type>
<tm:role>
<tm:type><tm:topicRef href="#constraint-role"/></tm:type>
- <tm:topicRef href="#written-role-player-constraint"/>
+ <tm:topicRef href="#located-in-containee-role-player-constraint"/>
</tm:role>
<tm:role>
<tm:type><tm:topicRef href="#roletype-role"/></tm:type>
- <tm:topicRef href="#written"/>
+ <tm:topicRef href="#containee"/>
</tm:role>
</tm:association>
-
- <!-- otherrole-constraint:
- If there is a role of the type written with a player of the type poem
- there must be another role of the type writer with a player of the
- type author.
- In contrast if there is a role of the type writer with a player of the
- type author there must be a role of the type written with a player of
- the type poem.
- So for this case there are two otherrole-constraints which handle this
- both cases. -->
-
- <tm:topic id="written-by-otherrole-constraint-for-writer">
- <tm:subjectIdentifier href="written-by-otherrole-constraint-for-writer"/>
+ <!-- otherplayer-constraints:
+ A "born-in" association must have exactly one writer-role with a
+ player of the type author and one place-role with a player of the
+ type city. -->
+ <tm:topic id="located-in-otherrole-constraint-for-container">
+ <tm:subjectIdentifier href="http://some.where/contraint-psis/located-in-otherrole-constraint-for-contai…"/>
<tm:instanceOf><tm:topicRef href="#otherrole-constraint"/></tm:instanceOf>
<tm:occurrence>
<tm:type>
@@ -1473,11 +2499,11 @@
<tm:type><tm:topicRef href="#applies-to"/></tm:type>
<tm:role>
<tm:type><tm:topicRef href="#constraint-role"/></tm:type>
- <tm:topicRef href="#written-by-otherrole-constraint-for-writer"/>
+ <tm:topicRef href="#located-in-otherrole-constraint-for-container"/>
</tm:role>
<tm:role>
<tm:type><tm:topicRef href="#associationtype-role"/></tm:type>
- <tm:topicRef href="#written-by"/>
+ <tm:topicRef href="#located-in"/>
</tm:role>
</tm:association>
@@ -1485,11 +2511,11 @@
<tm:type><tm:topicRef href="#applies-to"/></tm:type>
<tm:role>
<tm:type><tm:topicRef href="#constraint-role"/></tm:type>
- <tm:topicRef href="#written-by-otherrole-constraint-for-writer"/>
+ <tm:topicRef href="#located-in-otherrole-constraint-for-container"/>
</tm:role>
<tm:role>
<tm:type><tm:topicRef href="#roletype-role"/></tm:type>
- <tm:topicRef href="#writer"/>
+ <tm:topicRef href="#container"/>
</tm:role>
</tm:association>
@@ -1497,11 +2523,11 @@
<tm:type><tm:topicRef href="#applies-to"/></tm:type>
<tm:role>
<tm:type><tm:topicRef href="#constraint-role"/></tm:type>
- <tm:topicRef href="#written-by-otherrole-constraint-for-writer"/>
+ <tm:topicRef href="#located-in-otherrole-constraint-for-container"/>
</tm:role>
<tm:role>
<tm:type><tm:topicRef href="#topictype-role"/></tm:type>
- <tm:topicRef href="#author"/>
+ <tm:topicRef href="#country"/>
</tm:role>
</tm:association>
@@ -1509,11 +2535,11 @@
<tm:type><tm:topicRef href="#applies-to"/></tm:type>
<tm:role>
<tm:type><tm:topicRef href="#constraint-role"/></tm:type>
- <tm:topicRef href="#written-by-otherrole-constraint-for-writer"/>
+ <tm:topicRef href="#located-in-otherrole-constraint-for-container"/>
</tm:role>
<tm:role>
<tm:type><tm:topicRef href="#otherroletype-role"/></tm:type>
- <tm:topicRef href="#written"/>
+ <tm:topicRef href="#containee"/>
</tm:role>
</tm:association>
@@ -1521,16 +2547,16 @@
<tm:type><tm:topicRef href="#applies-to"/></tm:type>
<tm:role>
<tm:type><tm:topicRef href="#constraint-role"/></tm:type>
- <tm:topicRef href="#written-by-otherrole-constraint-for-writer"/>
+ <tm:topicRef href="#located-in-otherrole-constraint-for-container"/>
</tm:role>
<tm:role>
<tm:type><tm:topicRef href="#othertopictype-role"/></tm:type>
- <tm:topicRef href="#poem"/>
+ <tm:topicRef href="#region"/>
</tm:role>
</tm:association>
- <tm:topic id="written-by-otherrole-constraint-for-written">
- <tm:subjectIdentifier href="written-by-otherrole-constraint-for-written"/>
+ <tm:topic id="located-in-otherrole-constraint-for-containee">
+ <tm:subjectIdentifier href="http://some.where/contraint-psis/located-in-otherrole-constraint-for-contai…"/>
<tm:instanceOf><tm:topicRef href="#otherrole-constraint"/></tm:instanceOf>
<tm:occurrence>
<tm:type>
@@ -1550,11 +2576,11 @@
<tm:type><tm:topicRef href="#applies-to"/></tm:type>
<tm:role>
<tm:type><tm:topicRef href="#constraint-role"/></tm:type>
- <tm:topicRef href="#written-by-otherrole-constraint-for-written"/>
+ <tm:topicRef href="#located-in-otherrole-constraint-for-containee"/>
</tm:role>
<tm:role>
<tm:type><tm:topicRef href="#associationtype-role"/></tm:type>
- <tm:topicRef href="#written-by"/>
+ <tm:topicRef href="#born-in"/>
</tm:role>
</tm:association>
@@ -1562,11 +2588,11 @@
<tm:type><tm:topicRef href="#applies-to"/></tm:type>
<tm:role>
<tm:type><tm:topicRef href="#constraint-role"/></tm:type>
- <tm:topicRef href="#written-by-otherrole-constraint-for-written"/>
+ <tm:topicRef href="#located-in-otherrole-constraint-for-containee"/>
</tm:role>
<tm:role>
<tm:type><tm:topicRef href="#roletype-role"/></tm:type>
- <tm:topicRef href="#written"/>
+ <tm:topicRef href="#containee"/>
</tm:role>
</tm:association>
@@ -1574,11 +2600,11 @@
<tm:type><tm:topicRef href="#applies-to"/></tm:type>
<tm:role>
<tm:type><tm:topicRef href="#constraint-role"/></tm:type>
- <tm:topicRef href="#written-by-otherrole-constraint-for-written"/>
+ <tm:topicRef href="#located-in-otherrole-constraint-for-containee"/>
</tm:role>
<tm:role>
<tm:type><tm:topicRef href="#topictype-role"/></tm:type>
- <tm:topicRef href="#poem"/>
+ <tm:topicRef href="#region"/>
</tm:role>
</tm:association>
@@ -1586,11 +2612,11 @@
<tm:type><tm:topicRef href="#applies-to"/></tm:type>
<tm:role>
<tm:type><tm:topicRef href="#constraint-role"/></tm:type>
- <tm:topicRef href="#written-by-otherrole-constraint-for-written"/>
+ <tm:topicRef href="#located-in-otherrole-constraint-for-containee"/>
</tm:role>
<tm:role>
<tm:type><tm:topicRef href="#otherroletype-role"/></tm:type>
- <tm:topicRef href="#writer"/>
+ <tm:topicRef href="#container"/>
</tm:role>
</tm:association>
@@ -1598,17 +2624,131 @@
<tm:type><tm:topicRef href="#applies-to"/></tm:type>
<tm:role>
<tm:type><tm:topicRef href="#constraint-role"/></tm:type>
- <tm:topicRef href="#written-by-otherrole-constraint-for-written"/>
+ <tm:topicRef href="#located-in-otherrole-constraint-for-containee"/>
</tm:role>
<tm:role>
<tm:type><tm:topicRef href="#othertopictype-role"/></tm:type>
- <tm:topicRef href="#author"/>
+ <tm:topicRef href="#country"/>
</tm:role>
</tm:association>
<!-- ===================================================================== -->
<!-- === the "user's" topic map ========================================== -->
<!-- ===================================================================== -->
+ <tm:topic id="germany">
+ <tm:subjectIdentifier href="http://some.where/psis/country/germany"/>
+ <tm:instanceOf><tm:topicRef href="#country"/></tm:instanceOf>
+ <tm:name>
+ <tm:scope><tm:topicRef href="#de"/></tm:scope>
+ <tm:value>Deutschland</tm:value>
+ </tm:name>
+ <tm:name>
+ <tm:scope><tm:topicRef href="#en"/></tm:scope>
+ <tm:value>Germany</tm:value>
+ </tm:name>
+ </tm:topic>
+
+ <tm:topic id="poland">
+ <tm:subjectIdentifier href="http://some.where/psis/country/poland"/>
+ <tm:instanceOf><tm:topicRef href="#country"/></tm:instanceOf>
+ <tm:name>
+ <tm:scope><tm:topicRef href="#de"/></tm:scope>
+ <tm:value>Polen</tm:value>
+ </tm:name>
+ <tm:name>
+ <tm:scope><tm:topicRef href="#en"/></tm:scope>
+ <tm:value>Poland</tm:value>
+ </tm:name>
+ </tm:topic>
+
+ <tm:topic id="frankfurt_am_main">
+ <tm:subjectIdentifier href="http://some.where/psis/city/frankfurt_am_main"/>
+ <tm:instanceOf><tm:topicRef href="#metropolis"/></tm:instanceOf>
+ <tm:name>
+ <tm:type><tm:topicRef href="#region-name"/></tm:type>
+ <tm:value>Frankfurt am Main</tm:value>
+ </tm:name>
+ <tm:occurrence>
+ <tm:type><tm:topicRef href="#region-population"/></tm:type>
+ <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#unsignedLong">659021</tm:resourceData>
+ </tm:occurrence>
+ </tm:topic>
+
+ <tm:association>
+ <tm:type><tm:topicRef href="#located-in"/></tm:type>
+ <tm:role>
+ <tm:type><tm:topicRef href="#container"/></tm:type>
+ <tm:topicRef href="#germany"/>
+ </tm:role>
+ <tm:role>
+ <tm:type><tm:topicRef href="#containee"/></tm:type>
+ <tm:topicRef href="#frankfurt_am_main"/>
+ </tm:role>
+ </tm:association>
+
+ <tm:topic id="marbach_am_neckar">
+ <tm:subjectIdentifier href="http://some.where/psis/city/marbach_am_neckar"/>
+ <tm:instanceOf><tm:topicRef href="#city"/></tm:instanceOf>
+ <tm:name>
+ <tm:type><tm:topicRef href="#region-name"/></tm:type>
+ <tm:value>Marbach am Neckar</tm:value>
+ </tm:name>
+ <tm:occurrence>
+ <tm:type><tm:topicRef href="#region-population"/></tm:type>
+ <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#unsignedLong">15601</tm:resourceData>
+ </tm:occurrence>
+ </tm:topic>
+
+ <tm:association>
+ <tm:type><tm:topicRef href="#located-in"/></tm:type>
+ <tm:role>
+ <tm:type><tm:topicRef href="#container"/></tm:type>
+ <tm:topicRef href="#germany"/>
+ </tm:role>
+ <tm:role>
+ <tm:type><tm:topicRef href="#containee"/></tm:type>
+ <tm:topicRef href="#marbach_am_neckar"/>
+ </tm:role>
+ </tm:association>
+
+ <tm:topic id="lubowitz">
+ <tm:subjectIdentifier href="http://some.where/psis/city/lubowitz"/>
+ <tm:instanceOf><tm:topicRef href="#city"/></tm:instanceOf>
+ <tm:name>
+ <tm:type><tm:topicRef href="#region-name"/></tm:type>
+ <tm:value>Lubowitz</tm:value>
+ </tm:name>
+ <tm:occurrence>
+ <tm:type><tm:topicRef href="#region-population"/></tm:type>
+ <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#unsignedLong">365</tm:resourceData>
+ </tm:occurrence>
+ </tm:topic>
+
+ <tm:association>
+ <tm:type><tm:topicRef href="#located-in"/></tm:type>
+ <tm:role>
+ <tm:type><tm:topicRef href="#container"/></tm:type>
+ <tm:topicRef href="#poland"/>
+ </tm:role>
+ <tm:role>
+ <tm:type><tm:topicRef href="#containee"/></tm:type>
+ <tm:topicRef href="#lubowitz"/>
+ </tm:role>
+ </tm:association>
+
+ <tm:topic id="eichendorff">
+ <tm:subjectIdentifier href="http://some.where/psis/author/eichendorff"/>
+ <tm:instanceOf><tm:topicRef href="#author"/></tm:instanceOf>
+ <tm:name>
+ <tm:type><tm:topicRef href="#first-name"/></tm:type>
+ <tm:value>Joseph Karl Benedikt</tm:value>
+ </tm:name>
+ <tm:name>
+ <tm:type><tm:topicRef href="#last-name"/></tm:type>
+ <tm:value>von Eichendorff</tm:value>
+ </tm:name>
+ </tm:topic>
+
<tm:topic id="goethe">
<tm:subjectIdentifier href="http://some.where/psis/author/goethe"/> <!-- must have a psi of this form -->
<tm:subjectIdentifier href="http://some.where/psis/persons/goethe"/> <!-- can own psis of any form -->
@@ -1627,6 +2767,18 @@
</tm:occurrence>
</tm:topic>
+ <tm:association>
+ <tm:type><tm:topicRef href="#born-in"/></tm:type>
+ <tm:role>
+ <tm:type><tm:topicRef href="#place"/></tm:type>
+ <tm:topicRef href="#frankfurt_am_main"/>
+ </tm:role>
+ <tm:role>
+ <tm:type><tm:topicRef href="#writer"/></tm:type>
+ <tm:topicRef href="#goethe"/>
+ </tm:role>
+ </tm:association>
+
<tm:topic id="schiller">
<tm:subjectIdentifier href="http://some.where/psis/author/schiller"/> <!-- must have a psi of this form -->
<tm:instanceOf><tm:topicRef href="#author"/></tm:instanceOf> <!-- must be an instanceOf author -->
@@ -1644,15 +2796,23 @@
</tm:occurrence>
</tm:topic>
+ <tm:association>
+ <tm:type><tm:topicRef href="#born-in"/></tm:type>
+ <tm:role>
+ <tm:type><tm:topicRef href="#place"/></tm:type>
+ <tm:topicRef href="#marbach_am_neckar"/>
+ </tm:role>
+ <tm:role>
+ <tm:type><tm:topicRef href="#writer"/></tm:type>
+ <tm:topicRef href="#schiller"/>
+ </tm:role>
+ </tm:association>
+
<tm:topic id="zauberlehrling">
<tm:subjectIdentifier href="http://some.where/psis/poem/zauberlehrling"/> <!-- must have a psi of this form -->
<tm:subjectIdentifier href="http://some.where/psis/der_zauberlehrling"/> <!-- can own psis of any form -->
<tm:instanceOf>
- <tm:topicRef href="#poem"/><!--
- <tm:topicRef href="#author"/>
- <tm:topicRef href="#zauberlehrling"/>
- <tm:topicRef href="#topictype-constraint"/>-->
- </tm:instanceOf> <!-- must be an instanceOf poem -->
+ <tm:topicRef href="#poem"/></tm:instanceOf> <!-- must be an instanceOf poem -->
<tm:name>
<tm:type><tm:topicRef href="#title"/></tm:type> <!-- must have a name of the type title -->
<tm:value>Der Zauberlehrling</tm:value>
@@ -1826,10 +2986,6 @@
</tm:occurrence>
</tm:topic>
- <!-- some assocaitions between goethe and some of his poems,
- currently there are no associations between the topic schiller
- and any other topic, because there are no topic representing
- a poem of schiller -->
<tm:association>
<tm:type><tm:topicRef href="#written-by"/></tm:type>
<tm:role>
@@ -1854,4 +3010,187 @@
</tm:role>
</tm:association>
+ <tm:topic id="resignation">
+ <tm:subjectIdentifier href="http://some.where/psis/poem/resignation"/> <!-- must have a psi of this form -->
+ <tm:instanceOf><tm:topicRef href="#poem"/></tm:instanceOf> <!-- must be an instanceOf poem -->
+ <tm:name>
+ <tm:type><tm:topicRef href="#title"/></tm:type> <!-- must have a name of the type title -->
+ <tm:value>Resignation - Eine Phantasie</tm:value>
+ </tm:name>
+ <tm:occurrence>
+ <tm:type><tm:topicRef href="#poem-content"/></tm:type> <!-- must have an occurrence of the type poem-content with the scope de or en -->
+ <tm:scope><tm:topicRef href="#de"/></tm:scope>
+ <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#string">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."</tm:resourceData>
+ </tm:occurrence>
+ </tm:topic>
+
+ <tm:association>
+ <tm:type><tm:topicRef href="#written-by"/></tm:type>
+ <tm:role>
+ <tm:type><tm:topicRef href="#writer"/></tm:type>
+ <tm:topicRef href="#schiller"/>
+ </tm:role>
+ <tm:role>
+ <tm:type><tm:topicRef href="#written"/></tm:type>
+ <tm:topicRef href="#resignation"/>
+ </tm:role>
+ </tm:association>
+
+ <tm:topic id="mondnacht">
+ <tm:subjectIdentifier href="http://some.where/psis/poem/mondnacht"/> <!-- must have a psi of this form -->
+ <tm:instanceOf><tm:topicRef href="#poem"/></tm:instanceOf> <!-- must be an instanceOf poem -->
+ <tm:name>
+ <tm:type><tm:topicRef href="#title"/></tm:type> <!-- must have a name of the type title -->
+ <tm:value>Mondnacht</tm:value>
+ </tm:name>
+ <tm:occurrence>
+ <tm:type><tm:topicRef href="#poem-content"/></tm:type> <!-- must have an occurrence of the type poem-content with the scope de or en -->
+ <tm:scope><tm:topicRef href="#de"/></tm:scope>
+ <tm:resourceData datatype="http://www.w3.org/2001/XMLSchema#string">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.</tm:resourceData>
+ </tm:occurrence>
+ </tm:topic>
+
+ <tm:association>
+ <tm:type><tm:topicRef href="#written-by"/></tm:type>
+ <tm:role>
+ <tm:type><tm:topicRef href="#writer"/></tm:type>
+ <tm:topicRef href="#eichendorff"/>
+ </tm:role>
+ <tm:role>
+ <tm:type><tm:topicRef href="#written"/></tm:type>
+ <tm:topicRef href="#mondnacht"/>
+ </tm:role>
+ </tm:association>
+
</tm:topicMap>
1
0
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" : [ <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 <occurrencetype-topic>
- :constraints ( ( :regexp <string> :card-min <string> :card-max <string>)
- <...>)
- :scopes ( ( :scope <scope-topic> :regexp <string> :card-min <string> :card-max <string>)
- <...>)
- :datatype <string>
- :uniqe ( ( :regexp <string> :dard-min <string> :card-max <string> ) )
- <...>)."
+ [{occurrenceTypes:[{occurrenceType:[psi-1,psi-2],
+ scopeConstraints:[<scopeConstraints>],
+ datatypeConstraint:datatype},
+ <...>],
+ constraints:[<simpleConstraints>, <...>],
+ uniqueConstraint:[<uniqueConstraints>, <...> ]}
+ <...>]."
(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 (<topic> <...>) :checked-topics (<topic> <...>)"
- (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 (<topic> <...>) :checked-topics (<topic> <...>)"
+ (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
1
0

05 May '09
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".
//+-----------------------------------------------------------------------------
-<simepleConstraint>
+<simpleConstraint>
//+-----------------------------------------------------------------------------
@@ -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" : [ <simpleConstraint>, < ... > ],
- "scopeConstraints" : { <scopeConstraint> }
+ "nametypescopes" : [ {
+ "nametype" : [psi-1, psi-2, "..." ],
+ "scopeConstraints" : [ <scopeConstraints> ]
+ },
+ <...>
+ ]
+ "constraints" : [ <simpleConstraint>, < ... > ]
}
@@ -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" : [ <simpleConstraint>, < ... > ],
- "scopeConstraints" : { <scopeConstraint> },
- "dataConstraint" : "datatype",
- "uniqueConstraints" : [ <uniqueOccurrenceConstraint>, <...> ]
+//+ 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" : [ <scopeConstraints> ],
+ "datatypeConstraint" : "datatype",
+ },
+ <...>
+ ],
+ "constraints" : [ <simpleConstraints>, <...>],
+ "uniqueConstraint" : [ <uniqueConstraints>, <...> ]
}
@@ -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 <string> :card-min <string> :card-max <string>) <...>)
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 <nametype-topic>
- :constraints ( ( :regexp <string> :card-min <string> :card-max <string>)
- <...>)
- :scopes ( ( :scope <scope-topic> :regexp <string> :card-min <string> :card-max <string>)
- <...>))
- <...>)."
+ [{nametypescopes:[{nameType: [psi-1, psi-2], scopeConstraints: [<scopeConstraint>]},
+ {nameType: [subtype-1-psi-1], scopeConstriants: [<scopeConstraints>]},
+ constraints: [<simpleConstraint>, <...>]},
+ <...>]."
(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 <scope-topic>
- :constraint (:card-min <string> :card-max <string> ))."
+ 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: <int-as-string>,
+ cardMax <int-as-string | MAX_INT>}, <...>]."
(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 (<topic> <...>) :checked-topics (<topic> <...>)"
+ (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
1
0

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

[isidorus-cvs] r27 - in trunk/src: ajax ajax/javascripts json rest_interface unit_tests
by Lukas Giessmann 13 Apr '09
by Lukas Giessmann 13 Apr '09
13 Apr '09
Author: lgiessmann
Date: Mon Apr 13 13:17:57 2009
New Revision: 27
Log:
fixed some problems in the ajax and in the json interface; changed the json/ajax error handling of the server, so there will be sent the condition's content as error message to the client - therefor every json-handler has a case-handler
Modified:
trunk/src/ajax/isidorus.html
trunk/src/ajax/javascripts/make_fragment_node.js
trunk/src/json/json_exporter.lisp
trunk/src/rest_interface/set-up-json-interface.lisp
trunk/src/unit_tests/json_test.lisp
Modified: trunk/src/ajax/isidorus.html
==============================================================================
--- trunk/src/ajax/isidorus.html (original)
+++ trunk/src/ajax/isidorus.html Mon Apr 13 13:17:57 2009
@@ -19,10 +19,25 @@
<!-- includes all necessary css-files -->
<link rel="stylesheet" type="text/css" href="css/main.css"/>
<link rel="stylesheet" type="text/css" href="css/home.css"/>
- <link rel="stylesheet" type="text/css" href="css/search_topics.css"/>
- <link rel="stylesheet" type="text/css" href="css/edit_topics.css"/>
- <link rel="stylesheet" type="text/css" href="css/create_topics.css"/>
<link rel="stylesheet" type="text/css" href="css/navi.css"/>
+
+ <!-- error handling for javascript code -->
+ <script language="JavaScript" type="text/javascript"> <!--
+ var __DEBUG__ = true;
+
+ function onError(message, url, line)
+ {
+ window.alert("onError in \"" + url + "\" at line: " + line + "\n" + message);
+ return true;
+ }
+
+ if(__DEBUG__ === true){
+ window.onerror = onError;
+ }
+
+ // -->
+ </script>
+
<!-- includes the prototype and scriptaculous frameworks -->
<script language="JavaScript" type="text/javascript" src="javascripts/external/prototype/prototype.js"></script>
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 Apr 13 13:17:57 2009
@@ -1040,7 +1040,13 @@
}
var ioElems = topicFrame.getElementsByClassName(CLASSES.instanceOfFrame())[0].getElementsByClassName(CLASSES.textRow());
- var _instanceOfs = "\"instanceOfs\":" + makeList(ioElems);
+ var _instanceOfs = makeList(ioElems);
+ if(_instanceOfs === "null"){
+ _instanceOfs = "\"instanceOfs\":null";
+ }
+ else {
+ _instanceOfs = "\"instanceOfs\":[" + _instanceOfs + "]";
+ }
var naElems = topicFrame.getElementsByClassName(CLASSES.namesFrame())[0].getElementsByClassName(CLASSES.nameFrame());
var _names = "\"names\":";
@@ -1239,7 +1245,7 @@
method: "post",
requestHeaders:{ "Content-Type":"application/json"},
onSuccess: function(xhr){ window.alert("Fragment committed successfully!"); },
- onFailure: function(xhr){ window.alert("Something went wrong ...\n" + xhr.status + ": " + xhr.statusText); },
+ onFailure: function(xhr){ window.alert("Something went wrong ...\n" + xhr.status + ": " + xhr.statusText + "\n" + xhr.responseText); },
postBody: _fragment
});
}
@@ -1271,7 +1277,7 @@
$("content").insert(makeFragmentNode(jsonFragment), {"position" : "content"});
}
catch(err){
- alert("Got bad json data from " + GET_PREFIX + topicPsi.gsub("#", "%23"));
+ alert("Got bad json data from " + GET_PREFIX + topicPsi.gsub("#", "%23") + "\n" + err);
}
}
Modified: trunk/src/json/json_exporter.lisp
==============================================================================
--- trunk/src/json/json_exporter.lisp (original)
+++ trunk/src/json/json_exporter.lisp Mon Apr 13 13:17:57 2009
@@ -147,7 +147,7 @@
(defmethod to-json-string ((instance TopicC) &key (xtm-id d:*current-xtm*))
"transforms an TopicC object to a json string"
(let ((id
- (concatenate 'string "\"id\":\"" (topicid instance) "\""))
+ (concatenate 'string "\"id\":" (json:encode-json-to-string (topicid instance))))
(itemIdentity
(concatenate 'string "\"itemIdentities\":"
(identifiers-to-json-string instance :what 'item-identifiers)))
@@ -188,7 +188,7 @@
subjectIdentifiers"
(when topic
(let ((id
- (concatenate 'string "\"id\":\"" (topicid topic) "\""))
+ (concatenate 'string "\"id\":" (json:encode-json-to-string (topicid topic))))
(itemIdentity
(concatenate 'string "\"itemIdentities\":"
(identifiers-to-json-string topic :what 'item-identifiers)))
@@ -227,8 +227,7 @@
(type
(type-to-json-string instance))
(scope
- (let ((scopes (map 'list #'topicid (themes instance))))
- (concatenate 'string "\"scopes\":" (json:encode-json-to-string scopes))))
+ (concatenate 'string "\"scopes\":" (ref-topics-to-json-string (themes instance))))
(role
(concatenate 'string "\"roles\":"
(if (roles instance)
@@ -280,8 +279,10 @@
(if (in-topicmaps (topic instance))
(let ((j-tm-ids "["))
(loop for item in (in-topicmaps (topic instance))
- do (setf j-tm-ids (concatenate 'string j-tm-ids "\""
- (d:uri (first (d:item-identifiers item))) "\",")))
+ ;do (setf j-tm-ids (concatenate 'string j-tm-ids "\""
+ ; (d:uri (first (d:item-identifiers item))) "\",")))
+ do (setf j-tm-ids (concatenate 'string j-tm-ids
+ (json:encode-json-to-string (d:uri (first (d:item-identifiers item)))) ",")))
(concatenate 'string (subseq j-tm-ids 0 (- (length j-tm-ids) 1)) "]"))
"null"))))
(concatenate 'string "{" main-topic "," topicStubs "," associations "," tm-ids "}")))
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 Apr 13 13:17:57 2009
@@ -33,6 +33,12 @@
(ajax-javascripts-url-prefix *ajax-javascript-url-prefix*))
"registers the json im/exporter to the passed base-url in hunchentoot's dispatch-table
and also registers a file-hanlder to the html-user-interface"
+
+ ;; registers the http-code 500 for an internal server error to the standard
+ ;; return codes. so there won't be attached a hunchentoot default message,
+ ;; this is necessary to be able to send error messages in an individual way/syntax
+ ;; e.g. a json error-message.
+ (push hunchentoot:+http-internal-server-error+ hunchentoot:*approved-return-codes*)
;; === html and css files ====================================================
(push
(create-regex-dispatcher ajax-user-interface-url
@@ -83,7 +89,11 @@
(if (eq http-method :GET)
(progn
(setf (hunchentoot:content-type*) "application/json") ;RFC 4627
- (get-all-topic-psis))
+ (handler-case (get-all-topic-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+))))
@@ -108,7 +118,8 @@
(condition (err)
(progn
(setf (hunchentoot:return-code*) hunchentoot:+http-internal-server-error+)
- (format nil "<p>Condition: \"~a\"</p>" err))))
+ (setf (hunchentoot:content-type*) "text")
+ (format nil "Condition: \"~a\"" err))))
"{}")))
(setf (hunchentoot:return-code*) hunchentoot:+http-bad-request+))))
@@ -125,7 +136,8 @@
(condition (err)
(progn
(setf (hunchentoot:return-code*) hunchentoot:+http-internal-server-error+)
- (format nil "<p>Condition: \"~a\"</p>" err))))))
+ (setf (hunchentoot:content-type*) "text")
+ (format nil "Condition: \"~a\"" err))))))
(setf (hunchentoot:return-code*) hunchentoot:+http-bad-request+))))
@@ -138,32 +150,35 @@
(end-idx
(handler-case (parse-integer (hunchentoot:get-parameter "end"))
(condition () nil))))
-
- (let ((topics (elephant:get-instances-by-class 'd:TopicC)))
- (let ((end
- (cond
- ((not end-idx)
- (length topics))
- ((> end-idx (length topics))
- (length topics))
- ((< end-idx 0)
- 0)
- (t
- end-idx))))
- (let ((start
- (cond
- ((> start-idx (length topics))
- end)
- ((< start-idx 0)
- 0)
- (t
- start-idx))))
- (let ((topics-in-range
- (if (<= start end)
- (subseq topics start end)
- (reverse (subseq topics end start)))))
- (setf (hunchentoot:content-type*) "application/json") ;RFC 4627
- (json-exporter:make-topic-summary topics-in-range)))))))
+ (handler-case (let ((topics (elephant:get-instances-by-class 'd:TopicC)))
+ (let ((end
+ (cond
+ ((not end-idx)
+ (length topics))
+ ((> end-idx (length topics))
+ (length topics))
+ ((< end-idx 0)
+ 0)
+ (t
+ end-idx))))
+ (let ((start
+ (cond
+ ((> start-idx (length topics))
+ end)
+ ((< start-idx 0)
+ 0)
+ (t
+ start-idx))))
+ (let ((topics-in-range
+ (if (<= start end)
+ (subseq topics start end)
+ (reverse (subseq topics end start)))))
+ (setf (hunchentoot:content-type*) "application/json") ;RFC 4627
+ (json-exporter:make-topic-summary topics-in-range)))))
+ (condition (err) (progn
+ (setf (hunchentoot:return-code*) hunchentoot:+http-internal-server-error+)
+ (setf (hunchentoot:content-type*) "text")
+ (format nil "Condition: \"~a\"" err))))))
;; =============================================================================
Modified: trunk/src/unit_tests/json_test.lisp
==============================================================================
--- trunk/src/unit_tests/json_test.lisp (original)
+++ trunk/src/unit_tests/json_test.lisp Mon Apr 13 13:17:57 2009
@@ -116,7 +116,7 @@
(elephant:add-association association-7 'themes t62)
(let ((association-7-string (to-json-string association-7))
(json-string
- (concatenate 'string "{\"itemIdentities\":[\"http://psi.egovpt.org/itemIdentifiers#assoc_7\"],\"type\":null,\"scopes\":[\"" (topicid t62) "\",\"" (topicid t64) "\"],\"roles\":null}")))
+ (concatenate 'string "{\"itemIdentities\":[\"http://psi.egovpt.org/itemIdentifiers#assoc_7\"],\"type\":null,\"scopes\":[[\"http://psi.egovpt.org/types/StandardRoleType\"],[\"http://psi.egovpt.org/types/serviceUsesStandard\"]],\"roles\":null}")))
(is (string= association-7-string json-string))))))))
1
0

10 Apr '09
Author: lgiessmann
Date: Fri Apr 10 19:11:32 2009
New Revision: 26
Log:
added a license header to all files where the isidorus license is mentioned and referenced, in the ajax file there is also a reference to the MIT-license; an edit/create template for fragments is implemented in the ajax module, but it\'s really terrible and not really useable - this should be only the initial idea of realizing such a functionality\!
Added:
trunk/docs/LGPL-LICENSE.txt
trunk/src/ajax/javascripts/constants.js
- copied, changed from r25, /trunk/src/ajax/javascripts/ajax_constants.js
trunk/src/ajax/javascripts/edit_topic.js (contents, props changed)
- copied, changed from r25, /trunk/src/ajax/javascripts/ajax_edit_topic.js
trunk/src/ajax/javascripts/external/
trunk/src/ajax/javascripts/external/MIT-LICENSE.txt
trunk/src/ajax/javascripts/external/prototype/
trunk/src/ajax/javascripts/external/prototype/prototype.js
trunk/src/ajax/javascripts/external/scriptaculous/
trunk/src/ajax/javascripts/external/scriptaculous/builder.js
trunk/src/ajax/javascripts/external/scriptaculous/controls.js
trunk/src/ajax/javascripts/external/scriptaculous/dragdrop.js
trunk/src/ajax/javascripts/external/scriptaculous/effects.js
trunk/src/ajax/javascripts/external/scriptaculous/scriptaculous.js
trunk/src/ajax/javascripts/external/scriptaculous/slider.js
trunk/src/ajax/javascripts/external/scriptaculous/sound.js
trunk/src/ajax/javascripts/external/scriptaculous/unittest.js
trunk/src/ajax/javascripts/home.js (contents, props changed)
- copied, changed from r25, /trunk/src/ajax/javascripts/ajax_home.js
trunk/src/ajax/javascripts/make_fragment_node.js (contents, props changed)
trunk/src/ajax/javascripts/navi.js (contents, props changed)
- copied, changed from r25, /trunk/src/ajax/javascripts/ajax_navi.js
Removed:
trunk/src/ajax/css/create_topics.css
trunk/src/ajax/css/edit_topics.css
trunk/src/ajax/css/search_topics.css
trunk/src/ajax/javascripts/ajax_constants.js
trunk/src/ajax/javascripts/ajax_edit_topic.js
trunk/src/ajax/javascripts/ajax_home.js
trunk/src/ajax/javascripts/ajax_navi.js
trunk/src/ajax/javascripts/builder.js
trunk/src/ajax/javascripts/controls.js
trunk/src/ajax/javascripts/dragdrop.js
trunk/src/ajax/javascripts/effects.js
trunk/src/ajax/javascripts/prototype.js
trunk/src/ajax/javascripts/scriptaculous.js
trunk/src/ajax/javascripts/slider.js
trunk/src/ajax/javascripts/sound.js
trunk/src/ajax/javascripts/unittest.js
Modified:
trunk/docs/xtm_json.txt
trunk/src/ajax/css/home.css
trunk/src/ajax/css/main.css
trunk/src/ajax/css/navi.css
trunk/src/ajax/isidorus.html
trunk/src/atom/atom.lisp
trunk/src/atom/collection.lisp
trunk/src/atom/conf.lisp
trunk/src/atom/configuration.lisp
trunk/src/atom/confreader.lisp
trunk/src/atom/fragments.lisp
trunk/src/atom/read.lisp
trunk/src/atom/snapshots.lisp
trunk/src/constants.lisp
trunk/src/isidorus.asd
trunk/src/json/json_exporter.lisp
trunk/src/json/json_importer.lisp
trunk/src/model/changes.lisp
trunk/src/model/datamodel.lisp
trunk/src/model/exceptions.lisp
trunk/src/model/model_tools.lisp
trunk/src/rest_interface/publish_feeds.lisp
trunk/src/rest_interface/read.lisp
trunk/src/rest_interface/rest-interface.lisp
trunk/src/rest_interface/set-up-json-interface.lisp
trunk/src/threading/reader-writer.lisp
trunk/src/unit_tests/atom-conf.lisp
trunk/src/unit_tests/atom_test.lisp
trunk/src/unit_tests/atom_test.xtm
trunk/src/unit_tests/dangling_instanceof.xtm
trunk/src/unit_tests/dangling_topicref.xtm
trunk/src/unit_tests/duplicate_identifier.xtm
trunk/src/unit_tests/exporter_xtm1.0_test.lisp
trunk/src/unit_tests/exporter_xtm2.0_test.lisp
trunk/src/unit_tests/fixtures.lisp
trunk/src/unit_tests/importer_test.lisp
trunk/src/unit_tests/inconsistent.xtm
trunk/src/unit_tests/inconsistent_2_0.xtm
trunk/src/unit_tests/json_test.lisp
trunk/src/unit_tests/multiple_tms_ont.xtm
trunk/src/unit_tests/multiple_tms_worms.xtm
trunk/src/unit_tests/notification_merge1.xtm
trunk/src/unit_tests/notification_merge2.xtm
trunk/src/unit_tests/notificationbase.xtm
trunk/src/unit_tests/sample_objects.xtm
trunk/src/unit_tests/sample_objects_2_0.xtm
trunk/src/unit_tests/t100.xtm
trunk/src/unit_tests/testing_db.lisp
trunk/src/unit_tests/unittests-constants.lisp
trunk/src/unit_tests/versions_test.lisp
trunk/src/xml-constants.lisp
trunk/src/xml/core_psis.xtm
trunk/src/xml/exporter.lisp
trunk/src/xml/exporter_xtm1.0.lisp
trunk/src/xml/exporter_xtm2.0.lisp
trunk/src/xml/importer.lisp
trunk/src/xml/importer_xtm1.0.lisp
trunk/src/xml/importer_xtm2.0.lisp
trunk/src/xml/setup.lisp
trunk/src/xml/tools.lisp
Added: trunk/docs/LGPL-LICENSE.txt
==============================================================================
--- (empty file)
+++ trunk/docs/LGPL-LICENSE.txt Fri Apr 10 19:11:32 2009
@@ -0,0 +1,66 @@
+GNU LESSER GENERAL PUBLIC LICENSE
+
+Version 3, 29 June 2007
+
+Copyright © 2007 Free Software Foundation, Inc. <http://fsf.org/>
+
+Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed.
+
+This version of the GNU Lesser General Public License incorporates the terms and conditions of version 3 of the GNU General Public License, supplemented by the additional permissions listed below.
+0. Additional Definitions.
+
+As used herein, “this License” refers to version 3 of the GNU Lesser General Public License, and the “GNU GPL” refers to version 3 of the GNU General Public License.
+
+“The Library” refers to a covered work governed by this License, other than an Application or a Combined Work as defined below.
+
+An “Application” is any work that makes use of an interface provided by the Library, but which is not otherwise based on the Library. Defining a subclass of a class defined by the Library is deemed a mode of using an interface provided by the Library.
+
+A “Combined Work” is a work produced by combining or linking an Application with the Library. The particular version of the Library with which the Combined Work was made is also called the “Linked Version”.
+
+The “Minimal Corresponding Source” for a Combined Work means the Corresponding Source for the Combined Work, excluding any source code for portions of the Combined Work that, considered in isolation, are based on the Application, and not on the Linked Version.
+
+The “Corresponding Application Code” for a Combined Work means the object code and/or source code for the Application, including any data and utility programs needed for reproducing the Combined Work from the Application, but excluding the System Libraries of the Combined Work.
+1. Exception to Section 3 of the GNU GPL.
+
+You may convey a covered work under sections 3 and 4 of this License without being bound by section 3 of the GNU GPL.
+2. Conveying Modified Versions.
+
+If you modify a copy of the Library, and, in your modifications, a facility refers to a function or data to be supplied by an Application that uses the facility (other than as an argument passed when the facility is invoked), then you may convey a copy of the modified version:
+
+ * a) under this License, provided that you make a good faith effort to ensure that, in the event an Application does not supply the function or data, the facility still operates, and performs whatever part of its purpose remains meaningful, or
+ * b) under the GNU GPL, with none of the additional permissions of this License applicable to that copy.
+
+3. Object Code Incorporating Material from Library Header Files.
+
+The object code form of an Application may incorporate material from a header file that is part of the Library. You may convey such object code under terms of your choice, provided that, if the incorporated material is not limited to numerical parameters, data structure layouts and accessors, or small macros, inline functions and templates (ten or fewer lines in length), you do both of the following:
+
+ * a) Give prominent notice with each copy of the object code that the Library is used in it and that the Library and its use are covered by this License.
+ * b) Accompany the object code with a copy of the GNU GPL and this license document.
+
+4. Combined Works.
+
+You may convey a Combined Work under terms of your choice that, taken together, effectively do not restrict modification of the portions of the Library contained in the Combined Work and reverse engineering for debugging such modifications, if you also do each of the following:
+
+ * a) Give prominent notice with each copy of the Combined Work that the Library is used in it and that the Library and its use are covered by this License.
+ * b) Accompany the Combined Work with a copy of the GNU GPL and this license document.
+ * c) For a Combined Work that displays copyright notices during execution, include the copyright notice for the Library among these notices, as well as a reference directing the user to the copies of the GNU GPL and this license document.
+ * d) Do one of the following:
+ o 0) Convey the Minimal Corresponding Source under the terms of this License, and the Corresponding Application Code in a form suitable for, and under terms that permit, the user to recombine or relink the Application with a modified version of the Linked Version to produce a modified Combined Work, in the manner specified by section 6 of the GNU GPL for conveying Corresponding Source.
+ o 1) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (a) uses at run time a copy of the Library already present on the user's computer system, and (b) will operate properly with a modified version of the Library that is interface-compatible with the Linked Version.
+ * e) Provide Installation Information, but only if you would otherwise be required to provide such information under section 6 of the GNU GPL, and only to the extent that such information is necessary to install and execute a modified version of the Combined Work produced by recombining or relinking the Application with a modified version of the Linked Version. (If you use option 4d0, the Installation Information must accompany the Minimal Corresponding Source and Corresponding Application Code. If you use option 4d1, you must provide the Installation Information in the manner specified by section 6 of the GNU GPL for conveying Corresponding Source.)
+
+5. Combined Libraries.
+
+You may place library facilities that are a work based on the Library side by side in a single library together with other library facilities that are not Applications and are not covered by this License, and convey such a combined library under terms of your choice, if you do both of the following:
+
+ * a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities, conveyed under the terms of this License.
+ * b) Give prominent notice with the combined library that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work.
+
+6. Revised Versions of the GNU Lesser General Public License.
+
+The Free Software Foundation may publish revised and/or new versions of the GNU Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Library as you received it specifies that a certain numbered version of the GNU Lesser General Public License “or any later version” applies to it, you have the option of following the terms and conditions either of that published version or of any later version published by the Free Software Foundation. If the Library as you received it does not specify a version number of the GNU Lesser General Public License, you may choose any version of the GNU Lesser General Public License ever published by the Free Software Foundation.
+
+If the Library as you received it specifies that a proxy can decide whether future versions of the GNU Lesser General Public License shall apply, that proxy's public statement of acceptance of any version is permanent authorization for you to choose that version for the Library.
+
Modified: trunk/docs/xtm_json.txt
==============================================================================
--- trunk/docs/xtm_json.txt (original)
+++ trunk/docs/xtm_json.txt Fri Apr 10 19:11:32 2009
@@ -125,15 +125,15 @@
//+-----------------------------------------------------------------------------
//+ fragment
-//+ The field tm-ids should have only one tm-id in the list, because
+//+ The field tmIds should have only one tm-id in the list, because
//+ there will be used only the first, if the fragment is an incoming one
-//+ outgoing fragment have a list with more tm-ids but at least one
+//+ outgoing fragments have a list with more tmIds but at least one
//+-----------------------------------------------------------------------------
{
"topic" : { <topic> },
"topicStubs" : [ { <topicStub> }, { <...> } ],
"associations" : [ { <association> }, { <...> } ],
- "tm-ids" : [ "id-1", "id-2", "..." ]
+ "tmIds" : [ "id-1", "id-2", "..." ]
}
@@ -397,5 +397,5 @@
]
}
],
- "tm-ids" : [ "test-tm"]
+ "tmIds" : [ "test-tm"]
}
Modified: trunk/src/ajax/css/home.css
==============================================================================
--- trunk/src/ajax/css/home.css (original)
+++ trunk/src/ajax/css/home.css Fri Apr 10 19:11:32 2009
@@ -1,3 +1,15 @@
+/*----------------------------------------------------------------------------*/
+/* 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. */
+/*----------------------------------------------------------------------------*/
+
+
.topicSummaryTd {
width: 40px;
border: solid 1px gray;
Modified: trunk/src/ajax/css/main.css
==============================================================================
--- trunk/src/ajax/css/main.css (original)
+++ trunk/src/ajax/css/main.css Fri Apr 10 19:11:32 2009
@@ -1,5 +1,19 @@
+/*----------------------------------------------------------------------------*/
+/* 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. */
+/*----------------------------------------------------------------------------*/
+
+
.clickable{
cursor: pointer;
+ padding-left: 5px;
+ padding-right: 5px;
}
.clickable:hover{
@@ -8,4 +22,30 @@
.clickable:active{
color: red;
-}
\ No newline at end of file
+}
+
+.headerRow {
+ background-color: #EEEEFF;
+}
+
+
+.topicHeaderRow {
+ background-color: #CCE5FF;
+}
+
+.topicStubsHeaderRow {
+ background-color: #CCE5FF;
+}
+
+.associationsHeaderRow {
+ background-color: #CCE5FF;
+}
+
+.tmIdsHeaderRow {
+ background-color: #CCE5FF;
+}
+
+.frame{
+ border: 1px outset black;
+ margin: 5px;
+}
Modified: trunk/src/ajax/css/navi.css
==============================================================================
--- trunk/src/ajax/css/navi.css (original)
+++ trunk/src/ajax/css/navi.css Fri Apr 10 19:11:32 2009
@@ -1,3 +1,15 @@
+/*----------------------------------------------------------------------------*/
+/* 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. */
+/*----------------------------------------------------------------------------*/
+
+
#navi {
border: solid 1px;
margin-top: 10px;
Modified: trunk/src/ajax/isidorus.html
==============================================================================
--- trunk/src/ajax/isidorus.html (original)
+++ trunk/src/ajax/isidorus.html Fri Apr 10 19:11:32 2009
@@ -1,3 +1,15 @@
+<!-- ======================================================================= -->
+<!-- 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. -->
+<!-- ======================================================================= -->
+
+
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
@@ -13,14 +25,15 @@
<link rel="stylesheet" type="text/css" href="css/navi.css"/>
<!-- includes the prototype and scriptaculous frameworks -->
- <script language="JavaScript" type="text/javascript" src="javascripts/prototype.js"></script>
- <script language="JavaScript" type="text/javascript" src="javascripts/scriptaculous.js"></script>
+ <script language="JavaScript" type="text/javascript" src="javascripts/external/prototype/prototype.js"></script>
+ <script language="JavaScript" type="text/javascript" src="javascripts/external/scriptaculous/scriptaculous.js"></script>
<!-- includes own javascript files -->
- <script language="JavaScript" type="text/javascript" src="javascripts/ajax_constants.js"></script>
- <script language="JavaScript" type="text/javascript" src="javascripts/ajax_edit_topic.js"></script>
- <script language="JavaScript" type="text/javascript" src="javascripts/ajax_home.js"></script>
- <script language="JavaScript" type="text/javascript" src="javascripts/ajax_navi.js"></script>
+ <script language="JavaScript" type="text/javascript" src="javascripts/constants.js"></script>
+ <script language="JavaScript" type="text/javascript" src="javascripts/make_fragment_node.js"></script>
+ <script language="JavaScript" type="text/javascript" src="javascripts/edit_topic.js"></script>
+ <script language="JavaScript" type="text/javascript" src="javascripts/home.js"></script>
+ <script language="JavaScript" type="text/javascript" src="javascripts/navi.js"></script>
</head>
<body>
Copied: trunk/src/ajax/javascripts/constants.js (from r25, /trunk/src/ajax/javascripts/ajax_constants.js)
==============================================================================
--- /trunk/src/ajax/javascripts/ajax_constants.js (original)
+++ trunk/src/ajax/javascripts/constants.js Fri Apr 10 19:11:32 2009
@@ -1,3 +1,15 @@
+//+-----------------------------------------------------------------------------
+//+ 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
+//+-----------------------------------------------------------------------------
+
+
var TIMEOUT = 5000; // const TIMEOUT = 5000 --> "const" doesn't work under IE
var HOST_PREF = "http://localhost:8000/";
var GET_PREFIX = HOST_PREF + "json/get/";
@@ -8,4 +20,106 @@
// --- 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"};
\ No newline at end of file
+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; }
+ };
\ No newline at end of file
Copied: trunk/src/ajax/javascripts/edit_topic.js (from r25, /trunk/src/ajax/javascripts/ajax_edit_topic.js)
==============================================================================
--- /trunk/src/ajax/javascripts/ajax_edit_topic.js (original)
+++ trunk/src/ajax/javascripts/edit_topic.js Fri Apr 10 19:11:32 2009
@@ -1,4 +1,19 @@
-function makeEdit(psi)
+//+-----------------------------------------------------------------------------
+//+ 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
+//+-----------------------------------------------------------------------------
+
+
+// --- generates the page "edit topic"
+function makeEdit(topicPsi)
{
- alert("psi: " + psi);
-}
\ No newline at end of file
+ if($("content").getElementsByClassName("fragment " + PAGES.edit).length === 0){
+ getAndBuildFragment(topicPsi);
+ }
+}
Added: trunk/src/ajax/javascripts/external/MIT-LICENSE.txt
==============================================================================
--- (empty file)
+++ trunk/src/ajax/javascripts/external/MIT-LICENSE.txt Fri Apr 10 19:11:32 2009
@@ -0,0 +1,16 @@
+Copyright (c) 2005-2008 Sam Stephenson
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
Added: trunk/src/ajax/javascripts/external/prototype/prototype.js
==============================================================================
--- (empty file)
+++ trunk/src/ajax/javascripts/external/prototype/prototype.js Fri Apr 10 19:11:32 2009
@@ -0,0 +1,4320 @@
+/* Prototype JavaScript framework, version 1.6.0.3
+ * (c) 2005-2008 Sam Stephenson
+ *
+ * Prototype is freely distributable under the terms of an MIT-style license.
+ * For details, see the Prototype web site: http://www.prototypejs.org/
+ *
+ *--------------------------------------------------------------------------*/
+
+var Prototype = {
+ Version: '1.6.0.3',
+
+ Browser: {
+ IE: !!(window.attachEvent &&
+ navigator.userAgent.indexOf('Opera') === -1),
+ Opera: navigator.userAgent.indexOf('Opera') > -1,
+ WebKit: navigator.userAgent.indexOf('AppleWebKit/') > -1,
+ Gecko: navigator.userAgent.indexOf('Gecko') > -1 &&
+ navigator.userAgent.indexOf('KHTML') === -1,
+ MobileSafari: !!navigator.userAgent.match(/Apple.*Mobile.*Safari/)
+ },
+
+ BrowserFeatures: {
+ XPath: !!document.evaluate,
+ SelectorsAPI: !!document.querySelector,
+ ElementExtensions: !!window.HTMLElement,
+ SpecificElementExtensions:
+ document.createElement('div')['__proto__'] &&
+ document.createElement('div')['__proto__'] !==
+ document.createElement('form')['__proto__']
+ },
+
+ ScriptFragment: '<script[^>]*>([\\S\\s]*?)<\/script>',
+ JSONFilter: /^\/\*-secure-([\s\S]*)\*\/\s*$/,
+
+ emptyFunction: function() { },
+ K: function(x) { return x }
+};
+
+if (Prototype.Browser.MobileSafari)
+ Prototype.BrowserFeatures.SpecificElementExtensions = false;
+
+
+/* Based on Alex Arnell's inheritance implementation. */
+var Class = {
+ create: function() {
+ var parent = null, properties = $A(arguments);
+ if (Object.isFunction(properties[0]))
+ parent = properties.shift();
+
+ function klass() {
+ this.initialize.apply(this, arguments);
+ }
+
+ Object.extend(klass, Class.Methods);
+ klass.superclass = parent;
+ klass.subclasses = [];
+
+ if (parent) {
+ var subclass = function() { };
+ subclass.prototype = parent.prototype;
+ klass.prototype = new subclass;
+ parent.subclasses.push(klass);
+ }
+
+ for (var i = 0; i < properties.length; i++)
+ klass.addMethods(properties[i]);
+
+ if (!klass.prototype.initialize)
+ klass.prototype.initialize = Prototype.emptyFunction;
+
+ klass.prototype.constructor = klass;
+
+ return klass;
+ }
+};
+
+Class.Methods = {
+ addMethods: function(source) {
+ var ancestor = this.superclass && this.superclass.prototype;
+ var properties = Object.keys(source);
+
+ if (!Object.keys({ toString: true }).length)
+ properties.push("toString", "valueOf");
+
+ for (var i = 0, length = properties.length; i < length; i++) {
+ var property = properties[i], value = source[property];
+ if (ancestor && Object.isFunction(value) &&
+ value.argumentNames().first() == "$super") {
+ var method = value;
+ value = (function(m) {
+ return function() { return ancestor[m].apply(this, arguments) };
+ })(property).wrap(method);
+
+ value.valueOf = method.valueOf.bind(method);
+ value.toString = method.toString.bind(method);
+ }
+ this.prototype[property] = value;
+ }
+
+ return this;
+ }
+};
+
+var Abstract = { };
+
+Object.extend = function(destination, source) {
+ for (var property in source)
+ destination[property] = source[property];
+ return destination;
+};
+
+Object.extend(Object, {
+ inspect: function(object) {
+ try {
+ if (Object.isUndefined(object)) return 'undefined';
+ if (object === null) return 'null';
+ return object.inspect ? object.inspect() : String(object);
+ } catch (e) {
+ if (e instanceof RangeError) return '...';
+ throw e;
+ }
+ },
+
+ toJSON: function(object) {
+ var type = typeof object;
+ switch (type) {
+ case 'undefined':
+ case 'function':
+ case 'unknown': return;
+ case 'boolean': return object.toString();
+ }
+
+ if (object === null) return 'null';
+ if (object.toJSON) return object.toJSON();
+ if (Object.isElement(object)) return;
+
+ var results = [];
+ for (var property in object) {
+ var value = Object.toJSON(object[property]);
+ if (!Object.isUndefined(value))
+ results.push(property.toJSON() + ': ' + value);
+ }
+
+ return '{' + results.join(', ') + '}';
+ },
+
+ toQueryString: function(object) {
+ return $H(object).toQueryString();
+ },
+
+ toHTML: function(object) {
+ return object && object.toHTML ? object.toHTML() : String.interpret(object);
+ },
+
+ keys: function(object) {
+ var keys = [];
+ for (var property in object)
+ keys.push(property);
+ return keys;
+ },
+
+ values: function(object) {
+ var values = [];
+ for (var property in object)
+ values.push(object[property]);
+ return values;
+ },
+
+ clone: function(object) {
+ return Object.extend({ }, object);
+ },
+
+ isElement: function(object) {
+ return !!(object && object.nodeType == 1);
+ },
+
+ isArray: function(object) {
+ return object != null && typeof object == "object" &&
+ 'splice' in object && 'join' in object;
+ },
+
+ isHash: function(object) {
+ return object instanceof Hash;
+ },
+
+ isFunction: function(object) {
+ return typeof object == "function";
+ },
+
+ isString: function(object) {
+ return typeof object == "string";
+ },
+
+ isNumber: function(object) {
+ return typeof object == "number";
+ },
+
+ isUndefined: function(object) {
+ return typeof object == "undefined";
+ }
+});
+
+Object.extend(Function.prototype, {
+ argumentNames: function() {
+ var names = this.toString().match(/^[\s\(]*function[^(]*\(([^\)]*)\)/)[1]
+ .replace(/\s+/g, '').split(',');
+ return names.length == 1 && !names[0] ? [] : names;
+ },
+
+ bind: function() {
+ if (arguments.length < 2 && Object.isUndefined(arguments[0])) return this;
+ var __method = this, args = $A(arguments), object = args.shift();
+ return function() {
+ return __method.apply(object, args.concat($A(arguments)));
+ }
+ },
+
+ bindAsEventListener: function() {
+ var __method = this, args = $A(arguments), object = args.shift();
+ return function(event) {
+ return __method.apply(object, [event || window.event].concat(args));
+ }
+ },
+
+ curry: function() {
+ if (!arguments.length) return this;
+ var __method = this, args = $A(arguments);
+ return function() {
+ return __method.apply(this, args.concat($A(arguments)));
+ }
+ },
+
+ delay: function() {
+ var __method = this, args = $A(arguments), timeout = args.shift() * 1000;
+ return window.setTimeout(function() {
+ return __method.apply(__method, args);
+ }, timeout);
+ },
+
+ defer: function() {
+ var args = [0.01].concat($A(arguments));
+ return this.delay.apply(this, args);
+ },
+
+ wrap: function(wrapper) {
+ var __method = this;
+ return function() {
+ return wrapper.apply(this, [__method.bind(this)].concat($A(arguments)));
+ }
+ },
+
+ methodize: function() {
+ if (this._methodized) return this._methodized;
+ var __method = this;
+ return this._methodized = function() {
+ return __method.apply(null, [this].concat($A(arguments)));
+ };
+ }
+});
+
+Date.prototype.toJSON = function() {
+ return '"' + this.getUTCFullYear() + '-' +
+ (this.getUTCMonth() + 1).toPaddedString(2) + '-' +
+ this.getUTCDate().toPaddedString(2) + 'T' +
+ this.getUTCHours().toPaddedString(2) + ':' +
+ this.getUTCMinutes().toPaddedString(2) + ':' +
+ this.getUTCSeconds().toPaddedString(2) + 'Z"';
+};
+
+var Try = {
+ these: function() {
+ var returnValue;
+
+ for (var i = 0, length = arguments.length; i < length; i++) {
+ var lambda = arguments[i];
+ try {
+ returnValue = lambda();
+ break;
+ } catch (e) { }
+ }
+
+ return returnValue;
+ }
+};
+
+RegExp.prototype.match = RegExp.prototype.test;
+
+RegExp.escape = function(str) {
+ return String(str).replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1');
+};
+
+/*--------------------------------------------------------------------------*/
+
+var PeriodicalExecuter = Class.create({
+ initialize: function(callback, frequency) {
+ this.callback = callback;
+ this.frequency = frequency;
+ this.currentlyExecuting = false;
+
+ this.registerCallback();
+ },
+
+ registerCallback: function() {
+ this.timer = setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
+ },
+
+ execute: function() {
+ this.callback(this);
+ },
+
+ stop: function() {
+ if (!this.timer) return;
+ clearInterval(this.timer);
+ this.timer = null;
+ },
+
+ onTimerEvent: function() {
+ if (!this.currentlyExecuting) {
+ try {
+ this.currentlyExecuting = true;
+ this.execute();
+ } finally {
+ this.currentlyExecuting = false;
+ }
+ }
+ }
+});
+Object.extend(String, {
+ interpret: function(value) {
+ return value == null ? '' : String(value);
+ },
+ specialChar: {
+ '\b': '\\b',
+ '\t': '\\t',
+ '\n': '\\n',
+ '\f': '\\f',
+ '\r': '\\r',
+ '\\': '\\\\'
+ }
+});
+
+Object.extend(String.prototype, {
+ gsub: function(pattern, replacement) {
+ var result = '', source = this, match;
+ replacement = arguments.callee.prepareReplacement(replacement);
+
+ while (source.length > 0) {
+ if (match = source.match(pattern)) {
+ result += source.slice(0, match.index);
+ result += String.interpret(replacement(match));
+ source = source.slice(match.index + match[0].length);
+ } else {
+ result += source, source = '';
+ }
+ }
+ return result;
+ },
+
+ sub: function(pattern, replacement, count) {
+ replacement = this.gsub.prepareReplacement(replacement);
+ count = Object.isUndefined(count) ? 1 : count;
+
+ return this.gsub(pattern, function(match) {
+ if (--count < 0) return match[0];
+ return replacement(match);
+ });
+ },
+
+ scan: function(pattern, iterator) {
+ this.gsub(pattern, iterator);
+ return String(this);
+ },
+
+ truncate: function(length, truncation) {
+ length = length || 30;
+ truncation = Object.isUndefined(truncation) ? '...' : truncation;
+ return this.length > length ?
+ this.slice(0, length - truncation.length) + truncation : String(this);
+ },
+
+ strip: function() {
+ return this.replace(/^\s+/, '').replace(/\s+$/, '');
+ },
+
+ stripTags: function() {
+ return this.replace(/<\/?[^>]+>/gi, '');
+ },
+
+ stripScripts: function() {
+ return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), '');
+ },
+
+ extractScripts: function() {
+ var matchAll = new RegExp(Prototype.ScriptFragment, 'img');
+ var matchOne = new RegExp(Prototype.ScriptFragment, 'im');
+ return (this.match(matchAll) || []).map(function(scriptTag) {
+ return (scriptTag.match(matchOne) || ['', ''])[1];
+ });
+ },
+
+ evalScripts: function() {
+ return this.extractScripts().map(function(script) { return eval(script) });
+ },
+
+ escapeHTML: function() {
+ var self = arguments.callee;
+ self.text.data = this;
+ return self.div.innerHTML;
+ },
+
+ unescapeHTML: function() {
+ var div = new Element('div');
+ div.innerHTML = this.stripTags();
+ return div.childNodes[0] ? (div.childNodes.length > 1 ?
+ $A(div.childNodes).inject('', function(memo, node) { return memo+node.nodeValue }) :
+ div.childNodes[0].nodeValue) : '';
+ },
+
+ toQueryParams: function(separator) {
+ var match = this.strip().match(/([^?#]*)(#.*)?$/);
+ if (!match) return { };
+
+ return match[1].split(separator || '&').inject({ }, function(hash, pair) {
+ if ((pair = pair.split('='))[0]) {
+ var key = decodeURIComponent(pair.shift());
+ var value = pair.length > 1 ? pair.join('=') : pair[0];
+ if (value != undefined) value = decodeURIComponent(value);
+
+ if (key in hash) {
+ if (!Object.isArray(hash[key])) hash[key] = [hash[key]];
+ hash[key].push(value);
+ }
+ else hash[key] = value;
+ }
+ return hash;
+ });
+ },
+
+ toArray: function() {
+ return this.split('');
+ },
+
+ succ: function() {
+ return this.slice(0, this.length - 1) +
+ String.fromCharCode(this.charCodeAt(this.length - 1) + 1);
+ },
+
+ times: function(count) {
+ return count < 1 ? '' : new Array(count + 1).join(this);
+ },
+
+ camelize: function() {
+ var parts = this.split('-'), len = parts.length;
+ if (len == 1) return parts[0];
+
+ var camelized = this.charAt(0) == '-'
+ ? parts[0].charAt(0).toUpperCase() + parts[0].substring(1)
+ : parts[0];
+
+ for (var i = 1; i < len; i++)
+ camelized += parts[i].charAt(0).toUpperCase() + parts[i].substring(1);
+
+ return camelized;
+ },
+
+ capitalize: function() {
+ return this.charAt(0).toUpperCase() + this.substring(1).toLowerCase();
+ },
+
+ underscore: function() {
+ return this.gsub(/::/, '/').gsub(/([A-Z]+)([A-Z][a-z])/,'#{1}_#{2}').gsub(/([a-z\d])([A-Z])/,'#{1}_#{2}').gsub(/-/,'_').toLowerCase();
+ },
+
+ dasherize: function() {
+ return this.gsub(/_/,'-');
+ },
+
+ inspect: function(useDoubleQuotes) {
+ var escapedString = this.gsub(/[\x00-\x1f\\]/, function(match) {
+ var character = String.specialChar[match[0]];
+ return character ? character : '\\u00' + match[0].charCodeAt().toPaddedString(2, 16);
+ });
+ if (useDoubleQuotes) return '"' + escapedString.replace(/"/g, '\\"') + '"';
+ return "'" + escapedString.replace(/'/g, '\\\'') + "'";
+ },
+
+ toJSON: function() {
+ return this.inspect(true);
+ },
+
+ unfilterJSON: function(filter) {
+ return this.sub(filter || Prototype.JSONFilter, '#{1}');
+ },
+
+ isJSON: function() {
+ var str = this;
+ if (str.blank()) return false;
+ str = this.replace(/\\./g, '@').replace(/"[^"\\\n\r]*"/g, '');
+ return (/^[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]*$/).test(str);
+ },
+
+ evalJSON: function(sanitize) {
+ var json = this.unfilterJSON();
+ try {
+ if (!sanitize || json.isJSON()) return eval('(' + json + ')');
+ } catch (e) { }
+ throw new SyntaxError('Badly formed JSON string: ' + this.inspect());
+ },
+
+ include: function(pattern) {
+ return this.indexOf(pattern) > -1;
+ },
+
+ startsWith: function(pattern) {
+ return this.indexOf(pattern) === 0;
+ },
+
+ endsWith: function(pattern) {
+ var d = this.length - pattern.length;
+ return d >= 0 && this.lastIndexOf(pattern) === d;
+ },
+
+ empty: function() {
+ return this == '';
+ },
+
+ blank: function() {
+ return /^\s*$/.test(this);
+ },
+
+ interpolate: function(object, pattern) {
+ return new Template(this, pattern).evaluate(object);
+ }
+});
+
+if (Prototype.Browser.WebKit || Prototype.Browser.IE) Object.extend(String.prototype, {
+ escapeHTML: function() {
+ return this.replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>');
+ },
+ unescapeHTML: function() {
+ return this.stripTags().replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>');
+ }
+});
+
+String.prototype.gsub.prepareReplacement = function(replacement) {
+ if (Object.isFunction(replacement)) return replacement;
+ var template = new Template(replacement);
+ return function(match) { return template.evaluate(match) };
+};
+
+String.prototype.parseQuery = String.prototype.toQueryParams;
+
+Object.extend(String.prototype.escapeHTML, {
+ div: document.createElement('div'),
+ text: document.createTextNode('')
+});
+
+String.prototype.escapeHTML.div.appendChild(String.prototype.escapeHTML.text);
+
+var Template = Class.create({
+ initialize: function(template, pattern) {
+ this.template = template.toString();
+ this.pattern = pattern || Template.Pattern;
+ },
+
+ evaluate: function(object) {
+ if (Object.isFunction(object.toTemplateReplacements))
+ object = object.toTemplateReplacements();
+
+ return this.template.gsub(this.pattern, function(match) {
+ if (object == null) return '';
+
+ var before = match[1] || '';
+ if (before == '\\') return match[2];
+
+ var ctx = object, expr = match[3];
+ var pattern = /^([^.[]+|\[((?:.*?[^\\])?)\])(\.|\[|$)/;
+ match = pattern.exec(expr);
+ if (match == null) return before;
+
+ while (match != null) {
+ var comp = match[1].startsWith('[') ? match[2].gsub('\\\\]', ']') : match[1];
+ ctx = ctx[comp];
+ if (null == ctx || '' == match[3]) break;
+ expr = expr.substring('[' == match[3] ? match[1].length : match[0].length);
+ match = pattern.exec(expr);
+ }
+
+ return before + String.interpret(ctx);
+ });
+ }
+});
+Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/;
+
+var $break = { };
+
+var Enumerable = {
+ each: function(iterator, context) {
+ var index = 0;
+ try {
+ this._each(function(value) {
+ iterator.call(context, value, index++);
+ });
+ } catch (e) {
+ if (e != $break) throw e;
+ }
+ return this;
+ },
+
+ eachSlice: function(number, iterator, context) {
+ var index = -number, slices = [], array = this.toArray();
+ if (number < 1) return array;
+ while ((index += number) < array.length)
+ slices.push(array.slice(index, index+number));
+ return slices.collect(iterator, context);
+ },
+
+ all: function(iterator, context) {
+ iterator = iterator || Prototype.K;
+ var result = true;
+ this.each(function(value, index) {
+ result = result && !!iterator.call(context, value, index);
+ if (!result) throw $break;
+ });
+ return result;
+ },
+
+ any: function(iterator, context) {
+ iterator = iterator || Prototype.K;
+ var result = false;
+ this.each(function(value, index) {
+ if (result = !!iterator.call(context, value, index))
+ throw $break;
+ });
+ return result;
+ },
+
+ collect: function(iterator, context) {
+ iterator = iterator || Prototype.K;
+ var results = [];
+ this.each(function(value, index) {
+ results.push(iterator.call(context, value, index));
+ });
+ return results;
+ },
+
+ detect: function(iterator, context) {
+ var result;
+ this.each(function(value, index) {
+ if (iterator.call(context, value, index)) {
+ result = value;
+ throw $break;
+ }
+ });
+ return result;
+ },
+
+ findAll: function(iterator, context) {
+ var results = [];
+ this.each(function(value, index) {
+ if (iterator.call(context, value, index))
+ results.push(value);
+ });
+ return results;
+ },
+
+ grep: function(filter, iterator, context) {
+ iterator = iterator || Prototype.K;
+ var results = [];
+
+ if (Object.isString(filter))
+ filter = new RegExp(filter);
+
+ this.each(function(value, index) {
+ if (filter.match(value))
+ results.push(iterator.call(context, value, index));
+ });
+ return results;
+ },
+
+ include: function(object) {
+ if (Object.isFunction(this.indexOf))
+ if (this.indexOf(object) != -1) return true;
+
+ var found = false;
+ this.each(function(value) {
+ if (value == object) {
+ found = true;
+ throw $break;
+ }
+ });
+ return found;
+ },
+
+ inGroupsOf: function(number, fillWith) {
+ fillWith = Object.isUndefined(fillWith) ? null : fillWith;
+ return this.eachSlice(number, function(slice) {
+ while(slice.length < number) slice.push(fillWith);
+ return slice;
+ });
+ },
+
+ inject: function(memo, iterator, context) {
+ this.each(function(value, index) {
+ memo = iterator.call(context, memo, value, index);
+ });
+ return memo;
+ },
+
+ invoke: function(method) {
+ var args = $A(arguments).slice(1);
+ return this.map(function(value) {
+ return value[method].apply(value, args);
+ });
+ },
+
+ max: function(iterator, context) {
+ iterator = iterator || Prototype.K;
+ var result;
+ this.each(function(value, index) {
+ value = iterator.call(context, value, index);
+ if (result == null || value >= result)
+ result = value;
+ });
+ return result;
+ },
+
+ min: function(iterator, context) {
+ iterator = iterator || Prototype.K;
+ var result;
+ this.each(function(value, index) {
+ value = iterator.call(context, value, index);
+ if (result == null || value < result)
+ result = value;
+ });
+ return result;
+ },
+
+ partition: function(iterator, context) {
+ iterator = iterator || Prototype.K;
+ var trues = [], falses = [];
+ this.each(function(value, index) {
+ (iterator.call(context, value, index) ?
+ trues : falses).push(value);
+ });
+ return [trues, falses];
+ },
+
+ pluck: function(property) {
+ var results = [];
+ this.each(function(value) {
+ results.push(value[property]);
+ });
+ return results;
+ },
+
+ reject: function(iterator, context) {
+ var results = [];
+ this.each(function(value, index) {
+ if (!iterator.call(context, value, index))
+ results.push(value);
+ });
+ return results;
+ },
+
+ sortBy: function(iterator, context) {
+ return this.map(function(value, index) {
+ return {
+ value: value,
+ criteria: iterator.call(context, value, index)
+ };
+ }).sort(function(left, right) {
+ var a = left.criteria, b = right.criteria;
+ return a < b ? -1 : a > b ? 1 : 0;
+ }).pluck('value');
+ },
+
+ toArray: function() {
+ return this.map();
+ },
+
+ zip: function() {
+ var iterator = Prototype.K, args = $A(arguments);
+ if (Object.isFunction(args.last()))
+ iterator = args.pop();
+
+ var collections = [this].concat(args).map($A);
+ return this.map(function(value, index) {
+ return iterator(collections.pluck(index));
+ });
+ },
+
+ size: function() {
+ return this.toArray().length;
+ },
+
+ inspect: function() {
+ return '#<Enumerable:' + this.toArray().inspect() + '>';
+ }
+};
+
+Object.extend(Enumerable, {
+ map: Enumerable.collect,
+ find: Enumerable.detect,
+ select: Enumerable.findAll,
+ filter: Enumerable.findAll,
+ member: Enumerable.include,
+ entries: Enumerable.toArray,
+ every: Enumerable.all,
+ some: Enumerable.any
+});
+function $A(iterable) {
+ if (!iterable) return [];
+ if (iterable.toArray) return iterable.toArray();
+ var length = iterable.length || 0, results = new Array(length);
+ while (length--) results[length] = iterable[length];
+ return results;
+}
+
+if (Prototype.Browser.WebKit) {
+ $A = function(iterable) {
+ if (!iterable) return [];
+ // In Safari, only use the `toArray` method if it's not a NodeList.
+ // A NodeList is a function, has an function `item` property, and a numeric
+ // `length` property. Adapted from Google Doctype.
+ if (!(typeof iterable === 'function' && typeof iterable.length ===
+ 'number' && typeof iterable.item === 'function') && iterable.toArray)
+ return iterable.toArray();
+ var length = iterable.length || 0, results = new Array(length);
+ while (length--) results[length] = iterable[length];
+ return results;
+ };
+}
+
+Array.from = $A;
+
+Object.extend(Array.prototype, Enumerable);
+
+if (!Array.prototype._reverse) Array.prototype._reverse = Array.prototype.reverse;
+
+Object.extend(Array.prototype, {
+ _each: function(iterator) {
+ for (var i = 0, length = this.length; i < length; i++)
+ iterator(this[i]);
+ },
+
+ clear: function() {
+ this.length = 0;
+ return this;
+ },
+
+ first: function() {
+ return this[0];
+ },
+
+ last: function() {
+ return this[this.length - 1];
+ },
+
+ compact: function() {
+ return this.select(function(value) {
+ return value != null;
+ });
+ },
+
+ flatten: function() {
+ return this.inject([], function(array, value) {
+ return array.concat(Object.isArray(value) ?
+ value.flatten() : [value]);
+ });
+ },
+
+ without: function() {
+ var values = $A(arguments);
+ return this.select(function(value) {
+ return !values.include(value);
+ });
+ },
+
+ reverse: function(inline) {
+ return (inline !== false ? this : this.toArray())._reverse();
+ },
+
+ reduce: function() {
+ return this.length > 1 ? this : this[0];
+ },
+
+ uniq: function(sorted) {
+ return this.inject([], function(array, value, index) {
+ if (0 == index || (sorted ? array.last() != value : !array.include(value)))
+ array.push(value);
+ return array;
+ });
+ },
+
+ intersect: function(array) {
+ return this.uniq().findAll(function(item) {
+ return array.detect(function(value) { return item === value });
+ });
+ },
+
+ clone: function() {
+ return [].concat(this);
+ },
+
+ size: function() {
+ return this.length;
+ },
+
+ inspect: function() {
+ return '[' + this.map(Object.inspect).join(', ') + ']';
+ },
+
+ toJSON: function() {
+ var results = [];
+ this.each(function(object) {
+ var value = Object.toJSON(object);
+ if (!Object.isUndefined(value)) results.push(value);
+ });
+ return '[' + results.join(', ') + ']';
+ }
+});
+
+// use native browser JS 1.6 implementation if available
+if (Object.isFunction(Array.prototype.forEach))
+ Array.prototype._each = Array.prototype.forEach;
+
+if (!Array.prototype.indexOf) Array.prototype.indexOf = function(item, i) {
+ i || (i = 0);
+ var length = this.length;
+ if (i < 0) i = length + i;
+ for (; i < length; i++)
+ if (this[i] === item) return i;
+ return -1;
+};
+
+if (!Array.prototype.lastIndexOf) Array.prototype.lastIndexOf = function(item, i) {
+ i = isNaN(i) ? this.length : (i < 0 ? this.length + i : i) + 1;
+ var n = this.slice(0, i).reverse().indexOf(item);
+ return (n < 0) ? n : i - n - 1;
+};
+
+Array.prototype.toArray = Array.prototype.clone;
+
+function $w(string) {
+ if (!Object.isString(string)) return [];
+ string = string.strip();
+ return string ? string.split(/\s+/) : [];
+}
+
+if (Prototype.Browser.Opera){
+ Array.prototype.concat = function() {
+ var array = [];
+ for (var i = 0, length = this.length; i < length; i++) array.push(this[i]);
+ for (var i = 0, length = arguments.length; i < length; i++) {
+ if (Object.isArray(arguments[i])) {
+ for (var j = 0, arrayLength = arguments[i].length; j < arrayLength; j++)
+ array.push(arguments[i][j]);
+ } else {
+ array.push(arguments[i]);
+ }
+ }
+ return array;
+ };
+}
+Object.extend(Number.prototype, {
+ toColorPart: function() {
+ return this.toPaddedString(2, 16);
+ },
+
+ succ: function() {
+ return this + 1;
+ },
+
+ times: function(iterator, context) {
+ $R(0, this, true).each(iterator, context);
+ return this;
+ },
+
+ toPaddedString: function(length, radix) {
+ var string = this.toString(radix || 10);
+ return '0'.times(length - string.length) + string;
+ },
+
+ toJSON: function() {
+ return isFinite(this) ? this.toString() : 'null';
+ }
+});
+
+$w('abs round ceil floor').each(function(method){
+ Number.prototype[method] = Math[method].methodize();
+});
+function $H(object) {
+ return new Hash(object);
+};
+
+var Hash = Class.create(Enumerable, (function() {
+
+ function toQueryPair(key, value) {
+ if (Object.isUndefined(value)) return key;
+ return key + '=' + encodeURIComponent(String.interpret(value));
+ }
+
+ return {
+ initialize: function(object) {
+ this._object = Object.isHash(object) ? object.toObject() : Object.clone(object);
+ },
+
+ _each: function(iterator) {
+ for (var key in this._object) {
+ var value = this._object[key], pair = [key, value];
+ pair.key = key;
+ pair.value = value;
+ iterator(pair);
+ }
+ },
+
+ set: function(key, value) {
+ return this._object[key] = value;
+ },
+
+ get: function(key) {
+ // simulating poorly supported hasOwnProperty
+ if (this._object[key] !== Object.prototype[key])
+ return this._object[key];
+ },
+
+ unset: function(key) {
+ var value = this._object[key];
+ delete this._object[key];
+ return value;
+ },
+
+ toObject: function() {
+ return Object.clone(this._object);
+ },
+
+ keys: function() {
+ return this.pluck('key');
+ },
+
+ values: function() {
+ return this.pluck('value');
+ },
+
+ index: function(value) {
+ var match = this.detect(function(pair) {
+ return pair.value === value;
+ });
+ return match && match.key;
+ },
+
+ merge: function(object) {
+ return this.clone().update(object);
+ },
+
+ update: function(object) {
+ return new Hash(object).inject(this, function(result, pair) {
+ result.set(pair.key, pair.value);
+ return result;
+ });
+ },
+
+ toQueryString: function() {
+ return this.inject([], function(results, pair) {
+ var key = encodeURIComponent(pair.key), values = pair.value;
+
+ if (values && typeof values == 'object') {
+ if (Object.isArray(values))
+ return results.concat(values.map(toQueryPair.curry(key)));
+ } else results.push(toQueryPair(key, values));
+ return results;
+ }).join('&');
+ },
+
+ inspect: function() {
+ return '#<Hash:{' + this.map(function(pair) {
+ return pair.map(Object.inspect).join(': ');
+ }).join(', ') + '}>';
+ },
+
+ toJSON: function() {
+ return Object.toJSON(this.toObject());
+ },
+
+ clone: function() {
+ return new Hash(this);
+ }
+ }
+})());
+
+Hash.prototype.toTemplateReplacements = Hash.prototype.toObject;
+Hash.from = $H;
+var ObjectRange = Class.create(Enumerable, {
+ initialize: function(start, end, exclusive) {
+ this.start = start;
+ this.end = end;
+ this.exclusive = exclusive;
+ },
+
+ _each: function(iterator) {
+ var value = this.start;
+ while (this.include(value)) {
+ iterator(value);
+ value = value.succ();
+ }
+ },
+
+ include: function(value) {
+ if (value < this.start)
+ return false;
+ if (this.exclusive)
+ return value < this.end;
+ return value <= this.end;
+ }
+});
+
+var $R = function(start, end, exclusive) {
+ return new ObjectRange(start, end, exclusive);
+};
+
+var Ajax = {
+ getTransport: function() {
+ return Try.these(
+ function() {return new XMLHttpRequest()},
+ function() {return new ActiveXObject('Msxml2.XMLHTTP')},
+ function() {return new ActiveXObject('Microsoft.XMLHTTP')}
+ ) || false;
+ },
+
+ activeRequestCount: 0
+};
+
+Ajax.Responders = {
+ responders: [],
+
+ _each: function(iterator) {
+ this.responders._each(iterator);
+ },
+
+ register: function(responder) {
+ if (!this.include(responder))
+ this.responders.push(responder);
+ },
+
+ unregister: function(responder) {
+ this.responders = this.responders.without(responder);
+ },
+
+ dispatch: function(callback, request, transport, json) {
+ this.each(function(responder) {
+ if (Object.isFunction(responder[callback])) {
+ try {
+ responder[callback].apply(responder, [request, transport, json]);
+ } catch (e) { }
+ }
+ });
+ }
+};
+
+Object.extend(Ajax.Responders, Enumerable);
+
+Ajax.Responders.register({
+ onCreate: function() { Ajax.activeRequestCount++ },
+ onComplete: function() { Ajax.activeRequestCount-- }
+});
+
+Ajax.Base = Class.create({
+ initialize: function(options) {
+ this.options = {
+ method: 'post',
+ asynchronous: true,
+ contentType: 'application/x-www-form-urlencoded',
+ encoding: 'UTF-8',
+ parameters: '',
+ evalJSON: true,
+ evalJS: true
+ };
+ Object.extend(this.options, options || { });
+
+ this.options.method = this.options.method.toLowerCase();
+
+ if (Object.isString(this.options.parameters))
+ this.options.parameters = this.options.parameters.toQueryParams();
+ else if (Object.isHash(this.options.parameters))
+ this.options.parameters = this.options.parameters.toObject();
+ }
+});
+
+Ajax.Request = Class.create(Ajax.Base, {
+ _complete: false,
+
+ initialize: function($super, url, options) {
+ $super(options);
+ this.transport = Ajax.getTransport();
+ this.request(url);
+ },
+
+ request: function(url) {
+ this.url = url;
+ this.method = this.options.method;
+ var params = Object.clone(this.options.parameters);
+
+ if (!['get', 'post'].include(this.method)) {
+ // simulate other verbs over post
+ params['_method'] = this.method;
+ this.method = 'post';
+ }
+
+ this.parameters = params;
+
+ if (params = Object.toQueryString(params)) {
+ // when GET, append parameters to URL
+ if (this.method == 'get')
+ this.url += (this.url.include('?') ? '&' : '?') + params;
+ else if (/Konqueror|Safari|KHTML/.test(navigator.userAgent))
+ params += '&_=';
+ }
+
+ try {
+ var response = new Ajax.Response(this);
+ if (this.options.onCreate) this.options.onCreate(response);
+ Ajax.Responders.dispatch('onCreate', this, response);
+
+ this.transport.open(this.method.toUpperCase(), this.url,
+ this.options.asynchronous);
+
+ if (this.options.asynchronous) this.respondToReadyState.bind(this).defer(1);
+
+ this.transport.onreadystatechange = this.onStateChange.bind(this);
+ this.setRequestHeaders();
+
+ this.body = this.method == 'post' ? (this.options.postBody || params) : null;
+ this.transport.send(this.body);
+
+ /* Force Firefox to handle ready state 4 for synchronous requests */
+ if (!this.options.asynchronous && this.transport.overrideMimeType)
+ this.onStateChange();
+
+ }
+ catch (e) {
+ this.dispatchException(e);
+ }
+ },
+
+ onStateChange: function() {
+ var readyState = this.transport.readyState;
+ if (readyState > 1 && !((readyState == 4) && this._complete))
+ this.respondToReadyState(this.transport.readyState);
+ },
+
+ setRequestHeaders: function() {
+ var headers = {
+ 'X-Requested-With': 'XMLHttpRequest',
+ 'X-Prototype-Version': Prototype.Version,
+ 'Accept': 'text/javascript, text/html, application/xml, text/xml, */*'
+ };
+
+ if (this.method == 'post') {
+ headers['Content-type'] = this.options.contentType +
+ (this.options.encoding ? '; charset=' + this.options.encoding : '');
+
+ /* Force "Connection: close" for older Mozilla browsers to work
+ * around a bug where XMLHttpRequest sends an incorrect
+ * Content-length header. See Mozilla Bugzilla #246651.
+ */
+ if (this.transport.overrideMimeType &&
+ (navigator.userAgent.match(/Gecko\/(\d{4})/) || [0,2005])[1] < 2005)
+ headers['Connection'] = 'close';
+ }
+
+ // user-defined headers
+ if (typeof this.options.requestHeaders == 'object') {
+ var extras = this.options.requestHeaders;
+
+ if (Object.isFunction(extras.push))
+ for (var i = 0, length = extras.length; i < length; i += 2)
+ headers[extras[i]] = extras[i+1];
+ else
+ $H(extras).each(function(pair) { headers[pair.key] = pair.value });
+ }
+
+ for (var name in headers)
+ this.transport.setRequestHeader(name, headers[name]);
+ },
+
+ success: function() {
+ var status = this.getStatus();
+ return !status || (status >= 200 && status < 300);
+ },
+
+ getStatus: function() {
+ try {
+ return this.transport.status || 0;
+ } catch (e) { return 0 }
+ },
+
+ respondToReadyState: function(readyState) {
+ var state = Ajax.Request.Events[readyState], response = new Ajax.Response(this);
+
+ if (state == 'Complete') {
+ try {
+ this._complete = true;
+ (this.options['on' + response.status]
+ || this.options['on' + (this.success() ? 'Success' : 'Failure')]
+ || Prototype.emptyFunction)(response, response.headerJSON);
+ } catch (e) {
+ this.dispatchException(e);
+ }
+
+ var contentType = response.getHeader('Content-type');
+ if (this.options.evalJS == 'force'
+ || (this.options.evalJS && this.isSameOrigin() && contentType
+ && contentType.match(/^\s*(text|application)\/(x-)?(java|ecma)script(;.*)?\s*$/i)))
+ this.evalResponse();
+ }
+
+ try {
+ (this.options['on' + state] || Prototype.emptyFunction)(response, response.headerJSON);
+ Ajax.Responders.dispatch('on' + state, this, response, response.headerJSON);
+ } catch (e) {
+ this.dispatchException(e);
+ }
+
+ if (state == 'Complete') {
+ // avoid memory leak in MSIE: clean up
+ this.transport.onreadystatechange = Prototype.emptyFunction;
+ }
+ },
+
+ isSameOrigin: function() {
+ var m = this.url.match(/^\s*https?:\/\/[^\/]*/);
+ return !m || (m[0] == '#{protocol}//#{domain}#{port}'.interpolate({
+ protocol: location.protocol,
+ domain: document.domain,
+ port: location.port ? ':' + location.port : ''
+ }));
+ },
+
+ getHeader: function(name) {
+ try {
+ return this.transport.getResponseHeader(name) || null;
+ } catch (e) { return null }
+ },
+
+ evalResponse: function() {
+ try {
+ return eval((this.transport.responseText || '').unfilterJSON());
+ } catch (e) {
+ this.dispatchException(e);
+ }
+ },
+
+ dispatchException: function(exception) {
+ (this.options.onException || Prototype.emptyFunction)(this, exception);
+ Ajax.Responders.dispatch('onException', this, exception);
+ }
+});
+
+Ajax.Request.Events =
+ ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete'];
+
+Ajax.Response = Class.create({
+ initialize: function(request){
+ this.request = request;
+ var transport = this.transport = request.transport,
+ readyState = this.readyState = transport.readyState;
+
+ if((readyState > 2 && !Prototype.Browser.IE) || readyState == 4) {
+ this.status = this.getStatus();
+ this.statusText = this.getStatusText();
+ this.responseText = String.interpret(transport.responseText);
+ this.headerJSON = this._getHeaderJSON();
+ }
+
+ if(readyState == 4) {
+ var xml = transport.responseXML;
+ this.responseXML = Object.isUndefined(xml) ? null : xml;
+ this.responseJSON = this._getResponseJSON();
+ }
+ },
+
+ status: 0,
+ statusText: '',
+
+ getStatus: Ajax.Request.prototype.getStatus,
+
+ getStatusText: function() {
+ try {
+ return this.transport.statusText || '';
+ } catch (e) { return '' }
+ },
+
+ getHeader: Ajax.Request.prototype.getHeader,
+
+ getAllHeaders: function() {
+ try {
+ return this.getAllResponseHeaders();
+ } catch (e) { return null }
+ },
+
+ getResponseHeader: function(name) {
+ return this.transport.getResponseHeader(name);
+ },
+
+ getAllResponseHeaders: function() {
+ return this.transport.getAllResponseHeaders();
+ },
+
+ _getHeaderJSON: function() {
+ var json = this.getHeader('X-JSON');
+ if (!json) return null;
+ json = decodeURIComponent(escape(json));
+ try {
+ return json.evalJSON(this.request.options.sanitizeJSON ||
+ !this.request.isSameOrigin());
+ } catch (e) {
+ this.request.dispatchException(e);
+ }
+ },
+
+ _getResponseJSON: function() {
+ var options = this.request.options;
+ if (!options.evalJSON || (options.evalJSON != 'force' &&
+ !(this.getHeader('Content-type') || '').include('application/json')) ||
+ this.responseText.blank())
+ return null;
+ try {
+ return this.responseText.evalJSON(options.sanitizeJSON ||
+ !this.request.isSameOrigin());
+ } catch (e) {
+ this.request.dispatchException(e);
+ }
+ }
+});
+
+Ajax.Updater = Class.create(Ajax.Request, {
+ initialize: function($super, container, url, options) {
+ this.container = {
+ success: (container.success || container),
+ failure: (container.failure || (container.success ? null : container))
+ };
+
+ options = Object.clone(options);
+ var onComplete = options.onComplete;
+ options.onComplete = (function(response, json) {
+ this.updateContent(response.responseText);
+ if (Object.isFunction(onComplete)) onComplete(response, json);
+ }).bind(this);
+
+ $super(url, options);
+ },
+
+ updateContent: function(responseText) {
+ var receiver = this.container[this.success() ? 'success' : 'failure'],
+ options = this.options;
+
+ if (!options.evalScripts) responseText = responseText.stripScripts();
+
+ if (receiver = $(receiver)) {
+ if (options.insertion) {
+ if (Object.isString(options.insertion)) {
+ var insertion = { }; insertion[options.insertion] = responseText;
+ receiver.insert(insertion);
+ }
+ else options.insertion(receiver, responseText);
+ }
+ else receiver.update(responseText);
+ }
+ }
+});
+
+Ajax.PeriodicalUpdater = Class.create(Ajax.Base, {
+ initialize: function($super, container, url, options) {
+ $super(options);
+ this.onComplete = this.options.onComplete;
+
+ this.frequency = (this.options.frequency || 2);
+ this.decay = (this.options.decay || 1);
+
+ this.updater = { };
+ this.container = container;
+ this.url = url;
+
+ this.start();
+ },
+
+ start: function() {
+ this.options.onComplete = this.updateComplete.bind(this);
+ this.onTimerEvent();
+ },
+
+ stop: function() {
+ this.updater.options.onComplete = undefined;
+ clearTimeout(this.timer);
+ (this.onComplete || Prototype.emptyFunction).apply(this, arguments);
+ },
+
+ updateComplete: function(response) {
+ if (this.options.decay) {
+ this.decay = (response.responseText == this.lastText ?
+ this.decay * this.options.decay : 1);
+
+ this.lastText = response.responseText;
+ }
+ this.timer = this.onTimerEvent.bind(this).delay(this.decay * this.frequency);
+ },
+
+ onTimerEvent: function() {
+ this.updater = new Ajax.Updater(this.container, this.url, this.options);
+ }
+});
+function $(element) {
+ if (arguments.length > 1) {
+ for (var i = 0, elements = [], length = arguments.length; i < length; i++)
+ elements.push($(arguments[i]));
+ return elements;
+ }
+ if (Object.isString(element))
+ element = document.getElementById(element);
+ return Element.extend(element);
+}
+
+if (Prototype.BrowserFeatures.XPath) {
+ document._getElementsByXPath = function(expression, parentElement) {
+ var results = [];
+ var query = document.evaluate(expression, $(parentElement) || document,
+ null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
+ for (var i = 0, length = query.snapshotLength; i < length; i++)
+ results.push(Element.extend(query.snapshotItem(i)));
+ return results;
+ };
+}
+
+/*--------------------------------------------------------------------------*/
+
+if (!window.Node) var Node = { };
+
+if (!Node.ELEMENT_NODE) {
+ // DOM level 2 ECMAScript Language Binding
+ Object.extend(Node, {
+ ELEMENT_NODE: 1,
+ ATTRIBUTE_NODE: 2,
+ TEXT_NODE: 3,
+ CDATA_SECTION_NODE: 4,
+ ENTITY_REFERENCE_NODE: 5,
+ ENTITY_NODE: 6,
+ PROCESSING_INSTRUCTION_NODE: 7,
+ COMMENT_NODE: 8,
+ DOCUMENT_NODE: 9,
+ DOCUMENT_TYPE_NODE: 10,
+ DOCUMENT_FRAGMENT_NODE: 11,
+ NOTATION_NODE: 12
+ });
+}
+
+(function() {
+ var element = this.Element;
+ this.Element = function(tagName, attributes) {
+ attributes = attributes || { };
+ tagName = tagName.toLowerCase();
+ var cache = Element.cache;
+ if (Prototype.Browser.IE && attributes.name) {
+ tagName = '<' + tagName + ' name="' + attributes.name + '">';
+ delete attributes.name;
+ return Element.writeAttribute(document.createElement(tagName), attributes);
+ }
+ if (!cache[tagName]) cache[tagName] = Element.extend(document.createElement(tagName));
+ return Element.writeAttribute(cache[tagName].cloneNode(false), attributes);
+ };
+ Object.extend(this.Element, element || { });
+ if (element) this.Element.prototype = element.prototype;
+}).call(window);
+
+Element.cache = { };
+
+Element.Methods = {
+ visible: function(element) {
+ return $(element).style.display != 'none';
+ },
+
+ toggle: function(element) {
+ element = $(element);
+ Element[Element.visible(element) ? 'hide' : 'show'](element);
+ return element;
+ },
+
+ hide: function(element) {
+ element = $(element);
+ element.style.display = 'none';
+ return element;
+ },
+
+ show: function(element) {
+ element = $(element);
+ element.style.display = '';
+ return element;
+ },
+
+ remove: function(element) {
+ element = $(element);
+ element.parentNode.removeChild(element);
+ return element;
+ },
+
+ update: function(element, content) {
+ element = $(element);
+ if (content && content.toElement) content = content.toElement();
+ if (Object.isElement(content)) return element.update().insert(content);
+ content = Object.toHTML(content);
+ element.innerHTML = content.stripScripts();
+ content.evalScripts.bind(content).defer();
+ return element;
+ },
+
+ replace: function(element, content) {
+ element = $(element);
+ if (content && content.toElement) content = content.toElement();
+ else if (!Object.isElement(content)) {
+ content = Object.toHTML(content);
+ var range = element.ownerDocument.createRange();
+ range.selectNode(element);
+ content.evalScripts.bind(content).defer();
+ content = range.createContextualFragment(content.stripScripts());
+ }
+ element.parentNode.replaceChild(content, element);
+ return element;
+ },
+
+ insert: function(element, insertions) {
+ element = $(element);
+
+ if (Object.isString(insertions) || Object.isNumber(insertions) ||
+ Object.isElement(insertions) || (insertions && (insertions.toElement || insertions.toHTML)))
+ insertions = {bottom:insertions};
+
+ var content, insert, tagName, childNodes;
+
+ for (var position in insertions) {
+ content = insertions[position];
+ position = position.toLowerCase();
+ insert = Element._insertionTranslations[position];
+
+ if (content && content.toElement) content = content.toElement();
+ if (Object.isElement(content)) {
+ insert(element, content);
+ continue;
+ }
+
+ content = Object.toHTML(content);
+
+ tagName = ((position == 'before' || position == 'after')
+ ? element.parentNode : element).tagName.toUpperCase();
+
+ childNodes = Element._getContentFromAnonymousElement(tagName, content.stripScripts());
+
+ if (position == 'top' || position == 'after') childNodes.reverse();
+ childNodes.each(insert.curry(element));
+
+ content.evalScripts.bind(content).defer();
+ }
+
+ return element;
+ },
+
+ wrap: function(element, wrapper, attributes) {
+ element = $(element);
+ if (Object.isElement(wrapper))
+ $(wrapper).writeAttribute(attributes || { });
+ else if (Object.isString(wrapper)) wrapper = new Element(wrapper, attributes);
+ else wrapper = new Element('div', wrapper);
+ if (element.parentNode)
+ element.parentNode.replaceChild(wrapper, element);
+ wrapper.appendChild(element);
+ return wrapper;
+ },
+
+ inspect: function(element) {
+ element = $(element);
+ var result = '<' + element.tagName.toLowerCase();
+ $H({'id': 'id', 'className': 'class'}).each(function(pair) {
+ var property = pair.first(), attribute = pair.last();
+ var value = (element[property] || '').toString();
+ if (value) result += ' ' + attribute + '=' + value.inspect(true);
+ });
+ return result + '>';
+ },
+
+ recursivelyCollect: function(element, property) {
+ element = $(element);
+ var elements = [];
+ while (element = element[property])
+ if (element.nodeType == 1)
+ elements.push(Element.extend(element));
+ return elements;
+ },
+
+ ancestors: function(element) {
+ return $(element).recursivelyCollect('parentNode');
+ },
+
+ descendants: function(element) {
+ return $(element).select("*");
+ },
+
+ firstDescendant: function(element) {
+ element = $(element).firstChild;
+ while (element && element.nodeType != 1) element = element.nextSibling;
+ return $(element);
+ },
+
+ immediateDescendants: function(element) {
+ if (!(element = $(element).firstChild)) return [];
+ while (element && element.nodeType != 1) element = element.nextSibling;
+ if (element) return [element].concat($(element).nextSiblings());
+ return [];
+ },
+
+ previousSiblings: function(element) {
+ return $(element).recursivelyCollect('previousSibling');
+ },
+
+ nextSiblings: function(element) {
+ return $(element).recursivelyCollect('nextSibling');
+ },
+
+ siblings: function(element) {
+ element = $(element);
+ return element.previousSiblings().reverse().concat(element.nextSiblings());
+ },
+
+ match: function(element, selector) {
+ if (Object.isString(selector))
+ selector = new Selector(selector);
+ return selector.match($(element));
+ },
+
+ up: function(element, expression, index) {
+ element = $(element);
+ if (arguments.length == 1) return $(element.parentNode);
+ var ancestors = element.ancestors();
+ return Object.isNumber(expression) ? ancestors[expression] :
+ Selector.findElement(ancestors, expression, index);
+ },
+
+ down: function(element, expression, index) {
+ element = $(element);
+ if (arguments.length == 1) return element.firstDescendant();
+ return Object.isNumber(expression) ? element.descendants()[expression] :
+ Element.select(element, expression)[index || 0];
+ },
+
+ previous: function(element, expression, index) {
+ element = $(element);
+ if (arguments.length == 1) return $(Selector.handlers.previousElementSibling(element));
+ var previousSiblings = element.previousSiblings();
+ return Object.isNumber(expression) ? previousSiblings[expression] :
+ Selector.findElement(previousSiblings, expression, index);
+ },
+
+ next: function(element, expression, index) {
+ element = $(element);
+ if (arguments.length == 1) return $(Selector.handlers.nextElementSibling(element));
+ var nextSiblings = element.nextSiblings();
+ return Object.isNumber(expression) ? nextSiblings[expression] :
+ Selector.findElement(nextSiblings, expression, index);
+ },
+
+ select: function() {
+ var args = $A(arguments), element = $(args.shift());
+ return Selector.findChildElements(element, args);
+ },
+
+ adjacent: function() {
+ var args = $A(arguments), element = $(args.shift());
+ return Selector.findChildElements(element.parentNode, args).without(element);
+ },
+
+ identify: function(element) {
+ element = $(element);
+ var id = element.readAttribute('id'), self = arguments.callee;
+ if (id) return id;
+ do { id = 'anonymous_element_' + self.counter++ } while ($(id));
+ element.writeAttribute('id', id);
+ return id;
+ },
+
+ readAttribute: function(element, name) {
+ element = $(element);
+ if (Prototype.Browser.IE) {
+ var t = Element._attributeTranslations.read;
+ if (t.values[name]) return t.values[name](element, name);
+ if (t.names[name]) name = t.names[name];
+ if (name.include(':')) {
+ return (!element.attributes || !element.attributes[name]) ? null :
+ element.attributes[name].value;
+ }
+ }
+ return element.getAttribute(name);
+ },
+
+ writeAttribute: function(element, name, value) {
+ element = $(element);
+ var attributes = { }, t = Element._attributeTranslations.write;
+
+ if (typeof name == 'object') attributes = name;
+ else attributes[name] = Object.isUndefined(value) ? true : value;
+
+ for (var attr in attributes) {
+ name = t.names[attr] || attr;
+ value = attributes[attr];
+ if (t.values[attr]) name = t.values[attr](element, value);
+ if (value === false || value === null)
+ element.removeAttribute(name);
+ else if (value === true)
+ element.setAttribute(name, name);
+ else element.setAttribute(name, value);
+ }
+ return element;
+ },
+
+ getHeight: function(element) {
+ return $(element).getDimensions().height;
+ },
+
+ getWidth: function(element) {
+ return $(element).getDimensions().width;
+ },
+
+ classNames: function(element) {
+ return new Element.ClassNames(element);
+ },
+
+ hasClassName: function(element, className) {
+ if (!(element = $(element))) return;
+ var elementClassName = element.className;
+ return (elementClassName.length > 0 && (elementClassName == className ||
+ new RegExp("(^|\\s)" + className + "(\\s|$)").test(elementClassName)));
+ },
+
+ addClassName: function(element, className) {
+ if (!(element = $(element))) return;
+ if (!element.hasClassName(className))
+ element.className += (element.className ? ' ' : '') + className;
+ return element;
+ },
+
+ removeClassName: function(element, className) {
+ if (!(element = $(element))) return;
+ element.className = element.className.replace(
+ new RegExp("(^|\\s+)" + className + "(\\s+|$)"), ' ').strip();
+ return element;
+ },
+
+ toggleClassName: function(element, className) {
+ if (!(element = $(element))) return;
+ return element[element.hasClassName(className) ?
+ 'removeClassName' : 'addClassName'](className);
+ },
+
+ // removes whitespace-only text node children
+ cleanWhitespace: function(element) {
+ element = $(element);
+ var node = element.firstChild;
+ while (node) {
+ var nextNode = node.nextSibling;
+ if (node.nodeType == 3 && !/\S/.test(node.nodeValue))
+ element.removeChild(node);
+ node = nextNode;
+ }
+ return element;
+ },
+
+ empty: function(element) {
+ return $(element).innerHTML.blank();
+ },
+
+ descendantOf: function(element, ancestor) {
+ element = $(element), ancestor = $(ancestor);
+
+ if (element.compareDocumentPosition)
+ return (element.compareDocumentPosition(ancestor) & 8) === 8;
+
+ if (ancestor.contains)
+ return ancestor.contains(element) && ancestor !== element;
+
+ while (element = element.parentNode)
+ if (element == ancestor) return true;
+
+ return false;
+ },
+
+ scrollTo: function(element) {
+ element = $(element);
+ var pos = element.cumulativeOffset();
+ window.scrollTo(pos[0], pos[1]);
+ return element;
+ },
+
+ getStyle: function(element, style) {
+ element = $(element);
+ style = style == 'float' ? 'cssFloat' : style.camelize();
+ var value = element.style[style];
+ if (!value || value == 'auto') {
+ var css = document.defaultView.getComputedStyle(element, null);
+ value = css ? css[style] : null;
+ }
+ if (style == 'opacity') return value ? parseFloat(value) : 1.0;
+ return value == 'auto' ? null : value;
+ },
+
+ getOpacity: function(element) {
+ return $(element).getStyle('opacity');
+ },
+
+ setStyle: function(element, styles) {
+ element = $(element);
+ var elementStyle = element.style, match;
+ if (Object.isString(styles)) {
+ element.style.cssText += ';' + styles;
+ return styles.include('opacity') ?
+ element.setOpacity(styles.match(/opacity:\s*(\d?\.?\d*)/)[1]) : element;
+ }
+ for (var property in styles)
+ if (property == 'opacity') element.setOpacity(styles[property]);
+ else
+ elementStyle[(property == 'float' || property == 'cssFloat') ?
+ (Object.isUndefined(elementStyle.styleFloat) ? 'cssFloat' : 'styleFloat') :
+ property] = styles[property];
+
+ return element;
+ },
+
+ setOpacity: function(element, value) {
+ element = $(element);
+ element.style.opacity = (value == 1 || value === '') ? '' :
+ (value < 0.00001) ? 0 : value;
+ return element;
+ },
+
+ getDimensions: function(element) {
+ element = $(element);
+ var display = element.getStyle('display');
+ if (display != 'none' && display != null) // Safari bug
+ return {width: element.offsetWidth, height: element.offsetHeight};
+
+ // All *Width and *Height properties give 0 on elements with display none,
+ // so enable the element temporarily
+ var els = element.style;
+ var originalVisibility = els.visibility;
+ var originalPosition = els.position;
+ var originalDisplay = els.display;
+ els.visibility = 'hidden';
+ els.position = 'absolute';
+ els.display = 'block';
+ var originalWidth = element.clientWidth;
+ var originalHeight = element.clientHeight;
+ els.display = originalDisplay;
+ els.position = originalPosition;
+ els.visibility = originalVisibility;
+ return {width: originalWidth, height: originalHeight};
+ },
+
+ makePositioned: function(element) {
+ element = $(element);
+ var pos = Element.getStyle(element, 'position');
+ if (pos == 'static' || !pos) {
+ element._madePositioned = true;
+ element.style.position = 'relative';
+ // Opera returns the offset relative to the positioning context, when an
+ // element is position relative but top and left have not been defined
+ if (Prototype.Browser.Opera) {
+ element.style.top = 0;
+ element.style.left = 0;
+ }
+ }
+ return element;
+ },
+
+ undoPositioned: function(element) {
+ element = $(element);
+ if (element._madePositioned) {
+ element._madePositioned = undefined;
+ element.style.position =
+ element.style.top =
+ element.style.left =
+ element.style.bottom =
+ element.style.right = '';
+ }
+ return element;
+ },
+
+ makeClipping: function(element) {
+ element = $(element);
+ if (element._overflow) return element;
+ element._overflow = Element.getStyle(element, 'overflow') || 'auto';
+ if (element._overflow !== 'hidden')
+ element.style.overflow = 'hidden';
+ return element;
+ },
+
+ undoClipping: function(element) {
+ element = $(element);
+ if (!element._overflow) return element;
+ element.style.overflow = element._overflow == 'auto' ? '' : element._overflow;
+ element._overflow = null;
+ return element;
+ },
+
+ cumulativeOffset: function(element) {
+ var valueT = 0, valueL = 0;
+ do {
+ valueT += element.offsetTop || 0;
+ valueL += element.offsetLeft || 0;
+ element = element.offsetParent;
+ } while (element);
+ return Element._returnOffset(valueL, valueT);
+ },
+
+ positionedOffset: function(element) {
+ var valueT = 0, valueL = 0;
+ do {
+ valueT += element.offsetTop || 0;
+ valueL += element.offsetLeft || 0;
+ element = element.offsetParent;
+ if (element) {
+ if (element.tagName.toUpperCase() == 'BODY') break;
+ var p = Element.getStyle(element, 'position');
+ if (p !== 'static') break;
+ }
+ } while (element);
+ return Element._returnOffset(valueL, valueT);
+ },
+
+ absolutize: function(element) {
+ element = $(element);
+ if (element.getStyle('position') == 'absolute') return element;
+ // Position.prepare(); // To be done manually by Scripty when it needs it.
+
+ var offsets = element.positionedOffset();
+ var top = offsets[1];
+ var left = offsets[0];
+ var width = element.clientWidth;
+ var height = element.clientHeight;
+
+ element._originalLeft = left - parseFloat(element.style.left || 0);
+ element._originalTop = top - parseFloat(element.style.top || 0);
+ element._originalWidth = element.style.width;
+ element._originalHeight = element.style.height;
+
+ element.style.position = 'absolute';
+ element.style.top = top + 'px';
+ element.style.left = left + 'px';
+ element.style.width = width + 'px';
+ element.style.height = height + 'px';
+ return element;
+ },
+
+ relativize: function(element) {
+ element = $(element);
+ if (element.getStyle('position') == 'relative') return element;
+ // Position.prepare(); // To be done manually by Scripty when it needs it.
+
+ element.style.position = 'relative';
+ var top = parseFloat(element.style.top || 0) - (element._originalTop || 0);
+ var left = parseFloat(element.style.left || 0) - (element._originalLeft || 0);
+
+ element.style.top = top + 'px';
+ element.style.left = left + 'px';
+ element.style.height = element._originalHeight;
+ element.style.width = element._originalWidth;
+ return element;
+ },
+
+ cumulativeScrollOffset: function(element) {
+ var valueT = 0, valueL = 0;
+ do {
+ valueT += element.scrollTop || 0;
+ valueL += element.scrollLeft || 0;
+ element = element.parentNode;
+ } while (element);
+ return Element._returnOffset(valueL, valueT);
+ },
+
+ getOffsetParent: function(element) {
+ if (element.offsetParent) return $(element.offsetParent);
+ if (element == document.body) return $(element);
+
+ while ((element = element.parentNode) && element != document.body)
+ if (Element.getStyle(element, 'position') != 'static')
+ return $(element);
+
+ return $(document.body);
+ },
+
+ viewportOffset: function(forElement) {
+ var valueT = 0, valueL = 0;
+
+ var element = forElement;
+ do {
+ valueT += element.offsetTop || 0;
+ valueL += element.offsetLeft || 0;
+
+ // Safari fix
+ if (element.offsetParent == document.body &&
+ Element.getStyle(element, 'position') == 'absolute') break;
+
+ } while (element = element.offsetParent);
+
+ element = forElement;
+ do {
+ if (!Prototype.Browser.Opera || (element.tagName && (element.tagName.toUpperCase() == 'BODY'))) {
+ valueT -= element.scrollTop || 0;
+ valueL -= element.scrollLeft || 0;
+ }
+ } while (element = element.parentNode);
+
+ return Element._returnOffset(valueL, valueT);
+ },
+
+ clonePosition: function(element, source) {
+ var options = Object.extend({
+ setLeft: true,
+ setTop: true,
+ setWidth: true,
+ setHeight: true,
+ offsetTop: 0,
+ offsetLeft: 0
+ }, arguments[2] || { });
+
+ // find page position of source
+ source = $(source);
+ var p = source.viewportOffset();
+
+ // find coordinate system to use
+ element = $(element);
+ var delta = [0, 0];
+ var parent = null;
+ // delta [0,0] will do fine with position: fixed elements,
+ // position:absolute needs offsetParent deltas
+ if (Element.getStyle(element, 'position') == 'absolute') {
+ parent = element.getOffsetParent();
+ delta = parent.viewportOffset();
+ }
+
+ // correct by body offsets (fixes Safari)
+ if (parent == document.body) {
+ delta[0] -= document.body.offsetLeft;
+ delta[1] -= document.body.offsetTop;
+ }
+
+ // set position
+ if (options.setLeft) element.style.left = (p[0] - delta[0] + options.offsetLeft) + 'px';
+ if (options.setTop) element.style.top = (p[1] - delta[1] + options.offsetTop) + 'px';
+ if (options.setWidth) element.style.width = source.offsetWidth + 'px';
+ if (options.setHeight) element.style.height = source.offsetHeight + 'px';
+ return element;
+ }
+};
+
+Element.Methods.identify.counter = 1;
+
+Object.extend(Element.Methods, {
+ getElementsBySelector: Element.Methods.select,
+ childElements: Element.Methods.immediateDescendants
+});
+
+Element._attributeTranslations = {
+ write: {
+ names: {
+ className: 'class',
+ htmlFor: 'for'
+ },
+ values: { }
+ }
+};
+
+if (Prototype.Browser.Opera) {
+ Element.Methods.getStyle = Element.Methods.getStyle.wrap(
+ function(proceed, element, style) {
+ switch (style) {
+ case 'left': case 'top': case 'right': case 'bottom':
+ if (proceed(element, 'position') === 'static') return null;
+ case 'height': case 'width':
+ // returns '0px' for hidden elements; we want it to return null
+ if (!Element.visible(element)) return null;
+
+ // returns the border-box dimensions rather than the content-box
+ // dimensions, so we subtract padding and borders from the value
+ var dim = parseInt(proceed(element, style), 10);
+
+ if (dim !== element['offset' + style.capitalize()])
+ return dim + 'px';
+
+ var properties;
+ if (style === 'height') {
+ properties = ['border-top-width', 'padding-top',
+ 'padding-bottom', 'border-bottom-width'];
+ }
+ else {
+ properties = ['border-left-width', 'padding-left',
+ 'padding-right', 'border-right-width'];
+ }
+ return properties.inject(dim, function(memo, property) {
+ var val = proceed(element, property);
+ return val === null ? memo : memo - parseInt(val, 10);
+ }) + 'px';
+ default: return proceed(element, style);
+ }
+ }
+ );
+
+ Element.Methods.readAttribute = Element.Methods.readAttribute.wrap(
+ function(proceed, element, attribute) {
+ if (attribute === 'title') return element.title;
+ return proceed(element, attribute);
+ }
+ );
+}
+
+else if (Prototype.Browser.IE) {
+ // IE doesn't report offsets correctly for static elements, so we change them
+ // to "relative" to get the values, then change them back.
+ Element.Methods.getOffsetParent = Element.Methods.getOffsetParent.wrap(
+ function(proceed, element) {
+ element = $(element);
+ // IE throws an error if element is not in document
+ try { element.offsetParent }
+ catch(e) { return $(document.body) }
+ var position = element.getStyle('position');
+ if (position !== 'static') return proceed(element);
+ element.setStyle({ position: 'relative' });
+ var value = proceed(element);
+ element.setStyle({ position: position });
+ return value;
+ }
+ );
+
+ $w('positionedOffset viewportOffset').each(function(method) {
+ Element.Methods[method] = Element.Methods[method].wrap(
+ function(proceed, element) {
+ element = $(element);
+ try { element.offsetParent }
+ catch(e) { return Element._returnOffset(0,0) }
+ var position = element.getStyle('position');
+ if (position !== 'static') return proceed(element);
+ // Trigger hasLayout on the offset parent so that IE6 reports
+ // accurate offsetTop and offsetLeft values for position: fixed.
+ var offsetParent = element.getOffsetParent();
+ if (offsetParent && offsetParent.getStyle('position') === 'fixed')
+ offsetParent.setStyle({ zoom: 1 });
+ element.setStyle({ position: 'relative' });
+ var value = proceed(element);
+ element.setStyle({ position: position });
+ return value;
+ }
+ );
+ });
+
+ Element.Methods.cumulativeOffset = Element.Methods.cumulativeOffset.wrap(
+ function(proceed, element) {
+ try { element.offsetParent }
+ catch(e) { return Element._returnOffset(0,0) }
+ return proceed(element);
+ }
+ );
+
+ Element.Methods.getStyle = function(element, style) {
+ element = $(element);
+ style = (style == 'float' || style == 'cssFloat') ? 'styleFloat' : style.camelize();
+ var value = element.style[style];
+ if (!value && element.currentStyle) value = element.currentStyle[style];
+
+ if (style == 'opacity') {
+ if (value = (element.getStyle('filter') || '').match(/alpha\(opacity=(.*)\)/))
+ if (value[1]) return parseFloat(value[1]) / 100;
+ return 1.0;
+ }
+
+ if (value == 'auto') {
+ if ((style == 'width' || style == 'height') && (element.getStyle('display') != 'none'))
+ return element['offset' + style.capitalize()] + 'px';
+ return null;
+ }
+ return value;
+ };
+
+ Element.Methods.setOpacity = function(element, value) {
+ function stripAlpha(filter){
+ return filter.replace(/alpha\([^\)]*\)/gi,'');
+ }
+ element = $(element);
+ var currentStyle = element.currentStyle;
+ if ((currentStyle && !currentStyle.hasLayout) ||
+ (!currentStyle && element.style.zoom == 'normal'))
+ element.style.zoom = 1;
+
+ var filter = element.getStyle('filter'), style = element.style;
+ if (value == 1 || value === '') {
+ (filter = stripAlpha(filter)) ?
+ style.filter = filter : style.removeAttribute('filter');
+ return element;
+ } else if (value < 0.00001) value = 0;
+ style.filter = stripAlpha(filter) +
+ 'alpha(opacity=' + (value * 100) + ')';
+ return element;
+ };
+
+ Element._attributeTranslations = {
+ read: {
+ names: {
+ 'class': 'className',
+ 'for': 'htmlFor'
+ },
+ values: {
+ _getAttr: function(element, attribute) {
+ return element.getAttribute(attribute, 2);
+ },
+ _getAttrNode: function(element, attribute) {
+ var node = element.getAttributeNode(attribute);
+ return node ? node.value : "";
+ },
+ _getEv: function(element, attribute) {
+ attribute = element.getAttribute(attribute);
+ return attribute ? attribute.toString().slice(23, -2) : null;
+ },
+ _flag: function(element, attribute) {
+ return $(element).hasAttribute(attribute) ? attribute : null;
+ },
+ style: function(element) {
+ return element.style.cssText.toLowerCase();
+ },
+ title: function(element) {
+ return element.title;
+ }
+ }
+ }
+ };
+
+ Element._attributeTranslations.write = {
+ names: Object.extend({
+ cellpadding: 'cellPadding',
+ cellspacing: 'cellSpacing'
+ }, Element._attributeTranslations.read.names),
+ values: {
+ checked: function(element, value) {
+ element.checked = !!value;
+ },
+
+ style: function(element, value) {
+ element.style.cssText = value ? value : '';
+ }
+ }
+ };
+
+ Element._attributeTranslations.has = {};
+
+ $w('colSpan rowSpan vAlign dateTime accessKey tabIndex ' +
+ 'encType maxLength readOnly longDesc frameBorder').each(function(attr) {
+ Element._attributeTranslations.write.names[attr.toLowerCase()] = attr;
+ Element._attributeTranslations.has[attr.toLowerCase()] = attr;
+ });
+
+ (function(v) {
+ Object.extend(v, {
+ href: v._getAttr,
+ src: v._getAttr,
+ type: v._getAttr,
+ action: v._getAttrNode,
+ disabled: v._flag,
+ checked: v._flag,
+ readonly: v._flag,
+ multiple: v._flag,
+ onload: v._getEv,
+ onunload: v._getEv,
+ onclick: v._getEv,
+ ondblclick: v._getEv,
+ onmousedown: v._getEv,
+ onmouseup: v._getEv,
+ onmouseover: v._getEv,
+ onmousemove: v._getEv,
+ onmouseout: v._getEv,
+ onfocus: v._getEv,
+ onblur: v._getEv,
+ onkeypress: v._getEv,
+ onkeydown: v._getEv,
+ onkeyup: v._getEv,
+ onsubmit: v._getEv,
+ onreset: v._getEv,
+ onselect: v._getEv,
+ onchange: v._getEv
+ });
+ })(Element._attributeTranslations.read.values);
+}
+
+else if (Prototype.Browser.Gecko && /rv:1\.8\.0/.test(navigator.userAgent)) {
+ Element.Methods.setOpacity = function(element, value) {
+ element = $(element);
+ element.style.opacity = (value == 1) ? 0.999999 :
+ (value === '') ? '' : (value < 0.00001) ? 0 : value;
+ return element;
+ };
+}
+
+else if (Prototype.Browser.WebKit) {
+ Element.Methods.setOpacity = function(element, value) {
+ element = $(element);
+ element.style.opacity = (value == 1 || value === '') ? '' :
+ (value < 0.00001) ? 0 : value;
+
+ if (value == 1)
+ if(element.tagName.toUpperCase() == 'IMG' && element.width) {
+ element.width++; element.width--;
+ } else try {
+ var n = document.createTextNode(' ');
+ element.appendChild(n);
+ element.removeChild(n);
+ } catch (e) { }
+
+ return element;
+ };
+
+ // Safari returns margins on body which is incorrect if the child is absolutely
+ // positioned. For performance reasons, redefine Element#cumulativeOffset for
+ // KHTML/WebKit only.
+ Element.Methods.cumulativeOffset = function(element) {
+ var valueT = 0, valueL = 0;
+ do {
+ valueT += element.offsetTop || 0;
+ valueL += element.offsetLeft || 0;
+ if (element.offsetParent == document.body)
+ if (Element.getStyle(element, 'position') == 'absolute') break;
+
+ element = element.offsetParent;
+ } while (element);
+
+ return Element._returnOffset(valueL, valueT);
+ };
+}
+
+if (Prototype.Browser.IE || Prototype.Browser.Opera) {
+ // IE and Opera are missing .innerHTML support for TABLE-related and SELECT elements
+ Element.Methods.update = function(element, content) {
+ element = $(element);
+
+ if (content && content.toElement) content = content.toElement();
+ if (Object.isElement(content)) return element.update().insert(content);
+
+ content = Object.toHTML(content);
+ var tagName = element.tagName.toUpperCase();
+
+ if (tagName in Element._insertionTranslations.tags) {
+ $A(element.childNodes).each(function(node) { element.removeChild(node) });
+ Element._getContentFromAnonymousElement(tagName, content.stripScripts())
+ .each(function(node) { element.appendChild(node) });
+ }
+ else element.innerHTML = content.stripScripts();
+
+ content.evalScripts.bind(content).defer();
+ return element;
+ };
+}
+
+if ('outerHTML' in document.createElement('div')) {
+ Element.Methods.replace = function(element, content) {
+ element = $(element);
+
+ if (content && content.toElement) content = content.toElement();
+ if (Object.isElement(content)) {
+ element.parentNode.replaceChild(content, element);
+ return element;
+ }
+
+ content = Object.toHTML(content);
+ var parent = element.parentNode, tagName = parent.tagName.toUpperCase();
+
+ if (Element._insertionTranslations.tags[tagName]) {
+ var nextSibling = element.next();
+ var fragments = Element._getContentFromAnonymousElement(tagName, content.stripScripts());
+ parent.removeChild(element);
+ if (nextSibling)
+ fragments.each(function(node) { parent.insertBefore(node, nextSibling) });
+ else
+ fragments.each(function(node) { parent.appendChild(node) });
+ }
+ else element.outerHTML = content.stripScripts();
+
+ content.evalScripts.bind(content).defer();
+ return element;
+ };
+}
+
+Element._returnOffset = function(l, t) {
+ var result = [l, t];
+ result.left = l;
+ result.top = t;
+ return result;
+};
+
+Element._getContentFromAnonymousElement = function(tagName, html) {
+ var div = new Element('div'), t = Element._insertionTranslations.tags[tagName];
+ if (t) {
+ div.innerHTML = t[0] + html + t[1];
+ t[2].times(function() { div = div.firstChild });
+ } else div.innerHTML = html;
+ return $A(div.childNodes);
+};
+
+Element._insertionTranslations = {
+ before: function(element, node) {
+ element.parentNode.insertBefore(node, element);
+ },
+ top: function(element, node) {
+ element.insertBefore(node, element.firstChild);
+ },
+ bottom: function(element, node) {
+ element.appendChild(node);
+ },
+ after: function(element, node) {
+ element.parentNode.insertBefore(node, element.nextSibling);
+ },
+ tags: {
+ TABLE: ['<table>', '</table>', 1],
+ TBODY: ['<table><tbody>', '</tbody></table>', 2],
+ TR: ['<table><tbody><tr>', '</tr></tbody></table>', 3],
+ TD: ['<table><tbody><tr><td>', '</td></tr></tbody></table>', 4],
+ SELECT: ['<select>', '</select>', 1]
+ }
+};
+
+(function() {
+ Object.extend(this.tags, {
+ THEAD: this.tags.TBODY,
+ TFOOT: this.tags.TBODY,
+ TH: this.tags.TD
+ });
+}).call(Element._insertionTranslations);
+
+Element.Methods.Simulated = {
+ hasAttribute: function(element, attribute) {
+ attribute = Element._attributeTranslations.has[attribute] || attribute;
+ var node = $(element).getAttributeNode(attribute);
+ return !!(node && node.specified);
+ }
+};
+
+Element.Methods.ByTag = { };
+
+Object.extend(Element, Element.Methods);
+
+if (!Prototype.BrowserFeatures.ElementExtensions &&
+ document.createElement('div')['__proto__']) {
+ window.HTMLElement = { };
+ window.HTMLElement.prototype = document.createElement('div')['__proto__'];
+ Prototype.BrowserFeatures.ElementExtensions = true;
+}
+
+Element.extend = (function() {
+ if (Prototype.BrowserFeatures.SpecificElementExtensions)
+ return Prototype.K;
+
+ var Methods = { }, ByTag = Element.Methods.ByTag;
+
+ var extend = Object.extend(function(element) {
+ if (!element || element._extendedByPrototype ||
+ element.nodeType != 1 || element == window) return element;
+
+ var methods = Object.clone(Methods),
+ tagName = element.tagName.toUpperCase(), property, value;
+
+ // extend methods for specific tags
+ if (ByTag[tagName]) Object.extend(methods, ByTag[tagName]);
+
+ for (property in methods) {
+ value = methods[property];
+ if (Object.isFunction(value) && !(property in element))
+ element[property] = value.methodize();
+ }
+
+ element._extendedByPrototype = Prototype.emptyFunction;
+ return element;
+
+ }, {
+ refresh: function() {
+ // extend methods for all tags (Safari doesn't need this)
+ if (!Prototype.BrowserFeatures.ElementExtensions) {
+ Object.extend(Methods, Element.Methods);
+ Object.extend(Methods, Element.Methods.Simulated);
+ }
+ }
+ });
+
+ extend.refresh();
+ return extend;
+})();
+
+Element.hasAttribute = function(element, attribute) {
+ if (element.hasAttribute) return element.hasAttribute(attribute);
+ return Element.Methods.Simulated.hasAttribute(element, attribute);
+};
+
+Element.addMethods = function(methods) {
+ var F = Prototype.BrowserFeatures, T = Element.Methods.ByTag;
+
+ if (!methods) {
+ Object.extend(Form, Form.Methods);
+ Object.extend(Form.Element, Form.Element.Methods);
+ Object.extend(Element.Methods.ByTag, {
+ "FORM": Object.clone(Form.Methods),
+ "INPUT": Object.clone(Form.Element.Methods),
+ "SELECT": Object.clone(Form.Element.Methods),
+ "TEXTAREA": Object.clone(Form.Element.Methods)
+ });
+ }
+
+ if (arguments.length == 2) {
+ var tagName = methods;
+ methods = arguments[1];
+ }
+
+ if (!tagName) Object.extend(Element.Methods, methods || { });
+ else {
+ if (Object.isArray(tagName)) tagName.each(extend);
+ else extend(tagName);
+ }
+
+ function extend(tagName) {
+ tagName = tagName.toUpperCase();
+ if (!Element.Methods.ByTag[tagName])
+ Element.Methods.ByTag[tagName] = { };
+ Object.extend(Element.Methods.ByTag[tagName], methods);
+ }
+
+ function copy(methods, destination, onlyIfAbsent) {
+ onlyIfAbsent = onlyIfAbsent || false;
+ for (var property in methods) {
+ var value = methods[property];
+ if (!Object.isFunction(value)) continue;
+ if (!onlyIfAbsent || !(property in destination))
+ destination[property] = value.methodize();
+ }
+ }
+
+ function findDOMClass(tagName) {
+ var klass;
+ var trans = {
+ "OPTGROUP": "OptGroup", "TEXTAREA": "TextArea", "P": "Paragraph",
+ "FIELDSET": "FieldSet", "UL": "UList", "OL": "OList", "DL": "DList",
+ "DIR": "Directory", "H1": "Heading", "H2": "Heading", "H3": "Heading",
+ "H4": "Heading", "H5": "Heading", "H6": "Heading", "Q": "Quote",
+ "INS": "Mod", "DEL": "Mod", "A": "Anchor", "IMG": "Image", "CAPTION":
+ "TableCaption", "COL": "TableCol", "COLGROUP": "TableCol", "THEAD":
+ "TableSection", "TFOOT": "TableSection", "TBODY": "TableSection", "TR":
+ "TableRow", "TH": "TableCell", "TD": "TableCell", "FRAMESET":
+ "FrameSet", "IFRAME": "IFrame"
+ };
+ if (trans[tagName]) klass = 'HTML' + trans[tagName] + 'Element';
+ if (window[klass]) return window[klass];
+ klass = 'HTML' + tagName + 'Element';
+ if (window[klass]) return window[klass];
+ klass = 'HTML' + tagName.capitalize() + 'Element';
+ if (window[klass]) return window[klass];
+
+ window[klass] = { };
+ window[klass].prototype = document.createElement(tagName)['__proto__'];
+ return window[klass];
+ }
+
+ if (F.ElementExtensions) {
+ copy(Element.Methods, HTMLElement.prototype);
+ copy(Element.Methods.Simulated, HTMLElement.prototype, true);
+ }
+
+ if (F.SpecificElementExtensions) {
+ for (var tag in Element.Methods.ByTag) {
+ var klass = findDOMClass(tag);
+ if (Object.isUndefined(klass)) continue;
+ copy(T[tag], klass.prototype);
+ }
+ }
+
+ Object.extend(Element, Element.Methods);
+ delete Element.ByTag;
+
+ if (Element.extend.refresh) Element.extend.refresh();
+ Element.cache = { };
+};
+
+document.viewport = {
+ getDimensions: function() {
+ var dimensions = { }, B = Prototype.Browser;
+ $w('width height').each(function(d) {
+ var D = d.capitalize();
+ if (B.WebKit && !document.evaluate) {
+ // Safari <3.0 needs self.innerWidth/Height
+ dimensions[d] = self['inner' + D];
+ } else if (B.Opera && parseFloat(window.opera.version()) < 9.5) {
+ // Opera <9.5 needs document.body.clientWidth/Height
+ dimensions[d] = document.body['client' + D]
+ } else {
+ dimensions[d] = document.documentElement['client' + D];
+ }
+ });
+ return dimensions;
+ },
+
+ getWidth: function() {
+ return this.getDimensions().width;
+ },
+
+ getHeight: function() {
+ return this.getDimensions().height;
+ },
+
+ getScrollOffsets: function() {
+ return Element._returnOffset(
+ window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft,
+ window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop);
+ }
+};
+/* Portions of the Selector class are derived from Jack Slocum's DomQuery,
+ * part of YUI-Ext version 0.40, distributed under the terms of an MIT-style
+ * license. Please see http://www.yui-ext.com/ for more information. */
+
+var Selector = Class.create({
+ initialize: function(expression) {
+ this.expression = expression.strip();
+
+ if (this.shouldUseSelectorsAPI()) {
+ this.mode = 'selectorsAPI';
+ } else if (this.shouldUseXPath()) {
+ this.mode = 'xpath';
+ this.compileXPathMatcher();
+ } else {
+ this.mode = "normal";
+ this.compileMatcher();
+ }
+
+ },
+
+ shouldUseXPath: function() {
+ if (!Prototype.BrowserFeatures.XPath) return false;
+
+ var e = this.expression;
+
+ // Safari 3 chokes on :*-of-type and :empty
+ if (Prototype.Browser.WebKit &&
+ (e.include("-of-type") || e.include(":empty")))
+ return false;
+
+ // XPath can't do namespaced attributes, nor can it read
+ // the "checked" property from DOM nodes
+ if ((/(\[[\w-]*?:|:checked)/).test(e))
+ return false;
+
+ return true;
+ },
+
+ shouldUseSelectorsAPI: function() {
+ if (!Prototype.BrowserFeatures.SelectorsAPI) return false;
+
+ if (!Selector._div) Selector._div = new Element('div');
+
+ // Make sure the browser treats the selector as valid. Test on an
+ // isolated element to minimize cost of this check.
+ try {
+ Selector._div.querySelector(this.expression);
+ } catch(e) {
+ return false;
+ }
+
+ return true;
+ },
+
+ compileMatcher: function() {
+ var e = this.expression, ps = Selector.patterns, h = Selector.handlers,
+ c = Selector.criteria, le, p, m;
+
+ if (Selector._cache[e]) {
+ this.matcher = Selector._cache[e];
+ return;
+ }
+
+ this.matcher = ["this.matcher = function(root) {",
+ "var r = root, h = Selector.handlers, c = false, n;"];
+
+ while (e && le != e && (/\S/).test(e)) {
+ le = e;
+ for (var i in ps) {
+ p = ps[i];
+ if (m = e.match(p)) {
+ this.matcher.push(Object.isFunction(c[i]) ? c[i](m) :
+ new Template(c[i]).evaluate(m));
+ e = e.replace(m[0], '');
+ break;
+ }
+ }
+ }
+
+ this.matcher.push("return h.unique(n);\n}");
+ eval(this.matcher.join('\n'));
+ Selector._cache[this.expression] = this.matcher;
+ },
+
+ compileXPathMatcher: function() {
+ var e = this.expression, ps = Selector.patterns,
+ x = Selector.xpath, le, m;
+
+ if (Selector._cache[e]) {
+ this.xpath = Selector._cache[e]; return;
+ }
+
+ this.matcher = ['.//*'];
+ while (e && le != e && (/\S/).test(e)) {
+ le = e;
+ for (var i in ps) {
+ if (m = e.match(ps[i])) {
+ this.matcher.push(Object.isFunction(x[i]) ? x[i](m) :
+ new Template(x[i]).evaluate(m));
+ e = e.replace(m[0], '');
+ break;
+ }
+ }
+ }
+
+ this.xpath = this.matcher.join('');
+ Selector._cache[this.expression] = this.xpath;
+ },
+
+ findElements: function(root) {
+ root = root || document;
+ var e = this.expression, results;
+
+ switch (this.mode) {
+ case 'selectorsAPI':
+ // querySelectorAll queries document-wide, then filters to descendants
+ // of the context element. That's not what we want.
+ // Add an explicit context to the selector if necessary.
+ if (root !== document) {
+ var oldId = root.id, id = $(root).identify();
+ e = "#" + id + " " + e;
+ }
+
+ results = $A(root.querySelectorAll(e)).map(Element.extend);
+ root.id = oldId;
+
+ return results;
+ case 'xpath':
+ return document._getElementsByXPath(this.xpath, root);
+ default:
+ return this.matcher(root);
+ }
+ },
+
+ match: function(element) {
+ this.tokens = [];
+
+ var e = this.expression, ps = Selector.patterns, as = Selector.assertions;
+ var le, p, m;
+
+ while (e && le !== e && (/\S/).test(e)) {
+ le = e;
+ for (var i in ps) {
+ p = ps[i];
+ if (m = e.match(p)) {
+ // use the Selector.assertions methods unless the selector
+ // is too complex.
+ if (as[i]) {
+ this.tokens.push([i, Object.clone(m)]);
+ e = e.replace(m[0], '');
+ } else {
+ // reluctantly do a document-wide search
+ // and look for a match in the array
+ return this.findElements(document).include(element);
+ }
+ }
+ }
+ }
+
+ var match = true, name, matches;
+ for (var i = 0, token; token = this.tokens[i]; i++) {
+ name = token[0], matches = token[1];
+ if (!Selector.assertions[name](element, matches)) {
+ match = false; break;
+ }
+ }
+
+ return match;
+ },
+
+ toString: function() {
+ return this.expression;
+ },
+
+ inspect: function() {
+ return "#<Selector:" + this.expression.inspect() + ">";
+ }
+});
+
+Object.extend(Selector, {
+ _cache: { },
+
+ xpath: {
+ descendant: "//*",
+ child: "/*",
+ adjacent: "/following-sibling::*[1]",
+ laterSibling: '/following-sibling::*',
+ tagName: function(m) {
+ if (m[1] == '*') return '';
+ return "[local-name()='" + m[1].toLowerCase() +
+ "' or local-name()='" + m[1].toUpperCase() + "']";
+ },
+ className: "[contains(concat(' ', @class, ' '), ' #{1} ')]",
+ id: "[@id='#{1}']",
+ attrPresence: function(m) {
+ m[1] = m[1].toLowerCase();
+ return new Template("[@#{1}]").evaluate(m);
+ },
+ attr: function(m) {
+ m[1] = m[1].toLowerCase();
+ m[3] = m[5] || m[6];
+ return new Template(Selector.xpath.operators[m[2]]).evaluate(m);
+ },
+ pseudo: function(m) {
+ var h = Selector.xpath.pseudos[m[1]];
+ if (!h) return '';
+ if (Object.isFunction(h)) return h(m);
+ return new Template(Selector.xpath.pseudos[m[1]]).evaluate(m);
+ },
+ operators: {
+ '=': "[@#{1}='#{3}']",
+ '!=': "[@#{1}!='#{3}']",
+ '^=': "[starts-with(@#{1}, '#{3}')]",
+ '$=': "[substring(@#{1}, (string-length(@#{1}) - string-length('#{3}') + 1))='#{3}']",
+ '*=': "[contains(@#{1}, '#{3}')]",
+ '~=': "[contains(concat(' ', @#{1}, ' '), ' #{3} ')]",
+ '|=': "[contains(concat('-', @#{1}, '-'), '-#{3}-')]"
+ },
+ pseudos: {
+ 'first-child': '[not(preceding-sibling::*)]',
+ 'last-child': '[not(following-sibling::*)]',
+ 'only-child': '[not(preceding-sibling::* or following-sibling::*)]',
+ 'empty': "[count(*) = 0 and (count(text()) = 0)]",
+ 'checked': "[@checked]",
+ 'disabled': "[(@disabled) and (@type!='hidden')]",
+ 'enabled': "[not(@disabled) and (@type!='hidden')]",
+ 'not': function(m) {
+ var e = m[6], p = Selector.patterns,
+ x = Selector.xpath, le, v;
+
+ var exclusion = [];
+ while (e && le != e && (/\S/).test(e)) {
+ le = e;
+ for (var i in p) {
+ if (m = e.match(p[i])) {
+ v = Object.isFunction(x[i]) ? x[i](m) : new Template(x[i]).evaluate(m);
+ exclusion.push("(" + v.substring(1, v.length - 1) + ")");
+ e = e.replace(m[0], '');
+ break;
+ }
+ }
+ }
+ return "[not(" + exclusion.join(" and ") + ")]";
+ },
+ 'nth-child': function(m) {
+ return Selector.xpath.pseudos.nth("(count(./preceding-sibling::*) + 1) ", m);
+ },
+ 'nth-last-child': function(m) {
+ return Selector.xpath.pseudos.nth("(count(./following-sibling::*) + 1) ", m);
+ },
+ 'nth-of-type': function(m) {
+ return Selector.xpath.pseudos.nth("position() ", m);
+ },
+ 'nth-last-of-type': function(m) {
+ return Selector.xpath.pseudos.nth("(last() + 1 - position()) ", m);
+ },
+ 'first-of-type': function(m) {
+ m[6] = "1"; return Selector.xpath.pseudos['nth-of-type'](m);
+ },
+ 'last-of-type': function(m) {
+ m[6] = "1"; return Selector.xpath.pseudos['nth-last-of-type'](m);
+ },
+ 'only-of-type': function(m) {
+ var p = Selector.xpath.pseudos; return p['first-of-type'](m) + p['last-of-type'](m);
+ },
+ nth: function(fragment, m) {
+ var mm, formula = m[6], predicate;
+ if (formula == 'even') formula = '2n+0';
+ if (formula == 'odd') formula = '2n+1';
+ if (mm = formula.match(/^(\d+)$/)) // digit only
+ return '[' + fragment + "= " + mm[1] + ']';
+ if (mm = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { // an+b
+ if (mm[1] == "-") mm[1] = -1;
+ var a = mm[1] ? Number(mm[1]) : 1;
+ var b = mm[2] ? Number(mm[2]) : 0;
+ predicate = "[((#{fragment} - #{b}) mod #{a} = 0) and " +
+ "((#{fragment} - #{b}) div #{a} >= 0)]";
+ return new Template(predicate).evaluate({
+ fragment: fragment, a: a, b: b });
+ }
+ }
+ }
+ },
+
+ criteria: {
+ tagName: 'n = h.tagName(n, r, "#{1}", c); c = false;',
+ className: 'n = h.className(n, r, "#{1}", c); c = false;',
+ id: 'n = h.id(n, r, "#{1}", c); c = false;',
+ attrPresence: 'n = h.attrPresence(n, r, "#{1}", c); c = false;',
+ attr: function(m) {
+ m[3] = (m[5] || m[6]);
+ return new Template('n = h.attr(n, r, "#{1}", "#{3}", "#{2}", c); c = false;').evaluate(m);
+ },
+ pseudo: function(m) {
+ if (m[6]) m[6] = m[6].replace(/"/g, '\\"');
+ return new Template('n = h.pseudo(n, "#{1}", "#{6}", r, c); c = false;').evaluate(m);
+ },
+ descendant: 'c = "descendant";',
+ child: 'c = "child";',
+ adjacent: 'c = "adjacent";',
+ laterSibling: 'c = "laterSibling";'
+ },
+
+ patterns: {
+ // combinators must be listed first
+ // (and descendant needs to be last combinator)
+ laterSibling: /^\s*~\s*/,
+ child: /^\s*>\s*/,
+ adjacent: /^\s*\+\s*/,
+ descendant: /^\s/,
+
+ // selectors follow
+ tagName: /^\s*(\*|[\w\-]+)(\b|$)?/,
+ id: /^#([\w\-\*]+)(\b|$)/,
+ className: /^\.([\w\-\*]+)(\b|$)/,
+ pseudo:
+/^:((first|last|nth|nth-last|only)(-child|-of-type)|empty|checked|(en|dis)abled|not)(\((.*?)\))?(\b|$|(?=\s|[:+~>]))/,
+ attrPresence: /^\[((?:[\w]+:)?[\w]+)\]/,
+ attr: /\[((?:[\w-]*:)?[\w-]+)\s*(?:([!^$*~|]?=)\s*((['"])([^\4]*?)\4|([^'"][^\]]*?)))?\]/
+ },
+
+ // for Selector.match and Element#match
+ assertions: {
+ tagName: function(element, matches) {
+ return matches[1].toUpperCase() == element.tagName.toUpperCase();
+ },
+
+ className: function(element, matches) {
+ return Element.hasClassName(element, matches[1]);
+ },
+
+ id: function(element, matches) {
+ return element.id === matches[1];
+ },
+
+ attrPresence: function(element, matches) {
+ return Element.hasAttribute(element, matches[1]);
+ },
+
+ attr: function(element, matches) {
+ var nodeValue = Element.readAttribute(element, matches[1]);
+ return nodeValue && Selector.operators[matches[2]](nodeValue, matches[5] || matches[6]);
+ }
+ },
+
+ handlers: {
+ // UTILITY FUNCTIONS
+ // joins two collections
+ concat: function(a, b) {
+ for (var i = 0, node; node = b[i]; i++)
+ a.push(node);
+ return a;
+ },
+
+ // marks an array of nodes for counting
+ mark: function(nodes) {
+ var _true = Prototype.emptyFunction;
+ for (var i = 0, node; node = nodes[i]; i++)
+ node._countedByPrototype = _true;
+ return nodes;
+ },
+
+ unmark: function(nodes) {
+ for (var i = 0, node; node = nodes[i]; i++)
+ node._countedByPrototype = undefined;
+ return nodes;
+ },
+
+ // mark each child node with its position (for nth calls)
+ // "ofType" flag indicates whether we're indexing for nth-of-type
+ // rather than nth-child
+ index: function(parentNode, reverse, ofType) {
+ parentNode._countedByPrototype = Prototype.emptyFunction;
+ if (reverse) {
+ for (var nodes = parentNode.childNodes, i = nodes.length - 1, j = 1; i >= 0; i--) {
+ var node = nodes[i];
+ if (node.nodeType == 1 && (!ofType || node._countedByPrototype)) node.nodeIndex = j++;
+ }
+ } else {
+ for (var i = 0, j = 1, nodes = parentNode.childNodes; node = nodes[i]; i++)
+ if (node.nodeType == 1 && (!ofType || node._countedByPrototype)) node.nodeIndex = j++;
+ }
+ },
+
+ // filters out duplicates and extends all nodes
+ unique: function(nodes) {
+ if (nodes.length == 0) return nodes;
+ var results = [], n;
+ for (var i = 0, l = nodes.length; i < l; i++)
+ if (!(n = nodes[i])._countedByPrototype) {
+ n._countedByPrototype = Prototype.emptyFunction;
+ results.push(Element.extend(n));
+ }
+ return Selector.handlers.unmark(results);
+ },
+
+ // COMBINATOR FUNCTIONS
+ descendant: function(nodes) {
+ var h = Selector.handlers;
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
+ h.concat(results, node.getElementsByTagName('*'));
+ return results;
+ },
+
+ child: function(nodes) {
+ var h = Selector.handlers;
+ for (var i = 0, results = [], node; node = nodes[i]; i++) {
+ for (var j = 0, child; child = node.childNodes[j]; j++)
+ if (child.nodeType == 1 && child.tagName != '!') results.push(child);
+ }
+ return results;
+ },
+
+ adjacent: function(nodes) {
+ for (var i = 0, results = [], node; node = nodes[i]; i++) {
+ var next = this.nextElementSibling(node);
+ if (next) results.push(next);
+ }
+ return results;
+ },
+
+ laterSibling: function(nodes) {
+ var h = Selector.handlers;
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
+ h.concat(results, Element.nextSiblings(node));
+ return results;
+ },
+
+ nextElementSibling: function(node) {
+ while (node = node.nextSibling)
+ if (node.nodeType == 1) return node;
+ return null;
+ },
+
+ previousElementSibling: function(node) {
+ while (node = node.previousSibling)
+ if (node.nodeType == 1) return node;
+ return null;
+ },
+
+ // TOKEN FUNCTIONS
+ tagName: function(nodes, root, tagName, combinator) {
+ var uTagName = tagName.toUpperCase();
+ var results = [], h = Selector.handlers;
+ if (nodes) {
+ if (combinator) {
+ // fastlane for ordinary descendant combinators
+ if (combinator == "descendant") {
+ for (var i = 0, node; node = nodes[i]; i++)
+ h.concat(results, node.getElementsByTagName(tagName));
+ return results;
+ } else nodes = this[combinator](nodes);
+ if (tagName == "*") return nodes;
+ }
+ for (var i = 0, node; node = nodes[i]; i++)
+ if (node.tagName.toUpperCase() === uTagName) results.push(node);
+ return results;
+ } else return root.getElementsByTagName(tagName);
+ },
+
+ id: function(nodes, root, id, combinator) {
+ var targetNode = $(id), h = Selector.handlers;
+ if (!targetNode) return [];
+ if (!nodes && root == document) return [targetNode];
+ if (nodes) {
+ if (combinator) {
+ if (combinator == 'child') {
+ for (var i = 0, node; node = nodes[i]; i++)
+ if (targetNode.parentNode == node) return [targetNode];
+ } else if (combinator == 'descendant') {
+ for (var i = 0, node; node = nodes[i]; i++)
+ if (Element.descendantOf(targetNode, node)) return [targetNode];
+ } else if (combinator == 'adjacent') {
+ for (var i = 0, node; node = nodes[i]; i++)
+ if (Selector.handlers.previousElementSibling(targetNode) == node)
+ return [targetNode];
+ } else nodes = h[combinator](nodes);
+ }
+ for (var i = 0, node; node = nodes[i]; i++)
+ if (node == targetNode) return [targetNode];
+ return [];
+ }
+ return (targetNode && Element.descendantOf(targetNode, root)) ? [targetNode] : [];
+ },
+
+ className: function(nodes, root, className, combinator) {
+ if (nodes && combinator) nodes = this[combinator](nodes);
+ return Selector.handlers.byClassName(nodes, root, className);
+ },
+
+ byClassName: function(nodes, root, className) {
+ if (!nodes) nodes = Selector.handlers.descendant([root]);
+ var needle = ' ' + className + ' ';
+ for (var i = 0, results = [], node, nodeClassName; node = nodes[i]; i++) {
+ nodeClassName = node.className;
+ if (nodeClassName.length == 0) continue;
+ if (nodeClassName == className || (' ' + nodeClassName + ' ').include(needle))
+ results.push(node);
+ }
+ return results;
+ },
+
+ attrPresence: function(nodes, root, attr, combinator) {
+ if (!nodes) nodes = root.getElementsByTagName("*");
+ if (nodes && combinator) nodes = this[combinator](nodes);
+ var results = [];
+ for (var i = 0, node; node = nodes[i]; i++)
+ if (Element.hasAttribute(node, attr)) results.push(node);
+ return results;
+ },
+
+ attr: function(nodes, root, attr, value, operator, combinator) {
+ if (!nodes) nodes = root.getElementsByTagName("*");
+ if (nodes && combinator) nodes = this[combinator](nodes);
+ var handler = Selector.operators[operator], results = [];
+ for (var i = 0, node; node = nodes[i]; i++) {
+ var nodeValue = Element.readAttribute(node, attr);
+ if (nodeValue === null) continue;
+ if (handler(nodeValue, value)) results.push(node);
+ }
+ return results;
+ },
+
+ pseudo: function(nodes, name, value, root, combinator) {
+ if (nodes && combinator) nodes = this[combinator](nodes);
+ if (!nodes) nodes = root.getElementsByTagName("*");
+ return Selector.pseudos[name](nodes, value, root);
+ }
+ },
+
+ pseudos: {
+ 'first-child': function(nodes, value, root) {
+ for (var i = 0, results = [], node; node = nodes[i]; i++) {
+ if (Selector.handlers.previousElementSibling(node)) continue;
+ results.push(node);
+ }
+ return results;
+ },
+ 'last-child': function(nodes, value, root) {
+ for (var i = 0, results = [], node; node = nodes[i]; i++) {
+ if (Selector.handlers.nextElementSibling(node)) continue;
+ results.push(node);
+ }
+ return results;
+ },
+ 'only-child': function(nodes, value, root) {
+ var h = Selector.handlers;
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
+ if (!h.previousElementSibling(node) && !h.nextElementSibling(node))
+ results.push(node);
+ return results;
+ },
+ 'nth-child': function(nodes, formula, root) {
+ return Selector.pseudos.nth(nodes, formula, root);
+ },
+ 'nth-last-child': function(nodes, formula, root) {
+ return Selector.pseudos.nth(nodes, formula, root, true);
+ },
+ 'nth-of-type': function(nodes, formula, root) {
+ return Selector.pseudos.nth(nodes, formula, root, false, true);
+ },
+ 'nth-last-of-type': function(nodes, formula, root) {
+ return Selector.pseudos.nth(nodes, formula, root, true, true);
+ },
+ 'first-of-type': function(nodes, formula, root) {
+ return Selector.pseudos.nth(nodes, "1", root, false, true);
+ },
+ 'last-of-type': function(nodes, formula, root) {
+ return Selector.pseudos.nth(nodes, "1", root, true, true);
+ },
+ 'only-of-type': function(nodes, formula, root) {
+ var p = Selector.pseudos;
+ return p['last-of-type'](p['first-of-type'](nodes, formula, root), formula, root);
+ },
+
+ // handles the an+b logic
+ getIndices: function(a, b, total) {
+ if (a == 0) return b > 0 ? [b] : [];
+ return $R(1, total).inject([], function(memo, i) {
+ if (0 == (i - b) % a && (i - b) / a >= 0) memo.push(i);
+ return memo;
+ });
+ },
+
+ // handles nth(-last)-child, nth(-last)-of-type, and (first|last)-of-type
+ nth: function(nodes, formula, root, reverse, ofType) {
+ if (nodes.length == 0) return [];
+ if (formula == 'even') formula = '2n+0';
+ if (formula == 'odd') formula = '2n+1';
+ var h = Selector.handlers, results = [], indexed = [], m;
+ h.mark(nodes);
+ for (var i = 0, node; node = nodes[i]; i++) {
+ if (!node.parentNode._countedByPrototype) {
+ h.index(node.parentNode, reverse, ofType);
+ indexed.push(node.parentNode);
+ }
+ }
+ if (formula.match(/^\d+$/)) { // just a number
+ formula = Number(formula);
+ for (var i = 0, node; node = nodes[i]; i++)
+ if (node.nodeIndex == formula) results.push(node);
+ } else if (m = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { // an+b
+ if (m[1] == "-") m[1] = -1;
+ var a = m[1] ? Number(m[1]) : 1;
+ var b = m[2] ? Number(m[2]) : 0;
+ var indices = Selector.pseudos.getIndices(a, b, nodes.length);
+ for (var i = 0, node, l = indices.length; node = nodes[i]; i++) {
+ for (var j = 0; j < l; j++)
+ if (node.nodeIndex == indices[j]) results.push(node);
+ }
+ }
+ h.unmark(nodes);
+ h.unmark(indexed);
+ return results;
+ },
+
+ 'empty': function(nodes, value, root) {
+ for (var i = 0, results = [], node; node = nodes[i]; i++) {
+ // IE treats comments as element nodes
+ if (node.tagName == '!' || node.firstChild) continue;
+ results.push(node);
+ }
+ return results;
+ },
+
+ 'not': function(nodes, selector, root) {
+ var h = Selector.handlers, selectorType, m;
+ var exclusions = new Selector(selector).findElements(root);
+ h.mark(exclusions);
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
+ if (!node._countedByPrototype) results.push(node);
+ h.unmark(exclusions);
+ return results;
+ },
+
+ 'enabled': function(nodes, value, root) {
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
+ if (!node.disabled && (!node.type || node.type !== 'hidden'))
+ results.push(node);
+ return results;
+ },
+
+ 'disabled': function(nodes, value, root) {
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
+ if (node.disabled) results.push(node);
+ return results;
+ },
+
+ 'checked': function(nodes, value, root) {
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
+ if (node.checked) results.push(node);
+ return results;
+ }
+ },
+
+ operators: {
+ '=': function(nv, v) { return nv == v; },
+ '!=': function(nv, v) { return nv != v; },
+ '^=': function(nv, v) { return nv == v || nv && nv.startsWith(v); },
+ '$=': function(nv, v) { return nv == v || nv && nv.endsWith(v); },
+ '*=': function(nv, v) { return nv == v || nv && nv.include(v); },
+ '$=': function(nv, v) { return nv.endsWith(v); },
+ '*=': function(nv, v) { return nv.include(v); },
+ '~=': function(nv, v) { return (' ' + nv + ' ').include(' ' + v + ' '); },
+ '|=': function(nv, v) { return ('-' + (nv || "").toUpperCase() +
+ '-').include('-' + (v || "").toUpperCase() + '-'); }
+ },
+
+ split: function(expression) {
+ var expressions = [];
+ expression.scan(/(([\w#:.~>+()\s-]+|\*|\[.*?\])+)\s*(,|$)/, function(m) {
+ expressions.push(m[1].strip());
+ });
+ return expressions;
+ },
+
+ matchElements: function(elements, expression) {
+ var matches = $$(expression), h = Selector.handlers;
+ h.mark(matches);
+ for (var i = 0, results = [], element; element = elements[i]; i++)
+ if (element._countedByPrototype) results.push(element);
+ h.unmark(matches);
+ return results;
+ },
+
+ findElement: function(elements, expression, index) {
+ if (Object.isNumber(expression)) {
+ index = expression; expression = false;
+ }
+ return Selector.matchElements(elements, expression || '*')[index || 0];
+ },
+
+ findChildElements: function(element, expressions) {
+ expressions = Selector.split(expressions.join(','));
+ var results = [], h = Selector.handlers;
+ for (var i = 0, l = expressions.length, selector; i < l; i++) {
+ selector = new Selector(expressions[i].strip());
+ h.concat(results, selector.findElements(element));
+ }
+ return (l > 1) ? h.unique(results) : results;
+ }
+});
+
+if (Prototype.Browser.IE) {
+ Object.extend(Selector.handlers, {
+ // IE returns comment nodes on getElementsByTagName("*").
+ // Filter them out.
+ concat: function(a, b) {
+ for (var i = 0, node; node = b[i]; i++)
+ if (node.tagName !== "!") a.push(node);
+ return a;
+ },
+
+ // IE improperly serializes _countedByPrototype in (inner|outer)HTML.
+ unmark: function(nodes) {
+ for (var i = 0, node; node = nodes[i]; i++)
+ node.removeAttribute('_countedByPrototype');
+ return nodes;
+ }
+ });
+}
+
+function $$() {
+ return Selector.findChildElements(document, $A(arguments));
+}
+var Form = {
+ reset: function(form) {
+ $(form).reset();
+ return form;
+ },
+
+ serializeElements: function(elements, options) {
+ if (typeof options != 'object') options = { hash: !!options };
+ else if (Object.isUndefined(options.hash)) options.hash = true;
+ var key, value, submitted = false, submit = options.submit;
+
+ var data = elements.inject({ }, function(result, element) {
+ if (!element.disabled && element.name) {
+ key = element.name; value = $(element).getValue();
+ if (value != null && element.type != 'file' && (element.type != 'submit' || (!submitted &&
+ submit !== false && (!submit || key == submit) && (submitted = true)))) {
+ if (key in result) {
+ // a key is already present; construct an array of values
+ if (!Object.isArray(result[key])) result[key] = [result[key]];
+ result[key].push(value);
+ }
+ else result[key] = value;
+ }
+ }
+ return result;
+ });
+
+ return options.hash ? data : Object.toQueryString(data);
+ }
+};
+
+Form.Methods = {
+ serialize: function(form, options) {
+ return Form.serializeElements(Form.getElements(form), options);
+ },
+
+ getElements: function(form) {
+ return $A($(form).getElementsByTagName('*')).inject([],
+ function(elements, child) {
+ if (Form.Element.Serializers[child.tagName.toLowerCase()])
+ elements.push(Element.extend(child));
+ return elements;
+ }
+ );
+ },
+
+ getInputs: function(form, typeName, name) {
+ form = $(form);
+ var inputs = form.getElementsByTagName('input');
+
+ if (!typeName && !name) return $A(inputs).map(Element.extend);
+
+ for (var i = 0, matchingInputs = [], length = inputs.length; i < length; i++) {
+ var input = inputs[i];
+ if ((typeName && input.type != typeName) || (name && input.name != name))
+ continue;
+ matchingInputs.push(Element.extend(input));
+ }
+
+ return matchingInputs;
+ },
+
+ disable: function(form) {
+ form = $(form);
+ Form.getElements(form).invoke('disable');
+ return form;
+ },
+
+ enable: function(form) {
+ form = $(form);
+ Form.getElements(form).invoke('enable');
+ return form;
+ },
+
+ findFirstElement: function(form) {
+ var elements = $(form).getElements().findAll(function(element) {
+ return 'hidden' != element.type && !element.disabled;
+ });
+ var firstByIndex = elements.findAll(function(element) {
+ return element.hasAttribute('tabIndex') && element.tabIndex >= 0;
+ }).sortBy(function(element) { return element.tabIndex }).first();
+
+ return firstByIndex ? firstByIndex : elements.find(function(element) {
+ return ['input', 'select', 'textarea'].include(element.tagName.toLowerCase());
+ });
+ },
+
+ focusFirstElement: function(form) {
+ form = $(form);
+ form.findFirstElement().activate();
+ return form;
+ },
+
+ request: function(form, options) {
+ form = $(form), options = Object.clone(options || { });
+
+ var params = options.parameters, action = form.readAttribute('action') || '';
+ if (action.blank()) action = window.location.href;
+ options.parameters = form.serialize(true);
+
+ if (params) {
+ if (Object.isString(params)) params = params.toQueryParams();
+ Object.extend(options.parameters, params);
+ }
+
+ if (form.hasAttribute('method') && !options.method)
+ options.method = form.method;
+
+ return new Ajax.Request(action, options);
+ }
+};
+
+/*--------------------------------------------------------------------------*/
+
+Form.Element = {
+ focus: function(element) {
+ $(element).focus();
+ return element;
+ },
+
+ select: function(element) {
+ $(element).select();
+ return element;
+ }
+};
+
+Form.Element.Methods = {
+ serialize: function(element) {
+ element = $(element);
+ if (!element.disabled && element.name) {
+ var value = element.getValue();
+ if (value != undefined) {
+ var pair = { };
+ pair[element.name] = value;
+ return Object.toQueryString(pair);
+ }
+ }
+ return '';
+ },
+
+ getValue: function(element) {
+ element = $(element);
+ var method = element.tagName.toLowerCase();
+ return Form.Element.Serializers[method](element);
+ },
+
+ setValue: function(element, value) {
+ element = $(element);
+ var method = element.tagName.toLowerCase();
+ Form.Element.Serializers[method](element, value);
+ return element;
+ },
+
+ clear: function(element) {
+ $(element).value = '';
+ return element;
+ },
+
+ present: function(element) {
+ return $(element).value != '';
+ },
+
+ activate: function(element) {
+ element = $(element);
+ try {
+ element.focus();
+ if (element.select && (element.tagName.toLowerCase() != 'input' ||
+ !['button', 'reset', 'submit'].include(element.type)))
+ element.select();
+ } catch (e) { }
+ return element;
+ },
+
+ disable: function(element) {
+ element = $(element);
+ element.disabled = true;
+ return element;
+ },
+
+ enable: function(element) {
+ element = $(element);
+ element.disabled = false;
+ return element;
+ }
+};
+
+/*--------------------------------------------------------------------------*/
+
+var Field = Form.Element;
+var $F = Form.Element.Methods.getValue;
+
+/*--------------------------------------------------------------------------*/
+
+Form.Element.Serializers = {
+ input: function(element, value) {
+ switch (element.type.toLowerCase()) {
+ case 'checkbox':
+ case 'radio':
+ return Form.Element.Serializers.inputSelector(element, value);
+ default:
+ return Form.Element.Serializers.textarea(element, value);
+ }
+ },
+
+ inputSelector: function(element, value) {
+ if (Object.isUndefined(value)) return element.checked ? element.value : null;
+ else element.checked = !!value;
+ },
+
+ textarea: function(element, value) {
+ if (Object.isUndefined(value)) return element.value;
+ else element.value = value;
+ },
+
+ select: function(element, value) {
+ if (Object.isUndefined(value))
+ return this[element.type == 'select-one' ?
+ 'selectOne' : 'selectMany'](element);
+ else {
+ var opt, currentValue, single = !Object.isArray(value);
+ for (var i = 0, length = element.length; i < length; i++) {
+ opt = element.options[i];
+ currentValue = this.optionValue(opt);
+ if (single) {
+ if (currentValue == value) {
+ opt.selected = true;
+ return;
+ }
+ }
+ else opt.selected = value.include(currentValue);
+ }
+ }
+ },
+
+ selectOne: function(element) {
+ var index = element.selectedIndex;
+ return index >= 0 ? this.optionValue(element.options[index]) : null;
+ },
+
+ selectMany: function(element) {
+ var values, length = element.length;
+ if (!length) return null;
+
+ for (var i = 0, values = []; i < length; i++) {
+ var opt = element.options[i];
+ if (opt.selected) values.push(this.optionValue(opt));
+ }
+ return values;
+ },
+
+ optionValue: function(opt) {
+ // extend element because hasAttribute may not be native
+ return Element.extend(opt).hasAttribute('value') ? opt.value : opt.text;
+ }
+};
+
+/*--------------------------------------------------------------------------*/
+
+Abstract.TimedObserver = Class.create(PeriodicalExecuter, {
+ initialize: function($super, element, frequency, callback) {
+ $super(callback, frequency);
+ this.element = $(element);
+ this.lastValue = this.getValue();
+ },
+
+ execute: function() {
+ var value = this.getValue();
+ if (Object.isString(this.lastValue) && Object.isString(value) ?
+ this.lastValue != value : String(this.lastValue) != String(value)) {
+ this.callback(this.element, value);
+ this.lastValue = value;
+ }
+ }
+});
+
+Form.Element.Observer = Class.create(Abstract.TimedObserver, {
+ getValue: function() {
+ return Form.Element.getValue(this.element);
+ }
+});
+
+Form.Observer = Class.create(Abstract.TimedObserver, {
+ getValue: function() {
+ return Form.serialize(this.element);
+ }
+});
+
+/*--------------------------------------------------------------------------*/
+
+Abstract.EventObserver = Class.create({
+ initialize: function(element, callback) {
+ this.element = $(element);
+ this.callback = callback;
+
+ this.lastValue = this.getValue();
+ if (this.element.tagName.toLowerCase() == 'form')
+ this.registerFormCallbacks();
+ else
+ this.registerCallback(this.element);
+ },
+
+ onElementEvent: function() {
+ var value = this.getValue();
+ if (this.lastValue != value) {
+ this.callback(this.element, value);
+ this.lastValue = value;
+ }
+ },
+
+ registerFormCallbacks: function() {
+ Form.getElements(this.element).each(this.registerCallback, this);
+ },
+
+ registerCallback: function(element) {
+ if (element.type) {
+ switch (element.type.toLowerCase()) {
+ case 'checkbox':
+ case 'radio':
+ Event.observe(element, 'click', this.onElementEvent.bind(this));
+ break;
+ default:
+ Event.observe(element, 'change', this.onElementEvent.bind(this));
+ break;
+ }
+ }
+ }
+});
+
+Form.Element.EventObserver = Class.create(Abstract.EventObserver, {
+ getValue: function() {
+ return Form.Element.getValue(this.element);
+ }
+});
+
+Form.EventObserver = Class.create(Abstract.EventObserver, {
+ getValue: function() {
+ return Form.serialize(this.element);
+ }
+});
+if (!window.Event) var Event = { };
+
+Object.extend(Event, {
+ KEY_BACKSPACE: 8,
+ KEY_TAB: 9,
+ KEY_RETURN: 13,
+ KEY_ESC: 27,
+ KEY_LEFT: 37,
+ KEY_UP: 38,
+ KEY_RIGHT: 39,
+ KEY_DOWN: 40,
+ KEY_DELETE: 46,
+ KEY_HOME: 36,
+ KEY_END: 35,
+ KEY_PAGEUP: 33,
+ KEY_PAGEDOWN: 34,
+ KEY_INSERT: 45,
+
+ cache: { },
+
+ relatedTarget: function(event) {
+ var element;
+ switch(event.type) {
+ case 'mouseover': element = event.fromElement; break;
+ case 'mouseout': element = event.toElement; break;
+ default: return null;
+ }
+ return Element.extend(element);
+ }
+});
+
+Event.Methods = (function() {
+ var isButton;
+
+ if (Prototype.Browser.IE) {
+ var buttonMap = { 0: 1, 1: 4, 2: 2 };
+ isButton = function(event, code) {
+ return event.button == buttonMap[code];
+ };
+
+ } else if (Prototype.Browser.WebKit) {
+ isButton = function(event, code) {
+ switch (code) {
+ case 0: return event.which == 1 && !event.metaKey;
+ case 1: return event.which == 1 && event.metaKey;
+ default: return false;
+ }
+ };
+
+ } else {
+ isButton = function(event, code) {
+ return event.which ? (event.which === code + 1) : (event.button === code);
+ };
+ }
+
+ return {
+ isLeftClick: function(event) { return isButton(event, 0) },
+ isMiddleClick: function(event) { return isButton(event, 1) },
+ isRightClick: function(event) { return isButton(event, 2) },
+
+ element: function(event) {
+ event = Event.extend(event);
+
+ var node = event.target,
+ type = event.type,
+ currentTarget = event.currentTarget;
+
+ if (currentTarget && currentTarget.tagName) {
+ // Firefox screws up the "click" event when moving between radio buttons
+ // via arrow keys. It also screws up the "load" and "error" events on images,
+ // reporting the document as the target instead of the original image.
+ if (type === 'load' || type === 'error' ||
+ (type === 'click' && currentTarget.tagName.toLowerCase() === 'input'
+ && currentTarget.type === 'radio'))
+ node = currentTarget;
+ }
+ if (node.nodeType == Node.TEXT_NODE) node = node.parentNode;
+ return Element.extend(node);
+ },
+
+ findElement: function(event, expression) {
+ var element = Event.element(event);
+ if (!expression) return element;
+ var elements = [element].concat(element.ancestors());
+ return Selector.findElement(elements, expression, 0);
+ },
+
+ pointer: function(event) {
+ var docElement = document.documentElement,
+ body = document.body || { scrollLeft: 0, scrollTop: 0 };
+ return {
+ x: event.pageX || (event.clientX +
+ (docElement.scrollLeft || body.scrollLeft) -
+ (docElement.clientLeft || 0)),
+ y: event.pageY || (event.clientY +
+ (docElement.scrollTop || body.scrollTop) -
+ (docElement.clientTop || 0))
+ };
+ },
+
+ pointerX: function(event) { return Event.pointer(event).x },
+ pointerY: function(event) { return Event.pointer(event).y },
+
+ stop: function(event) {
+ Event.extend(event);
+ event.preventDefault();
+ event.stopPropagation();
+ event.stopped = true;
+ }
+ };
+})();
+
+Event.extend = (function() {
+ var methods = Object.keys(Event.Methods).inject({ }, function(m, name) {
+ m[name] = Event.Methods[name].methodize();
+ return m;
+ });
+
+ if (Prototype.Browser.IE) {
+ Object.extend(methods, {
+ stopPropagation: function() { this.cancelBubble = true },
+ preventDefault: function() { this.returnValue = false },
+ inspect: function() { return "[object Event]" }
+ });
+
+ return function(event) {
+ if (!event) return false;
+ if (event._extendedByPrototype) return event;
+
+ event._extendedByPrototype = Prototype.emptyFunction;
+ var pointer = Event.pointer(event);
+ Object.extend(event, {
+ target: event.srcElement,
+ relatedTarget: Event.relatedTarget(event),
+ pageX: pointer.x,
+ pageY: pointer.y
+ });
+ return Object.extend(event, methods);
+ };
+
+ } else {
+ Event.prototype = Event.prototype || document.createEvent("HTMLEvents")['__proto__'];
+ Object.extend(Event.prototype, methods);
+ return Prototype.K;
+ }
+})();
+
+Object.extend(Event, (function() {
+ var cache = Event.cache;
+
+ function getEventID(element) {
+ if (element._prototypeEventID) return element._prototypeEventID[0];
+ arguments.callee.id = arguments.callee.id || 1;
+ return element._prototypeEventID = [++arguments.callee.id];
+ }
+
+ function getDOMEventName(eventName) {
+ if (eventName && eventName.include(':')) return "dataavailable";
+ return eventName;
+ }
+
+ function getCacheForID(id) {
+ return cache[id] = cache[id] || { };
+ }
+
+ function getWrappersForEventName(id, eventName) {
+ var c = getCacheForID(id);
+ return c[eventName] = c[eventName] || [];
+ }
+
+ function createWrapper(element, eventName, handler) {
+ var id = getEventID(element);
+ var c = getWrappersForEventName(id, eventName);
+ if (c.pluck("handler").include(handler)) return false;
+
+ var wrapper = function(event) {
+ if (!Event || !Event.extend ||
+ (event.eventName && event.eventName != eventName))
+ return false;
+
+ Event.extend(event);
+ handler.call(element, event);
+ };
+
+ wrapper.handler = handler;
+ c.push(wrapper);
+ return wrapper;
+ }
+
+ function findWrapper(id, eventName, handler) {
+ var c = getWrappersForEventName(id, eventName);
+ return c.find(function(wrapper) { return wrapper.handler == handler });
+ }
+
+ function destroyWrapper(id, eventName, handler) {
+ var c = getCacheForID(id);
+ if (!c[eventName]) return false;
+ c[eventName] = c[eventName].without(findWrapper(id, eventName, handler));
+ }
+
+ function destroyCache() {
+ for (var id in cache)
+ for (var eventName in cache[id])
+ cache[id][eventName] = null;
+ }
+
+
+ // Internet Explorer needs to remove event handlers on page unload
+ // in order to avoid memory leaks.
+ if (window.attachEvent) {
+ window.attachEvent("onunload", destroyCache);
+ }
+
+ // Safari has a dummy event handler on page unload so that it won't
+ // use its bfcache. Safari <= 3.1 has an issue with restoring the "document"
+ // object when page is returned to via the back button using its bfcache.
+ if (Prototype.Browser.WebKit) {
+ window.addEventListener('unload', Prototype.emptyFunction, false);
+ }
+
+ return {
+ observe: function(element, eventName, handler) {
+ element = $(element);
+ var name = getDOMEventName(eventName);
+
+ var wrapper = createWrapper(element, eventName, handler);
+ if (!wrapper) return element;
+
+ if (element.addEventListener) {
+ element.addEventListener(name, wrapper, false);
+ } else {
+ element.attachEvent("on" + name, wrapper);
+ }
+
+ return element;
+ },
+
+ stopObserving: function(element, eventName, handler) {
+ element = $(element);
+ var id = getEventID(element), name = getDOMEventName(eventName);
+
+ if (!handler && eventName) {
+ getWrappersForEventName(id, eventName).each(function(wrapper) {
+ element.stopObserving(eventName, wrapper.handler);
+ });
+ return element;
+
+ } else if (!eventName) {
+ Object.keys(getCacheForID(id)).each(function(eventName) {
+ element.stopObserving(eventName);
+ });
+ return element;
+ }
+
+ var wrapper = findWrapper(id, eventName, handler);
+ if (!wrapper) return element;
+
+ if (element.removeEventListener) {
+ element.removeEventListener(name, wrapper, false);
+ } else {
+ element.detachEvent("on" + name, wrapper);
+ }
+
+ destroyWrapper(id, eventName, handler);
+
+ return element;
+ },
+
+ fire: function(element, eventName, memo) {
+ element = $(element);
+ if (element == document && document.createEvent && !element.dispatchEvent)
+ element = document.documentElement;
+
+ var event;
+ if (document.createEvent) {
+ event = document.createEvent("HTMLEvents");
+ event.initEvent("dataavailable", true, true);
+ } else {
+ event = document.createEventObject();
+ event.eventType = "ondataavailable";
+ }
+
+ event.eventName = eventName;
+ event.memo = memo || { };
+
+ if (document.createEvent) {
+ element.dispatchEvent(event);
+ } else {
+ element.fireEvent(event.eventType, event);
+ }
+
+ return Event.extend(event);
+ }
+ };
+})());
+
+Object.extend(Event, Event.Methods);
+
+Element.addMethods({
+ fire: Event.fire,
+ observe: Event.observe,
+ stopObserving: Event.stopObserving
+});
+
+Object.extend(document, {
+ fire: Element.Methods.fire.methodize(),
+ observe: Element.Methods.observe.methodize(),
+ stopObserving: Element.Methods.stopObserving.methodize(),
+ loaded: false
+});
+
+(function() {
+ /* Support for the DOMContentLoaded event is based on work by Dan Webb,
+ Matthias Miller, Dean Edwards and John Resig. */
+
+ var timer;
+
+ function fireContentLoadedEvent() {
+ if (document.loaded) return;
+ if (timer) window.clearInterval(timer);
+ document.fire("dom:loaded");
+ document.loaded = true;
+ }
+
+ if (document.addEventListener) {
+ if (Prototype.Browser.WebKit) {
+ timer = window.setInterval(function() {
+ if (/loaded|complete/.test(document.readyState))
+ fireContentLoadedEvent();
+ }, 0);
+
+ Event.observe(window, "load", fireContentLoadedEvent);
+
+ } else {
+ document.addEventListener("DOMContentLoaded",
+ fireContentLoadedEvent, false);
+ }
+
+ } else {
+ document.write("<script id=__onDOMContentLoaded defer src=//:><\/script>");
+ $("__onDOMContentLoaded").onreadystatechange = function() {
+ if (this.readyState == "complete") {
+ this.onreadystatechange = null;
+ fireContentLoadedEvent();
+ }
+ };
+ }
+})();
+/*------------------------------- DEPRECATED -------------------------------*/
+
+Hash.toQueryString = Object.toQueryString;
+
+var Toggle = { display: Element.toggle };
+
+Element.Methods.childOf = Element.Methods.descendantOf;
+
+var Insertion = {
+ Before: function(element, content) {
+ return Element.insert(element, {before:content});
+ },
+
+ Top: function(element, content) {
+ return Element.insert(element, {top:content});
+ },
+
+ Bottom: function(element, content) {
+ return Element.insert(element, {bottom:content});
+ },
+
+ After: function(element, content) {
+ return Element.insert(element, {after:content});
+ }
+};
+
+var $continue = new Error('"throw $continue" is deprecated, use "return" instead');
+
+// This should be moved to script.aculo.us; notice the deprecated methods
+// further below, that map to the newer Element methods.
+var Position = {
+ // set to true if needed, warning: firefox performance problems
+ // NOT neeeded for page scrolling, only if draggable contained in
+ // scrollable elements
+ includeScrollOffsets: false,
+
+ // must be called before calling withinIncludingScrolloffset, every time the
+ // page is scrolled
+ prepare: function() {
+ this.deltaX = window.pageXOffset
+ || document.documentElement.scrollLeft
+ || document.body.scrollLeft
+ || 0;
+ this.deltaY = window.pageYOffset
+ || document.documentElement.scrollTop
+ || document.body.scrollTop
+ || 0;
+ },
+
+ // caches x/y coordinate pair to use with overlap
+ within: function(element, x, y) {
+ if (this.includeScrollOffsets)
+ return this.withinIncludingScrolloffsets(element, x, y);
+ this.xcomp = x;
+ this.ycomp = y;
+ this.offset = Element.cumulativeOffset(element);
+
+ return (y >= this.offset[1] &&
+ y < this.offset[1] + element.offsetHeight &&
+ x >= this.offset[0] &&
+ x < this.offset[0] + element.offsetWidth);
+ },
+
+ withinIncludingScrolloffsets: function(element, x, y) {
+ var offsetcache = Element.cumulativeScrollOffset(element);
+
+ this.xcomp = x + offsetcache[0] - this.deltaX;
+ this.ycomp = y + offsetcache[1] - this.deltaY;
+ this.offset = Element.cumulativeOffset(element);
+
+ return (this.ycomp >= this.offset[1] &&
+ this.ycomp < this.offset[1] + element.offsetHeight &&
+ this.xcomp >= this.offset[0] &&
+ this.xcomp < this.offset[0] + element.offsetWidth);
+ },
+
+ // within must be called directly before
+ overlap: function(mode, element) {
+ if (!mode) return 0;
+ if (mode == 'vertical')
+ return ((this.offset[1] + element.offsetHeight) - this.ycomp) /
+ element.offsetHeight;
+ if (mode == 'horizontal')
+ return ((this.offset[0] + element.offsetWidth) - this.xcomp) /
+ element.offsetWidth;
+ },
+
+ // Deprecation layer -- use newer Element methods now (1.5.2).
+
+ cumulativeOffset: Element.Methods.cumulativeOffset,
+
+ positionedOffset: Element.Methods.positionedOffset,
+
+ absolutize: function(element) {
+ Position.prepare();
+ return Element.absolutize(element);
+ },
+
+ relativize: function(element) {
+ Position.prepare();
+ return Element.relativize(element);
+ },
+
+ realOffset: Element.Methods.cumulativeScrollOffset,
+
+ offsetParent: Element.Methods.getOffsetParent,
+
+ page: Element.Methods.viewportOffset,
+
+ clone: function(source, target, options) {
+ options = options || { };
+ return Element.clonePosition(target, source, options);
+ }
+};
+
+/*--------------------------------------------------------------------------*/
+
+if (!document.getElementsByClassName) document.getElementsByClassName = function(instanceMethods){
+ function iter(name) {
+ return name.blank() ? null : "[contains(concat(' ', @class, ' '), ' " + name + " ')]";
+ }
+
+ instanceMethods.getElementsByClassName = Prototype.BrowserFeatures.XPath ?
+ function(element, className) {
+ className = className.toString().strip();
+ var cond = /\s/.test(className) ? $w(className).map(iter).join('') : iter(className);
+ return cond ? document._getElementsByXPath('.//*' + cond, element) : [];
+ } : function(element, className) {
+ className = className.toString().strip();
+ var elements = [], classNames = (/\s/.test(className) ? $w(className) : null);
+ if (!classNames && !className) return elements;
+
+ var nodes = $(element).getElementsByTagName('*');
+ className = ' ' + className + ' ';
+
+ for (var i = 0, child, cn; child = nodes[i]; i++) {
+ if (child.className && (cn = ' ' + child.className + ' ') && (cn.include(className) ||
+ (classNames && classNames.all(function(name) {
+ return !name.toString().blank() && cn.include(' ' + name + ' ');
+ }))))
+ elements.push(Element.extend(child));
+ }
+ return elements;
+ };
+
+ return function(className, parentElement) {
+ return $(parentElement || document.body).getElementsByClassName(className);
+ };
+}(Element.Methods);
+
+/*--------------------------------------------------------------------------*/
+
+Element.ClassNames = Class.create();
+Element.ClassNames.prototype = {
+ initialize: function(element) {
+ this.element = $(element);
+ },
+
+ _each: function(iterator) {
+ this.element.className.split(/\s+/).select(function(name) {
+ return name.length > 0;
+ })._each(iterator);
+ },
+
+ set: function(className) {
+ this.element.className = className;
+ },
+
+ add: function(classNameToAdd) {
+ if (this.include(classNameToAdd)) return;
+ this.set($A(this).concat(classNameToAdd).join(' '));
+ },
+
+ remove: function(classNameToRemove) {
+ if (!this.include(classNameToRemove)) return;
+ this.set($A(this).without(classNameToRemove).join(' '));
+ },
+
+ toString: function() {
+ return $A(this).join(' ');
+ }
+};
+
+Object.extend(Element.ClassNames.prototype, Enumerable);
+
+/*--------------------------------------------------------------------------*/
+
+Element.addMethods();
\ No newline at end of file
Added: trunk/src/ajax/javascripts/external/scriptaculous/builder.js
==============================================================================
--- (empty file)
+++ trunk/src/ajax/javascripts/external/scriptaculous/builder.js Fri Apr 10 19:11:32 2009
@@ -0,0 +1,136 @@
+// script.aculo.us builder.js v1.8.2, Tue Nov 18 18:30:58 +0100 2008
+
+// Copyright (c) 2005-2008 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
+//
+// script.aculo.us is freely distributable under the terms of an MIT-style license.
+// For details, see the script.aculo.us web site: http://script.aculo.us/
+
+var Builder = {
+ NODEMAP: {
+ AREA: 'map',
+ CAPTION: 'table',
+ COL: 'table',
+ COLGROUP: 'table',
+ LEGEND: 'fieldset',
+ OPTGROUP: 'select',
+ OPTION: 'select',
+ PARAM: 'object',
+ TBODY: 'table',
+ TD: 'table',
+ TFOOT: 'table',
+ TH: 'table',
+ THEAD: 'table',
+ TR: 'table'
+ },
+ // note: For Firefox < 1.5, OPTION and OPTGROUP tags are currently broken,
+ // due to a Firefox bug
+ node: function(elementName) {
+ elementName = elementName.toUpperCase();
+
+ // try innerHTML approach
+ var parentTag = this.NODEMAP[elementName] || 'div';
+ var parentElement = document.createElement(parentTag);
+ try { // prevent IE "feature": http://dev.rubyonrails.org/ticket/2707
+ parentElement.innerHTML = "<" + elementName + "></" + elementName + ">";
+ } catch(e) {}
+ var element = parentElement.firstChild || null;
+
+ // see if browser added wrapping tags
+ if(element && (element.tagName.toUpperCase() != elementName))
+ element = element.getElementsByTagName(elementName)[0];
+
+ // fallback to createElement approach
+ if(!element) element = document.createElement(elementName);
+
+ // abort if nothing could be created
+ if(!element) return;
+
+ // attributes (or text)
+ if(arguments[1])
+ if(this._isStringOrNumber(arguments[1]) ||
+ (arguments[1] instanceof Array) ||
+ arguments[1].tagName) {
+ this._children(element, arguments[1]);
+ } else {
+ var attrs = this._attributes(arguments[1]);
+ if(attrs.length) {
+ try { // prevent IE "feature": http://dev.rubyonrails.org/ticket/2707
+ parentElement.innerHTML = "<" +elementName + " " +
+ attrs + "></" + elementName + ">";
+ } catch(e) {}
+ element = parentElement.firstChild || null;
+ // workaround firefox 1.0.X bug
+ if(!element) {
+ element = document.createElement(elementName);
+ for(attr in arguments[1])
+ element[attr == 'class' ? 'className' : attr] = arguments[1][attr];
+ }
+ if(element.tagName.toUpperCase() != elementName)
+ element = parentElement.getElementsByTagName(elementName)[0];
+ }
+ }
+
+ // text, or array of children
+ if(arguments[2])
+ this._children(element, arguments[2]);
+
+ return $(element);
+ },
+ _text: function(text) {
+ return document.createTextNode(text);
+ },
+
+ ATTR_MAP: {
+ 'className': 'class',
+ 'htmlFor': 'for'
+ },
+
+ _attributes: function(attributes) {
+ var attrs = [];
+ for(attribute in attributes)
+ attrs.push((attribute in this.ATTR_MAP ? this.ATTR_MAP[attribute] : attribute) +
+ '="' + attributes[attribute].toString().escapeHTML().gsub(/"/,'"') + '"');
+ return attrs.join(" ");
+ },
+ _children: function(element, children) {
+ if(children.tagName) {
+ element.appendChild(children);
+ return;
+ }
+ if(typeof children=='object') { // array can hold nodes and text
+ children.flatten().each( function(e) {
+ if(typeof e=='object')
+ element.appendChild(e);
+ else
+ if(Builder._isStringOrNumber(e))
+ element.appendChild(Builder._text(e));
+ });
+ } else
+ if(Builder._isStringOrNumber(children))
+ element.appendChild(Builder._text(children));
+ },
+ _isStringOrNumber: function(param) {
+ return(typeof param=='string' || typeof param=='number');
+ },
+ build: function(html) {
+ var element = this.node('div');
+ $(element).update(html.strip());
+ return element.down();
+ },
+ dump: function(scope) {
+ if(typeof scope != 'object' && typeof scope != 'function') scope = window; //global scope
+
+ var tags = ("A ABBR ACRONYM ADDRESS APPLET AREA B BASE BASEFONT BDO BIG BLOCKQUOTE BODY " +
+ "BR BUTTON CAPTION CENTER CITE CODE COL COLGROUP DD DEL DFN DIR DIV DL DT EM FIELDSET " +
+ "FONT FORM FRAME FRAMESET H1 H2 H3 H4 H5 H6 HEAD HR HTML I IFRAME IMG INPUT INS ISINDEX "+
+ "KBD LABEL LEGEND LI LINK MAP MENU META NOFRAMES NOSCRIPT OBJECT OL OPTGROUP OPTION P "+
+ "PARAM PRE Q S SAMP SCRIPT SELECT SMALL SPAN STRIKE STRONG STYLE SUB SUP TABLE TBODY TD "+
+ "TEXTAREA TFOOT TH THEAD TITLE TR TT U UL VAR").split(/\s+/);
+
+ tags.each( function(tag){
+ scope[tag] = function() {
+ return Builder.node.apply(Builder, [tag].concat($A(arguments)));
+ };
+ });
+ }
+};
\ No newline at end of file
Added: trunk/src/ajax/javascripts/external/scriptaculous/controls.js
==============================================================================
--- (empty file)
+++ trunk/src/ajax/javascripts/external/scriptaculous/controls.js Fri Apr 10 19:11:32 2009
@@ -0,0 +1,965 @@
+// script.aculo.us controls.js v1.8.2, Tue Nov 18 18:30:58 +0100 2008
+
+// Copyright (c) 2005-2008 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
+// (c) 2005-2008 Ivan Krstic (http://blogs.law.harvard.edu/ivan)
+// (c) 2005-2008 Jon Tirsen (http://www.tirsen.com)
+// Contributors:
+// Richard Livsey
+// Rahul Bhargava
+// Rob Wills
+//
+// script.aculo.us is freely distributable under the terms of an MIT-style license.
+// For details, see the script.aculo.us web site: http://script.aculo.us/
+
+// Autocompleter.Base handles all the autocompletion functionality
+// that's independent of the data source for autocompletion. This
+// includes drawing the autocompletion menu, observing keyboard
+// and mouse events, and similar.
+//
+// Specific autocompleters need to provide, at the very least,
+// a getUpdatedChoices function that will be invoked every time
+// the text inside the monitored textbox changes. This method
+// should get the text for which to provide autocompletion by
+// invoking this.getToken(), NOT by directly accessing
+// this.element.value. This is to allow incremental tokenized
+// autocompletion. Specific auto-completion logic (AJAX, etc)
+// belongs in getUpdatedChoices.
+//
+// Tokenized incremental autocompletion is enabled automatically
+// when an autocompleter is instantiated with the 'tokens' option
+// in the options parameter, e.g.:
+// new Ajax.Autocompleter('id','upd', '/url/', { tokens: ',' });
+// will incrementally autocomplete with a comma as the token.
+// Additionally, ',' in the above example can be replaced with
+// a token array, e.g. { tokens: [',', '\n'] } which
+// enables autocompletion on multiple tokens. This is most
+// useful when one of the tokens is \n (a newline), as it
+// allows smart autocompletion after linebreaks.
+
+if(typeof Effect == 'undefined')
+ throw("controls.js requires including script.aculo.us' effects.js library");
+
+var Autocompleter = { };
+Autocompleter.Base = Class.create({
+ baseInitialize: function(element, update, options) {
+ element = $(element);
+ this.element = element;
+ this.update = $(update);
+ this.hasFocus = false;
+ this.changed = false;
+ this.active = false;
+ this.index = 0;
+ this.entryCount = 0;
+ this.oldElementValue = this.element.value;
+
+ if(this.setOptions)
+ this.setOptions(options);
+ else
+ this.options = options || { };
+
+ this.options.paramName = this.options.paramName || this.element.name;
+ this.options.tokens = this.options.tokens || [];
+ this.options.frequency = this.options.frequency || 0.4;
+ this.options.minChars = this.options.minChars || 1;
+ this.options.onShow = this.options.onShow ||
+ function(element, update){
+ if(!update.style.position || update.style.position=='absolute') {
+ update.style.position = 'absolute';
+ Position.clone(element, update, {
+ setHeight: false,
+ offsetTop: element.offsetHeight
+ });
+ }
+ Effect.Appear(update,{duration:0.15});
+ };
+ this.options.onHide = this.options.onHide ||
+ function(element, update){ new Effect.Fade(update,{duration:0.15}) };
+
+ if(typeof(this.options.tokens) == 'string')
+ this.options.tokens = new Array(this.options.tokens);
+ // Force carriage returns as token delimiters anyway
+ if (!this.options.tokens.include('\n'))
+ this.options.tokens.push('\n');
+
+ this.observer = null;
+
+ this.element.setAttribute('autocomplete','off');
+
+ Element.hide(this.update);
+
+ Event.observe(this.element, 'blur', this.onBlur.bindAsEventListener(this));
+ Event.observe(this.element, 'keydown', this.onKeyPress.bindAsEventListener(this));
+ },
+
+ show: function() {
+ if(Element.getStyle(this.update, 'display')=='none') this.options.onShow(this.element, this.update);
+ if(!this.iefix &&
+ (Prototype.Browser.IE) &&
+ (Element.getStyle(this.update, 'position')=='absolute')) {
+ new Insertion.After(this.update,
+ '<iframe id="' + this.update.id + '_iefix" '+
+ 'style="display:none;position:absolute;filter:progid:DXImageTransform.Microsoft.Alpha(opacity=0);" ' +
+ 'src="javascript:false;" frameborder="0" scrolling="no"></iframe>');
+ this.iefix = $(this.update.id+'_iefix');
+ }
+ if(this.iefix) setTimeout(this.fixIEOverlapping.bind(this), 50);
+ },
+
+ fixIEOverlapping: function() {
+ Position.clone(this.update, this.iefix, {setTop:(!this.update.style.height)});
+ this.iefix.style.zIndex = 1;
+ this.update.style.zIndex = 2;
+ Element.show(this.iefix);
+ },
+
+ hide: function() {
+ this.stopIndicator();
+ if(Element.getStyle(this.update, 'display')!='none') this.options.onHide(this.element, this.update);
+ if(this.iefix) Element.hide(this.iefix);
+ },
+
+ startIndicator: function() {
+ if(this.options.indicator) Element.show(this.options.indicator);
+ },
+
+ stopIndicator: function() {
+ if(this.options.indicator) Element.hide(this.options.indicator);
+ },
+
+ onKeyPress: function(event) {
+ if(this.active)
+ switch(event.keyCode) {
+ case Event.KEY_TAB:
+ case Event.KEY_RETURN:
+ this.selectEntry();
+ Event.stop(event);
+ case Event.KEY_ESC:
+ this.hide();
+ this.active = false;
+ Event.stop(event);
+ return;
+ case Event.KEY_LEFT:
+ case Event.KEY_RIGHT:
+ return;
+ case Event.KEY_UP:
+ this.markPrevious();
+ this.render();
+ Event.stop(event);
+ return;
+ case Event.KEY_DOWN:
+ this.markNext();
+ this.render();
+ Event.stop(event);
+ return;
+ }
+ else
+ if(event.keyCode==Event.KEY_TAB || event.keyCode==Event.KEY_RETURN ||
+ (Prototype.Browser.WebKit > 0 && event.keyCode == 0)) return;
+
+ this.changed = true;
+ this.hasFocus = true;
+
+ if(this.observer) clearTimeout(this.observer);
+ this.observer =
+ setTimeout(this.onObserverEvent.bind(this), this.options.frequency*1000);
+ },
+
+ activate: function() {
+ this.changed = false;
+ this.hasFocus = true;
+ this.getUpdatedChoices();
+ },
+
+ onHover: function(event) {
+ var element = Event.findElement(event, 'LI');
+ if(this.index != element.autocompleteIndex)
+ {
+ this.index = element.autocompleteIndex;
+ this.render();
+ }
+ Event.stop(event);
+ },
+
+ onClick: function(event) {
+ var element = Event.findElement(event, 'LI');
+ this.index = element.autocompleteIndex;
+ this.selectEntry();
+ this.hide();
+ },
+
+ onBlur: function(event) {
+ // needed to make click events working
+ setTimeout(this.hide.bind(this), 250);
+ this.hasFocus = false;
+ this.active = false;
+ },
+
+ render: function() {
+ if(this.entryCount > 0) {
+ for (var i = 0; i < this.entryCount; i++)
+ this.index==i ?
+ Element.addClassName(this.getEntry(i),"selected") :
+ Element.removeClassName(this.getEntry(i),"selected");
+ if(this.hasFocus) {
+ this.show();
+ this.active = true;
+ }
+ } else {
+ this.active = false;
+ this.hide();
+ }
+ },
+
+ markPrevious: function() {
+ if(this.index > 0) this.index--;
+ else this.index = this.entryCount-1;
+ this.getEntry(this.index).scrollIntoView(true);
+ },
+
+ markNext: function() {
+ if(this.index < this.entryCount-1) this.index++;
+ else this.index = 0;
+ this.getEntry(this.index).scrollIntoView(false);
+ },
+
+ getEntry: function(index) {
+ return this.update.firstChild.childNodes[index];
+ },
+
+ getCurrentEntry: function() {
+ return this.getEntry(this.index);
+ },
+
+ selectEntry: function() {
+ this.active = false;
+ this.updateElement(this.getCurrentEntry());
+ },
+
+ updateElement: function(selectedElement) {
+ if (this.options.updateElement) {
+ this.options.updateElement(selectedElement);
+ return;
+ }
+ var value = '';
+ if (this.options.select) {
+ var nodes = $(selectedElement).select('.' + this.options.select) || [];
+ if(nodes.length>0) value = Element.collectTextNodes(nodes[0], this.options.select);
+ } else
+ value = Element.collectTextNodesIgnoreClass(selectedElement, 'informal');
+
+ var bounds = this.getTokenBounds();
+ if (bounds[0] != -1) {
+ var newValue = this.element.value.substr(0, bounds[0]);
+ var whitespace = this.element.value.substr(bounds[0]).match(/^\s+/);
+ if (whitespace)
+ newValue += whitespace[0];
+ this.element.value = newValue + value + this.element.value.substr(bounds[1]);
+ } else {
+ this.element.value = value;
+ }
+ this.oldElementValue = this.element.value;
+ this.element.focus();
+
+ if (this.options.afterUpdateElement)
+ this.options.afterUpdateElement(this.element, selectedElement);
+ },
+
+ updateChoices: function(choices) {
+ if(!this.changed && this.hasFocus) {
+ this.update.innerHTML = choices;
+ Element.cleanWhitespace(this.update);
+ Element.cleanWhitespace(this.update.down());
+
+ if(this.update.firstChild && this.update.down().childNodes) {
+ this.entryCount =
+ this.update.down().childNodes.length;
+ for (var i = 0; i < this.entryCount; i++) {
+ var entry = this.getEntry(i);
+ entry.autocompleteIndex = i;
+ this.addObservers(entry);
+ }
+ } else {
+ this.entryCount = 0;
+ }
+
+ this.stopIndicator();
+ this.index = 0;
+
+ if(this.entryCount==1 && this.options.autoSelect) {
+ this.selectEntry();
+ this.hide();
+ } else {
+ this.render();
+ }
+ }
+ },
+
+ addObservers: function(element) {
+ Event.observe(element, "mouseover", this.onHover.bindAsEventListener(this));
+ Event.observe(element, "click", this.onClick.bindAsEventListener(this));
+ },
+
+ onObserverEvent: function() {
+ this.changed = false;
+ this.tokenBounds = null;
+ if(this.getToken().length>=this.options.minChars) {
+ this.getUpdatedChoices();
+ } else {
+ this.active = false;
+ this.hide();
+ }
+ this.oldElementValue = this.element.value;
+ },
+
+ getToken: function() {
+ var bounds = this.getTokenBounds();
+ return this.element.value.substring(bounds[0], bounds[1]).strip();
+ },
+
+ getTokenBounds: function() {
+ if (null != this.tokenBounds) return this.tokenBounds;
+ var value = this.element.value;
+ if (value.strip().empty()) return [-1, 0];
+ var diff = arguments.callee.getFirstDifferencePos(value, this.oldElementValue);
+ var offset = (diff == this.oldElementValue.length ? 1 : 0);
+ var prevTokenPos = -1, nextTokenPos = value.length;
+ var tp;
+ for (var index = 0, l = this.options.tokens.length; index < l; ++index) {
+ tp = value.lastIndexOf(this.options.tokens[index], diff + offset - 1);
+ if (tp > prevTokenPos) prevTokenPos = tp;
+ tp = value.indexOf(this.options.tokens[index], diff + offset);
+ if (-1 != tp && tp < nextTokenPos) nextTokenPos = tp;
+ }
+ return (this.tokenBounds = [prevTokenPos + 1, nextTokenPos]);
+ }
+});
+
+Autocompleter.Base.prototype.getTokenBounds.getFirstDifferencePos = function(newS, oldS) {
+ var boundary = Math.min(newS.length, oldS.length);
+ for (var index = 0; index < boundary; ++index)
+ if (newS[index] != oldS[index])
+ return index;
+ return boundary;
+};
+
+Ajax.Autocompleter = Class.create(Autocompleter.Base, {
+ initialize: function(element, update, url, options) {
+ this.baseInitialize(element, update, options);
+ this.options.asynchronous = true;
+ this.options.onComplete = this.onComplete.bind(this);
+ this.options.defaultParams = this.options.parameters || null;
+ this.url = url;
+ },
+
+ getUpdatedChoices: function() {
+ this.startIndicator();
+
+ var entry = encodeURIComponent(this.options.paramName) + '=' +
+ encodeURIComponent(this.getToken());
+
+ this.options.parameters = this.options.callback ?
+ this.options.callback(this.element, entry) : entry;
+
+ if(this.options.defaultParams)
+ this.options.parameters += '&' + this.options.defaultParams;
+
+ new Ajax.Request(this.url, this.options);
+ },
+
+ onComplete: function(request) {
+ this.updateChoices(request.responseText);
+ }
+});
+
+// The local array autocompleter. Used when you'd prefer to
+// inject an array of autocompletion options into the page, rather
+// than sending out Ajax queries, which can be quite slow sometimes.
+//
+// The constructor takes four parameters. The first two are, as usual,
+// the id of the monitored textbox, and id of the autocompletion menu.
+// The third is the array you want to autocomplete from, and the fourth
+// is the options block.
+//
+// Extra local autocompletion options:
+// - choices - How many autocompletion choices to offer
+//
+// - partialSearch - If false, the autocompleter will match entered
+// text only at the beginning of strings in the
+// autocomplete array. Defaults to true, which will
+// match text at the beginning of any *word* in the
+// strings in the autocomplete array. If you want to
+// search anywhere in the string, additionally set
+// the option fullSearch to true (default: off).
+//
+// - fullSsearch - Search anywhere in autocomplete array strings.
+//
+// - partialChars - How many characters to enter before triggering
+// a partial match (unlike minChars, which defines
+// how many characters are required to do any match
+// at all). Defaults to 2.
+//
+// - ignoreCase - Whether to ignore case when autocompleting.
+// Defaults to true.
+//
+// It's possible to pass in a custom function as the 'selector'
+// option, if you prefer to write your own autocompletion logic.
+// In that case, the other options above will not apply unless
+// you support them.
+
+Autocompleter.Local = Class.create(Autocompleter.Base, {
+ initialize: function(element, update, array, options) {
+ this.baseInitialize(element, update, options);
+ this.options.array = array;
+ },
+
+ getUpdatedChoices: function() {
+ this.updateChoices(this.options.selector(this));
+ },
+
+ setOptions: function(options) {
+ this.options = Object.extend({
+ choices: 10,
+ partialSearch: true,
+ partialChars: 2,
+ ignoreCase: true,
+ fullSearch: false,
+ selector: function(instance) {
+ var ret = []; // Beginning matches
+ var partial = []; // Inside matches
+ var entry = instance.getToken();
+ var count = 0;
+
+ for (var i = 0; i < instance.options.array.length &&
+ ret.length < instance.options.choices ; i++) {
+
+ var elem = instance.options.array[i];
+ var foundPos = instance.options.ignoreCase ?
+ elem.toLowerCase().indexOf(entry.toLowerCase()) :
+ elem.indexOf(entry);
+
+ while (foundPos != -1) {
+ if (foundPos == 0 && elem.length != entry.length) {
+ ret.push("<li><strong>" + elem.substr(0, entry.length) + "</strong>" +
+ elem.substr(entry.length) + "</li>");
+ break;
+ } else if (entry.length >= instance.options.partialChars &&
+ instance.options.partialSearch && foundPos != -1) {
+ if (instance.options.fullSearch || /\s/.test(elem.substr(foundPos-1,1))) {
+ partial.push("<li>" + elem.substr(0, foundPos) + "<strong>" +
+ elem.substr(foundPos, entry.length) + "</strong>" + elem.substr(
+ foundPos + entry.length) + "</li>");
+ break;
+ }
+ }
+
+ foundPos = instance.options.ignoreCase ?
+ elem.toLowerCase().indexOf(entry.toLowerCase(), foundPos + 1) :
+ elem.indexOf(entry, foundPos + 1);
+
+ }
+ }
+ if (partial.length)
+ ret = ret.concat(partial.slice(0, instance.options.choices - ret.length));
+ return "<ul>" + ret.join('') + "</ul>";
+ }
+ }, options || { });
+ }
+});
+
+// AJAX in-place editor and collection editor
+// Full rewrite by Christophe Porteneuve <tdd(a)tddsworld.com> (April 2007).
+
+// Use this if you notice weird scrolling problems on some browsers,
+// the DOM might be a bit confused when this gets called so do this
+// waits 1 ms (with setTimeout) until it does the activation
+Field.scrollFreeActivate = function(field) {
+ setTimeout(function() {
+ Field.activate(field);
+ }, 1);
+};
+
+Ajax.InPlaceEditor = Class.create({
+ initialize: function(element, url, options) {
+ this.url = url;
+ this.element = element = $(element);
+ this.prepareOptions();
+ this._controls = { };
+ arguments.callee.dealWithDeprecatedOptions(options); // DEPRECATION LAYER!!!
+ Object.extend(this.options, options || { });
+ if (!this.options.formId && this.element.id) {
+ this.options.formId = this.element.id + '-inplaceeditor';
+ if ($(this.options.formId))
+ this.options.formId = '';
+ }
+ if (this.options.externalControl)
+ this.options.externalControl = $(this.options.externalControl);
+ if (!this.options.externalControl)
+ this.options.externalControlOnly = false;
+ this._originalBackground = this.element.getStyle('background-color') || 'transparent';
+ this.element.title = this.options.clickToEditText;
+ this._boundCancelHandler = this.handleFormCancellation.bind(this);
+ this._boundComplete = (this.options.onComplete || Prototype.emptyFunction).bind(this);
+ this._boundFailureHandler = this.handleAJAXFailure.bind(this);
+ this._boundSubmitHandler = this.handleFormSubmission.bind(this);
+ this._boundWrapperHandler = this.wrapUp.bind(this);
+ this.registerListeners();
+ },
+ checkForEscapeOrReturn: function(e) {
+ if (!this._editing || e.ctrlKey || e.altKey || e.shiftKey) return;
+ if (Event.KEY_ESC == e.keyCode)
+ this.handleFormCancellation(e);
+ else if (Event.KEY_RETURN == e.keyCode)
+ this.handleFormSubmission(e);
+ },
+ createControl: function(mode, handler, extraClasses) {
+ var control = this.options[mode + 'Control'];
+ var text = this.options[mode + 'Text'];
+ if ('button' == control) {
+ var btn = document.createElement('input');
+ btn.type = 'submit';
+ btn.value = text;
+ btn.className = 'editor_' + mode + '_button';
+ if ('cancel' == mode)
+ btn.onclick = this._boundCancelHandler;
+ this._form.appendChild(btn);
+ this._controls[mode] = btn;
+ } else if ('link' == control) {
+ var link = document.createElement('a');
+ link.href = '#';
+ link.appendChild(document.createTextNode(text));
+ link.onclick = 'cancel' == mode ? this._boundCancelHandler : this._boundSubmitHandler;
+ link.className = 'editor_' + mode + '_link';
+ if (extraClasses)
+ link.className += ' ' + extraClasses;
+ this._form.appendChild(link);
+ this._controls[mode] = link;
+ }
+ },
+ createEditField: function() {
+ var text = (this.options.loadTextURL ? this.options.loadingText : this.getText());
+ var fld;
+ if (1 >= this.options.rows && !/\r|\n/.test(this.getText())) {
+ fld = document.createElement('input');
+ fld.type = 'text';
+ var size = this.options.size || this.options.cols || 0;
+ if (0 < size) fld.size = size;
+ } else {
+ fld = document.createElement('textarea');
+ fld.rows = (1 >= this.options.rows ? this.options.autoRows : this.options.rows);
+ fld.cols = this.options.cols || 40;
+ }
+ fld.name = this.options.paramName;
+ fld.value = text; // No HTML breaks conversion anymore
+ fld.className = 'editor_field';
+ if (this.options.submitOnBlur)
+ fld.onblur = this._boundSubmitHandler;
+ this._controls.editor = fld;
+ if (this.options.loadTextURL)
+ this.loadExternalText();
+ this._form.appendChild(this._controls.editor);
+ },
+ createForm: function() {
+ var ipe = this;
+ function addText(mode, condition) {
+ var text = ipe.options['text' + mode + 'Controls'];
+ if (!text || condition === false) return;
+ ipe._form.appendChild(document.createTextNode(text));
+ };
+ this._form = $(document.createElement('form'));
+ this._form.id = this.options.formId;
+ this._form.addClassName(this.options.formClassName);
+ this._form.onsubmit = this._boundSubmitHandler;
+ this.createEditField();
+ if ('textarea' == this._controls.editor.tagName.toLowerCase())
+ this._form.appendChild(document.createElement('br'));
+ if (this.options.onFormCustomization)
+ this.options.onFormCustomization(this, this._form);
+ addText('Before', this.options.okControl || this.options.cancelControl);
+ this.createControl('ok', this._boundSubmitHandler);
+ addText('Between', this.options.okControl && this.options.cancelControl);
+ this.createControl('cancel', this._boundCancelHandler, 'editor_cancel');
+ addText('After', this.options.okControl || this.options.cancelControl);
+ },
+ destroy: function() {
+ if (this._oldInnerHTML)
+ this.element.innerHTML = this._oldInnerHTML;
+ this.leaveEditMode();
+ this.unregisterListeners();
+ },
+ enterEditMode: function(e) {
+ if (this._saving || this._editing) return;
+ this._editing = true;
+ this.triggerCallback('onEnterEditMode');
+ if (this.options.externalControl)
+ this.options.externalControl.hide();
+ this.element.hide();
+ this.createForm();
+ this.element.parentNode.insertBefore(this._form, this.element);
+ if (!this.options.loadTextURL)
+ this.postProcessEditField();
+ if (e) Event.stop(e);
+ },
+ enterHover: function(e) {
+ if (this.options.hoverClassName)
+ this.element.addClassName(this.options.hoverClassName);
+ if (this._saving) return;
+ this.triggerCallback('onEnterHover');
+ },
+ getText: function() {
+ return this.element.innerHTML.unescapeHTML();
+ },
+ handleAJAXFailure: function(transport) {
+ this.triggerCallback('onFailure', transport);
+ if (this._oldInnerHTML) {
+ this.element.innerHTML = this._oldInnerHTML;
+ this._oldInnerHTML = null;
+ }
+ },
+ handleFormCancellation: function(e) {
+ this.wrapUp();
+ if (e) Event.stop(e);
+ },
+ handleFormSubmission: function(e) {
+ var form = this._form;
+ var value = $F(this._controls.editor);
+ this.prepareSubmission();
+ var params = this.options.callback(form, value) || '';
+ if (Object.isString(params))
+ params = params.toQueryParams();
+ params.editorId = this.element.id;
+ if (this.options.htmlResponse) {
+ var options = Object.extend({ evalScripts: true }, this.options.ajaxOptions);
+ Object.extend(options, {
+ parameters: params,
+ onComplete: this._boundWrapperHandler,
+ onFailure: this._boundFailureHandler
+ });
+ new Ajax.Updater({ success: this.element }, this.url, options);
+ } else {
+ var options = Object.extend({ method: 'get' }, this.options.ajaxOptions);
+ Object.extend(options, {
+ parameters: params,
+ onComplete: this._boundWrapperHandler,
+ onFailure: this._boundFailureHandler
+ });
+ new Ajax.Request(this.url, options);
+ }
+ if (e) Event.stop(e);
+ },
+ leaveEditMode: function() {
+ this.element.removeClassName(this.options.savingClassName);
+ this.removeForm();
+ this.leaveHover();
+ this.element.style.backgroundColor = this._originalBackground;
+ this.element.show();
+ if (this.options.externalControl)
+ this.options.externalControl.show();
+ this._saving = false;
+ this._editing = false;
+ this._oldInnerHTML = null;
+ this.triggerCallback('onLeaveEditMode');
+ },
+ leaveHover: function(e) {
+ if (this.options.hoverClassName)
+ this.element.removeClassName(this.options.hoverClassName);
+ if (this._saving) return;
+ this.triggerCallback('onLeaveHover');
+ },
+ loadExternalText: function() {
+ this._form.addClassName(this.options.loadingClassName);
+ this._controls.editor.disabled = true;
+ var options = Object.extend({ method: 'get' }, this.options.ajaxOptions);
+ Object.extend(options, {
+ parameters: 'editorId=' + encodeURIComponent(this.element.id),
+ onComplete: Prototype.emptyFunction,
+ onSuccess: function(transport) {
+ this._form.removeClassName(this.options.loadingClassName);
+ var text = transport.responseText;
+ if (this.options.stripLoadedTextTags)
+ text = text.stripTags();
+ this._controls.editor.value = text;
+ this._controls.editor.disabled = false;
+ this.postProcessEditField();
+ }.bind(this),
+ onFailure: this._boundFailureHandler
+ });
+ new Ajax.Request(this.options.loadTextURL, options);
+ },
+ postProcessEditField: function() {
+ var fpc = this.options.fieldPostCreation;
+ if (fpc)
+ $(this._controls.editor)['focus' == fpc ? 'focus' : 'activate']();
+ },
+ prepareOptions: function() {
+ this.options = Object.clone(Ajax.InPlaceEditor.DefaultOptions);
+ Object.extend(this.options, Ajax.InPlaceEditor.DefaultCallbacks);
+ [this._extraDefaultOptions].flatten().compact().each(function(defs) {
+ Object.extend(this.options, defs);
+ }.bind(this));
+ },
+ prepareSubmission: function() {
+ this._saving = true;
+ this.removeForm();
+ this.leaveHover();
+ this.showSaving();
+ },
+ registerListeners: function() {
+ this._listeners = { };
+ var listener;
+ $H(Ajax.InPlaceEditor.Listeners).each(function(pair) {
+ listener = this[pair.value].bind(this);
+ this._listeners[pair.key] = listener;
+ if (!this.options.externalControlOnly)
+ this.element.observe(pair.key, listener);
+ if (this.options.externalControl)
+ this.options.externalControl.observe(pair.key, listener);
+ }.bind(this));
+ },
+ removeForm: function() {
+ if (!this._form) return;
+ this._form.remove();
+ this._form = null;
+ this._controls = { };
+ },
+ showSaving: function() {
+ this._oldInnerHTML = this.element.innerHTML;
+ this.element.innerHTML = this.options.savingText;
+ this.element.addClassName(this.options.savingClassName);
+ this.element.style.backgroundColor = this._originalBackground;
+ this.element.show();
+ },
+ triggerCallback: function(cbName, arg) {
+ if ('function' == typeof this.options[cbName]) {
+ this.options[cbName](this, arg);
+ }
+ },
+ unregisterListeners: function() {
+ $H(this._listeners).each(function(pair) {
+ if (!this.options.externalControlOnly)
+ this.element.stopObserving(pair.key, pair.value);
+ if (this.options.externalControl)
+ this.options.externalControl.stopObserving(pair.key, pair.value);
+ }.bind(this));
+ },
+ wrapUp: function(transport) {
+ this.leaveEditMode();
+ // Can't use triggerCallback due to backward compatibility: requires
+ // binding + direct element
+ this._boundComplete(transport, this.element);
+ }
+});
+
+Object.extend(Ajax.InPlaceEditor.prototype, {
+ dispose: Ajax.InPlaceEditor.prototype.destroy
+});
+
+Ajax.InPlaceCollectionEditor = Class.create(Ajax.InPlaceEditor, {
+ initialize: function($super, element, url, options) {
+ this._extraDefaultOptions = Ajax.InPlaceCollectionEditor.DefaultOptions;
+ $super(element, url, options);
+ },
+
+ createEditField: function() {
+ var list = document.createElement('select');
+ list.name = this.options.paramName;
+ list.size = 1;
+ this._controls.editor = list;
+ this._collection = this.options.collection || [];
+ if (this.options.loadCollectionURL)
+ this.loadCollection();
+ else
+ this.checkForExternalText();
+ this._form.appendChild(this._controls.editor);
+ },
+
+ loadCollection: function() {
+ this._form.addClassName(this.options.loadingClassName);
+ this.showLoadingText(this.options.loadingCollectionText);
+ var options = Object.extend({ method: 'get' }, this.options.ajaxOptions);
+ Object.extend(options, {
+ parameters: 'editorId=' + encodeURIComponent(this.element.id),
+ onComplete: Prototype.emptyFunction,
+ onSuccess: function(transport) {
+ var js = transport.responseText.strip();
+ if (!/^\[.*\]$/.test(js)) // TODO: improve sanity check
+ throw('Server returned an invalid collection representation.');
+ this._collection = eval(js);
+ this.checkForExternalText();
+ }.bind(this),
+ onFailure: this.onFailure
+ });
+ new Ajax.Request(this.options.loadCollectionURL, options);
+ },
+
+ showLoadingText: function(text) {
+ this._controls.editor.disabled = true;
+ var tempOption = this._controls.editor.firstChild;
+ if (!tempOption) {
+ tempOption = document.createElement('option');
+ tempOption.value = '';
+ this._controls.editor.appendChild(tempOption);
+ tempOption.selected = true;
+ }
+ tempOption.update((text || '').stripScripts().stripTags());
+ },
+
+ checkForExternalText: function() {
+ this._text = this.getText();
+ if (this.options.loadTextURL)
+ this.loadExternalText();
+ else
+ this.buildOptionList();
+ },
+
+ loadExternalText: function() {
+ this.showLoadingText(this.options.loadingText);
+ var options = Object.extend({ method: 'get' }, this.options.ajaxOptions);
+ Object.extend(options, {
+ parameters: 'editorId=' + encodeURIComponent(this.element.id),
+ onComplete: Prototype.emptyFunction,
+ onSuccess: function(transport) {
+ this._text = transport.responseText.strip();
+ this.buildOptionList();
+ }.bind(this),
+ onFailure: this.onFailure
+ });
+ new Ajax.Request(this.options.loadTextURL, options);
+ },
+
+ buildOptionList: function() {
+ this._form.removeClassName(this.options.loadingClassName);
+ this._collection = this._collection.map(function(entry) {
+ return 2 === entry.length ? entry : [entry, entry].flatten();
+ });
+ var marker = ('value' in this.options) ? this.options.value : this._text;
+ var textFound = this._collection.any(function(entry) {
+ return entry[0] == marker;
+ }.bind(this));
+ this._controls.editor.update('');
+ var option;
+ this._collection.each(function(entry, index) {
+ option = document.createElement('option');
+ option.value = entry[0];
+ option.selected = textFound ? entry[0] == marker : 0 == index;
+ option.appendChild(document.createTextNode(entry[1]));
+ this._controls.editor.appendChild(option);
+ }.bind(this));
+ this._controls.editor.disabled = false;
+ Field.scrollFreeActivate(this._controls.editor);
+ }
+});
+
+//**** DEPRECATION LAYER FOR InPlace[Collection]Editor! ****
+//**** This only exists for a while, in order to let ****
+//**** users adapt to the new API. Read up on the new ****
+//**** API and convert your code to it ASAP! ****
+
+Ajax.InPlaceEditor.prototype.initialize.dealWithDeprecatedOptions = function(options) {
+ if (!options) return;
+ function fallback(name, expr) {
+ if (name in options || expr === undefined) return;
+ options[name] = expr;
+ };
+ fallback('cancelControl', (options.cancelLink ? 'link' : (options.cancelButton ? 'button' :
+ options.cancelLink == options.cancelButton == false ? false : undefined)));
+ fallback('okControl', (options.okLink ? 'link' : (options.okButton ? 'button' :
+ options.okLink == options.okButton == false ? false : undefined)));
+ fallback('highlightColor', options.highlightcolor);
+ fallback('highlightEndColor', options.highlightendcolor);
+};
+
+Object.extend(Ajax.InPlaceEditor, {
+ DefaultOptions: {
+ ajaxOptions: { },
+ autoRows: 3, // Use when multi-line w/ rows == 1
+ cancelControl: 'link', // 'link'|'button'|false
+ cancelText: 'cancel',
+ clickToEditText: 'Click to edit',
+ externalControl: null, // id|elt
+ externalControlOnly: false,
+ fieldPostCreation: 'activate', // 'activate'|'focus'|false
+ formClassName: 'inplaceeditor-form',
+ formId: null, // id|elt
+ highlightColor: '#ffff99',
+ highlightEndColor: '#ffffff',
+ hoverClassName: '',
+ htmlResponse: true,
+ loadingClassName: 'inplaceeditor-loading',
+ loadingText: 'Loading...',
+ okControl: 'button', // 'link'|'button'|false
+ okText: 'ok',
+ paramName: 'value',
+ rows: 1, // If 1 and multi-line, uses autoRows
+ savingClassName: 'inplaceeditor-saving',
+ savingText: 'Saving...',
+ size: 0,
+ stripLoadedTextTags: false,
+ submitOnBlur: false,
+ textAfterControls: '',
+ textBeforeControls: '',
+ textBetweenControls: ''
+ },
+ DefaultCallbacks: {
+ callback: function(form) {
+ return Form.serialize(form);
+ },
+ onComplete: function(transport, element) {
+ // For backward compatibility, this one is bound to the IPE, and passes
+ // the element directly. It was too often customized, so we don't break it.
+ new Effect.Highlight(element, {
+ startcolor: this.options.highlightColor, keepBackgroundImage: true });
+ },
+ onEnterEditMode: null,
+ onEnterHover: function(ipe) {
+ ipe.element.style.backgroundColor = ipe.options.highlightColor;
+ if (ipe._effect)
+ ipe._effect.cancel();
+ },
+ onFailure: function(transport, ipe) {
+ alert('Error communication with the server: ' + transport.responseText.stripTags());
+ },
+ onFormCustomization: null, // Takes the IPE and its generated form, after editor, before controls.
+ onLeaveEditMode: null,
+ onLeaveHover: function(ipe) {
+ ipe._effect = new Effect.Highlight(ipe.element, {
+ startcolor: ipe.options.highlightColor, endcolor: ipe.options.highlightEndColor,
+ restorecolor: ipe._originalBackground, keepBackgroundImage: true
+ });
+ }
+ },
+ Listeners: {
+ click: 'enterEditMode',
+ keydown: 'checkForEscapeOrReturn',
+ mouseover: 'enterHover',
+ mouseout: 'leaveHover'
+ }
+});
+
+Ajax.InPlaceCollectionEditor.DefaultOptions = {
+ loadingCollectionText: 'Loading options...'
+};
+
+// Delayed observer, like Form.Element.Observer,
+// but waits for delay after last key input
+// Ideal for live-search fields
+
+Form.Element.DelayedObserver = Class.create({
+ initialize: function(element, delay, callback) {
+ this.delay = delay || 0.5;
+ this.element = $(element);
+ this.callback = callback;
+ this.timer = null;
+ this.lastValue = $F(this.element);
+ Event.observe(this.element,'keyup',this.delayedListener.bindAsEventListener(this));
+ },
+ delayedListener: function(event) {
+ if(this.lastValue == $F(this.element)) return;
+ if(this.timer) clearTimeout(this.timer);
+ this.timer = setTimeout(this.onTimerEvent.bind(this), this.delay * 1000);
+ this.lastValue = $F(this.element);
+ },
+ onTimerEvent: function() {
+ this.timer = null;
+ this.callback(this.element, $F(this.element));
+ }
+});
\ No newline at end of file
Added: trunk/src/ajax/javascripts/external/scriptaculous/dragdrop.js
==============================================================================
--- (empty file)
+++ trunk/src/ajax/javascripts/external/scriptaculous/dragdrop.js Fri Apr 10 19:11:32 2009
@@ -0,0 +1,975 @@
+// script.aculo.us dragdrop.js v1.8.2, Tue Nov 18 18:30:58 +0100 2008
+
+// Copyright (c) 2005-2008 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
+// (c) 2005-2008 Sammi Williams (http://www.oriontransfer.co.nz, sammi(a)oriontransfer.co.nz)
+//
+// script.aculo.us is freely distributable under the terms of an MIT-style license.
+// For details, see the script.aculo.us web site: http://script.aculo.us/
+
+if(Object.isUndefined(Effect))
+ throw("dragdrop.js requires including script.aculo.us' effects.js library");
+
+var Droppables = {
+ drops: [],
+
+ remove: function(element) {
+ this.drops = this.drops.reject(function(d) { return d.element==$(element) });
+ },
+
+ add: function(element) {
+ element = $(element);
+ var options = Object.extend({
+ greedy: true,
+ hoverclass: null,
+ tree: false
+ }, arguments[1] || { });
+
+ // cache containers
+ if(options.containment) {
+ options._containers = [];
+ var containment = options.containment;
+ if(Object.isArray(containment)) {
+ containment.each( function(c) { options._containers.push($(c)) });
+ } else {
+ options._containers.push($(containment));
+ }
+ }
+
+ if(options.accept) options.accept = [options.accept].flatten();
+
+ Element.makePositioned(element); // fix IE
+ options.element = element;
+
+ this.drops.push(options);
+ },
+
+ findDeepestChild: function(drops) {
+ deepest = drops[0];
+
+ for (i = 1; i < drops.length; ++i)
+ if (Element.isParent(drops[i].element, deepest.element))
+ deepest = drops[i];
+
+ return deepest;
+ },
+
+ isContained: function(element, drop) {
+ var containmentNode;
+ if(drop.tree) {
+ containmentNode = element.treeNode;
+ } else {
+ containmentNode = element.parentNode;
+ }
+ return drop._containers.detect(function(c) { return containmentNode == c });
+ },
+
+ isAffected: function(point, element, drop) {
+ return (
+ (drop.element!=element) &&
+ ((!drop._containers) ||
+ this.isContained(element, drop)) &&
+ ((!drop.accept) ||
+ (Element.classNames(element).detect(
+ function(v) { return drop.accept.include(v) } ) )) &&
+ Position.within(drop.element, point[0], point[1]) );
+ },
+
+ deactivate: function(drop) {
+ if(drop.hoverclass)
+ Element.removeClassName(drop.element, drop.hoverclass);
+ this.last_active = null;
+ },
+
+ activate: function(drop) {
+ if(drop.hoverclass)
+ Element.addClassName(drop.element, drop.hoverclass);
+ this.last_active = drop;
+ },
+
+ show: function(point, element) {
+ if(!this.drops.length) return;
+ var drop, affected = [];
+
+ this.drops.each( function(drop) {
+ if(Droppables.isAffected(point, element, drop))
+ affected.push(drop);
+ });
+
+ if(affected.length>0)
+ drop = Droppables.findDeepestChild(affected);
+
+ if(this.last_active && this.last_active != drop) this.deactivate(this.last_active);
+ if (drop) {
+ Position.within(drop.element, point[0], point[1]);
+ if(drop.onHover)
+ drop.onHover(element, drop.element, Position.overlap(drop.overlap, drop.element));
+
+ if (drop != this.last_active) Droppables.activate(drop);
+ }
+ },
+
+ fire: function(event, element) {
+ if(!this.last_active) return;
+ Position.prepare();
+
+ if (this.isAffected([Event.pointerX(event), Event.pointerY(event)], element, this.last_active))
+ if (this.last_active.onDrop) {
+ this.last_active.onDrop(element, this.last_active.element, event);
+ return true;
+ }
+ },
+
+ reset: function() {
+ if(this.last_active)
+ this.deactivate(this.last_active);
+ }
+};
+
+var Draggables = {
+ drags: [],
+ observers: [],
+
+ register: function(draggable) {
+ if(this.drags.length == 0) {
+ this.eventMouseUp = this.endDrag.bindAsEventListener(this);
+ this.eventMouseMove = this.updateDrag.bindAsEventListener(this);
+ this.eventKeypress = this.keyPress.bindAsEventListener(this);
+
+ Event.observe(document, "mouseup", this.eventMouseUp);
+ Event.observe(document, "mousemove", this.eventMouseMove);
+ Event.observe(document, "keypress", this.eventKeypress);
+ }
+ this.drags.push(draggable);
+ },
+
+ unregister: function(draggable) {
+ this.drags = this.drags.reject(function(d) { return d==draggable });
+ if(this.drags.length == 0) {
+ Event.stopObserving(document, "mouseup", this.eventMouseUp);
+ Event.stopObserving(document, "mousemove", this.eventMouseMove);
+ Event.stopObserving(document, "keypress", this.eventKeypress);
+ }
+ },
+
+ activate: function(draggable) {
+ if(draggable.options.delay) {
+ this._timeout = setTimeout(function() {
+ Draggables._timeout = null;
+ window.focus();
+ Draggables.activeDraggable = draggable;
+ }.bind(this), draggable.options.delay);
+ } else {
+ window.focus(); // allows keypress events if window isn't currently focused, fails for Safari
+ this.activeDraggable = draggable;
+ }
+ },
+
+ deactivate: function() {
+ this.activeDraggable = null;
+ },
+
+ updateDrag: function(event) {
+ if(!this.activeDraggable) return;
+ var pointer = [Event.pointerX(event), Event.pointerY(event)];
+ // Mozilla-based browsers fire successive mousemove events with
+ // the same coordinates, prevent needless redrawing (moz bug?)
+ if(this._lastPointer && (this._lastPointer.inspect() == pointer.inspect())) return;
+ this._lastPointer = pointer;
+
+ this.activeDraggable.updateDrag(event, pointer);
+ },
+
+ endDrag: function(event) {
+ if(this._timeout) {
+ clearTimeout(this._timeout);
+ this._timeout = null;
+ }
+ if(!this.activeDraggable) return;
+ this._lastPointer = null;
+ this.activeDraggable.endDrag(event);
+ this.activeDraggable = null;
+ },
+
+ keyPress: function(event) {
+ if(this.activeDraggable)
+ this.activeDraggable.keyPress(event);
+ },
+
+ addObserver: function(observer) {
+ this.observers.push(observer);
+ this._cacheObserverCallbacks();
+ },
+
+ removeObserver: function(element) { // element instead of observer fixes mem leaks
+ this.observers = this.observers.reject( function(o) { return o.element==element });
+ this._cacheObserverCallbacks();
+ },
+
+ notify: function(eventName, draggable, event) { // 'onStart', 'onEnd', 'onDrag'
+ if(this[eventName+'Count'] > 0)
+ this.observers.each( function(o) {
+ if(o[eventName]) o[eventName](eventName, draggable, event);
+ });
+ if(draggable.options[eventName]) draggable.options[eventName](draggable, event);
+ },
+
+ _cacheObserverCallbacks: function() {
+ ['onStart','onEnd','onDrag'].each( function(eventName) {
+ Draggables[eventName+'Count'] = Draggables.observers.select(
+ function(o) { return o[eventName]; }
+ ).length;
+ });
+ }
+};
+
+/*--------------------------------------------------------------------------*/
+
+var Draggable = Class.create({
+ initialize: function(element) {
+ var defaults = {
+ handle: false,
+ reverteffect: function(element, top_offset, left_offset) {
+ var dur = Math.sqrt(Math.abs(top_offset^2)+Math.abs(left_offset^2))*0.02;
+ new Effect.Move(element, { x: -left_offset, y: -top_offset, duration: dur,
+ queue: {scope:'_draggable', position:'end'}
+ });
+ },
+ endeffect: function(element) {
+ var toOpacity = Object.isNumber(element._opacity) ? element._opacity : 1.0;
+ new Effect.Opacity(element, {duration:0.2, from:0.7, to:toOpacity,
+ queue: {scope:'_draggable', position:'end'},
+ afterFinish: function(){
+ Draggable._dragging[element] = false
+ }
+ });
+ },
+ zindex: 1000,
+ revert: false,
+ quiet: false,
+ scroll: false,
+ scrollSensitivity: 20,
+ scrollSpeed: 15,
+ snap: false, // false, or xy or [x,y] or function(x,y){ return [x,y] }
+ delay: 0
+ };
+
+ if(!arguments[1] || Object.isUndefined(arguments[1].endeffect))
+ Object.extend(defaults, {
+ starteffect: function(element) {
+ element._opacity = Element.getOpacity(element);
+ Draggable._dragging[element] = true;
+ new Effect.Opacity(element, {duration:0.2, from:element._opacity, to:0.7});
+ }
+ });
+
+ var options = Object.extend(defaults, arguments[1] || { });
+
+ this.element = $(element);
+
+ if(options.handle && Object.isString(options.handle))
+ this.handle = this.element.down('.'+options.handle, 0);
+
+ if(!this.handle) this.handle = $(options.handle);
+ if(!this.handle) this.handle = this.element;
+
+ if(options.scroll && !options.scroll.scrollTo && !options.scroll.outerHTML) {
+ options.scroll = $(options.scroll);
+ this._isScrollChild = Element.childOf(this.element, options.scroll);
+ }
+
+ Element.makePositioned(this.element); // fix IE
+
+ this.options = options;
+ this.dragging = false;
+
+ this.eventMouseDown = this.initDrag.bindAsEventListener(this);
+ Event.observe(this.handle, "mousedown", this.eventMouseDown);
+
+ Draggables.register(this);
+ },
+
+ destroy: function() {
+ Event.stopObserving(this.handle, "mousedown", this.eventMouseDown);
+ Draggables.unregister(this);
+ },
+
+ currentDelta: function() {
+ return([
+ parseInt(Element.getStyle(this.element,'left') || '0'),
+ parseInt(Element.getStyle(this.element,'top') || '0')]);
+ },
+
+ initDrag: function(event) {
+ if(!Object.isUndefined(Draggable._dragging[this.element]) &&
+ Draggable._dragging[this.element]) return;
+ if(Event.isLeftClick(event)) {
+ // abort on form elements, fixes a Firefox issue
+ var src = Event.element(event);
+ if((tag_name = src.tagName.toUpperCase()) && (
+ tag_name=='INPUT' ||
+ tag_name=='SELECT' ||
+ tag_name=='OPTION' ||
+ tag_name=='BUTTON' ||
+ tag_name=='TEXTAREA')) return;
+
+ var pointer = [Event.pointerX(event), Event.pointerY(event)];
+ var pos = Position.cumulativeOffset(this.element);
+ this.offset = [0,1].map( function(i) { return (pointer[i] - pos[i]) });
+
+ Draggables.activate(this);
+ Event.stop(event);
+ }
+ },
+
+ startDrag: function(event) {
+ this.dragging = true;
+ if(!this.delta)
+ this.delta = this.currentDelta();
+
+ if(this.options.zindex) {
+ this.originalZ = parseInt(Element.getStyle(this.element,'z-index') || 0);
+ this.element.style.zIndex = this.options.zindex;
+ }
+
+ if(this.options.ghosting) {
+ this._clone = this.element.cloneNode(true);
+ this._originallyAbsolute = (this.element.getStyle('position') == 'absolute');
+ if (!this._originallyAbsolute)
+ Position.absolutize(this.element);
+ this.element.parentNode.insertBefore(this._clone, this.element);
+ }
+
+ if(this.options.scroll) {
+ if (this.options.scroll == window) {
+ var where = this._getWindowScroll(this.options.scroll);
+ this.originalScrollLeft = where.left;
+ this.originalScrollTop = where.top;
+ } else {
+ this.originalScrollLeft = this.options.scroll.scrollLeft;
+ this.originalScrollTop = this.options.scroll.scrollTop;
+ }
+ }
+
+ Draggables.notify('onStart', this, event);
+
+ if(this.options.starteffect) this.options.starteffect(this.element);
+ },
+
+ updateDrag: function(event, pointer) {
+ if(!this.dragging) this.startDrag(event);
+
+ if(!this.options.quiet){
+ Position.prepare();
+ Droppables.show(pointer, this.element);
+ }
+
+ Draggables.notify('onDrag', this, event);
+
+ this.draw(pointer);
+ if(this.options.change) this.options.change(this);
+
+ if(this.options.scroll) {
+ this.stopScrolling();
+
+ var p;
+ if (this.options.scroll == window) {
+ with(this._getWindowScroll(this.options.scroll)) { p = [ left, top, left+width, top+height ]; }
+ } else {
+ p = Position.page(this.options.scroll);
+ p[0] += this.options.scroll.scrollLeft + Position.deltaX;
+ p[1] += this.options.scroll.scrollTop + Position.deltaY;
+ p.push(p[0]+this.options.scroll.offsetWidth);
+ p.push(p[1]+this.options.scroll.offsetHeight);
+ }
+ var speed = [0,0];
+ if(pointer[0] < (p[0]+this.options.scrollSensitivity)) speed[0] = pointer[0]-(p[0]+this.options.scrollSensitivity);
+ if(pointer[1] < (p[1]+this.options.scrollSensitivity)) speed[1] = pointer[1]-(p[1]+this.options.scrollSensitivity);
+ if(pointer[0] > (p[2]-this.options.scrollSensitivity)) speed[0] = pointer[0]-(p[2]-this.options.scrollSensitivity);
+ if(pointer[1] > (p[3]-this.options.scrollSensitivity)) speed[1] = pointer[1]-(p[3]-this.options.scrollSensitivity);
+ this.startScrolling(speed);
+ }
+
+ // fix AppleWebKit rendering
+ if(Prototype.Browser.WebKit) window.scrollBy(0,0);
+
+ Event.stop(event);
+ },
+
+ finishDrag: function(event, success) {
+ this.dragging = false;
+
+ if(this.options.quiet){
+ Position.prepare();
+ var pointer = [Event.pointerX(event), Event.pointerY(event)];
+ Droppables.show(pointer, this.element);
+ }
+
+ if(this.options.ghosting) {
+ if (!this._originallyAbsolute)
+ Position.relativize(this.element);
+ delete this._originallyAbsolute;
+ Element.remove(this._clone);
+ this._clone = null;
+ }
+
+ var dropped = false;
+ if(success) {
+ dropped = Droppables.fire(event, this.element);
+ if (!dropped) dropped = false;
+ }
+ if(dropped && this.options.onDropped) this.options.onDropped(this.element);
+ Draggables.notify('onEnd', this, event);
+
+ var revert = this.options.revert;
+ if(revert && Object.isFunction(revert)) revert = revert(this.element);
+
+ var d = this.currentDelta();
+ if(revert && this.options.reverteffect) {
+ if (dropped == 0 || revert != 'failure')
+ this.options.reverteffect(this.element,
+ d[1]-this.delta[1], d[0]-this.delta[0]);
+ } else {
+ this.delta = d;
+ }
+
+ if(this.options.zindex)
+ this.element.style.zIndex = this.originalZ;
+
+ if(this.options.endeffect)
+ this.options.endeffect(this.element);
+
+ Draggables.deactivate(this);
+ Droppables.reset();
+ },
+
+ keyPress: function(event) {
+ if(event.keyCode!=Event.KEY_ESC) return;
+ this.finishDrag(event, false);
+ Event.stop(event);
+ },
+
+ endDrag: function(event) {
+ if(!this.dragging) return;
+ this.stopScrolling();
+ this.finishDrag(event, true);
+ Event.stop(event);
+ },
+
+ draw: function(point) {
+ var pos = Position.cumulativeOffset(this.element);
+ if(this.options.ghosting) {
+ var r = Position.realOffset(this.element);
+ pos[0] += r[0] - Position.deltaX; pos[1] += r[1] - Position.deltaY;
+ }
+
+ var d = this.currentDelta();
+ pos[0] -= d[0]; pos[1] -= d[1];
+
+ if(this.options.scroll && (this.options.scroll != window && this._isScrollChild)) {
+ pos[0] -= this.options.scroll.scrollLeft-this.originalScrollLeft;
+ pos[1] -= this.options.scroll.scrollTop-this.originalScrollTop;
+ }
+
+ var p = [0,1].map(function(i){
+ return (point[i]-pos[i]-this.offset[i])
+ }.bind(this));
+
+ if(this.options.snap) {
+ if(Object.isFunction(this.options.snap)) {
+ p = this.options.snap(p[0],p[1],this);
+ } else {
+ if(Object.isArray(this.options.snap)) {
+ p = p.map( function(v, i) {
+ return (v/this.options.snap[i]).round()*this.options.snap[i] }.bind(this));
+ } else {
+ p = p.map( function(v) {
+ return (v/this.options.snap).round()*this.options.snap }.bind(this));
+ }
+ }}
+
+ var style = this.element.style;
+ if((!this.options.constraint) || (this.options.constraint=='horizontal'))
+ style.left = p[0] + "px";
+ if((!this.options.constraint) || (this.options.constraint=='vertical'))
+ style.top = p[1] + "px";
+
+ if(style.visibility=="hidden") style.visibility = ""; // fix gecko rendering
+ },
+
+ stopScrolling: function() {
+ if(this.scrollInterval) {
+ clearInterval(this.scrollInterval);
+ this.scrollInterval = null;
+ Draggables._lastScrollPointer = null;
+ }
+ },
+
+ startScrolling: function(speed) {
+ if(!(speed[0] || speed[1])) return;
+ this.scrollSpeed = [speed[0]*this.options.scrollSpeed,speed[1]*this.options.scrollSpeed];
+ this.lastScrolled = new Date();
+ this.scrollInterval = setInterval(this.scroll.bind(this), 10);
+ },
+
+ scroll: function() {
+ var current = new Date();
+ var delta = current - this.lastScrolled;
+ this.lastScrolled = current;
+ if(this.options.scroll == window) {
+ with (this._getWindowScroll(this.options.scroll)) {
+ if (this.scrollSpeed[0] || this.scrollSpeed[1]) {
+ var d = delta / 1000;
+ this.options.scroll.scrollTo( left + d*this.scrollSpeed[0], top + d*this.scrollSpeed[1] );
+ }
+ }
+ } else {
+ this.options.scroll.scrollLeft += this.scrollSpeed[0] * delta / 1000;
+ this.options.scroll.scrollTop += this.scrollSpeed[1] * delta / 1000;
+ }
+
+ Position.prepare();
+ Droppables.show(Draggables._lastPointer, this.element);
+ Draggables.notify('onDrag', this);
+ if (this._isScrollChild) {
+ Draggables._lastScrollPointer = Draggables._lastScrollPointer || $A(Draggables._lastPointer);
+ Draggables._lastScrollPointer[0] += this.scrollSpeed[0] * delta / 1000;
+ Draggables._lastScrollPointer[1] += this.scrollSpeed[1] * delta / 1000;
+ if (Draggables._lastScrollPointer[0] < 0)
+ Draggables._lastScrollPointer[0] = 0;
+ if (Draggables._lastScrollPointer[1] < 0)
+ Draggables._lastScrollPointer[1] = 0;
+ this.draw(Draggables._lastScrollPointer);
+ }
+
+ if(this.options.change) this.options.change(this);
+ },
+
+ _getWindowScroll: function(w) {
+ var T, L, W, H;
+ with (w.document) {
+ if (w.document.documentElement && documentElement.scrollTop) {
+ T = documentElement.scrollTop;
+ L = documentElement.scrollLeft;
+ } else if (w.document.body) {
+ T = body.scrollTop;
+ L = body.scrollLeft;
+ }
+ if (w.innerWidth) {
+ W = w.innerWidth;
+ H = w.innerHeight;
+ } else if (w.document.documentElement && documentElement.clientWidth) {
+ W = documentElement.clientWidth;
+ H = documentElement.clientHeight;
+ } else {
+ W = body.offsetWidth;
+ H = body.offsetHeight;
+ }
+ }
+ return { top: T, left: L, width: W, height: H };
+ }
+});
+
+Draggable._dragging = { };
+
+/*--------------------------------------------------------------------------*/
+
+var SortableObserver = Class.create({
+ initialize: function(element, observer) {
+ this.element = $(element);
+ this.observer = observer;
+ this.lastValue = Sortable.serialize(this.element);
+ },
+
+ onStart: function() {
+ this.lastValue = Sortable.serialize(this.element);
+ },
+
+ onEnd: function() {
+ Sortable.unmark();
+ if(this.lastValue != Sortable.serialize(this.element))
+ this.observer(this.element)
+ }
+});
+
+var Sortable = {
+ SERIALIZE_RULE: /^[^_\-](?:[A-Za-z0-9\-\_]*)[_](.*)$/,
+
+ sortables: { },
+
+ _findRootElement: function(element) {
+ while (element.tagName.toUpperCase() != "BODY") {
+ if(element.id && Sortable.sortables[element.id]) return element;
+ element = element.parentNode;
+ }
+ },
+
+ options: function(element) {
+ element = Sortable._findRootElement($(element));
+ if(!element) return;
+ return Sortable.sortables[element.id];
+ },
+
+ destroy: function(element){
+ element = $(element);
+ var s = Sortable.sortables[element.id];
+
+ if(s) {
+ Draggables.removeObserver(s.element);
+ s.droppables.each(function(d){ Droppables.remove(d) });
+ s.draggables.invoke('destroy');
+
+ delete Sortable.sortables[s.element.id];
+ }
+ },
+
+ create: function(element) {
+ element = $(element);
+ var options = Object.extend({
+ element: element,
+ tag: 'li', // assumes li children, override with tag: 'tagname'
+ dropOnEmpty: false,
+ tree: false,
+ treeTag: 'ul',
+ overlap: 'vertical', // one of 'vertical', 'horizontal'
+ constraint: 'vertical', // one of 'vertical', 'horizontal', false
+ containment: element, // also takes array of elements (or id's); or false
+ handle: false, // or a CSS class
+ only: false,
+ delay: 0,
+ hoverclass: null,
+ ghosting: false,
+ quiet: false,
+ scroll: false,
+ scrollSensitivity: 20,
+ scrollSpeed: 15,
+ format: this.SERIALIZE_RULE,
+
+ // these take arrays of elements or ids and can be
+ // used for better initialization performance
+ elements: false,
+ handles: false,
+
+ onChange: Prototype.emptyFunction,
+ onUpdate: Prototype.emptyFunction
+ }, arguments[1] || { });
+
+ // clear any old sortable with same element
+ this.destroy(element);
+
+ // build options for the draggables
+ var options_for_draggable = {
+ revert: true,
+ quiet: options.quiet,
+ scroll: options.scroll,
+ scrollSpeed: options.scrollSpeed,
+ scrollSensitivity: options.scrollSensitivity,
+ delay: options.delay,
+ ghosting: options.ghosting,
+ constraint: options.constraint,
+ handle: options.handle };
+
+ if(options.starteffect)
+ options_for_draggable.starteffect = options.starteffect;
+
+ if(options.reverteffect)
+ options_for_draggable.reverteffect = options.reverteffect;
+ else
+ if(options.ghosting) options_for_draggable.reverteffect = function(element) {
+ element.style.top = 0;
+ element.style.left = 0;
+ };
+
+ if(options.endeffect)
+ options_for_draggable.endeffect = options.endeffect;
+
+ if(options.zindex)
+ options_for_draggable.zindex = options.zindex;
+
+ // build options for the droppables
+ var options_for_droppable = {
+ overlap: options.overlap,
+ containment: options.containment,
+ tree: options.tree,
+ hoverclass: options.hoverclass,
+ onHover: Sortable.onHover
+ };
+
+ var options_for_tree = {
+ onHover: Sortable.onEmptyHover,
+ overlap: options.overlap,
+ containment: options.containment,
+ hoverclass: options.hoverclass
+ };
+
+ // fix for gecko engine
+ Element.cleanWhitespace(element);
+
+ options.draggables = [];
+ options.droppables = [];
+
+ // drop on empty handling
+ if(options.dropOnEmpty || options.tree) {
+ Droppables.add(element, options_for_tree);
+ options.droppables.push(element);
+ }
+
+ (options.elements || this.findElements(element, options) || []).each( function(e,i) {
+ var handle = options.handles ? $(options.handles[i]) :
+ (options.handle ? $(e).select('.' + options.handle)[0] : e);
+ options.draggables.push(
+ new Draggable(e, Object.extend(options_for_draggable, { handle: handle })));
+ Droppables.add(e, options_for_droppable);
+ if(options.tree) e.treeNode = element;
+ options.droppables.push(e);
+ });
+
+ if(options.tree) {
+ (Sortable.findTreeElements(element, options) || []).each( function(e) {
+ Droppables.add(e, options_for_tree);
+ e.treeNode = element;
+ options.droppables.push(e);
+ });
+ }
+
+ // keep reference
+ this.sortables[element.id] = options;
+
+ // for onupdate
+ Draggables.addObserver(new SortableObserver(element, options.onUpdate));
+
+ },
+
+ // return all suitable-for-sortable elements in a guaranteed order
+ findElements: function(element, options) {
+ return Element.findChildren(
+ element, options.only, options.tree ? true : false, options.tag);
+ },
+
+ findTreeElements: function(element, options) {
+ return Element.findChildren(
+ element, options.only, options.tree ? true : false, options.treeTag);
+ },
+
+ onHover: function(element, dropon, overlap) {
+ if(Element.isParent(dropon, element)) return;
+
+ if(overlap > .33 && overlap < .66 && Sortable.options(dropon).tree) {
+ return;
+ } else if(overlap>0.5) {
+ Sortable.mark(dropon, 'before');
+ if(dropon.previousSibling != element) {
+ var oldParentNode = element.parentNode;
+ element.style.visibility = "hidden"; // fix gecko rendering
+ dropon.parentNode.insertBefore(element, dropon);
+ if(dropon.parentNode!=oldParentNode)
+ Sortable.options(oldParentNode).onChange(element);
+ Sortable.options(dropon.parentNode).onChange(element);
+ }
+ } else {
+ Sortable.mark(dropon, 'after');
+ var nextElement = dropon.nextSibling || null;
+ if(nextElement != element) {
+ var oldParentNode = element.parentNode;
+ element.style.visibility = "hidden"; // fix gecko rendering
+ dropon.parentNode.insertBefore(element, nextElement);
+ if(dropon.parentNode!=oldParentNode)
+ Sortable.options(oldParentNode).onChange(element);
+ Sortable.options(dropon.parentNode).onChange(element);
+ }
+ }
+ },
+
+ onEmptyHover: function(element, dropon, overlap) {
+ var oldParentNode = element.parentNode;
+ var droponOptions = Sortable.options(dropon);
+
+ if(!Element.isParent(dropon, element)) {
+ var index;
+
+ var children = Sortable.findElements(dropon, {tag: droponOptions.tag, only: droponOptions.only});
+ var child = null;
+
+ if(children) {
+ var offset = Element.offsetSize(dropon, droponOptions.overlap) * (1.0 - overlap);
+
+ for (index = 0; index < children.length; index += 1) {
+ if (offset - Element.offsetSize (children[index], droponOptions.overlap) >= 0) {
+ offset -= Element.offsetSize (children[index], droponOptions.overlap);
+ } else if (offset - (Element.offsetSize (children[index], droponOptions.overlap) / 2) >= 0) {
+ child = index + 1 < children.length ? children[index + 1] : null;
+ break;
+ } else {
+ child = children[index];
+ break;
+ }
+ }
+ }
+
+ dropon.insertBefore(element, child);
+
+ Sortable.options(oldParentNode).onChange(element);
+ droponOptions.onChange(element);
+ }
+ },
+
+ unmark: function() {
+ if(Sortable._marker) Sortable._marker.hide();
+ },
+
+ mark: function(dropon, position) {
+ // mark on ghosting only
+ var sortable = Sortable.options(dropon.parentNode);
+ if(sortable && !sortable.ghosting) return;
+
+ if(!Sortable._marker) {
+ Sortable._marker =
+ ($('dropmarker') || Element.extend(document.createElement('DIV'))).
+ hide().addClassName('dropmarker').setStyle({position:'absolute'});
+ document.getElementsByTagName("body").item(0).appendChild(Sortable._marker);
+ }
+ var offsets = Position.cumulativeOffset(dropon);
+ Sortable._marker.setStyle({left: offsets[0]+'px', top: offsets[1] + 'px'});
+
+ if(position=='after')
+ if(sortable.overlap == 'horizontal')
+ Sortable._marker.setStyle({left: (offsets[0]+dropon.clientWidth) + 'px'});
+ else
+ Sortable._marker.setStyle({top: (offsets[1]+dropon.clientHeight) + 'px'});
+
+ Sortable._marker.show();
+ },
+
+ _tree: function(element, options, parent) {
+ var children = Sortable.findElements(element, options) || [];
+
+ for (var i = 0; i < children.length; ++i) {
+ var match = children[i].id.match(options.format);
+
+ if (!match) continue;
+
+ var child = {
+ id: encodeURIComponent(match ? match[1] : null),
+ element: element,
+ parent: parent,
+ children: [],
+ position: parent.children.length,
+ container: $(children[i]).down(options.treeTag)
+ };
+
+ /* Get the element containing the children and recurse over it */
+ if (child.container)
+ this._tree(child.container, options, child);
+
+ parent.children.push (child);
+ }
+
+ return parent;
+ },
+
+ tree: function(element) {
+ element = $(element);
+ var sortableOptions = this.options(element);
+ var options = Object.extend({
+ tag: sortableOptions.tag,
+ treeTag: sortableOptions.treeTag,
+ only: sortableOptions.only,
+ name: element.id,
+ format: sortableOptions.format
+ }, arguments[1] || { });
+
+ var root = {
+ id: null,
+ parent: null,
+ children: [],
+ container: element,
+ position: 0
+ };
+
+ return Sortable._tree(element, options, root);
+ },
+
+ /* Construct a [i] index for a particular node */
+ _constructIndex: function(node) {
+ var index = '';
+ do {
+ if (node.id) index = '[' + node.position + ']' + index;
+ } while ((node = node.parent) != null);
+ return index;
+ },
+
+ sequence: function(element) {
+ element = $(element);
+ var options = Object.extend(this.options(element), arguments[1] || { });
+
+ return $(this.findElements(element, options) || []).map( function(item) {
+ return item.id.match(options.format) ? item.id.match(options.format)[1] : '';
+ });
+ },
+
+ setSequence: function(element, new_sequence) {
+ element = $(element);
+ var options = Object.extend(this.options(element), arguments[2] || { });
+
+ var nodeMap = { };
+ this.findElements(element, options).each( function(n) {
+ if (n.id.match(options.format))
+ nodeMap[n.id.match(options.format)[1]] = [n, n.parentNode];
+ n.parentNode.removeChild(n);
+ });
+
+ new_sequence.each(function(ident) {
+ var n = nodeMap[ident];
+ if (n) {
+ n[1].appendChild(n[0]);
+ delete nodeMap[ident];
+ }
+ });
+ },
+
+ serialize: function(element) {
+ element = $(element);
+ var options = Object.extend(Sortable.options(element), arguments[1] || { });
+ var name = encodeURIComponent(
+ (arguments[1] && arguments[1].name) ? arguments[1].name : element.id);
+
+ if (options.tree) {
+ return Sortable.tree(element, arguments[1]).children.map( function (item) {
+ return [name + Sortable._constructIndex(item) + "[id]=" +
+ encodeURIComponent(item.id)].concat(item.children.map(arguments.callee));
+ }).flatten().join('&');
+ } else {
+ return Sortable.sequence(element, arguments[1]).map( function(item) {
+ return name + "[]=" + encodeURIComponent(item);
+ }).join('&');
+ }
+ }
+};
+
+// Returns true if child is contained within element
+Element.isParent = function(child, element) {
+ if (!child.parentNode || child == element) return false;
+ if (child.parentNode == element) return true;
+ return Element.isParent(child.parentNode, element);
+};
+
+Element.findChildren = function(element, only, recursive, tagName) {
+ if(!element.hasChildNodes()) return null;
+ tagName = tagName.toUpperCase();
+ if(only) only = [only].flatten();
+ var elements = [];
+ $A(element.childNodes).each( function(e) {
+ if(e.tagName && e.tagName.toUpperCase()==tagName &&
+ (!only || (Element.classNames(e).detect(function(v) { return only.include(v) }))))
+ elements.push(e);
+ if(recursive) {
+ var grandchildren = Element.findChildren(e, only, recursive, tagName);
+ if(grandchildren) elements.push(grandchildren);
+ }
+ });
+
+ return (elements.length>0 ? elements.flatten() : []);
+};
+
+Element.offsetSize = function (element, type) {
+ return element['offset' + ((type=='vertical' || type=='height') ? 'Height' : 'Width')];
+};
\ No newline at end of file
Added: trunk/src/ajax/javascripts/external/scriptaculous/effects.js
==============================================================================
--- (empty file)
+++ trunk/src/ajax/javascripts/external/scriptaculous/effects.js Fri Apr 10 19:11:32 2009
@@ -0,0 +1,1130 @@
+// script.aculo.us effects.js v1.8.2, Tue Nov 18 18:30:58 +0100 2008
+
+// Copyright (c) 2005-2008 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
+// Contributors:
+// Justin Palmer (http://encytemedia.com/)
+// Mark Pilgrim (http://diveintomark.org/)
+// Martin Bialasinki
+//
+// script.aculo.us is freely distributable under the terms of an MIT-style license.
+// For details, see the script.aculo.us web site: http://script.aculo.us/
+
+// converts rgb() and #xxx to #xxxxxx format,
+// returns self (or first argument) if not convertable
+String.prototype.parseColor = function() {
+ var color = '#';
+ if (this.slice(0,4) == 'rgb(') {
+ var cols = this.slice(4,this.length-1).split(',');
+ var i=0; do { color += parseInt(cols[i]).toColorPart() } while (++i<3);
+ } else {
+ if (this.slice(0,1) == '#') {
+ if (this.length==4) for(var i=1;i<4;i++) color += (this.charAt(i) + this.charAt(i)).toLowerCase();
+ if (this.length==7) color = this.toLowerCase();
+ }
+ }
+ return (color.length==7 ? color : (arguments[0] || this));
+};
+
+/*--------------------------------------------------------------------------*/
+
+Element.collectTextNodes = function(element) {
+ return $A($(element).childNodes).collect( function(node) {
+ return (node.nodeType==3 ? node.nodeValue :
+ (node.hasChildNodes() ? Element.collectTextNodes(node) : ''));
+ }).flatten().join('');
+};
+
+Element.collectTextNodesIgnoreClass = function(element, className) {
+ return $A($(element).childNodes).collect( function(node) {
+ return (node.nodeType==3 ? node.nodeValue :
+ ((node.hasChildNodes() && !Element.hasClassName(node,className)) ?
+ Element.collectTextNodesIgnoreClass(node, className) : ''));
+ }).flatten().join('');
+};
+
+Element.setContentZoom = function(element, percent) {
+ element = $(element);
+ element.setStyle({fontSize: (percent/100) + 'em'});
+ if (Prototype.Browser.WebKit) window.scrollBy(0,0);
+ return element;
+};
+
+Element.getInlineOpacity = function(element){
+ return $(element).style.opacity || '';
+};
+
+Element.forceRerendering = function(element) {
+ try {
+ element = $(element);
+ var n = document.createTextNode(' ');
+ element.appendChild(n);
+ element.removeChild(n);
+ } catch(e) { }
+};
+
+/*--------------------------------------------------------------------------*/
+
+var Effect = {
+ _elementDoesNotExistError: {
+ name: 'ElementDoesNotExistError',
+ message: 'The specified DOM element does not exist, but is required for this effect to operate'
+ },
+ Transitions: {
+ linear: Prototype.K,
+ sinoidal: function(pos) {
+ return (-Math.cos(pos*Math.PI)/2) + .5;
+ },
+ reverse: function(pos) {
+ return 1-pos;
+ },
+ flicker: function(pos) {
+ var pos = ((-Math.cos(pos*Math.PI)/4) + .75) + Math.random()/4;
+ return pos > 1 ? 1 : pos;
+ },
+ wobble: function(pos) {
+ return (-Math.cos(pos*Math.PI*(9*pos))/2) + .5;
+ },
+ pulse: function(pos, pulses) {
+ return (-Math.cos((pos*((pulses||5)-.5)*2)*Math.PI)/2) + .5;
+ },
+ spring: function(pos) {
+ return 1 - (Math.cos(pos * 4.5 * Math.PI) * Math.exp(-pos * 6));
+ },
+ none: function(pos) {
+ return 0;
+ },
+ full: function(pos) {
+ return 1;
+ }
+ },
+ DefaultOptions: {
+ duration: 1.0, // seconds
+ fps: 100, // 100= assume 66fps max.
+ sync: false, // true for combining
+ from: 0.0,
+ to: 1.0,
+ delay: 0.0,
+ queue: 'parallel'
+ },
+ tagifyText: function(element) {
+ var tagifyStyle = 'position:relative';
+ if (Prototype.Browser.IE) tagifyStyle += ';zoom:1';
+
+ element = $(element);
+ $A(element.childNodes).each( function(child) {
+ if (child.nodeType==3) {
+ child.nodeValue.toArray().each( function(character) {
+ element.insertBefore(
+ new Element('span', {style: tagifyStyle}).update(
+ character == ' ' ? String.fromCharCode(160) : character),
+ child);
+ });
+ Element.remove(child);
+ }
+ });
+ },
+ multiple: function(element, effect) {
+ var elements;
+ if (((typeof element == 'object') ||
+ Object.isFunction(element)) &&
+ (element.length))
+ elements = element;
+ else
+ elements = $(element).childNodes;
+
+ var options = Object.extend({
+ speed: 0.1,
+ delay: 0.0
+ }, arguments[2] || { });
+ var masterDelay = options.delay;
+
+ $A(elements).each( function(element, index) {
+ new effect(element, Object.extend(options, { delay: index * options.speed + masterDelay }));
+ });
+ },
+ PAIRS: {
+ 'slide': ['SlideDown','SlideUp'],
+ 'blind': ['BlindDown','BlindUp'],
+ 'appear': ['Appear','Fade']
+ },
+ toggle: function(element, effect) {
+ element = $(element);
+ effect = (effect || 'appear').toLowerCase();
+ var options = Object.extend({
+ queue: { position:'end', scope:(element.id || 'global'), limit: 1 }
+ }, arguments[2] || { });
+ Effect[element.visible() ?
+ Effect.PAIRS[effect][1] : Effect.PAIRS[effect][0]](element, options);
+ }
+};
+
+Effect.DefaultOptions.transition = Effect.Transitions.sinoidal;
+
+/* ------------- core effects ------------- */
+
+Effect.ScopedQueue = Class.create(Enumerable, {
+ initialize: function() {
+ this.effects = [];
+ this.interval = null;
+ },
+ _each: function(iterator) {
+ this.effects._each(iterator);
+ },
+ add: function(effect) {
+ var timestamp = new Date().getTime();
+
+ var position = Object.isString(effect.options.queue) ?
+ effect.options.queue : effect.options.queue.position;
+
+ switch(position) {
+ case 'front':
+ // move unstarted effects after this effect
+ this.effects.findAll(function(e){ return e.state=='idle' }).each( function(e) {
+ e.startOn += effect.finishOn;
+ e.finishOn += effect.finishOn;
+ });
+ break;
+ case 'with-last':
+ timestamp = this.effects.pluck('startOn').max() || timestamp;
+ break;
+ case 'end':
+ // start effect after last queued effect has finished
+ timestamp = this.effects.pluck('finishOn').max() || timestamp;
+ break;
+ }
+
+ effect.startOn += timestamp;
+ effect.finishOn += timestamp;
+
+ if (!effect.options.queue.limit || (this.effects.length < effect.options.queue.limit))
+ this.effects.push(effect);
+
+ if (!this.interval)
+ this.interval = setInterval(this.loop.bind(this), 15);
+ },
+ remove: function(effect) {
+ this.effects = this.effects.reject(function(e) { return e==effect });
+ if (this.effects.length == 0) {
+ clearInterval(this.interval);
+ this.interval = null;
+ }
+ },
+ loop: function() {
+ var timePos = new Date().getTime();
+ for(var i=0, len=this.effects.length;i<len;i++)
+ this.effects[i] && this.effects[i].loop(timePos);
+ }
+});
+
+Effect.Queues = {
+ instances: $H(),
+ get: function(queueName) {
+ if (!Object.isString(queueName)) return queueName;
+
+ return this.instances.get(queueName) ||
+ this.instances.set(queueName, new Effect.ScopedQueue());
+ }
+};
+Effect.Queue = Effect.Queues.get('global');
+
+Effect.Base = Class.create({
+ position: null,
+ start: function(options) {
+ function codeForEvent(options,eventName){
+ return (
+ (options[eventName+'Internal'] ? 'this.options.'+eventName+'Internal(this);' : '') +
+ (options[eventName] ? 'this.options.'+eventName+'(this);' : '')
+ );
+ }
+ if (options && options.transition === false) options.transition = Effect.Transitions.linear;
+ this.options = Object.extend(Object.extend({ },Effect.DefaultOptions), options || { });
+ this.currentFrame = 0;
+ this.state = 'idle';
+ this.startOn = this.options.delay*1000;
+ this.finishOn = this.startOn+(this.options.duration*1000);
+ this.fromToDelta = this.options.to-this.options.from;
+ this.totalTime = this.finishOn-this.startOn;
+ this.totalFrames = this.options.fps*this.options.duration;
+
+ this.render = (function() {
+ function dispatch(effect, eventName) {
+ if (effect.options[eventName + 'Internal'])
+ effect.options[eventName + 'Internal'](effect);
+ if (effect.options[eventName])
+ effect.options[eventName](effect);
+ }
+
+ return function(pos) {
+ if (this.state === "idle") {
+ this.state = "running";
+ dispatch(this, 'beforeSetup');
+ if (this.setup) this.setup();
+ dispatch(this, 'afterSetup');
+ }
+ if (this.state === "running") {
+ pos = (this.options.transition(pos) * this.fromToDelta) + this.options.from;
+ this.position = pos;
+ dispatch(this, 'beforeUpdate');
+ if (this.update) this.update(pos);
+ dispatch(this, 'afterUpdate');
+ }
+ };
+ })();
+
+ this.event('beforeStart');
+ if (!this.options.sync)
+ Effect.Queues.get(Object.isString(this.options.queue) ?
+ 'global' : this.options.queue.scope).add(this);
+ },
+ loop: function(timePos) {
+ if (timePos >= this.startOn) {
+ if (timePos >= this.finishOn) {
+ this.render(1.0);
+ this.cancel();
+ this.event('beforeFinish');
+ if (this.finish) this.finish();
+ this.event('afterFinish');
+ return;
+ }
+ var pos = (timePos - this.startOn) / this.totalTime,
+ frame = (pos * this.totalFrames).round();
+ if (frame > this.currentFrame) {
+ this.render(pos);
+ this.currentFrame = frame;
+ }
+ }
+ },
+ cancel: function() {
+ if (!this.options.sync)
+ Effect.Queues.get(Object.isString(this.options.queue) ?
+ 'global' : this.options.queue.scope).remove(this);
+ this.state = 'finished';
+ },
+ event: function(eventName) {
+ if (this.options[eventName + 'Internal']) this.options[eventName + 'Internal'](this);
+ if (this.options[eventName]) this.options[eventName](this);
+ },
+ inspect: function() {
+ var data = $H();
+ for(property in this)
+ if (!Object.isFunction(this[property])) data.set(property, this[property]);
+ return '#<Effect:' + data.inspect() + ',options:' + $H(this.options).inspect() + '>';
+ }
+});
+
+Effect.Parallel = Class.create(Effect.Base, {
+ initialize: function(effects) {
+ this.effects = effects || [];
+ this.start(arguments[1]);
+ },
+ update: function(position) {
+ this.effects.invoke('render', position);
+ },
+ finish: function(position) {
+ this.effects.each( function(effect) {
+ effect.render(1.0);
+ effect.cancel();
+ effect.event('beforeFinish');
+ if (effect.finish) effect.finish(position);
+ effect.event('afterFinish');
+ });
+ }
+});
+
+Effect.Tween = Class.create(Effect.Base, {
+ initialize: function(object, from, to) {
+ object = Object.isString(object) ? $(object) : object;
+ var args = $A(arguments), method = args.last(),
+ options = args.length == 5 ? args[3] : null;
+ this.method = Object.isFunction(method) ? method.bind(object) :
+ Object.isFunction(object[method]) ? object[method].bind(object) :
+ function(value) { object[method] = value };
+ this.start(Object.extend({ from: from, to: to }, options || { }));
+ },
+ update: function(position) {
+ this.method(position);
+ }
+});
+
+Effect.Event = Class.create(Effect.Base, {
+ initialize: function() {
+ this.start(Object.extend({ duration: 0 }, arguments[0] || { }));
+ },
+ update: Prototype.emptyFunction
+});
+
+Effect.Opacity = Class.create(Effect.Base, {
+ initialize: function(element) {
+ this.element = $(element);
+ if (!this.element) throw(Effect._elementDoesNotExistError);
+ // make this work on IE on elements without 'layout'
+ if (Prototype.Browser.IE && (!this.element.currentStyle.hasLayout))
+ this.element.setStyle({zoom: 1});
+ var options = Object.extend({
+ from: this.element.getOpacity() || 0.0,
+ to: 1.0
+ }, arguments[1] || { });
+ this.start(options);
+ },
+ update: function(position) {
+ this.element.setOpacity(position);
+ }
+});
+
+Effect.Move = Class.create(Effect.Base, {
+ initialize: function(element) {
+ this.element = $(element);
+ if (!this.element) throw(Effect._elementDoesNotExistError);
+ var options = Object.extend({
+ x: 0,
+ y: 0,
+ mode: 'relative'
+ }, arguments[1] || { });
+ this.start(options);
+ },
+ setup: function() {
+ this.element.makePositioned();
+ this.originalLeft = parseFloat(this.element.getStyle('left') || '0');
+ this.originalTop = parseFloat(this.element.getStyle('top') || '0');
+ if (this.options.mode == 'absolute') {
+ this.options.x = this.options.x - this.originalLeft;
+ this.options.y = this.options.y - this.originalTop;
+ }
+ },
+ update: function(position) {
+ this.element.setStyle({
+ left: (this.options.x * position + this.originalLeft).round() + 'px',
+ top: (this.options.y * position + this.originalTop).round() + 'px'
+ });
+ }
+});
+
+// for backwards compatibility
+Effect.MoveBy = function(element, toTop, toLeft) {
+ return new Effect.Move(element,
+ Object.extend({ x: toLeft, y: toTop }, arguments[3] || { }));
+};
+
+Effect.Scale = Class.create(Effect.Base, {
+ initialize: function(element, percent) {
+ this.element = $(element);
+ if (!this.element) throw(Effect._elementDoesNotExistError);
+ var options = Object.extend({
+ scaleX: true,
+ scaleY: true,
+ scaleContent: true,
+ scaleFromCenter: false,
+ scaleMode: 'box', // 'box' or 'contents' or { } with provided values
+ scaleFrom: 100.0,
+ scaleTo: percent
+ }, arguments[2] || { });
+ this.start(options);
+ },
+ setup: function() {
+ this.restoreAfterFinish = this.options.restoreAfterFinish || false;
+ this.elementPositioning = this.element.getStyle('position');
+
+ this.originalStyle = { };
+ ['top','left','width','height','fontSize'].each( function(k) {
+ this.originalStyle[k] = this.element.style[k];
+ }.bind(this));
+
+ this.originalTop = this.element.offsetTop;
+ this.originalLeft = this.element.offsetLeft;
+
+ var fontSize = this.element.getStyle('font-size') || '100%';
+ ['em','px','%','pt'].each( function(fontSizeType) {
+ if (fontSize.indexOf(fontSizeType)>0) {
+ this.fontSize = parseFloat(fontSize);
+ this.fontSizeType = fontSizeType;
+ }
+ }.bind(this));
+
+ this.factor = (this.options.scaleTo - this.options.scaleFrom)/100;
+
+ this.dims = null;
+ if (this.options.scaleMode=='box')
+ this.dims = [this.element.offsetHeight, this.element.offsetWidth];
+ if (/^content/.test(this.options.scaleMode))
+ this.dims = [this.element.scrollHeight, this.element.scrollWidth];
+ if (!this.dims)
+ this.dims = [this.options.scaleMode.originalHeight,
+ this.options.scaleMode.originalWidth];
+ },
+ update: function(position) {
+ var currentScale = (this.options.scaleFrom/100.0) + (this.factor * position);
+ if (this.options.scaleContent && this.fontSize)
+ this.element.setStyle({fontSize: this.fontSize * currentScale + this.fontSizeType });
+ this.setDimensions(this.dims[0] * currentScale, this.dims[1] * currentScale);
+ },
+ finish: function(position) {
+ if (this.restoreAfterFinish) this.element.setStyle(this.originalStyle);
+ },
+ setDimensions: function(height, width) {
+ var d = { };
+ if (this.options.scaleX) d.width = width.round() + 'px';
+ if (this.options.scaleY) d.height = height.round() + 'px';
+ if (this.options.scaleFromCenter) {
+ var topd = (height - this.dims[0])/2;
+ var leftd = (width - this.dims[1])/2;
+ if (this.elementPositioning == 'absolute') {
+ if (this.options.scaleY) d.top = this.originalTop-topd + 'px';
+ if (this.options.scaleX) d.left = this.originalLeft-leftd + 'px';
+ } else {
+ if (this.options.scaleY) d.top = -topd + 'px';
+ if (this.options.scaleX) d.left = -leftd + 'px';
+ }
+ }
+ this.element.setStyle(d);
+ }
+});
+
+Effect.Highlight = Class.create(Effect.Base, {
+ initialize: function(element) {
+ this.element = $(element);
+ if (!this.element) throw(Effect._elementDoesNotExistError);
+ var options = Object.extend({ startcolor: '#ffff99' }, arguments[1] || { });
+ this.start(options);
+ },
+ setup: function() {
+ // Prevent executing on elements not in the layout flow
+ if (this.element.getStyle('display')=='none') { this.cancel(); return; }
+ // Disable background image during the effect
+ this.oldStyle = { };
+ if (!this.options.keepBackgroundImage) {
+ this.oldStyle.backgroundImage = this.element.getStyle('background-image');
+ this.element.setStyle({backgroundImage: 'none'});
+ }
+ if (!this.options.endcolor)
+ this.options.endcolor = this.element.getStyle('background-color').parseColor('#ffffff');
+ if (!this.options.restorecolor)
+ this.options.restorecolor = this.element.getStyle('background-color');
+ // init color calculations
+ this._base = $R(0,2).map(function(i){ return parseInt(this.options.startcolor.slice(i*2+1,i*2+3),16) }.bind(this));
+ this._delta = $R(0,2).map(function(i){ return parseInt(this.options.endcolor.slice(i*2+1,i*2+3),16)-this._base[i] }.bind(this));
+ },
+ update: function(position) {
+ this.element.setStyle({backgroundColor: $R(0,2).inject('#',function(m,v,i){
+ return m+((this._base[i]+(this._delta[i]*position)).round().toColorPart()); }.bind(this)) });
+ },
+ finish: function() {
+ this.element.setStyle(Object.extend(this.oldStyle, {
+ backgroundColor: this.options.restorecolor
+ }));
+ }
+});
+
+Effect.ScrollTo = function(element) {
+ var options = arguments[1] || { },
+ scrollOffsets = document.viewport.getScrollOffsets(),
+ elementOffsets = $(element).cumulativeOffset();
+
+ if (options.offset) elementOffsets[1] += options.offset;
+
+ return new Effect.Tween(null,
+ scrollOffsets.top,
+ elementOffsets[1],
+ options,
+ function(p){ scrollTo(scrollOffsets.left, p.round()); }
+ );
+};
+
+/* ------------- combination effects ------------- */
+
+Effect.Fade = function(element) {
+ element = $(element);
+ var oldOpacity = element.getInlineOpacity();
+ var options = Object.extend({
+ from: element.getOpacity() || 1.0,
+ to: 0.0,
+ afterFinishInternal: function(effect) {
+ if (effect.options.to!=0) return;
+ effect.element.hide().setStyle({opacity: oldOpacity});
+ }
+ }, arguments[1] || { });
+ return new Effect.Opacity(element,options);
+};
+
+Effect.Appear = function(element) {
+ element = $(element);
+ var options = Object.extend({
+ from: (element.getStyle('display') == 'none' ? 0.0 : element.getOpacity() || 0.0),
+ to: 1.0,
+ // force Safari to render floated elements properly
+ afterFinishInternal: function(effect) {
+ effect.element.forceRerendering();
+ },
+ beforeSetup: function(effect) {
+ effect.element.setOpacity(effect.options.from).show();
+ }}, arguments[1] || { });
+ return new Effect.Opacity(element,options);
+};
+
+Effect.Puff = function(element) {
+ element = $(element);
+ var oldStyle = {
+ opacity: element.getInlineOpacity(),
+ position: element.getStyle('position'),
+ top: element.style.top,
+ left: element.style.left,
+ width: element.style.width,
+ height: element.style.height
+ };
+ return new Effect.Parallel(
+ [ new Effect.Scale(element, 200,
+ { sync: true, scaleFromCenter: true, scaleContent: true, restoreAfterFinish: true }),
+ new Effect.Opacity(element, { sync: true, to: 0.0 } ) ],
+ Object.extend({ duration: 1.0,
+ beforeSetupInternal: function(effect) {
+ Position.absolutize(effect.effects[0].element);
+ },
+ afterFinishInternal: function(effect) {
+ effect.effects[0].element.hide().setStyle(oldStyle); }
+ }, arguments[1] || { })
+ );
+};
+
+Effect.BlindUp = function(element) {
+ element = $(element);
+ element.makeClipping();
+ return new Effect.Scale(element, 0,
+ Object.extend({ scaleContent: false,
+ scaleX: false,
+ restoreAfterFinish: true,
+ afterFinishInternal: function(effect) {
+ effect.element.hide().undoClipping();
+ }
+ }, arguments[1] || { })
+ );
+};
+
+Effect.BlindDown = function(element) {
+ element = $(element);
+ var elementDimensions = element.getDimensions();
+ return new Effect.Scale(element, 100, Object.extend({
+ scaleContent: false,
+ scaleX: false,
+ scaleFrom: 0,
+ scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width},
+ restoreAfterFinish: true,
+ afterSetup: function(effect) {
+ effect.element.makeClipping().setStyle({height: '0px'}).show();
+ },
+ afterFinishInternal: function(effect) {
+ effect.element.undoClipping();
+ }
+ }, arguments[1] || { }));
+};
+
+Effect.SwitchOff = function(element) {
+ element = $(element);
+ var oldOpacity = element.getInlineOpacity();
+ return new Effect.Appear(element, Object.extend({
+ duration: 0.4,
+ from: 0,
+ transition: Effect.Transitions.flicker,
+ afterFinishInternal: function(effect) {
+ new Effect.Scale(effect.element, 1, {
+ duration: 0.3, scaleFromCenter: true,
+ scaleX: false, scaleContent: false, restoreAfterFinish: true,
+ beforeSetup: function(effect) {
+ effect.element.makePositioned().makeClipping();
+ },
+ afterFinishInternal: function(effect) {
+ effect.element.hide().undoClipping().undoPositioned().setStyle({opacity: oldOpacity});
+ }
+ });
+ }
+ }, arguments[1] || { }));
+};
+
+Effect.DropOut = function(element) {
+ element = $(element);
+ var oldStyle = {
+ top: element.getStyle('top'),
+ left: element.getStyle('left'),
+ opacity: element.getInlineOpacity() };
+ return new Effect.Parallel(
+ [ new Effect.Move(element, {x: 0, y: 100, sync: true }),
+ new Effect.Opacity(element, { sync: true, to: 0.0 }) ],
+ Object.extend(
+ { duration: 0.5,
+ beforeSetup: function(effect) {
+ effect.effects[0].element.makePositioned();
+ },
+ afterFinishInternal: function(effect) {
+ effect.effects[0].element.hide().undoPositioned().setStyle(oldStyle);
+ }
+ }, arguments[1] || { }));
+};
+
+Effect.Shake = function(element) {
+ element = $(element);
+ var options = Object.extend({
+ distance: 20,
+ duration: 0.5
+ }, arguments[1] || {});
+ var distance = parseFloat(options.distance);
+ var split = parseFloat(options.duration) / 10.0;
+ var oldStyle = {
+ top: element.getStyle('top'),
+ left: element.getStyle('left') };
+ return new Effect.Move(element,
+ { x: distance, y: 0, duration: split, afterFinishInternal: function(effect) {
+ new Effect.Move(effect.element,
+ { x: -distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) {
+ new Effect.Move(effect.element,
+ { x: distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) {
+ new Effect.Move(effect.element,
+ { x: -distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) {
+ new Effect.Move(effect.element,
+ { x: distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) {
+ new Effect.Move(effect.element,
+ { x: -distance, y: 0, duration: split, afterFinishInternal: function(effect) {
+ effect.element.undoPositioned().setStyle(oldStyle);
+ }}); }}); }}); }}); }}); }});
+};
+
+Effect.SlideDown = function(element) {
+ element = $(element).cleanWhitespace();
+ // SlideDown need to have the content of the element wrapped in a container element with fixed height!
+ var oldInnerBottom = element.down().getStyle('bottom');
+ var elementDimensions = element.getDimensions();
+ return new Effect.Scale(element, 100, Object.extend({
+ scaleContent: false,
+ scaleX: false,
+ scaleFrom: window.opera ? 0 : 1,
+ scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width},
+ restoreAfterFinish: true,
+ afterSetup: function(effect) {
+ effect.element.makePositioned();
+ effect.element.down().makePositioned();
+ if (window.opera) effect.element.setStyle({top: ''});
+ effect.element.makeClipping().setStyle({height: '0px'}).show();
+ },
+ afterUpdateInternal: function(effect) {
+ effect.element.down().setStyle({bottom:
+ (effect.dims[0] - effect.element.clientHeight) + 'px' });
+ },
+ afterFinishInternal: function(effect) {
+ effect.element.undoClipping().undoPositioned();
+ effect.element.down().undoPositioned().setStyle({bottom: oldInnerBottom}); }
+ }, arguments[1] || { })
+ );
+};
+
+Effect.SlideUp = function(element) {
+ element = $(element).cleanWhitespace();
+ var oldInnerBottom = element.down().getStyle('bottom');
+ var elementDimensions = element.getDimensions();
+ return new Effect.Scale(element, window.opera ? 0 : 1,
+ Object.extend({ scaleContent: false,
+ scaleX: false,
+ scaleMode: 'box',
+ scaleFrom: 100,
+ scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width},
+ restoreAfterFinish: true,
+ afterSetup: function(effect) {
+ effect.element.makePositioned();
+ effect.element.down().makePositioned();
+ if (window.opera) effect.element.setStyle({top: ''});
+ effect.element.makeClipping().show();
+ },
+ afterUpdateInternal: function(effect) {
+ effect.element.down().setStyle({bottom:
+ (effect.dims[0] - effect.element.clientHeight) + 'px' });
+ },
+ afterFinishInternal: function(effect) {
+ effect.element.hide().undoClipping().undoPositioned();
+ effect.element.down().undoPositioned().setStyle({bottom: oldInnerBottom});
+ }
+ }, arguments[1] || { })
+ );
+};
+
+// Bug in opera makes the TD containing this element expand for a instance after finish
+Effect.Squish = function(element) {
+ return new Effect.Scale(element, window.opera ? 1 : 0, {
+ restoreAfterFinish: true,
+ beforeSetup: function(effect) {
+ effect.element.makeClipping();
+ },
+ afterFinishInternal: function(effect) {
+ effect.element.hide().undoClipping();
+ }
+ });
+};
+
+Effect.Grow = function(element) {
+ element = $(element);
+ var options = Object.extend({
+ direction: 'center',
+ moveTransition: Effect.Transitions.sinoidal,
+ scaleTransition: Effect.Transitions.sinoidal,
+ opacityTransition: Effect.Transitions.full
+ }, arguments[1] || { });
+ var oldStyle = {
+ top: element.style.top,
+ left: element.style.left,
+ height: element.style.height,
+ width: element.style.width,
+ opacity: element.getInlineOpacity() };
+
+ var dims = element.getDimensions();
+ var initialMoveX, initialMoveY;
+ var moveX, moveY;
+
+ switch (options.direction) {
+ case 'top-left':
+ initialMoveX = initialMoveY = moveX = moveY = 0;
+ break;
+ case 'top-right':
+ initialMoveX = dims.width;
+ initialMoveY = moveY = 0;
+ moveX = -dims.width;
+ break;
+ case 'bottom-left':
+ initialMoveX = moveX = 0;
+ initialMoveY = dims.height;
+ moveY = -dims.height;
+ break;
+ case 'bottom-right':
+ initialMoveX = dims.width;
+ initialMoveY = dims.height;
+ moveX = -dims.width;
+ moveY = -dims.height;
+ break;
+ case 'center':
+ initialMoveX = dims.width / 2;
+ initialMoveY = dims.height / 2;
+ moveX = -dims.width / 2;
+ moveY = -dims.height / 2;
+ break;
+ }
+
+ return new Effect.Move(element, {
+ x: initialMoveX,
+ y: initialMoveY,
+ duration: 0.01,
+ beforeSetup: function(effect) {
+ effect.element.hide().makeClipping().makePositioned();
+ },
+ afterFinishInternal: function(effect) {
+ new Effect.Parallel(
+ [ new Effect.Opacity(effect.element, { sync: true, to: 1.0, from: 0.0, transition: options.opacityTransition }),
+ new Effect.Move(effect.element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition }),
+ new Effect.Scale(effect.element, 100, {
+ scaleMode: { originalHeight: dims.height, originalWidth: dims.width },
+ sync: true, scaleFrom: window.opera ? 1 : 0, transition: options.scaleTransition, restoreAfterFinish: true})
+ ], Object.extend({
+ beforeSetup: function(effect) {
+ effect.effects[0].element.setStyle({height: '0px'}).show();
+ },
+ afterFinishInternal: function(effect) {
+ effect.effects[0].element.undoClipping().undoPositioned().setStyle(oldStyle);
+ }
+ }, options)
+ );
+ }
+ });
+};
+
+Effect.Shrink = function(element) {
+ element = $(element);
+ var options = Object.extend({
+ direction: 'center',
+ moveTransition: Effect.Transitions.sinoidal,
+ scaleTransition: Effect.Transitions.sinoidal,
+ opacityTransition: Effect.Transitions.none
+ }, arguments[1] || { });
+ var oldStyle = {
+ top: element.style.top,
+ left: element.style.left,
+ height: element.style.height,
+ width: element.style.width,
+ opacity: element.getInlineOpacity() };
+
+ var dims = element.getDimensions();
+ var moveX, moveY;
+
+ switch (options.direction) {
+ case 'top-left':
+ moveX = moveY = 0;
+ break;
+ case 'top-right':
+ moveX = dims.width;
+ moveY = 0;
+ break;
+ case 'bottom-left':
+ moveX = 0;
+ moveY = dims.height;
+ break;
+ case 'bottom-right':
+ moveX = dims.width;
+ moveY = dims.height;
+ break;
+ case 'center':
+ moveX = dims.width / 2;
+ moveY = dims.height / 2;
+ break;
+ }
+
+ return new Effect.Parallel(
+ [ new Effect.Opacity(element, { sync: true, to: 0.0, from: 1.0, transition: options.opacityTransition }),
+ new Effect.Scale(element, window.opera ? 1 : 0, { sync: true, transition: options.scaleTransition, restoreAfterFinish: true}),
+ new Effect.Move(element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition })
+ ], Object.extend({
+ beforeStartInternal: function(effect) {
+ effect.effects[0].element.makePositioned().makeClipping();
+ },
+ afterFinishInternal: function(effect) {
+ effect.effects[0].element.hide().undoClipping().undoPositioned().setStyle(oldStyle); }
+ }, options)
+ );
+};
+
+Effect.Pulsate = function(element) {
+ element = $(element);
+ var options = arguments[1] || { },
+ oldOpacity = element.getInlineOpacity(),
+ transition = options.transition || Effect.Transitions.linear,
+ reverser = function(pos){
+ return 1 - transition((-Math.cos((pos*(options.pulses||5)*2)*Math.PI)/2) + .5);
+ };
+
+ return new Effect.Opacity(element,
+ Object.extend(Object.extend({ duration: 2.0, from: 0,
+ afterFinishInternal: function(effect) { effect.element.setStyle({opacity: oldOpacity}); }
+ }, options), {transition: reverser}));
+};
+
+Effect.Fold = function(element) {
+ element = $(element);
+ var oldStyle = {
+ top: element.style.top,
+ left: element.style.left,
+ width: element.style.width,
+ height: element.style.height };
+ element.makeClipping();
+ return new Effect.Scale(element, 5, Object.extend({
+ scaleContent: false,
+ scaleX: false,
+ afterFinishInternal: function(effect) {
+ new Effect.Scale(element, 1, {
+ scaleContent: false,
+ scaleY: false,
+ afterFinishInternal: function(effect) {
+ effect.element.hide().undoClipping().setStyle(oldStyle);
+ } });
+ }}, arguments[1] || { }));
+};
+
+Effect.Morph = Class.create(Effect.Base, {
+ initialize: function(element) {
+ this.element = $(element);
+ if (!this.element) throw(Effect._elementDoesNotExistError);
+ var options = Object.extend({
+ style: { }
+ }, arguments[1] || { });
+
+ if (!Object.isString(options.style)) this.style = $H(options.style);
+ else {
+ if (options.style.include(':'))
+ this.style = options.style.parseStyle();
+ else {
+ this.element.addClassName(options.style);
+ this.style = $H(this.element.getStyles());
+ this.element.removeClassName(options.style);
+ var css = this.element.getStyles();
+ this.style = this.style.reject(function(style) {
+ return style.value == css[style.key];
+ });
+ options.afterFinishInternal = function(effect) {
+ effect.element.addClassName(effect.options.style);
+ effect.transforms.each(function(transform) {
+ effect.element.style[transform.style] = '';
+ });
+ };
+ }
+ }
+ this.start(options);
+ },
+
+ setup: function(){
+ function parseColor(color){
+ if (!color || ['rgba(0, 0, 0, 0)','transparent'].include(color)) color = '#ffffff';
+ color = color.parseColor();
+ return $R(0,2).map(function(i){
+ return parseInt( color.slice(i*2+1,i*2+3), 16 );
+ });
+ }
+ this.transforms = this.style.map(function(pair){
+ var property = pair[0], value = pair[1], unit = null;
+
+ if (value.parseColor('#zzzzzz') != '#zzzzzz') {
+ value = value.parseColor();
+ unit = 'color';
+ } else if (property == 'opacity') {
+ value = parseFloat(value);
+ if (Prototype.Browser.IE && (!this.element.currentStyle.hasLayout))
+ this.element.setStyle({zoom: 1});
+ } else if (Element.CSS_LENGTH.test(value)) {
+ var components = value.match(/^([\+\-]?[0-9\.]+)(.*)$/);
+ value = parseFloat(components[1]);
+ unit = (components.length == 3) ? components[2] : null;
+ }
+
+ var originalValue = this.element.getStyle(property);
+ return {
+ style: property.camelize(),
+ originalValue: unit=='color' ? parseColor(originalValue) : parseFloat(originalValue || 0),
+ targetValue: unit=='color' ? parseColor(value) : value,
+ unit: unit
+ };
+ }.bind(this)).reject(function(transform){
+ return (
+ (transform.originalValue == transform.targetValue) ||
+ (
+ transform.unit != 'color' &&
+ (isNaN(transform.originalValue) || isNaN(transform.targetValue))
+ )
+ );
+ });
+ },
+ update: function(position) {
+ var style = { }, transform, i = this.transforms.length;
+ while(i--)
+ style[(transform = this.transforms[i]).style] =
+ transform.unit=='color' ? '#'+
+ (Math.round(transform.originalValue[0]+
+ (transform.targetValue[0]-transform.originalValue[0])*position)).toColorPart() +
+ (Math.round(transform.originalValue[1]+
+ (transform.targetValue[1]-transform.originalValue[1])*position)).toColorPart() +
+ (Math.round(transform.originalValue[2]+
+ (transform.targetValue[2]-transform.originalValue[2])*position)).toColorPart() :
+ (transform.originalValue +
+ (transform.targetValue - transform.originalValue) * position).toFixed(3) +
+ (transform.unit === null ? '' : transform.unit);
+ this.element.setStyle(style, true);
+ }
+});
+
+Effect.Transform = Class.create({
+ initialize: function(tracks){
+ this.tracks = [];
+ this.options = arguments[1] || { };
+ this.addTracks(tracks);
+ },
+ addTracks: function(tracks){
+ tracks.each(function(track){
+ track = $H(track);
+ var data = track.values().first();
+ this.tracks.push($H({
+ ids: track.keys().first(),
+ effect: Effect.Morph,
+ options: { style: data }
+ }));
+ }.bind(this));
+ return this;
+ },
+ play: function(){
+ return new Effect.Parallel(
+ this.tracks.map(function(track){
+ var ids = track.get('ids'), effect = track.get('effect'), options = track.get('options');
+ var elements = [$(ids) || $$(ids)].flatten();
+ return elements.map(function(e){ return new effect(e, Object.extend({ sync:true }, options)) });
+ }).flatten(),
+ this.options
+ );
+ }
+});
+
+Element.CSS_PROPERTIES = $w(
+ 'backgroundColor backgroundPosition borderBottomColor borderBottomStyle ' +
+ 'borderBottomWidth borderLeftColor borderLeftStyle borderLeftWidth ' +
+ 'borderRightColor borderRightStyle borderRightWidth borderSpacing ' +
+ 'borderTopColor borderTopStyle borderTopWidth bottom clip color ' +
+ 'fontSize fontWeight height left letterSpacing lineHeight ' +
+ 'marginBottom marginLeft marginRight marginTop markerOffset maxHeight '+
+ 'maxWidth minHeight minWidth opacity outlineColor outlineOffset ' +
+ 'outlineWidth paddingBottom paddingLeft paddingRight paddingTop ' +
+ 'right textIndent top width wordSpacing zIndex');
+
+Element.CSS_LENGTH = /^(([\+\-]?[0-9\.]+)(em|ex|px|in|cm|mm|pt|pc|\%))|0$/;
+
+String.__parseStyleElement = document.createElement('div');
+String.prototype.parseStyle = function(){
+ var style, styleRules = $H();
+ if (Prototype.Browser.WebKit)
+ style = new Element('div',{style:this}).style;
+ else {
+ String.__parseStyleElement.innerHTML = '<div style="' + this + '"></div>';
+ style = String.__parseStyleElement.childNodes[0].style;
+ }
+
+ Element.CSS_PROPERTIES.each(function(property){
+ if (style[property]) styleRules.set(property, style[property]);
+ });
+
+ if (Prototype.Browser.IE && this.include('opacity'))
+ styleRules.set('opacity', this.match(/opacity:\s*((?:0|1)?(?:\.\d*)?)/)[1]);
+
+ return styleRules;
+};
+
+if (document.defaultView && document.defaultView.getComputedStyle) {
+ Element.getStyles = function(element) {
+ var css = document.defaultView.getComputedStyle($(element), null);
+ return Element.CSS_PROPERTIES.inject({ }, function(styles, property) {
+ styles[property] = css[property];
+ return styles;
+ });
+ };
+} else {
+ Element.getStyles = function(element) {
+ element = $(element);
+ var css = element.currentStyle, styles;
+ styles = Element.CSS_PROPERTIES.inject({ }, function(results, property) {
+ results[property] = css[property];
+ return results;
+ });
+ if (!styles.opacity) styles.opacity = element.getOpacity();
+ return styles;
+ };
+}
+
+Effect.Methods = {
+ morph: function(element, style) {
+ element = $(element);
+ new Effect.Morph(element, Object.extend({ style: style }, arguments[2] || { }));
+ return element;
+ },
+ visualEffect: function(element, effect, options) {
+ element = $(element);
+ var s = effect.dasherize().camelize(), klass = s.charAt(0).toUpperCase() + s.substring(1);
+ new Effect[klass](element, options);
+ return element;
+ },
+ highlight: function(element, options) {
+ element = $(element);
+ new Effect.Highlight(element, options);
+ return element;
+ }
+};
+
+$w('fade appear grow shrink fold blindUp blindDown slideUp slideDown '+
+ 'pulsate shake puff squish switchOff dropOut').each(
+ function(effect) {
+ Effect.Methods[effect] = function(element, options){
+ element = $(element);
+ Effect[effect.charAt(0).toUpperCase() + effect.substring(1)](element, options);
+ return element;
+ };
+ }
+);
+
+$w('getInlineOpacity forceRerendering setContentZoom collectTextNodes collectTextNodesIgnoreClass getStyles').each(
+ function(f) { Effect.Methods[f] = Element[f]; }
+);
+
+Element.addMethods(Effect.Methods);
\ No newline at end of file
Added: trunk/src/ajax/javascripts/external/scriptaculous/scriptaculous.js
==============================================================================
--- (empty file)
+++ trunk/src/ajax/javascripts/external/scriptaculous/scriptaculous.js Fri Apr 10 19:11:32 2009
@@ -0,0 +1,60 @@
+// script.aculo.us scriptaculous.js v1.8.2, Tue Nov 18 18:30:58 +0100 2008
+
+// Copyright (c) 2005-2008 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// For details, see the script.aculo.us web site: http://script.aculo.us/
+
+var Scriptaculous = {
+ Version: '1.8.2',
+ require: function(libraryName) {
+ // inserting via DOM fails in Safari 2.0, so brute force approach
+ document.write('<script type="text/javascript" src="'+libraryName+'"><\/script>');
+ },
+ REQUIRED_PROTOTYPE: '1.6.0.3',
+ load: function() {
+ function convertVersionString(versionString) {
+ var v = versionString.replace(/_.*|\./g, '');
+ v = parseInt(v + '0'.times(4-v.length));
+ return versionString.indexOf('_') > -1 ? v-1 : v;
+ }
+
+ if((typeof Prototype=='undefined') ||
+ (typeof Element == 'undefined') ||
+ (typeof Element.Methods=='undefined') ||
+ (convertVersionString(Prototype.Version) <
+ convertVersionString(Scriptaculous.REQUIRED_PROTOTYPE)))
+ throw("script.aculo.us requires the Prototype JavaScript framework >= " +
+ Scriptaculous.REQUIRED_PROTOTYPE);
+
+ var js = /scriptaculous\.js(\?.*)?$/;
+ $$('head script[src]').findAll(function(s) {
+ return s.src.match(js);
+ }).each(function(s) {
+ var path = s.src.replace(js, ''),
+ includes = s.src.match(/\?.*load=([a-z,]*)/);
+ (includes ? includes[1] : 'builder,effects,dragdrop,controls,slider,sound').split(',').each(
+ function(include) { Scriptaculous.require(path+include+'.js') });
+ });
+ }
+};
+
+Scriptaculous.load();
\ No newline at end of file
Added: trunk/src/ajax/javascripts/external/scriptaculous/slider.js
==============================================================================
--- (empty file)
+++ trunk/src/ajax/javascripts/external/scriptaculous/slider.js Fri Apr 10 19:11:32 2009
@@ -0,0 +1,275 @@
+// script.aculo.us slider.js v1.8.2, Tue Nov 18 18:30:58 +0100 2008
+
+// Copyright (c) 2005-2008 Marty Haught, Thomas Fuchs
+//
+// script.aculo.us is freely distributable under the terms of an MIT-style license.
+// For details, see the script.aculo.us web site: http://script.aculo.us/
+
+if (!Control) var Control = { };
+
+// options:
+// axis: 'vertical', or 'horizontal' (default)
+//
+// callbacks:
+// onChange(value)
+// onSlide(value)
+Control.Slider = Class.create({
+ initialize: function(handle, track, options) {
+ var slider = this;
+
+ if (Object.isArray(handle)) {
+ this.handles = handle.collect( function(e) { return $(e) });
+ } else {
+ this.handles = [$(handle)];
+ }
+
+ this.track = $(track);
+ this.options = options || { };
+
+ this.axis = this.options.axis || 'horizontal';
+ this.increment = this.options.increment || 1;
+ this.step = parseInt(this.options.step || '1');
+ this.range = this.options.range || $R(0,1);
+
+ this.value = 0; // assure backwards compat
+ this.values = this.handles.map( function() { return 0 });
+ this.spans = this.options.spans ? this.options.spans.map(function(s){ return $(s) }) : false;
+ this.options.startSpan = $(this.options.startSpan || null);
+ this.options.endSpan = $(this.options.endSpan || null);
+
+ this.restricted = this.options.restricted || false;
+
+ this.maximum = this.options.maximum || this.range.end;
+ this.minimum = this.options.minimum || this.range.start;
+
+ // Will be used to align the handle onto the track, if necessary
+ this.alignX = parseInt(this.options.alignX || '0');
+ this.alignY = parseInt(this.options.alignY || '0');
+
+ this.trackLength = this.maximumOffset() - this.minimumOffset();
+
+ this.handleLength = this.isVertical() ?
+ (this.handles[0].offsetHeight != 0 ?
+ this.handles[0].offsetHeight : this.handles[0].style.height.replace(/px$/,"")) :
+ (this.handles[0].offsetWidth != 0 ? this.handles[0].offsetWidth :
+ this.handles[0].style.width.replace(/px$/,""));
+
+ this.active = false;
+ this.dragging = false;
+ this.disabled = false;
+
+ if (this.options.disabled) this.setDisabled();
+
+ // Allowed values array
+ this.allowedValues = this.options.values ? this.options.values.sortBy(Prototype.K) : false;
+ if (this.allowedValues) {
+ this.minimum = this.allowedValues.min();
+ this.maximum = this.allowedValues.max();
+ }
+
+ this.eventMouseDown = this.startDrag.bindAsEventListener(this);
+ this.eventMouseUp = this.endDrag.bindAsEventListener(this);
+ this.eventMouseMove = this.update.bindAsEventListener(this);
+
+ // Initialize handles in reverse (make sure first handle is active)
+ this.handles.each( function(h,i) {
+ i = slider.handles.length-1-i;
+ slider.setValue(parseFloat(
+ (Object.isArray(slider.options.sliderValue) ?
+ slider.options.sliderValue[i] : slider.options.sliderValue) ||
+ slider.range.start), i);
+ h.makePositioned().observe("mousedown", slider.eventMouseDown);
+ });
+
+ this.track.observe("mousedown", this.eventMouseDown);
+ document.observe("mouseup", this.eventMouseUp);
+ document.observe("mousemove", this.eventMouseMove);
+
+ this.initialized = true;
+ },
+ dispose: function() {
+ var slider = this;
+ Event.stopObserving(this.track, "mousedown", this.eventMouseDown);
+ Event.stopObserving(document, "mouseup", this.eventMouseUp);
+ Event.stopObserving(document, "mousemove", this.eventMouseMove);
+ this.handles.each( function(h) {
+ Event.stopObserving(h, "mousedown", slider.eventMouseDown);
+ });
+ },
+ setDisabled: function(){
+ this.disabled = true;
+ },
+ setEnabled: function(){
+ this.disabled = false;
+ },
+ getNearestValue: function(value){
+ if (this.allowedValues){
+ if (value >= this.allowedValues.max()) return(this.allowedValues.max());
+ if (value <= this.allowedValues.min()) return(this.allowedValues.min());
+
+ var offset = Math.abs(this.allowedValues[0] - value);
+ var newValue = this.allowedValues[0];
+ this.allowedValues.each( function(v) {
+ var currentOffset = Math.abs(v - value);
+ if (currentOffset <= offset){
+ newValue = v;
+ offset = currentOffset;
+ }
+ });
+ return newValue;
+ }
+ if (value > this.range.end) return this.range.end;
+ if (value < this.range.start) return this.range.start;
+ return value;
+ },
+ setValue: function(sliderValue, handleIdx){
+ if (!this.active) {
+ this.activeHandleIdx = handleIdx || 0;
+ this.activeHandle = this.handles[this.activeHandleIdx];
+ this.updateStyles();
+ }
+ handleIdx = handleIdx || this.activeHandleIdx || 0;
+ if (this.initialized && this.restricted) {
+ if ((handleIdx>0) && (sliderValue<this.values[handleIdx-1]))
+ sliderValue = this.values[handleIdx-1];
+ if ((handleIdx < (this.handles.length-1)) && (sliderValue>this.values[handleIdx+1]))
+ sliderValue = this.values[handleIdx+1];
+ }
+ sliderValue = this.getNearestValue(sliderValue);
+ this.values[handleIdx] = sliderValue;
+ this.value = this.values[0]; // assure backwards compat
+
+ this.handles[handleIdx].style[this.isVertical() ? 'top' : 'left'] =
+ this.translateToPx(sliderValue);
+
+ this.drawSpans();
+ if (!this.dragging || !this.event) this.updateFinished();
+ },
+ setValueBy: function(delta, handleIdx) {
+ this.setValue(this.values[handleIdx || this.activeHandleIdx || 0] + delta,
+ handleIdx || this.activeHandleIdx || 0);
+ },
+ translateToPx: function(value) {
+ return Math.round(
+ ((this.trackLength-this.handleLength)/(this.range.end-this.range.start)) *
+ (value - this.range.start)) + "px";
+ },
+ translateToValue: function(offset) {
+ return ((offset/(this.trackLength-this.handleLength) *
+ (this.range.end-this.range.start)) + this.range.start);
+ },
+ getRange: function(range) {
+ var v = this.values.sortBy(Prototype.K);
+ range = range || 0;
+ return $R(v[range],v[range+1]);
+ },
+ minimumOffset: function(){
+ return(this.isVertical() ? this.alignY : this.alignX);
+ },
+ maximumOffset: function(){
+ return(this.isVertical() ?
+ (this.track.offsetHeight != 0 ? this.track.offsetHeight :
+ this.track.style.height.replace(/px$/,"")) - this.alignY :
+ (this.track.offsetWidth != 0 ? this.track.offsetWidth :
+ this.track.style.width.replace(/px$/,"")) - this.alignX);
+ },
+ isVertical: function(){
+ return (this.axis == 'vertical');
+ },
+ drawSpans: function() {
+ var slider = this;
+ if (this.spans)
+ $R(0, this.spans.length-1).each(function(r) { slider.setSpan(slider.spans[r], slider.getRange(r)) });
+ if (this.options.startSpan)
+ this.setSpan(this.options.startSpan,
+ $R(0, this.values.length>1 ? this.getRange(0).min() : this.value ));
+ if (this.options.endSpan)
+ this.setSpan(this.options.endSpan,
+ $R(this.values.length>1 ? this.getRange(this.spans.length-1).max() : this.value, this.maximum));
+ },
+ setSpan: function(span, range) {
+ if (this.isVertical()) {
+ span.style.top = this.translateToPx(range.start);
+ span.style.height = this.translateToPx(range.end - range.start + this.range.start);
+ } else {
+ span.style.left = this.translateToPx(range.start);
+ span.style.width = this.translateToPx(range.end - range.start + this.range.start);
+ }
+ },
+ updateStyles: function() {
+ this.handles.each( function(h){ Element.removeClassName(h, 'selected') });
+ Element.addClassName(this.activeHandle, 'selected');
+ },
+ startDrag: function(event) {
+ if (Event.isLeftClick(event)) {
+ if (!this.disabled){
+ this.active = true;
+
+ var handle = Event.element(event);
+ var pointer = [Event.pointerX(event), Event.pointerY(event)];
+ var track = handle;
+ if (track==this.track) {
+ var offsets = Position.cumulativeOffset(this.track);
+ this.event = event;
+ this.setValue(this.translateToValue(
+ (this.isVertical() ? pointer[1]-offsets[1] : pointer[0]-offsets[0])-(this.handleLength/2)
+ ));
+ var offsets = Position.cumulativeOffset(this.activeHandle);
+ this.offsetX = (pointer[0] - offsets[0]);
+ this.offsetY = (pointer[1] - offsets[1]);
+ } else {
+ // find the handle (prevents issues with Safari)
+ while((this.handles.indexOf(handle) == -1) && handle.parentNode)
+ handle = handle.parentNode;
+
+ if (this.handles.indexOf(handle)!=-1) {
+ this.activeHandle = handle;
+ this.activeHandleIdx = this.handles.indexOf(this.activeHandle);
+ this.updateStyles();
+
+ var offsets = Position.cumulativeOffset(this.activeHandle);
+ this.offsetX = (pointer[0] - offsets[0]);
+ this.offsetY = (pointer[1] - offsets[1]);
+ }
+ }
+ }
+ Event.stop(event);
+ }
+ },
+ update: function(event) {
+ if (this.active) {
+ if (!this.dragging) this.dragging = true;
+ this.draw(event);
+ if (Prototype.Browser.WebKit) window.scrollBy(0,0);
+ Event.stop(event);
+ }
+ },
+ draw: function(event) {
+ var pointer = [Event.pointerX(event), Event.pointerY(event)];
+ var offsets = Position.cumulativeOffset(this.track);
+ pointer[0] -= this.offsetX + offsets[0];
+ pointer[1] -= this.offsetY + offsets[1];
+ this.event = event;
+ this.setValue(this.translateToValue( this.isVertical() ? pointer[1] : pointer[0] ));
+ if (this.initialized && this.options.onSlide)
+ this.options.onSlide(this.values.length>1 ? this.values : this.value, this);
+ },
+ endDrag: function(event) {
+ if (this.active && this.dragging) {
+ this.finishDrag(event, true);
+ Event.stop(event);
+ }
+ this.active = false;
+ this.dragging = false;
+ },
+ finishDrag: function(event, success) {
+ this.active = false;
+ this.dragging = false;
+ this.updateFinished();
+ },
+ updateFinished: function() {
+ if (this.initialized && this.options.onChange)
+ this.options.onChange(this.values.length>1 ? this.values : this.value, this);
+ this.event = null;
+ }
+});
\ No newline at end of file
Added: trunk/src/ajax/javascripts/external/scriptaculous/sound.js
==============================================================================
--- (empty file)
+++ trunk/src/ajax/javascripts/external/scriptaculous/sound.js Fri Apr 10 19:11:32 2009
@@ -0,0 +1,55 @@
+// script.aculo.us sound.js v1.8.2, Tue Nov 18 18:30:58 +0100 2008
+
+// Copyright (c) 2005-2008 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
+//
+// Based on code created by Jules Gravinese (http://www.webveteran.com/)
+//
+// script.aculo.us is freely distributable under the terms of an MIT-style license.
+// For details, see the script.aculo.us web site: http://script.aculo.us/
+
+Sound = {
+ tracks: {},
+ _enabled: true,
+ template:
+ new Template('<embed style="height:0" id="sound_#{track}_#{id}" src="#{url}" loop="false" autostart="true" hidden="true"/>'),
+ enable: function(){
+ Sound._enabled = true;
+ },
+ disable: function(){
+ Sound._enabled = false;
+ },
+ play: function(url){
+ if(!Sound._enabled) return;
+ var options = Object.extend({
+ track: 'global', url: url, replace: false
+ }, arguments[1] || {});
+
+ if(options.replace && this.tracks[options.track]) {
+ $R(0, this.tracks[options.track].id).each(function(id){
+ var sound = $('sound_'+options.track+'_'+id);
+ sound.Stop && sound.Stop();
+ sound.remove();
+ });
+ this.tracks[options.track] = null;
+ }
+
+ if(!this.tracks[options.track])
+ this.tracks[options.track] = { id: 0 };
+ else
+ this.tracks[options.track].id++;
+
+ options.id = this.tracks[options.track].id;
+ $$('body')[0].insert(
+ Prototype.Browser.IE ? new Element('bgsound',{
+ id: 'sound_'+options.track+'_'+options.id,
+ src: options.url, loop: 1, autostart: true
+ }) : Sound.template.evaluate(options));
+ }
+};
+
+if(Prototype.Browser.Gecko && navigator.userAgent.indexOf("Win") > 0){
+ if(navigator.plugins && $A(navigator.plugins).detect(function(p){ return p.name.indexOf('QuickTime') != -1 }))
+ Sound.template = new Template('<object id="sound_#{track}_#{id}" width="0" height="0" type="audio/mpeg" data="#{url}"/>');
+ else
+ Sound.play = function(){};
+}
\ No newline at end of file
Added: trunk/src/ajax/javascripts/external/scriptaculous/unittest.js
==============================================================================
--- (empty file)
+++ trunk/src/ajax/javascripts/external/scriptaculous/unittest.js Fri Apr 10 19:11:32 2009
@@ -0,0 +1,568 @@
+// script.aculo.us unittest.js v1.8.2, Tue Nov 18 18:30:58 +0100 2008
+
+// Copyright (c) 2005-2008 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
+// (c) 2005-2008 Jon Tirsen (http://www.tirsen.com)
+// (c) 2005-2008 Michael Schuerig (http://www.schuerig.de/michael/)
+//
+// script.aculo.us is freely distributable under the terms of an MIT-style license.
+// For details, see the script.aculo.us web site: http://script.aculo.us/
+
+// experimental, Firefox-only
+Event.simulateMouse = function(element, eventName) {
+ var options = Object.extend({
+ pointerX: 0,
+ pointerY: 0,
+ buttons: 0,
+ ctrlKey: false,
+ altKey: false,
+ shiftKey: false,
+ metaKey: false
+ }, arguments[2] || {});
+ var oEvent = document.createEvent("MouseEvents");
+ oEvent.initMouseEvent(eventName, true, true, document.defaultView,
+ options.buttons, options.pointerX, options.pointerY, options.pointerX, options.pointerY,
+ options.ctrlKey, options.altKey, options.shiftKey, options.metaKey, 0, $(element));
+
+ if(this.mark) Element.remove(this.mark);
+ this.mark = document.createElement('div');
+ this.mark.appendChild(document.createTextNode(" "));
+ document.body.appendChild(this.mark);
+ this.mark.style.position = 'absolute';
+ this.mark.style.top = options.pointerY + "px";
+ this.mark.style.left = options.pointerX + "px";
+ this.mark.style.width = "5px";
+ this.mark.style.height = "5px;";
+ this.mark.style.borderTop = "1px solid red;";
+ this.mark.style.borderLeft = "1px solid red;";
+
+ if(this.step)
+ alert('['+new Date().getTime().toString()+'] '+eventName+'/'+Test.Unit.inspect(options));
+
+ $(element).dispatchEvent(oEvent);
+};
+
+// Note: Due to a fix in Firefox 1.0.5/6 that probably fixed "too much", this doesn't work in 1.0.6 or DP2.
+// You need to downgrade to 1.0.4 for now to get this working
+// See https://bugzilla.mozilla.org/show_bug.cgi?id=289940 for the fix that fixed too much
+Event.simulateKey = function(element, eventName) {
+ var options = Object.extend({
+ ctrlKey: false,
+ altKey: false,
+ shiftKey: false,
+ metaKey: false,
+ keyCode: 0,
+ charCode: 0
+ }, arguments[2] || {});
+
+ var oEvent = document.createEvent("KeyEvents");
+ oEvent.initKeyEvent(eventName, true, true, window,
+ options.ctrlKey, options.altKey, options.shiftKey, options.metaKey,
+ options.keyCode, options.charCode );
+ $(element).dispatchEvent(oEvent);
+};
+
+Event.simulateKeys = function(element, command) {
+ for(var i=0; i<command.length; i++) {
+ Event.simulateKey(element,'keypress',{charCode:command.charCodeAt(i)});
+ }
+};
+
+var Test = {};
+Test.Unit = {};
+
+// security exception workaround
+Test.Unit.inspect = Object.inspect;
+
+Test.Unit.Logger = Class.create();
+Test.Unit.Logger.prototype = {
+ initialize: function(log) {
+ this.log = $(log);
+ if (this.log) {
+ this._createLogTable();
+ }
+ },
+ start: function(testName) {
+ if (!this.log) return;
+ this.testName = testName;
+ this.lastLogLine = document.createElement('tr');
+ this.statusCell = document.createElement('td');
+ this.nameCell = document.createElement('td');
+ this.nameCell.className = "nameCell";
+ this.nameCell.appendChild(document.createTextNode(testName));
+ this.messageCell = document.createElement('td');
+ this.lastLogLine.appendChild(this.statusCell);
+ this.lastLogLine.appendChild(this.nameCell);
+ this.lastLogLine.appendChild(this.messageCell);
+ this.loglines.appendChild(this.lastLogLine);
+ },
+ finish: function(status, summary) {
+ if (!this.log) return;
+ this.lastLogLine.className = status;
+ this.statusCell.innerHTML = status;
+ this.messageCell.innerHTML = this._toHTML(summary);
+ this.addLinksToResults();
+ },
+ message: function(message) {
+ if (!this.log) return;
+ this.messageCell.innerHTML = this._toHTML(message);
+ },
+ summary: function(summary) {
+ if (!this.log) return;
+ this.logsummary.innerHTML = this._toHTML(summary);
+ },
+ _createLogTable: function() {
+ this.log.innerHTML =
+ '<div id="logsummary"></div>' +
+ '<table id="logtable">' +
+ '<thead><tr><th>Status</th><th>Test</th><th>Message</th></tr></thead>' +
+ '<tbody id="loglines"></tbody>' +
+ '</table>';
+ this.logsummary = $('logsummary');
+ this.loglines = $('loglines');
+ },
+ _toHTML: function(txt) {
+ return txt.escapeHTML().replace(/\n/g,"<br/>");
+ },
+ addLinksToResults: function(){
+ $$("tr.failed .nameCell").each( function(td){ // todo: limit to children of this.log
+ td.title = "Run only this test";
+ Event.observe(td, 'click', function(){ window.location.search = "?tests=" + td.innerHTML;});
+ });
+ $$("tr.passed .nameCell").each( function(td){ // todo: limit to children of this.log
+ td.title = "Run all tests";
+ Event.observe(td, 'click', function(){ window.location.search = "";});
+ });
+ }
+};
+
+Test.Unit.Runner = Class.create();
+Test.Unit.Runner.prototype = {
+ initialize: function(testcases) {
+ this.options = Object.extend({
+ testLog: 'testlog'
+ }, arguments[1] || {});
+ this.options.resultsURL = this.parseResultsURLQueryParameter();
+ this.options.tests = this.parseTestsQueryParameter();
+ if (this.options.testLog) {
+ this.options.testLog = $(this.options.testLog) || null;
+ }
+ if(this.options.tests) {
+ this.tests = [];
+ for(var i = 0; i < this.options.tests.length; i++) {
+ if(/^test/.test(this.options.tests[i])) {
+ this.tests.push(new Test.Unit.Testcase(this.options.tests[i], testcases[this.options.tests[i]], testcases["setup"], testcases["teardown"]));
+ }
+ }
+ } else {
+ if (this.options.test) {
+ this.tests = [new Test.Unit.Testcase(this.options.test, testcases[this.options.test], testcases["setup"], testcases["teardown"])];
+ } else {
+ this.tests = [];
+ for(var testcase in testcases) {
+ if(/^test/.test(testcase)) {
+ this.tests.push(
+ new Test.Unit.Testcase(
+ this.options.context ? ' -> ' + this.options.titles[testcase] : testcase,
+ testcases[testcase], testcases["setup"], testcases["teardown"]
+ ));
+ }
+ }
+ }
+ }
+ this.currentTest = 0;
+ this.logger = new Test.Unit.Logger(this.options.testLog);
+ setTimeout(this.runTests.bind(this), 1000);
+ },
+ parseResultsURLQueryParameter: function() {
+ return window.location.search.parseQuery()["resultsURL"];
+ },
+ parseTestsQueryParameter: function(){
+ if (window.location.search.parseQuery()["tests"]){
+ return window.location.search.parseQuery()["tests"].split(',');
+ };
+ },
+ // Returns:
+ // "ERROR" if there was an error,
+ // "FAILURE" if there was a failure, or
+ // "SUCCESS" if there was neither
+ getResult: function() {
+ var hasFailure = false;
+ for(var i=0;i<this.tests.length;i++) {
+ if (this.tests[i].errors > 0) {
+ return "ERROR";
+ }
+ if (this.tests[i].failures > 0) {
+ hasFailure = true;
+ }
+ }
+ if (hasFailure) {
+ return "FAILURE";
+ } else {
+ return "SUCCESS";
+ }
+ },
+ postResults: function() {
+ if (this.options.resultsURL) {
+ new Ajax.Request(this.options.resultsURL,
+ { method: 'get', parameters: 'result=' + this.getResult(), asynchronous: false });
+ }
+ },
+ runTests: function() {
+ var test = this.tests[this.currentTest];
+ if (!test) {
+ // finished!
+ this.postResults();
+ this.logger.summary(this.summary());
+ return;
+ }
+ if(!test.isWaiting) {
+ this.logger.start(test.name);
+ }
+ test.run();
+ if(test.isWaiting) {
+ this.logger.message("Waiting for " + test.timeToWait + "ms");
+ setTimeout(this.runTests.bind(this), test.timeToWait || 1000);
+ } else {
+ this.logger.finish(test.status(), test.summary());
+ this.currentTest++;
+ // tail recursive, hopefully the browser will skip the stackframe
+ this.runTests();
+ }
+ },
+ summary: function() {
+ var assertions = 0;
+ var failures = 0;
+ var errors = 0;
+ var messages = [];
+ for(var i=0;i<this.tests.length;i++) {
+ assertions += this.tests[i].assertions;
+ failures += this.tests[i].failures;
+ errors += this.tests[i].errors;
+ }
+ return (
+ (this.options.context ? this.options.context + ': ': '') +
+ this.tests.length + " tests, " +
+ assertions + " assertions, " +
+ failures + " failures, " +
+ errors + " errors");
+ }
+};
+
+Test.Unit.Assertions = Class.create();
+Test.Unit.Assertions.prototype = {
+ initialize: function() {
+ this.assertions = 0;
+ this.failures = 0;
+ this.errors = 0;
+ this.messages = [];
+ },
+ summary: function() {
+ return (
+ this.assertions + " assertions, " +
+ this.failures + " failures, " +
+ this.errors + " errors" + "\n" +
+ this.messages.join("\n"));
+ },
+ pass: function() {
+ this.assertions++;
+ },
+ fail: function(message) {
+ this.failures++;
+ this.messages.push("Failure: " + message);
+ },
+ info: function(message) {
+ this.messages.push("Info: " + message);
+ },
+ error: function(error) {
+ this.errors++;
+ this.messages.push(error.name + ": "+ error.message + "(" + Test.Unit.inspect(error) +")");
+ },
+ status: function() {
+ if (this.failures > 0) return 'failed';
+ if (this.errors > 0) return 'error';
+ return 'passed';
+ },
+ assert: function(expression) {
+ var message = arguments[1] || 'assert: got "' + Test.Unit.inspect(expression) + '"';
+ try { expression ? this.pass() :
+ this.fail(message); }
+ catch(e) { this.error(e); }
+ },
+ assertEqual: function(expected, actual) {
+ var message = arguments[2] || "assertEqual";
+ try { (expected == actual) ? this.pass() :
+ this.fail(message + ': expected "' + Test.Unit.inspect(expected) +
+ '", actual "' + Test.Unit.inspect(actual) + '"'); }
+ catch(e) { this.error(e); }
+ },
+ assertInspect: function(expected, actual) {
+ var message = arguments[2] || "assertInspect";
+ try { (expected == actual.inspect()) ? this.pass() :
+ this.fail(message + ': expected "' + Test.Unit.inspect(expected) +
+ '", actual "' + Test.Unit.inspect(actual) + '"'); }
+ catch(e) { this.error(e); }
+ },
+ assertEnumEqual: function(expected, actual) {
+ var message = arguments[2] || "assertEnumEqual";
+ try { $A(expected).length == $A(actual).length &&
+ expected.zip(actual).all(function(pair) { return pair[0] == pair[1] }) ?
+ this.pass() : this.fail(message + ': expected ' + Test.Unit.inspect(expected) +
+ ', actual ' + Test.Unit.inspect(actual)); }
+ catch(e) { this.error(e); }
+ },
+ assertNotEqual: function(expected, actual) {
+ var message = arguments[2] || "assertNotEqual";
+ try { (expected != actual) ? this.pass() :
+ this.fail(message + ': got "' + Test.Unit.inspect(actual) + '"'); }
+ catch(e) { this.error(e); }
+ },
+ assertIdentical: function(expected, actual) {
+ var message = arguments[2] || "assertIdentical";
+ try { (expected === actual) ? this.pass() :
+ this.fail(message + ': expected "' + Test.Unit.inspect(expected) +
+ '", actual "' + Test.Unit.inspect(actual) + '"'); }
+ catch(e) { this.error(e); }
+ },
+ assertNotIdentical: function(expected, actual) {
+ var message = arguments[2] || "assertNotIdentical";
+ try { !(expected === actual) ? this.pass() :
+ this.fail(message + ': expected "' + Test.Unit.inspect(expected) +
+ '", actual "' + Test.Unit.inspect(actual) + '"'); }
+ catch(e) { this.error(e); }
+ },
+ assertNull: function(obj) {
+ var message = arguments[1] || 'assertNull';
+ try { (obj==null) ? this.pass() :
+ this.fail(message + ': got "' + Test.Unit.inspect(obj) + '"'); }
+ catch(e) { this.error(e); }
+ },
+ assertMatch: function(expected, actual) {
+ var message = arguments[2] || 'assertMatch';
+ var regex = new RegExp(expected);
+ try { (regex.exec(actual)) ? this.pass() :
+ this.fail(message + ' : regex: "' + Test.Unit.inspect(expected) + ' did not match: ' + Test.Unit.inspect(actual) + '"'); }
+ catch(e) { this.error(e); }
+ },
+ assertHidden: function(element) {
+ var message = arguments[1] || 'assertHidden';
+ this.assertEqual("none", element.style.display, message);
+ },
+ assertNotNull: function(object) {
+ var message = arguments[1] || 'assertNotNull';
+ this.assert(object != null, message);
+ },
+ assertType: function(expected, actual) {
+ var message = arguments[2] || 'assertType';
+ try {
+ (actual.constructor == expected) ? this.pass() :
+ this.fail(message + ': expected "' + Test.Unit.inspect(expected) +
+ '", actual "' + (actual.constructor) + '"'); }
+ catch(e) { this.error(e); }
+ },
+ assertNotOfType: function(expected, actual) {
+ var message = arguments[2] || 'assertNotOfType';
+ try {
+ (actual.constructor != expected) ? this.pass() :
+ this.fail(message + ': expected "' + Test.Unit.inspect(expected) +
+ '", actual "' + (actual.constructor) + '"'); }
+ catch(e) { this.error(e); }
+ },
+ assertInstanceOf: function(expected, actual) {
+ var message = arguments[2] || 'assertInstanceOf';
+ try {
+ (actual instanceof expected) ? this.pass() :
+ this.fail(message + ": object was not an instance of the expected type"); }
+ catch(e) { this.error(e); }
+ },
+ assertNotInstanceOf: function(expected, actual) {
+ var message = arguments[2] || 'assertNotInstanceOf';
+ try {
+ !(actual instanceof expected) ? this.pass() :
+ this.fail(message + ": object was an instance of the not expected type"); }
+ catch(e) { this.error(e); }
+ },
+ assertRespondsTo: function(method, obj) {
+ var message = arguments[2] || 'assertRespondsTo';
+ try {
+ (obj[method] && typeof obj[method] == 'function') ? this.pass() :
+ this.fail(message + ": object doesn't respond to [" + method + "]"); }
+ catch(e) { this.error(e); }
+ },
+ assertReturnsTrue: function(method, obj) {
+ var message = arguments[2] || 'assertReturnsTrue';
+ try {
+ var m = obj[method];
+ if(!m) m = obj['is'+method.charAt(0).toUpperCase()+method.slice(1)];
+ m() ? this.pass() :
+ this.fail(message + ": method returned false"); }
+ catch(e) { this.error(e); }
+ },
+ assertReturnsFalse: function(method, obj) {
+ var message = arguments[2] || 'assertReturnsFalse';
+ try {
+ var m = obj[method];
+ if(!m) m = obj['is'+method.charAt(0).toUpperCase()+method.slice(1)];
+ !m() ? this.pass() :
+ this.fail(message + ": method returned true"); }
+ catch(e) { this.error(e); }
+ },
+ assertRaise: function(exceptionName, method) {
+ var message = arguments[2] || 'assertRaise';
+ try {
+ method();
+ this.fail(message + ": exception expected but none was raised"); }
+ catch(e) {
+ ((exceptionName == null) || (e.name==exceptionName)) ? this.pass() : this.error(e);
+ }
+ },
+ assertElementsMatch: function() {
+ var expressions = $A(arguments), elements = $A(expressions.shift());
+ if (elements.length != expressions.length) {
+ this.fail('assertElementsMatch: size mismatch: ' + elements.length + ' elements, ' + expressions.length + ' expressions');
+ return false;
+ }
+ elements.zip(expressions).all(function(pair, index) {
+ var element = $(pair.first()), expression = pair.last();
+ if (element.match(expression)) return true;
+ this.fail('assertElementsMatch: (in index ' + index + ') expected ' + expression.inspect() + ' but got ' + element.inspect());
+ }.bind(this)) && this.pass();
+ },
+ assertElementMatches: function(element, expression) {
+ this.assertElementsMatch([element], expression);
+ },
+ benchmark: function(operation, iterations) {
+ var startAt = new Date();
+ (iterations || 1).times(operation);
+ var timeTaken = ((new Date())-startAt);
+ this.info((arguments[2] || 'Operation') + ' finished ' +
+ iterations + ' iterations in ' + (timeTaken/1000)+'s' );
+ return timeTaken;
+ },
+ _isVisible: function(element) {
+ element = $(element);
+ if(!element.parentNode) return true;
+ this.assertNotNull(element);
+ if(element.style && Element.getStyle(element, 'display') == 'none')
+ return false;
+
+ return this._isVisible(element.parentNode);
+ },
+ assertNotVisible: function(element) {
+ this.assert(!this._isVisible(element), Test.Unit.inspect(element) + " was not hidden and didn't have a hidden parent either. " + ("" || arguments[1]));
+ },
+ assertVisible: function(element) {
+ this.assert(this._isVisible(element), Test.Unit.inspect(element) + " was not visible. " + ("" || arguments[1]));
+ },
+ benchmark: function(operation, iterations) {
+ var startAt = new Date();
+ (iterations || 1).times(operation);
+ var timeTaken = ((new Date())-startAt);
+ this.info((arguments[2] || 'Operation') + ' finished ' +
+ iterations + ' iterations in ' + (timeTaken/1000)+'s' );
+ return timeTaken;
+ }
+};
+
+Test.Unit.Testcase = Class.create();
+Object.extend(Object.extend(Test.Unit.Testcase.prototype, Test.Unit.Assertions.prototype), {
+ initialize: function(name, test, setup, teardown) {
+ Test.Unit.Assertions.prototype.initialize.bind(this)();
+ this.name = name;
+
+ if(typeof test == 'string') {
+ test = test.gsub(/(\.should[^\(]+\()/,'#{0}this,');
+ test = test.gsub(/(\.should[^\(]+)\(this,\)/,'#{1}(this)');
+ this.test = function() {
+ eval('with(this){'+test+'}');
+ }
+ } else {
+ this.test = test || function() {};
+ }
+
+ this.setup = setup || function() {};
+ this.teardown = teardown || function() {};
+ this.isWaiting = false;
+ this.timeToWait = 1000;
+ },
+ wait: function(time, nextPart) {
+ this.isWaiting = true;
+ this.test = nextPart;
+ this.timeToWait = time;
+ },
+ run: function() {
+ try {
+ try {
+ if (!this.isWaiting) this.setup.bind(this)();
+ this.isWaiting = false;
+ this.test.bind(this)();
+ } finally {
+ if(!this.isWaiting) {
+ this.teardown.bind(this)();
+ }
+ }
+ }
+ catch(e) { this.error(e); }
+ }
+});
+
+// *EXPERIMENTAL* BDD-style testing to please non-technical folk
+// This draws many ideas from RSpec http://rspec.rubyforge.org/
+
+Test.setupBDDExtensionMethods = function(){
+ var METHODMAP = {
+ shouldEqual: 'assertEqual',
+ shouldNotEqual: 'assertNotEqual',
+ shouldEqualEnum: 'assertEnumEqual',
+ shouldBeA: 'assertType',
+ shouldNotBeA: 'assertNotOfType',
+ shouldBeAn: 'assertType',
+ shouldNotBeAn: 'assertNotOfType',
+ shouldBeNull: 'assertNull',
+ shouldNotBeNull: 'assertNotNull',
+
+ shouldBe: 'assertReturnsTrue',
+ shouldNotBe: 'assertReturnsFalse',
+ shouldRespondTo: 'assertRespondsTo'
+ };
+ var makeAssertion = function(assertion, args, object) {
+ this[assertion].apply(this,(args || []).concat([object]));
+ };
+
+ Test.BDDMethods = {};
+ $H(METHODMAP).each(function(pair) {
+ Test.BDDMethods[pair.key] = function() {
+ var args = $A(arguments);
+ var scope = args.shift();
+ makeAssertion.apply(scope, [pair.value, args, this]); };
+ });
+
+ [Array.prototype, String.prototype, Number.prototype, Boolean.prototype].each(
+ function(p){ Object.extend(p, Test.BDDMethods) }
+ );
+};
+
+Test.context = function(name, spec, log){
+ Test.setupBDDExtensionMethods();
+
+ var compiledSpec = {};
+ var titles = {};
+ for(specName in spec) {
+ switch(specName){
+ case "setup":
+ case "teardown":
+ compiledSpec[specName] = spec[specName];
+ break;
+ default:
+ var testName = 'test'+specName.gsub(/\s+/,'-').camelize();
+ var body = spec[specName].toString().split('\n').slice(1);
+ if(/^\{/.test(body[0])) body = body.slice(1);
+ body.pop();
+ body = body.map(function(statement){
+ return statement.strip()
+ });
+ compiledSpec[testName] = body.join('\n');
+ titles[testName] = specName;
+ }
+ }
+ new Test.Unit.Runner(compiledSpec, { titles: titles, testLog: log || 'testlog', context: name });
+};
\ No newline at end of file
Copied: trunk/src/ajax/javascripts/home.js (from r25, /trunk/src/ajax/javascripts/ajax_home.js)
==============================================================================
--- /trunk/src/ajax/javascripts/ajax_home.js (original)
+++ trunk/src/ajax/javascripts/home.js Fri Apr 10 19:11:32 2009
@@ -1,7 +1,21 @@
+//+-----------------------------------------------------------------------------
+//+ 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.
+//+-----------------------------------------------------------------------------
+
+
// --- 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; },
@@ -9,6 +23,7 @@
"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;
@@ -23,7 +38,6 @@
"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"; }
@@ -83,16 +97,18 @@
makeHome(parentId, tableId, false);
});
- var select = new Element("select", {"id" : (top ? "topicTableSelectTop" : "topicTableSelectBottom"), "class" : "topicTable"});
- var selectValues = new Array("5", "10", "15", "25", "50", "100", "200", "300", "All");
+ var select = new Element("select", {"id" : (top === true ? "topicTableSelectTop" : "topicTableSelectBottom"), "class" : "topicTable"});
+ var selectValues = __idx.getTopicPerPageVals();
var selectInnerHTML = "";
selectValues.each(function(value, idx)
{
- if(Number(value) !== __idx.getTopicsPerPage()){
- select.insert(new Element("option", {"value" : (value === "All" ? -1 : value)}).update(value), {"position" : "bottom"});
+ 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" : (value === "All" ? -1 : value), "selected" : "selected"}).update(value), {"position" : "bottom"});
+ select.insert(new Element("option", {"value" : numberValue, "selected" : "selected"}).update(value), {"position" : "bottom"});
}
});
div.insert(select, {"position" : "content"});
@@ -113,7 +129,7 @@
if(topicSummaries !== null || $(tableId) === null){
// --- removes the old table - if there exists an element with the id "tableId"
if($(tableId) !== null)$(tableId).remove();
- if($("naviDivBottom") !== null)$("naviDivBottom").remove();
+ if($("naviDivTop") !== null)$("naviDivTop").remove();
if($("naviDivBottom") !== null)$("naviDivBottom").remove();
createTableNavi(true);
@@ -144,7 +160,7 @@
if(topicSummary.itemIdentities){
topicSummary.itemIdentities.each(function(itemIdentityJ, innerIdx)
{
- ul.insert(new Element("li").update(itemIdentityJ));
+ ul.insert(new Element("li").update(itemIdentityJ), {"position" : "bottom"});
});
}
@@ -154,7 +170,7 @@
if(topicSummary.subjectLocators){
topicSummary.subjectLocators.each(function(subjectLocatorJ, innerIdx)
{
- ul.insert(new Element("li").update(subjectLocatorJ));
+ ul.insert(new Element("li").update(subjectLocatorJ), {"position" : "bottom"});
});
}
@@ -165,11 +181,11 @@
topicSummary.subjectIdentifiers.each(function(subjectIdentifierJ, innerIdx)
{
var li = new Element("li", {"class" : "clickable"}).update(subjectIdentifierJ);
- ul.insert(li);
+ ul.insert(li, {"position" : "bottom"});
li.observe("click", function(event)
{
var node = event.element();
- makePage(PAGES.edit);//, node.textContent);
+ makePage(PAGES.edit, node.textContent);
});
});
}
@@ -183,7 +199,7 @@
if(instanceOfJ){
instanceOfJ.each(function(psi, psiIdx)
{
- ul.insert(new Element("li").update(psi));
+ ul.insert(new Element("li").update(psi), {"position" : "top"});
});
}
});
@@ -195,7 +211,7 @@
if(topicSummary.names){
topicSummary.names.each(function(nameJ, innerIdx)
{
- ul.insert(new Element("li").update(nameJ));
+ ul.insert(new Element("li").update(nameJ), {"position" : "top"});
});
}
@@ -205,7 +221,7 @@
if(topicSummary.occurrences){
topicSummary.occurrences.each(function(occurrenceJ, innerIdx)
{
- ul.insert(new Element("li").update(occurrenceJ));
+ ul.insert(new Element("li").update(occurrenceJ), {"position" : "top"});
});
}
@@ -248,7 +264,7 @@
}
- // --- the real ajax request
+ // --- the real ajax request
new Ajax.Request(SUMMARY_URL,
{"method" : "get",
"onSuccess" : onSuccessHandler,
Added: trunk/src/ajax/javascripts/make_fragment_node.js
==============================================================================
--- (empty file)
+++ trunk/src/ajax/javascripts/make_fragment_node.js Fri Apr 10 19:11:32 2009
@@ -0,0 +1,1304 @@
+//+-----------------------------------------------------------------------------
+//+ 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
+//+-----------------------------------------------------------------------------
+
+
+// --- creates a div-DOM-Element which contains all necessary information
+// --- of a topic.
+// --- the information itself will be generated from the passed json data
+// --- representing a fragment.
+// --- changed values can also be commmited
+function makeFragmentNode(content)
+{
+ if(!content)content = new Object(); // to avoid null-reference errors
+
+ // --- flattens a two dimensional array and returns a one dimensional array
+ // --- with all elements of the passed array
+ function flatten(x2Array)
+ {
+ try{
+ var fArray = new Array();
+ x2Array.each(function(x1Array, idx)
+ {
+ if(x1Array !== null){
+ x1Array.each(function(elem, innerIdx)
+ {
+ fArray.push(elem);
+ });
+ }
+ });
+ return fArray;
+ }
+ catch(err){
+ return new Object();
+ }
+ }
+
+
+ // --- creates a row -> a div element with a span element which allows to remove this row
+ // --- and a text field.
+ // --- content will be set as the value of the text field
+ function makeRow(content)
+ {
+ var row = new Element("div", {"class" : CLASSES.row()});
+ var rowDel = new Element("span", {"class" : CLASSES.removeBtnRow()}).update("x");
+ row.insert(rowDel, {"position" : "bottom"});
+ rowDel.observe("click", function(event)
+ {
+ var parent = event.element().parentNode;
+ var rows = parent.parentNode.getElementsByClassName(CLASSES.row());
+ if(rows.length > 1){
+ parent.remove();
+ if(rows.length === 1){
+ rows[0].childElements()[0].hide();
+ }
+ }
+ });
+ var textfield = new Element("input", {"type" : "text", "class" : CLASSES.textRow(), "value" : content});
+ row.insert(textfield, {"position" : "bottom"});
+ return row;
+ }// makeRow
+
+
+ // --- creates a header div with a title, a remove button, add button and show/hide button.
+ // --- the title should be a string which will inserted into a span element within the header.
+ // --- if withHideBtn is set to a string with a length greater 0, the header will contain a hide button
+ // --- and all elements of the header's owner node with a class name equal to the string withHideBtn will
+ // --- be hidden or shown.
+ // --- if with addButton is set to true, the header will contain an addButton, which allows to
+ // --- adds a new row with a text field and a removeButton for the row.
+ // --- if withRemoveButton is set to true, the header will contain a removeButton which allows
+ // --- to remove the entire parent node.
+ function makeHeader(title, withHideBtn, withAddBtn, withRemoveBtn, addHandler)
+ {
+ if(typeof(addHandler) !== "function"){
+ addHandler = function(event)
+ {
+ var parentNode = event.element().parentNode;
+ var ownerNode = parentNode.parentNode;
+ var row = makeRow("");
+ ownerNode.insert(row, {"position" : "bottom"});
+ var rows = ownerNode.getElementsByClassName(CLASSES.row());
+ if(rows.length === 1){
+ rows[0].childElements()[0].hide();
+ }
+ else if(rows.length > 1){
+ rows[0].childElements()[0].show();
+ }
+
+ // --- the owner frame is hidden, so the new created node has to be hidden, too
+ if(withAddBtn === true && parentNode.getElementsByClassName(CLASSES.hideBtnHeader())[0].textContent === "show"){
+ row.hide();
+ }
+ };
+ }
+
+ var headerNode = new Element("div" , {"class" : CLASSES.header()});
+ var titleNode = new Element("span", {"class" : CLASSES.headerTitle()}).update(title);
+ headerNode.insert(titleNode, {"position" : "bottom"});
+
+ if(typeof(withHideBtn) === "string" && withHideBtn.length !== 0){
+ var hideNode = new Element("span", {"class" : CLASSES.hideBtnHeader()}).update("hide");
+ headerNode.insert(hideNode, {"position" : "bottom"});
+ hideNode.observe("click", function(event){
+ var me = event.element();
+ var ownerNode = me.parentNode.parentNode;
+
+ if(me.textContent === "hide"){
+ var rowsToHide = ownerNode.getElementsByClassName(withHideBtn);
+ for(var i = 0; i !== rowsToHide.length; ++i)
+ rowsToHide[i].hide();
+ me.textContent = "show";
+ }
+ else {
+ var rowsToShow = ownerNode.getElementsByClassName(withHideBtn);
+ for(var i = 0; i !== rowsToShow.length; ++i)
+ rowsToShow[i].show();
+ me.textContent = "hide";
+ }
+ });
+ }
+
+ if(withAddBtn === true){
+ var addNode = new Element("span", {"class" : CLASSES.addBtnHeader()}).update("add");
+ headerNode.insert(addNode, {"position" : "bottom"});
+ addNode.observe("click", addHandler);
+ }
+
+ if(withRemoveBtn === true){
+ var removeNode = new Element("span", {"class" : CLASSES.removeBtnHeader()}).update("del");
+ headerNode.insert(removeNode, {"position" : "bottom"});
+ removeNode.observe("click", function(event)
+ {
+ var ownerNode = event.element().parentNode.parentNode;
+ ownerNode.remove();
+ });
+ }
+
+ return headerNode;
+ }// makeHeader
+
+
+ // --- returns a div-node representing a list frame of a variable amount of rows.
+ // --- title is a string describing the heade title.
+ // --- classValue is the class-attribute's value of the outer frame element (div).
+ // --- contents is an array which will be set as the content of a row, everey element of the
+ // --- array will be boudn to one row.
+ // --- withHideBtn is a boolean value describing if the header row will have a hide button.
+ // --- withAddBtn is a boolean value describing if the header row will have an add button
+ // --- withRemoveBtn is a boolean value describing if the header row will have a remove button
+ function makeListFrame(title, classValue, contents, withHideBtn, withAddBtn, withRemoveBtn)
+ {
+ var listElem = new Element("div", {"class" : CLASSES.listFrame() + " " + classValue});
+ var header = makeHeader(title, "row", withAddBtn, withRemoveBtn, null);
+ listElem.insert(header, {"position" : "bottom"});
+
+ try{
+ contents.each(function(content, idx)
+ {
+ listElem.insert(makeRow(content), {"position" : "bottom"});
+ });
+
+ if(contents.length === 1)
+ listElem.getElementsByClassName(CLASSES.row())[0].childElements()[0].hide();
+ }
+ catch(err){
+ listElem.insert(makeRow(""), {"position" : "bottom"});
+ listElem.getElementsByClassName(CLASSES.row())[0].childElements()[0].hide();
+ }
+
+ return listElem;
+ }// makeListFrame
+
+
+
+ // --- returns a div element representing a resourceRef or resourceData frame.
+ // --- title describes the title field of the header - if title is set to false
+ // --- there will be generated the title "resourceRef", "resourceData" or resource
+ // --- depending on the passed values resourceRef and resourceData.
+ // --- if withHideBtn is set to true, the header will contain a hide button.
+ function makeResourceFrame(title, classValue, resourceRef, resourceData, withHideBtn)
+ {
+ var content = "";
+ var contentType = "";
+
+ if(resourceRef !== null && typeof(resourceRef) !== "undefined"){
+ content = resourceRef;
+ contentType = "http://www.w3.org/2001/XMLSchema#anyURI";
+ if(title === false || title === null)title = "resourceRef";
+ }
+ else if(resourceData !== null && typeof(resourceData) !== "undefined"){
+ content = resourceData.value;
+ contentType = (resourceData.datatype === null ? "http://www.w3.org/2001/XMLSchema#string" : resourceData.datatype);
+ if(title === false || title === null)title = "resourceData";
+ }
+ else {
+ if(title === false || title === null)title = "resource";
+ }
+
+ var resourceFrame = new Element("div", {"class" : CLASSES.resourceFrame() + " " + classValue});
+ var header = makeHeader(title, (withHideBtn === true ? CLASSES.row() : false), false, false, null);
+ resourceFrame.insert(header, {"position" : "bottom"});
+ var dataRow = new Element("div", {"class" : CLASSES.row()});
+ dataRow.insert(new Element("textarea", {"class" : CLASSES.textareaRow()}).update(content));
+ resourceFrame.insert(dataRow, {"position" : "bottom"});
+ var datatypeRow = new Element("div", {"class" : CLASSES.row()});
+ datatypeRow.insert(new Element("input", {"type" : "text", "class" : CLASSES.textRow(), "value" : contentType}));
+ resourceFrame.insert(datatypeRow, {"position" : "bottom"});
+ return resourceFrame;
+ }// makeResourceFrame
+
+
+ // --- returns a node representing a variant frame with
+ // --- an itemIdentity frame, a scope frame and a resource frame.
+ // --- if title is set to a string this will be set as the header titlte of this varian frame.
+ // --- content is the json representation of a variant.
+ // --- withHideBtn is a boolean value, if it is set to true, there will be a hide button in the
+ // --- frame header which is able to hide/whow all subframes.
+ // --- if withRemoveBtn is set to true, there will be a remove button available in the header row.
+ function makeVariantFrame(title, content, withHideBtn, withRemoveBtn)
+ {
+ if(!content)content = new Object(); // to avoid null reference errors
+
+ var variantFrame = new Element("div", {"class" : CLASSES.variantFrame()});
+ var header = makeHeader(title, (withHideBtn === true ? CLASSES.inVariantFrame() : false), false, withRemoveBtn, null);
+ variantFrame.insert(header, {"position" : "bottom"});
+ var itemIdentityFrame = makeListFrame("itemIdentity", CLASSES.itemIdentityFrame() + " " + CLASSES.inVariantFrame(), content.itemIdentities, true, true, false);
+ variantFrame.insert(itemIdentityFrame, {"position" : "bottom"});
+ var scopeFrame = makeListFrame("scope", CLASSES.scopeFrame() + " " + CLASSES.inVariantFrame(), content.scopes, true, true, false);
+ variantFrame.insert(scopeFrame, {"position" : "bottom"});
+ var resourceFrame = makeResourceFrame(null, CLASSES.inVariantFrame(), content.resourceRef, content.resourceData, true);
+ variantFrame.insert(resourceFrame, {"position" : "bottom"});
+ return variantFrame;
+ }// makeVariantFrame
+
+
+ // --- returns a node representing a list of variant frames.
+ // --- title is the header title of the entire list frame.
+ // --- subtitle sets every variant's header title.
+ // --- content is the json representaiton of a list of variant elements.
+ // --- withHideBtn is a boolean value, if set to true, the header will contain a hide
+ // --- button which is able to hide/show all sub frames
+ // --- withAddBtn describes if there is an add button available in the header.
+ function makeVariantsFrame(title, subTitle, classValue, content, withHideBtn, withAddBtn)
+ {
+ // --- defines the clickhandler of the header's add button,
+ // --- so there will be created new varaint frames instead of
+ // --- new rows
+ var headerAddHandler = function(event)
+ {
+ var variantFrame = makeVariantFrame(subTitle, null, true, true);
+ variantsFrame.insert(variantFrame, {"position" : "bottom"});
+
+ // --- the owner frame is hidden, so the new created node has to be hidden, too
+ var parentNode = event.element().parentNode;
+ if(withAddBtn === true && parentNode.getElementsByClassName(CLASSES.hideBtnHeader())[0].textContent === "show"){
+ variantFrame.hide();
+ }
+ };
+
+ var variantsFrame = new Element("div", {"class" : CLASSES.variantsFrame() + " " + classValue});
+ var header = makeHeader(title, CLASSES.variantFrame(), withAddBtn, false, headerAddHandler);
+ variantsFrame.insert(header, {"position" : "bottom"});
+
+ // --- tries to itereate through the content array and create a variant
+ // --- frame for every element
+ try{
+ content.each(function(elem, idx)
+ {
+ var variantFrame = makeVariantFrame(subTitle, elem, true, true);
+ variantsFrame.insert(variantFrame, {"position" : "bottom"});
+ });
+ }
+ catch(err){}
+
+ return variantsFrame;
+ }// makeVariantsFrame
+
+
+
+ // --- returns a node representing a name frame.
+ // --- title represents the frame's header title.
+ // --- content is the json representation of a name element.
+ // --- withHideBtn should be a string with the length > 0, so there will be a hide button
+ // --- available which hides/shows all frame elements with the class contained in withHideBtn.
+ // --- withRemoveBtn describes if the frame header has a remove button to remove the entire frame.
+ function makeNameFrame(title, content, withHideBtn, withRemoveBtn)
+ {
+ if(!content)content = new Object(); // to avoid null reference errors
+
+ var nameFrame = new Element("div", {"class" : CLASSES.nameFrame()});
+ var header = makeHeader(title, (withHideBtn === true ? CLASSES.inNameFrame() : false), false, withRemoveBtn, null);
+ nameFrame.insert(header, {"position" : "bottom"});
+ var itemIdentityFrame = makeListFrame("itemIdentity", CLASSES.itemIdentityFrame() + " " + CLASSES.inNameFrame(), content.itemIdentities, true, true, false);
+ nameFrame.insert(itemIdentityFrame, {"position" : "bottom"});
+ var typeFrame = makeListFrame("type", CLASSES.typeFrame() + " " + CLASSES.inNameFrame(), content.type, true, false, false);
+ nameFrame.insert(typeFrame, {"position" : "bottom"});
+ var scopeFrame = makeListFrame("scope", CLASSES.scopeFrame() + " " + CLASSES.inNameFrame(), content.scopes, true, true, false);
+ nameFrame.insert(scopeFrame, {"position" : "bottom"});
+ var nameValue = (content.value ? new Array(content.value) : new Array(""));
+ var valueFrame = makeListFrame("value", CLASSES.valueFrame() + " " + CLASSES.inNameFrame(), nameValue, true, false, false);
+ nameFrame.insert(valueFrame, {"position" : "bottom"});
+ var variantsFrame = makeVariantsFrame("variants", "variant", CLASSES.inNameFrame(), content.variants, CLASSES.frame(), true);
+ nameFrame.insert(variantsFrame);
+
+ return nameFrame;
+ }// makeNameFrame
+
+
+ // --- returns a node representing a list of name frames.
+ // --- title is the title of the entire list frame.
+ // --- subtitle will be used as title of every inner name frame.
+ // --- content is the json representation of a list of topic names.
+ // --- if withHideBtn is set to true, the main header will contain a hide button.
+ // --- if withAddBtn is set to true, the main header will contain an add button,
+ // --- so it is possible to add new name frames to the list.
+ function makeNamesFrame(title, subtitle, classValue, content, withHideBtn, withAddBtn)
+ {
+ // --- defines the clickhandler of the header's add button,
+ // --- so there will be created new name frames instead of
+ // --- new rows
+ var headerAddHandler = function(event)
+ {
+ var nameFrame = makeNameFrame(subtitle, null, true, true);
+ namesFrame.insert(nameFrame, {"position" : "bottom"});
+
+ // --- the owner frame is hidden, so the new created node has to be hidden, too
+ var parentNode = event.element().parentNode;
+ if(withAddBtn === true && parentNode.getElementsByClassName(CLASSES.hideBtnHeader())[0].textContent === "show"){
+ nameFrame.hide();
+ }
+ };
+
+ var namesFrame = new Element("div", {"class" : CLASSES.namesFrame() + " " + classValue});
+ var header = makeHeader(title, CLASSES.nameFrame(), withAddBtn, false, headerAddHandler);
+ namesFrame.insert(header, {"position" : "bottom"});
+
+ // --- tries to itereate through the content array and create a name
+ // --- frame for every element
+ try{
+ content.each(function(elem, idx)
+ {
+ var nameFrame = makeNameFrame(subtitle, elem, true, true);
+ namesFrame.insert(nameFrame, {"position" : "bottom"});
+ });
+ }
+ catch(err){}
+
+ return namesFrame;
+ }// makeNamesFrame
+
+
+ // --- returns a node representing a name frame.
+ // --- title is the frame's header title.
+ // --- content is the json representation of a name.
+ // --- if withHideBtn is set tot true, the header will conatina a hide button.
+ // --- if withRemoveBtn is set to true the header will contain a remove button.
+ function makeOccurrenceFrame(title, content, withHideBtn, withRemoveBtn)
+ {
+ if(!content)content = new Object(); // to avoid null reference errors
+
+ var occurrenceFrame = new Element("div", {"class" : CLASSES.occurrenceFrame()});
+ var header = makeHeader(title, (withHideBtn === true ? CLASSES.inOccurrenceFrame() : false), false, withRemoveBtn, null);
+ occurrenceFrame.insert(header, {"position" : "bottom"});
+
+ var itemIdentityFrame = makeListFrame("itemIdentity", CLASSES.itemIdentityFrame() + " " + CLASSES.inOccurrenceFrame(), content.itemIdentities, true, true, false);
+ occurrenceFrame.insert(itemIdentityFrame, {"position" : "bottom"});
+ var typeFrame = makeListFrame("type", CLASSES.typeFrame() + " " + CLASSES.inOccurrenceFrame(), content.type, true, false, false);
+ occurrenceFrame.insert(typeFrame, {"position" : "bottom"});
+ var scopeFrame = makeListFrame("scope", CLASSES.scopeFrame() + " " + CLASSES.inOccurrenceFrame(), content.scopes, true, true, false);
+ occurrenceFrame.insert(scopeFrame, {"position" : "bottom"});
+ var resourceFrame = makeResourceFrame(null, CLASSES.inOccurrenceFrame(), content.resourceRef, content.resourceData, true);
+ occurrenceFrame.insert(resourceFrame, {"position" : "bottom"});
+
+ return occurrenceFrame;
+ }// makeOccurrenceFrame
+
+
+ // --- returns a node representing list of occurrences.
+ // --- title is the title of the entire list frame.
+ // --- subtitle is the title of all inner occurrence frames.
+ // --- if withHideBtn is set tot true, the header will conatina a hide button.
+ // --- if withRemoveBtn is set to true the header will contain a remove button.
+ function makeOccurrencesFrame(title, subtitle, classValue, content, withHideBtn, withAddBtn)
+ {
+ // --- defines the clickhandler of the header's add button,
+ // --- so there will be created new occurrence frames instead of
+ // --- new rows
+ var headerAddHandler = function(event)
+ {
+ var occurrenceFrame = makeOccurrenceFrame(subtitle, null, true, true);
+ occurrencesFrame.insert(occurrenceFrame, {"position" : "bottom"});
+
+ // --- the owner frame is hidden, so the new created node has to be hidden, too
+ var parentNode = event.element().parentNode;
+ if(withAddBtn === true && parentNode.getElementsByClassName(CLASSES.hideBtnHeader())[0].textContent === "show"){
+ occurrenceFrame.hide();
+ }
+ };
+
+ var occurrencesFrame = new Element("div", {"class" : CLASSES.occurrencesFrame() + " " + classValue});
+ var header = makeHeader(title, CLASSES.occurrenceFrame(), withAddBtn, false, headerAddHandler);
+ occurrencesFrame.insert(header, {"position" : "bottom"});
+
+ // --- tries to itereate through the content array and create a name
+ // --- frame for every element
+ try{
+ content.each(function(elem, idx)
+ {
+ var occurrenceFrame = makeOccurrenceFrame(subtitle, elem, true, true);
+ occurrencesFrame.insert(occurrenceFrame, {"position" : "bottom"});
+ });
+ }
+ catch(err){}
+ return occurrencesFrame;
+ }// makeOccurrencesFrame
+
+
+ // --- returns a node representing a topic frame.
+ // --- title is the title of the main topic frame.
+ // --- content is the json representation of a topic.
+ // --- if withHideBtn is set to true, there will be a hide button in the frame's header.
+ // --- if withRemoveBtn is set to true, there will be a remove button in the frame's header.
+ function makeTopicFrame(title, content, withHideBtn)
+ {
+ if(!content)content = new Object(); // to avoid null reference errors
+
+ // --- creates the topic's main frame
+ var topicFrame = new Element("div", {"class" : CLASSES.topicFrame()});
+ var header = makeHeader(title, (withHideBtn === true ? CLASSES.inTopicFrame() : false), false, false, null);
+ header.writeAttribute({"class" : CLASSES.topicHeader()});
+ topicFrame.insert(header, {"position" : "bottom"});
+
+ // --- creates the topic's id frame
+ var topicId = (typeof(content.id) !== "string" ? "" : [content.id]);
+ var topicIdFrame = makeListFrame("topic id", CLASSES.topicIdFrame() + " " + CLASSES.inTopicFrame(), topicId, true, false, false);
+ topicFrame.insert(topicIdFrame);
+
+ // --- creates the topic's itemIdentity frame
+ var itemIdentityFrame = makeListFrame("itemIdentity", CLASSES.itemIdentityFrame() + " " + CLASSES.inTopicFrame(), content.itemIdentities, true, true, false);
+ topicFrame.insert(itemIdentityFrame, {"position" : "bottom"});
+
+ // --- creates the topic's subjectLocator frame
+ var subjectLocatorFrame = makeListFrame("subjectLocator", CLASSES.subjectLocatorFrame() + " " + CLASSES.inTopicFrame(), content.subjectLocators, true, true, false);
+ topicFrame.insert(subjectLocatorFrame, {"position" : "bottom"});
+
+ // --- creates the topic's subjectIdentifier frame
+ var subjectIdentifierFrame = makeListFrame("subjectIdentifier", CLASSES.subjectIdentifierFrame() + " " + CLASSES.inTopicFrame(), content.subjectIdentifiers, true, true, false);
+ topicFrame.insert(subjectIdentifierFrame, {"position" : "bottom"});
+
+ // --- creates the topic's instanceOf frame
+ var instanceOfFrame = makeListFrame("instanceOf", CLASSES.instanceOfFrame() + " " + CLASSES.inTopicFrame(), flatten(content.instanceOfs), true, true, false);
+ topicFrame.insert(instanceOfFrame, {"position" : "bottom"});
+
+ // --- creates the topic's name frame
+ var nameFrame = makeNamesFrame("names", "name", CLASSES.inTopicFrame(), content.names, CLASSES.namesFrame(), true);
+ topicFrame.insert(nameFrame, {"position" : "bottom"});
+
+ // --- creates the topic's name frame
+ var occurrenceFrame = makeOccurrencesFrame("occurrences", "occurrence", CLASSES.inTopicFrame(), content.occurrences, CLASSES.occurrencesFrame(), true);
+ topicFrame.insert(occurrenceFrame, {"position" : "bottom"});
+
+ return topicFrame;
+ }// makeTopicFrame
+
+
+
+ // --- returns a node representing a topicStub.
+ // --- title is the topicStub frame's title.
+ // --- content is the json representation of a topicstub.
+ // --- if withHideBtn is set to true, the frame's header will contain a hide button.
+ function makeTopicStubFrame(title, content, withHideBtn, withRemoveBtn)
+ {
+ if(!content)content = new Object(); // to avoid null reference errors
+
+ // --- creates the frame
+ var topicStubFrame = new Element("div", {"class" : CLASSES.topicStubFrame()});
+ var header = makeHeader(title, (withHideBtn === true ? CLASSES.inTopicStubFrame() : false), false, withRemoveBtn, null);
+ topicStubFrame.insert(header, {"position" : "bottom"});
+
+ // --- creates the topicStub's id frame
+ var topicId = (typeof(content.id) !== "string" ? "" : [content.id]);
+ var topicIdFrame = makeListFrame("topic id", CLASSES.topicIdFrame() + " " + CLASSES.inTopicStubFrame(), topicId, true, false, false);
+ topicStubFrame.insert(topicIdFrame);
+
+ // --- creates the topic's itemIdentity frame
+ var itemIdentityFrame = makeListFrame("itemIdentity", CLASSES.itemIdentityFrame() + " " + CLASSES.inTopicStubFrame(), content.itemIdentities, true, true, false);
+ topicStubFrame.insert(itemIdentityFrame, {"position" : "bottom"});
+
+ // --- creates the topic's subjectLocator frame
+ var subjectLocatorFrame = makeListFrame("subjectLocator", CLASSES.subjectLocatorFrame() + " " + CLASSES.inTopicStubFrame(), content.subjectLocators, true, true, false);
+ topicStubFrame.insert(subjectLocatorFrame, {"position" : "bottom"});
+
+ // --- creates the topic's subjectIdentifier frame
+ var subjectIdentifierFrame = makeListFrame("subjectIdentifier", CLASSES.subjectIdentifierFrame() + " " + CLASSES.inTopicStubFrame(), content.subjectIdentifiers, true, true, false);
+ topicStubFrame.insert(subjectIdentifierFrame, {"position" : "bottom"});
+
+ return topicStubFrame;
+ }// makeTopicStubFrame
+
+
+ // --- returns a node representing a list of topicStub frames.
+ // --- title is the title of the main frame's header.
+ // --- subtitle is the title of all topicStub frames within the main frame.
+ // --- content is the json representation of a list of topicStubs.
+ // --- withHideBtn is a boolean value. is it set to true the main frame will contain a hide button.
+ // --- withAddBtn is a boolean value. is it set to true the main frame will contain an add button.
+ function makeTopicStubsFrame(title, subtitle, content, withHideBtn, withAddBtn)
+ {
+ // --- defines the clickhandler of the header's add button,
+ // --- so there will be created new topicStub frames instead of
+ // --- new rows
+ var headerAddHandler = function(event)
+ {
+ var topicStubFrame = makeTopicStubFrame(subtitle, null, true, true);
+ topicStubsFrame.insert(topicStubFrame, {"position" : "bottom"});
+
+ // --- the owner frame is hidden, so the new created node has to be hidden, too
+ var parentNode = event.element().parentNode;
+ if(withAddBtn === true && parentNode.getElementsByClassName(CLASSES.hideBtnHeader())[0].textContent === "show"){
+ topicStubFrame.hide();
+ }
+ };
+
+ var topicStubsFrame = new Element("div", {"class" : CLASSES.topicStubsFrame()});
+ var header = makeHeader(title, (withHideBtn === true ? CLASSES.topicStubFrame() : false), withAddBtn, false, headerAddHandler);
+ header.writeAttribute({"class" : CLASSES.topicStubsHeader()});
+ topicStubsFrame.insert(header, {"position" : "bottom"});
+
+ // --- tries to itereate through the content array and create a name
+ // --- frame for every element
+ try{
+ content.each(function(elem, idx)
+ {
+ var topicStubFrame = makeTopicStubFrame(subtitle, elem, true, true);
+ topicStubsFrame.insert(topicStubFrame, {"position" : "bottom"});
+ });
+ }
+ catch(err){}
+ return topicStubsFrame;
+ }// makeTopicStubsFrame
+
+
+ // --- returns a node representing an association role frame.
+ // --- title is the main frame's title.
+ // --- content is the json representation of a role.
+ // --- withHideBtn is a boolean value. is it set to true, the frame's header will contain a hide button.
+ // --- withRemove is a boolean value. is it set to true, the frame's header will contain a remove button.
+ function makeRoleFrame(title, content, withHideBtn, withRemoveBtn)
+ {
+ if(!content)content = new Object(); // to avoid null reference errors
+
+ // --- creates the frame
+ var roleFrame = new Element("div", {"class" : CLASSES.roleFrame()});
+ var header = makeHeader(title, (withHideBtn === true ? CLASSES.inRoleFrame() : false), false, withRemoveBtn, null);
+ roleFrame.insert(header, {"position" : "bottom"});
+
+ // --- creates the topic's itemIdentity frame
+ var itemIdentityFrame = makeListFrame("itemIdentity", CLASSES.itemIdentityFrame() + " " + CLASSES.inRoleFrame(), content.itemIdentities, true, true, false);
+ roleFrame.insert(itemIdentityFrame, {"position" : "bottom"});
+
+ var typeFrame = makeListFrame("type", CLASSES.typeFrame() + " " + CLASSES.inRoleFrame(), content.type, true, false, false);
+ roleFrame.insert(typeFrame, {"position" : "bottom"});
+
+ var playerFrame = makeListFrame("player", CLASSES.playerFrame() + " " + CLASSES.inRoleFrame(), content.topicRef, true, true, false);
+ roleFrame.insert(playerFrame, {"position" : "bottom"});
+
+ return roleFrame;
+ }// withRemoveBtn
+
+
+ // --- returns a node representing a list of role frames.
+ // --- title is the title of the main frame's header.
+ // --- subtitle is the title of all role frames within the main frame.
+ // --- content is the json representation of a list of association roles.
+ // --- withHideBtn is a boolean value. is it set to true the main frame will contain a hide button.
+ // --- withAddBtn is a boolean value. is it set tot true the main frame will contain an add button.
+ function makeRolesFrame(title, subtitle, classValue, content, withHideBtn, withAddBtn)
+ {
+ // --- defines the clickhandler of the header's add button,
+ // --- so there will be created new role frames instead of
+ // --- new rows
+ var headerAddHandler = function(event)
+ {
+ var roleFrame = makeRoleFrame(subtitle, null, true, true);
+ rolesFrame.insert(roleFrame, {"position" : "bottom"});
+
+ // --- the owner frame is hidden, so the new created node has to be hidden, too
+ var parentNode = event.element().parentNode;
+ if(withAddBtn === true && parentNode.getElementsByClassName(CLASSES.hideBtnHeader())[0].textContent === "show"){
+ roleFrame.hide();
+ }
+ };
+
+ var rolesFrame = new Element("div", {"class" : CLASSES.rolesFrame() + " " + classValue});
+ var header = makeHeader(title, (withHideBtn === true ? CLASSES.roleFrame() : false), withAddBtn, false, headerAddHandler);
+ rolesFrame.insert(header, {"position" : "bottom"});
+
+ // --- tries to itereate through the content array and create a name
+ // --- frame for every element
+ try{
+ content.each(function(elem, idx)
+ {
+ var roleFrame = makeRoleFrame(subtitle, elem, true, true);
+ rolesFrame.insert(roleFrame, {"position" : "bottom"});
+ });
+ }
+ catch(err){}
+
+ return rolesFrame;
+ }// makeRolesFrame
+
+
+ // --- returns a node representing an assocaition frame.
+ // --- title is the association frame's header title.
+ // --- content is the json representation of an association.
+ // --- withHideBtn is a boolean value. is it set to true the main frame will contain a hide button.
+ // --- withAddBtn is a boolean value. is it set to true the main frame will contain an add button.
+ function makeAssociationFrame(title, content, withHideBtn, withRemoveBtn)
+ {
+ if(!content)content = new Object(); // to avoid null reference errors
+
+ // --- creates the frame
+ var associationFrame = new Element("div", {"class" : CLASSES.associationFrame()});
+ var header = makeHeader(title, (withHideBtn === true ? CLASSES.inAssociationFrame() : false), false, withRemoveBtn, null);
+ associationFrame.insert(header, {"position" : "bottom"});
+
+ // --- creates the topic's itemIdentity frame
+ var itemIdentityFrame = makeListFrame("itemIdentity", CLASSES.itemIdentityFrame() + " " + CLASSES.inAssociationFrame(), content.itemIdentities, true, true, false);
+ associationFrame.insert(itemIdentityFrame, {"position" : "bottom"});
+
+ var typeFrame = makeListFrame("type", CLASSES.typeFrame() + " " + CLASSES.inAssociationFrame(), content.type, true, false, false);
+ associationFrame.insert(typeFrame, {"position" : "bottom"});
+
+ var scopeFrame = makeListFrame("scope", CLASSES.scopeFrame() + " " + CLASSES.inAssociationFrame(), content.scopes, true, true, false);
+ associationFrame.insert(scopeFrame, {"position" : "bottom"});
+
+ var roleFrame = makeRolesFrame("roles", "role", CLASSES.inAssociationFrame(), content.roles, true, true);
+ associationFrame.insert(roleFrame, {"position" : "bottom"});
+
+ return associationFrame;
+ }// makeAssociaitonFrame
+
+
+ // --- returns a node representing a list of association frames.
+ // --- title is the title of the main frame's header.
+ // --- subtitle is the title of all association frames within the main frame.
+ // --- content is the json representation of a list of associations.
+ // --- withHideBtn is a boolean value. is it set to true the main frame will contain a hide button.
+ // --- withAddBtn is a boolean value. is it set to true the main frame will contain an add button.
+ function makeAssociationsFrame(title, subtitle, content, withHideBtn, withAddBtn)
+ {
+ // --- defines the clickhandler of the header's add button,
+ // --- so there will be created new role frames instead of
+ // --- new rows
+ var headerAddHandler = function(event)
+ {
+ var associationFrame = makeAssociationFrame(subtitle, null, true, true);
+ associationsFrame.insert(associationFrame, {"position" : "bottom"});
+
+ // --- the owner frame is hidden, so the new created node has to be hidden, too
+ var parentNode = event.element().parentNode;
+ if(withAddBtn === true && parentNode.getElementsByClassName(CLASSES.hideBtnHeader())[0].textContent === "show"){
+ associationFrame.hide();
+ }
+ };
+
+ var associationsFrame = new Element("div", {"class" : CLASSES.associationsFrame()});
+ var header = makeHeader(title, (withHideBtn === true ? CLASSES.associationFrame() : false), withAddBtn, false, headerAddHandler);
+ header.writeAttribute({"class" : CLASSES.associationsHeader()});
+ associationsFrame.insert(header, {"position" : "bottom"});
+
+ // --- tries to itereate through the content array and create a name
+ // --- frame for every element
+ try{
+ content.each(function(elem, idx)
+ {
+ var associationFrame = makeAssociationFrame(subtitle, elem, true, true);
+ associationsFrame.insert(associationFrame, {"position" : "bottom"});
+ });
+ }
+ catch(err){}
+
+ return associationsFrame;
+ }// makeAssociationsFrame
+
+
+ function makeTmIdsFrame(title, content, withHideBtn, withAddBtn)
+ {
+ var tmIdsFrame = makeListFrame("tm ids", CLASSES.tmIdsFrame(), content, true, true, false);
+ tmIdsFrame.childElements()[0].writeAttribute({"class" : CLASSES.tmIdsHeader()});
+ return tmIdsFrame;
+ }// makeTmIdsFrame
+
+
+
+ // --- some test data to debug this function
+ var testData = {"topic" : {"id" : "topic-id",
+ "itemIdentities" : ["itemIdentity-1", "itemIdentity-2"],
+ "subjectLocators" : ["subjectLocator-1", "subjectLocator-2"],
+ "subjectIdentifiers" : ["psi-1", "psi-2"],
+ "instanceOfs" : [["psi-1-1", "psi-1-2"], ["psi-2-1"]],
+ "names" : [{"itemIdentities" : ["itemIdentity-n1-1", "itemIdentity-n1-2"],
+ "type" : ["type-n1-1", "type-n1-2"],
+ "scopes" : ["scope-n1-1", "scope-n1-2"],
+ "value" : "value-n1",
+ "variants" : [{"itemIdentities" : ["itemIdentity-n1-v1-1", "itemIdentity-n1-v1-2"],
+ "scopes" : ["scope-n1-v1-1", "scope-n1-v1-2"],
+ "resourceRef": "resourceRef",
+ "resourceData" : null},
+ {"itemIdentities" : ["itemIdentity-n1-v2-1", "itemIdentity-n1-v2-2"],
+ "scopes" : ["scope-n1-v2-1", "scope-n1-v2-2"],
+ "resourceRef": null,
+ "resourceData" : {"datatype" : "datatype-n1-v2",
+ "value" : "value-n1-v2"}}]},
+ {"itemIdentities" : ["itemIdentity-n1-1", "itemIdentity-n1-2"],
+ "type" : ["type-n1-1", "type-n1-2"],
+ "scopes" : ["scope-n1-1", "scope-n1-2"],
+ "value" : "value-n1",
+ "variants" : null}],
+ "occurrences" : [{"itemIdentities" : ["itemIdentity-o1-1", "itemIdentity-o1-2"],
+ "type" : ["type-o1-1"],
+ "scopes" : [["scope-o1-s1-1"], ["scope-o1-s2-1", "scope-o1-s2-2"]],
+ "resourceRef" : "resourceRef-o1"},
+ {"itemIdentities" : null,
+ "type" : ["type-o2-1", "type-o2-2"],
+ "scopes" : [["scope-o2-s2-1", "scope-o2-s2-2"]],
+ "resourceData" : {"datatype" : "datatype-o2",
+ "value" : "value-o2"}}]},
+ "topicStubs" : [{"id" : "stub-id-1",
+ "itemIdentities" : null,
+ "subjectLocators" : null,
+ "subjectIdentifiers" : ["stub-1-psi-1"]},
+ {"id" : "stub-id-2",
+ "itemIdentities" : ["stub-2-itemIdentity-1", "stub-2-itemIdentity-2"],
+ "subjectLocators" : null,
+ "subjectIdentifiers" : ["stub-2-psi-1", "stub-2-psi-2"]},
+ {"id" : "stub-id-3",
+ "itemIdentities" : ["stub-3-itemIdentity-1", "stub-3-itemIdentity-2"],
+ "subjectLocators" : ["stub-1-subjectLocator-1"],
+ "subjectIdentifiers" : ["stub-3-psi-1"]}],
+ "associations" : [{"itemIdentities" : ["itemIdentity-a1-1", "itemIdentity-a1-2"],
+ "type" : ["type-a1-1"],
+ "scopes" : [["scope-1-a1-1"], ["scope-2-a1-1", "scope-2-a1-2"]],
+ "roles": [{"itemIdentities" : ["itemIdentity-a1-r1-1", "itemIdentity-a1-r1-2"],
+ "type" : ["type-a1-r1-1"],
+ "topicRef" : ["player-a1-r1"]},
+ {"itemIdentities" : null,
+ "type" : ["type-a1-r2-1", "type-a1-r2-2"],
+ "topicRef" : ["player-a1-r1-1", "player-a1-r1-2"]}]},
+ {"itemIdentities" : null,
+ "type" : ["type-a2-1", "type-a1-2"],
+ "scopes" : [["scope-1-a2-1"]],
+ "roles": [{"itemIdentities" : ["itemIdentity-a2-r1-1"],
+ "type" : ["type-a2-r1-1"],
+ "topicRef" : ["player-a2-r1"]},
+ {"itemIdentities" : null,
+ "type" : ["type-a2-r2-1"],
+ "topicRef" : ["player-a2-r1-1"]}]}],
+ "tmIds" : ["tm-id-1", "tm-id-2"]};
+
+ // --- creates the fragment frame
+ var fragment = new Element("div", {"class" : CLASSES.fragmentFrame() + " " + PAGES.edit});
+ var topicFrame = makeTopicFrame("topic", content.topic, true);
+ fragment.insert(topicFrame, {"position" : "bottom"});
+ var topicStubsFrame = makeTopicStubsFrame("topicStubs", "topicStub", content.topicStubs, true, true)
+ fragment.insert(topicStubsFrame, {"position" : "bottom"});
+ var associationsFrame = makeAssociationsFrame("associations", "association", content.associations, true, true)
+ fragment.insert(associationsFrame, {"position" : "bottom"});
+ var tmIdsFrame = makeTmIdsFrame("tm ids", content.tmIds, true, true);
+ fragment.insert(tmIdsFrame, {"position" : "bottom"});
+ var commitButton = new Element("input", {"type" : "button", "value" : "commit", "class" : CLASSES.button()});
+ fragment.insert(commitButton, {"position" : "bottom"});
+
+
+ // --- the onClickHandler for the commit button.
+ // --- this handler will generate json string of all contents of this fragment node
+ // --- valid to the json schema in docs/xtm_json.txt.
+ function onclickHandler(event)
+ {
+ var validToBeSent = true;
+
+ var fragmentString = "";
+ var topicString = "";
+ var topicStubsString = "";
+ var associationsString = "";
+ var tmIdsString = "";
+
+
+ // --- a helper function to display error messages
+ function errMsg(what)
+ {
+ alert("\"" + what + "\" is missing, the json fragment could not be committed - please enter a valid \"" + what + "\"!");
+ validToBeSent = false;
+ }
+
+
+ // --- a helper function to create a list of strings.
+ // --- nodes is a nodeList.
+ // --- the return value is a json list.
+ function makeList(nodes)
+ {
+ if(!nodes || nodes.length === 0) return "null";
+
+ // --- separates only values which are a valid string, i.e. the string trimmed
+ // --- of leading and trailing spaces must be greater than 0
+ var textValues = new Array();
+ for(var i = 0; i !== nodes.length; ++i){
+ var clearedValue = nodes[i].value.strip();
+ if(clearedValue.length === 0);
+ else textValues.push(clearedValue);
+ }
+
+
+ // --- creates a json list of all values in the array textValues
+ var jsonList = "null";
+ for(var i = 0; i !== textValues.length; ++i){
+ // --- adds the first item
+ if(i === 0)jsonList = "[";
+
+ // --- adds the text value
+ jsonList += textValues[i].toJSON();
+
+ // --- adds the separator or the end character
+ if(i !== textValues.length - 1)jsonList += ",";
+ else jsonList += "]";
+ }
+
+ return jsonList;
+ }
+
+
+ // --- like the function makeList, but the parameter strings is an array of strings
+ // --- and there will be no string escaped to a json string (.toJSON())
+ function makeListFromStrings(textValues)
+ {
+ if(!textValues || textValues.length === 0)return "null";
+
+ var jsonList = "null";
+ for(var i = 0; i !== textValues.length; ++i){
+ // --- adds the first item
+ if(i === 0)jsonList = "[";
+
+ // --- adds the text value
+ jsonList += textValues[i];
+
+ // --- adds the separator or the end character
+ if(i !== textValues.length - 1)jsonList += ",";
+ else jsonList += "]";
+ }
+
+ return jsonList;
+ }
+
+
+ // --- a helper function to get all resourceRef and REsourceData values
+ function resourceToJson(reElem)
+ {
+ if(!reElem)return {"resourceRef" : "null", "resourceData" : "null"};
+
+ try{
+ var daElem = reElem.getElementsByClassName(CLASSES.textRow())[0];
+ var _datatype = daElem.value.strip().toJSON();
+ if(_datatype.length === 2){
+ _datatype = "\"http://www.w3.org/2001/XMLSchema#string\"";
+ }
+
+ var vaElem = reElem.getElementsByClassName(CLASSES.textareaRow())[0];
+ var _value = vaElem.value.strip().toJSON();
+ if(_value.length === 2){
+ errMsg("Resource value");
+ return;
+ }
+
+ var resourceX = {"resourceRef" : "null", "resourceData" : "null"};
+ if(_datatype === "\"http://www.w3.org/2001/XMLSchema#anyURI\""){
+ resourceX.resourceRef = _value;
+ }
+ else {
+ resourceX.resourceData = {"datatype" : _datatype, "value" : _value};
+ }
+
+ return resourceX;
+ }
+ catch(err){
+ validToBeSent = false;
+ }
+ }
+
+
+ // --- a helper function to transform all variant values to
+ // --- a json string.
+ function variantToJson(varElem)
+ {
+ if(!varElem)return "null";
+
+ try{
+ var iiElems = varElem.getElementsByClassName(CLASSES.itemIdentityFrame())[0].getElementsByClassName(CLASSES.textRow());
+ var _itemIdentities = makeList(iiElems);
+ _itemIdentities = "\"itemIdentities\":" + _itemIdentities;
+
+ var scElems = varElem.getElementsByClassName(CLASSES.scopeFrame())[0].getElementsByClassName(CLASSES.textRow());
+ var _scopes = makeList(scElems);
+ _scopes = "\"scopes\":" + _scopes;
+
+ var reElem = varElem.getElementsByClassName(CLASSES.resourceFrame())[0];
+ var _resource = resourceToJson(reElem);
+ var _resourceRef = "\"resourceRef\":" + _resource.resourceRef;
+ var _resourceData = "\"resourceData\":";
+ if(_resource.resourceData === "null"){
+ _resourceData += "null";
+ }
+ else {
+ _resourceData += "{\"datatype\":" + _resource.resourceData.datatype + ",\"value\":" + _resource.resourceData.value + "}";
+ }
+
+ return "{" + _itemIdentities + "," + _scopes + "," + _resourceRef + "," + _resourceData + "}";
+ }
+ catch(err){
+ validToBeSent = false;
+ }
+ }
+
+
+ // --- a helper function to extrahate all values from a name node.
+ // --- the reurn value is a name in json representation of the
+ // --- way described in docs/xtm_json.txt.
+ function nameToJson(naElem)
+ {
+ if(!naElem)return "null";
+
+ try{
+ var iiElems = naElem.getElementsByClassName(CLASSES.itemIdentityFrame())[0].getElementsByClassName(CLASSES.textRow());
+ var _itemIdentities = makeList(iiElems);
+ _itemIdentities = "\"itemIdentities\":" + _itemIdentities;
+
+ var tyElem = naElem.getElementsByClassName(CLASSES.typeFrame())[0].getElementsByClassName(CLASSES.textRow());
+ var _type = makeList(tyElem);
+ _type = "\"type\":" + _type;
+
+ var scElems = naElem.getElementsByClassName(CLASSES.scopeFrame())[0].getElementsByClassName(CLASSES.textRow());
+ var _scopes = makeList(scElems);
+ _scopes = "\"scopes\":" + _scopes;
+
+ var vaElems = naElem.getElementsByClassName(CLASSES.valueFrame())[0].getElementsByClassName(CLASSES.textRow());
+ var _value = vaElems[0].value.strip().toJSON();
+ if(_value.length === 2){
+ errMsg("Name value"); // === 2 -> "".toJSON() => "\"\""
+ return;
+ }
+ _value = "\"value\":" + _value;
+
+ var varElems = naElem.getElementsByClassName(CLASSES.variantsFrame())[0].getElementsByClassName(CLASSES.variantFrame());
+ var _variants = "\"variants\":";
+ if(varElems.length === 0){
+ _variants += "null";
+ }
+ else {
+ var _varStrings = new Array();
+ for(var i = 0; i !== varElems.length; ++i){
+ _varStrings.push(variantToJson(varElems[i]));
+ }
+ _variants += makeListFromStrings(_varStrings);
+ }
+
+ return "{" + _itemIdentities + "," + _type + "," + _scopes + "," + _value + "," + _variants + "}";
+ }
+ catch(err){
+ validToBeSent = false;
+ }
+ }
+
+
+ // --- a helper function to extrahate all values from an occurrence node.
+ // --- the reurn value is an occurrence in json representation of the
+ // --- way described in docs/xtm_json.txt.
+ function occurrenceToJson(ocElem)
+ {
+ if(!ocElem)return "null";
+
+ try{
+ var iiElems = ocElem.getElementsByClassName(CLASSES.itemIdentityFrame())[0].getElementsByClassName(CLASSES.textRow());
+ var _itemIdentities = makeList(iiElems);
+ _itemIdentities = "\"itemIdentities\":" + _itemIdentities;
+
+ var tyElem = ocElem.getElementsByClassName(CLASSES.typeFrame())[0].getElementsByClassName(CLASSES.textRow());
+ var _type = makeList(tyElem);
+ _type = "\"type\":" + _type;
+
+ var scElems = ocElem.getElementsByClassName(CLASSES.scopeFrame())[0].getElementsByClassName(CLASSES.textRow());
+ var _scopes = makeList(scElems);
+ _scopes = "\"scopes\":" + _scopes;
+
+ var reElem = ocElem.getElementsByClassName(CLASSES.resourceFrame())[0];
+ var _resource = resourceToJson(reElem);
+ var _resourceRef = "\"resourceRef\":" + _resource.resourceRef;
+ var _resourceData = "\"resourceData\":";
+ if(_resource.resourceData === "null"){
+ _resourceData += "null";
+ }
+ else {
+ _resourceData += "{\"datatype\":" + _resource.resourceData.datatype + ",\"value\":" + _resource.resourceData.value + "}";
+ }
+
+ return "{" + _itemIdentities + "," + _type + "," + _scopes + "," + _resourceRef + "," + _resourceData + "}";
+ }
+ catch(err){
+ validToBeSent = false;
+ }
+ }
+
+
+ // --- a helper function to extrahate all topic values and return them as
+ // --- a json string.
+ function topicToJson()
+ {
+ try{
+ var _topicId = "";
+ _topicId = topicFrame.getElementsByClassName(CLASSES.topicIdFrame())[0].getElementsByClassName(CLASSES.textRow())[0].value;
+ if(_topicId.length === 0){ errMsg("topic id"); return; }
+ _topicId = "\"id\":" + _topicId.toJSON();
+
+ var iiElems = topicFrame.getElementsByClassName(CLASSES.itemIdentityFrame())[0].getElementsByClassName(CLASSES.textRow());
+ var _itemIdentities = "\"itemIdentities\":" + makeList(iiElems);
+
+ var slElems = topicFrame.getElementsByClassName(CLASSES.subjectLocatorFrame())[0].getElementsByClassName(CLASSES.textRow());
+ var _subjectLocators = "\"subjectLocators\":" + makeList(slElems);
+
+ var siElems = topicFrame.getElementsByClassName(CLASSES.subjectIdentifierFrame())[0].getElementsByClassName(CLASSES.textRow());
+ var _subjectIdentifiers = "\"subjectIdentifiers\":" + makeList(siElems);
+ if(_itemIdentities === "\"itemIdentities\":null" && _subjectLocators === "\"subjectLocators\":null" && _subjectIdentifiers === "\"subjectIdentifiers\":null"){
+ alert("An identifier is missing one of the elements \"itemIdentity\", \"subjectLocator\" or \"subjectIdentifier\" must be set!");
+ validToBeSent = false;
+ }
+
+ var ioElems = topicFrame.getElementsByClassName(CLASSES.instanceOfFrame())[0].getElementsByClassName(CLASSES.textRow());
+ var _instanceOfs = "\"instanceOfs\":" + makeList(ioElems);
+
+ var naElems = topicFrame.getElementsByClassName(CLASSES.namesFrame())[0].getElementsByClassName(CLASSES.nameFrame());
+ var _names = "\"names\":";
+ if(naElems.length === 0){
+ _names += "null";
+ }
+ else {
+ var _naStrings = new Array();
+ for(var i = 0; i !== naElems.length; ++i){
+ _naStrings.push(nameToJson(naElems[i]));
+ }
+ _names += makeListFromStrings(_naStrings);
+ }
+
+ var ocElems = topicFrame.getElementsByClassName(CLASSES.occurrencesFrame())[0].getElementsByClassName(CLASSES.occurrenceFrame());
+ var _occurrences = "\"occurrences\":";
+ if(ocElems.length === 0){
+ _occurrences += "null";
+ }
+ else {
+ var _ocStrings = new Array();
+ for(var i = 0; i !== ocElems.length; ++i){
+ _ocStrings.push(occurrenceToJson(ocElems[i]));
+ }
+ _occurrences += makeListFromStrings(_ocStrings);
+ }
+
+ return "{" + _topicId + "," + _itemIdentities + "," + _subjectLocators + "," +_instanceOfs + "," + _subjectIdentifiers + "," + _names + "," + _occurrences + "}";
+ }
+ catch(err){
+ validToBeSent = false;
+ }
+ }
+
+
+ // --- a helper function to extrahate all topicstubs values and return them as
+ // --- a json string.
+ function topicStubToJson(tsElem)
+ {
+ if(!tsElem) return "null";
+ try{
+ var _topicId = "";
+ _topicId = tsElem.getElementsByClassName(CLASSES.topicIdFrame())[0].getElementsByClassName(CLASSES.textRow())[0].value;
+ if(_topicId.length === 0){ errMsg("topic id"); return; }
+ _topicId = "\"id\":" + _topicId.toJSON();
+
+ var iiElems = tsElem.getElementsByClassName(CLASSES.itemIdentityFrame())[0].getElementsByClassName(CLASSES.textRow());
+ var _itemIdentities = "\"itemIdentities\":" + makeList(iiElems);
+
+ var slElems = tsElem.getElementsByClassName(CLASSES.subjectLocatorFrame())[0].getElementsByClassName(CLASSES.textRow());
+ var _subjectLocators = "\"subjectLocators\":" + makeList(slElems);
+
+ var siElems = tsElem.getElementsByClassName(CLASSES.subjectIdentifierFrame())[0].getElementsByClassName(CLASSES.textRow());
+ var _subjectIdentifiers = "\"subjectIdentifiers\":" + makeList(siElems);
+ if(_itemIdentities === "\"itemIdentities\":null" && _subjectLocators === "\"subjectLocators\":null" && _subjectIdentifiers === "\"subjectIdentifiers\":null"){
+ alert("An identifier is missing one of the elements \"itemIdentity\", \"subjectLocator\" or \"subjectIdentifier\" must be set!");
+ validToBeSent = false;
+ }
+
+ return "{" + _topicId + "," + _itemIdentities + "," + _subjectLocators + "," + _subjectIdentifiers + "}";
+ }
+ catch(err){
+ validToBeSent = false;
+ }
+ }
+
+
+ // --- a helper function to extrahate all association role values and return them as
+ // --- a json string.
+ function roleToJson(rlElem)
+ {
+ if(!rlElem)return "null";
+
+ try{
+ var iiElems = rlElem.getElementsByClassName(CLASSES.itemIdentityFrame())[0].getElementsByClassName(CLASSES.textRow());
+ var _itemIdentities = makeList(iiElems);
+ _itemIdentities = "\"itemIdentities\":" + _itemIdentities;
+
+ var tyElem = rlElem.getElementsByClassName(CLASSES.typeFrame())[0].getElementsByClassName(CLASSES.textRow());
+ var _type = makeList(tyElem);
+ _type = "\"type\":" + _type;
+
+ var plElem = rlElem.getElementsByClassName(CLASSES.playerFrame())[0].getElementsByClassName(CLASSES.textRow());
+ var _player = "\"topicRef\":" + makeList(plElem);
+ if(_player === "\"topicRef\":null"){
+ errMsg("Player");
+ return;
+ }
+
+ return "{" + _itemIdentities + "," + _type + "," + _player + "}";
+ }
+ catch(err){
+ validToBeSent = false;
+ }
+ }
+
+
+ // --- a helper function to extrahate all association values and return them as
+ // --- a json string.
+ function associationToJson(asElem)
+ {
+ if(!asElem)return "null";
+
+ try{
+ var iiElems = asElem.getElementsByClassName(CLASSES.itemIdentityFrame())[0].getElementsByClassName(CLASSES.textRow());
+ var _itemIdentities = makeList(iiElems);
+ _itemIdentities = "\"itemIdentities\":" + _itemIdentities;
+
+ var tyElem = asElem.getElementsByClassName(CLASSES.typeFrame())[0].getElementsByClassName(CLASSES.textRow());
+ var _type = makeList(tyElem);
+ _type = "\"type\":" + _type;
+
+ var scElems = asElem.getElementsByClassName(CLASSES.scopeFrame())[0].getElementsByClassName(CLASSES.textRow());
+ var _scopes = makeList(scElems);
+ _scopes = "\"scopes\":" + _scopes;
+
+ var rlElems = associationsFrame.getElementsByClassName(CLASSES.rolesFrame())[0].getElementsByClassName(CLASSES.roleFrame());
+ var _roles = "\"roles\":";
+ if(rlElems.length === 0){
+ _roles += "null";
+ }
+ else {
+ var _rlStrings = new Array();
+ for(var i = 0; i !== rlElems.length; ++i){
+ _rlStrings.push(roleToJson(rlElems[i]));
+ }
+ _roles += makeListFromStrings(_rlStrings);
+ }
+
+ return "{" + _itemIdentities + "," + _type + "," + _scopes + "," + _roles + "}";
+ }
+ catch(err){
+ validToBeSent = false;
+ }
+ }
+
+
+ // --- gets all topic values -------------------------------------------
+ var _topic = "\"topic\":" + topicToJson();
+
+ var _topicStubs = "\"topicStubs\":";
+ try{
+ var tsElems = topicStubsFrame.getElementsByClassName(CLASSES.topicStubFrame());
+ if(tsElems.length === 0){
+ _topicStubs += "null";
+ }
+ else {
+ var _tsStrings = new Array();
+ for(var i = 0; i !== tsElems.length; ++i){
+ _tsStrings.push(topicStubToJson(tsElems[i]));
+ }
+ _topicStubs += makeListFromStrings(_tsStrings);
+ }
+ }
+ catch(err){
+ validToBeSent = false;
+ }
+
+ var _associations = "\"associations\":";
+ try{
+ var asElems = associationsFrame.getElementsByClassName(CLASSES.associationFrame());
+ if(asElems.length === 0){
+ _associations += "null";
+ }
+ else {
+ var _asStrings = new Array();
+ for(var i = 0; i !== asElems.length; ++i){
+ _asStrings.push(associationToJson(asElems[i]));
+ }
+ _associations += makeListFromStrings(_asStrings);
+ }
+ }
+ catch(err){
+ validToBeSent = false;
+ }
+
+ var _tmIds = "\"tmIds\":";
+ try{
+ var tmElem = tmIdsFrame.getElementsByClassName(CLASSES.textRow());
+ _tmIds += makeList(tmElem);
+ if(_tmIds === "\"tmIds\":null"){
+ errMsg("Topic Map ID");
+ }
+ }
+ catch(err){
+ alert(err);
+ validToBeSent = false;
+ }
+
+ // --- sending the data
+ if(validToBeSent === true){
+ var _fragment = "{" + _topic + "," + _topicStubs + "," + _associations + "," + _tmIds + "}";
+
+ new Ajax.Request(COMMIT_URL,
+ {
+ method: "post",
+ requestHeaders:{ "Content-Type":"application/json"},
+ onSuccess: function(xhr){ window.alert("Fragment committed successfully!"); },
+ onFailure: function(xhr){ window.alert("Something went wrong ...\n" + xhr.status + ": " + xhr.statusText); },
+ postBody: _fragment
+ });
+ }
+ else {
+ alert("You have entered som invalid data - please check your input!");
+ }
+ }
+
+ commitButton.observe("click", onclickHandler);
+
+ return fragment;
+}
+
+
+// --- calls the getFragment function with a onSuccessHandler.
+// --- the handler uses the function makeFragmentNode to create a
+// --- DOM node with the jsonFragment, if the answer is null,
+// --- the fragments content fields are set to "" or the are hidden.
+function getAndBuildFragment(topicPsi)
+{
+ // --- if there was passed an invalid topicPsi or onSuccessHandler, the return value is null
+ if(typeof(topicPsi) !== "string" || topicPsi.length === 0)
+ $("content").insert(makeFragmentNode(null), {"position" : "content"});
+
+ function onSuccessHandler(xhr)
+ {
+ try{
+ var jsonFragment = xhr.responseText.evalJSON();
+ $("content").insert(makeFragmentNode(jsonFragment), {"position" : "content"});
+ }
+ catch(err){
+ alert("Got bad json data from " + GET_PREFIX + topicPsi.gsub("#", "%23"));
+ }
+ }
+
+ getFragment(topicPsi, onSuccessHandler);
+}
+
+
+// --- creates an ajax request for a fragment to the url mconcatenated of
+// --- the GET_PREFIX and the topicPsi
+function getFragment(topicPsi, onSuccessHandler)
+{
+ // --- if there was passed an invalid topicPsi or onSuccessHandler, the return value is null
+ if(typeof(topicPsi) !== "string" || topicPsi.length === 0 || !onSuccessHandler)return null;
+
+
+ // --- the ajax-request error handler
+ function onFailureHandler(xhr)
+ {
+ window.alert("Something went wrong ...\n" + xhr.status + ": " + xhr.statusText);
+ }
+
+ // --- the real ajax request
+ var fragment = null;
+ var requestUrl = GET_PREFIX + topicPsi.gsub("#", "%23");
+ var request = new Ajax.Request(requestUrl,
+ {"method" : "get",
+ "onSuccess" : onSuccessHandler,
+ "onFailure" : onFailureHandler
+ });
+}
\ No newline at end of file
Copied: trunk/src/ajax/javascripts/navi.js (from r25, /trunk/src/ajax/javascripts/ajax_navi.js)
==============================================================================
--- /trunk/src/ajax/javascripts/ajax_navi.js (original)
+++ trunk/src/ajax/javascripts/navi.js Fri Apr 10 19:11:32 2009
@@ -1,3 +1,15 @@
+//+-----------------------------------------------------------------------------
+//+ 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
+//+-----------------------------------------------------------------------------
+
+
// --- adds some event handlers to the navigation elements
function addHandlersToNavi()
{
Modified: trunk/src/atom/atom.lisp
==============================================================================
--- trunk/src/atom/atom.lisp (original)
+++ trunk/src/atom/atom.lisp Fri Apr 10 19:11:32 2009
@@ -1,3 +1,12 @@
+;;+-----------------------------------------------------------------------------
+;;+ 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 :atom
(:use :cl :cxml :constants :xml-tools :datamodel :drakma)
(:export :collection-feed
Modified: trunk/src/atom/collection.lisp
==============================================================================
--- trunk/src/atom/collection.lisp (original)
+++ trunk/src/atom/collection.lisp Fri Apr 10 19:11:32 2009
@@ -1,3 +1,12 @@
+;;+-----------------------------------------------------------------------------
+;;+ 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.
+;;+-----------------------------------------------------------------------------
+
+
(in-package :atom)
(defclass collection-feed (feed)
Modified: trunk/src/atom/conf.lisp
==============================================================================
--- trunk/src/atom/conf.lisp (original)
+++ trunk/src/atom/conf.lisp Fri Apr 10 19:11:32 2009
@@ -1,3 +1,12 @@
+;;+-----------------------------------------------------------------------------
+;;+ 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.
+;;+-----------------------------------------------------------------------------
+
+
(in-package :atom)
(defsite psi.egovpt.org
;;(base-url "http://london.ztt.fh-worms.de:8000") ;the base-url
Modified: trunk/src/atom/configuration.lisp
==============================================================================
--- trunk/src/atom/configuration.lisp (original)
+++ trunk/src/atom/configuration.lisp Fri Apr 10 19:11:32 2009
@@ -1,3 +1,12 @@
+;;+-----------------------------------------------------------------------------
+;;+ 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.
+;;+-----------------------------------------------------------------------------
+
+
(in-package :atom)
;the configuration of the eGov application (at present)
;TODO: convert to an XML configuration file for the site
Modified: trunk/src/atom/confreader.lisp
==============================================================================
--- trunk/src/atom/confreader.lisp (original)
+++ trunk/src/atom/confreader.lisp Fri Apr 10 19:11:32 2009
@@ -1,3 +1,12 @@
+;;+-----------------------------------------------------------------------------
+;;+ 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.
+;;+-----------------------------------------------------------------------------
+
+
;; (defmacro site (&body lines)
;; `(dolist (line (quote ,lines))
;; (format t "~a~&" line)))
Modified: trunk/src/atom/fragments.lisp
==============================================================================
--- trunk/src/atom/fragments.lisp (original)
+++ trunk/src/atom/fragments.lisp Fri Apr 10 19:11:32 2009
@@ -1,3 +1,12 @@
+;;+-----------------------------------------------------------------------------
+;;+ 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.
+;;+-----------------------------------------------------------------------------
+
+
(in-package :atom)
(defclass fragment-entry (entry)
Modified: trunk/src/atom/read.lisp
==============================================================================
--- trunk/src/atom/read.lisp (original)
+++ trunk/src/atom/read.lisp Fri Apr 10 19:11:32 2009
@@ -1,3 +1,12 @@
+;;+-----------------------------------------------------------------------------
+;;+ 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.
+;;+-----------------------------------------------------------------------------
+
+
(in-package :atom)
(defmacro parse-feed ((feed-string feed-type) &body make-entry)
Modified: trunk/src/atom/snapshots.lisp
==============================================================================
--- trunk/src/atom/snapshots.lisp (original)
+++ trunk/src/atom/snapshots.lisp Fri Apr 10 19:11:32 2009
@@ -1,3 +1,12 @@
+;;+-----------------------------------------------------------------------------
+;;+ 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.
+;;+-----------------------------------------------------------------------------
+
+
(in-package :atom)
(defclass snapshots-feed (feed)
Modified: trunk/src/constants.lisp
==============================================================================
--- trunk/src/constants.lisp (original)
+++ trunk/src/constants.lisp Fri Apr 10 19:11:32 2009
@@ -1,3 +1,12 @@
+;;+-----------------------------------------------------------------------------
+;;+ 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 :constants
(:use :cl)
(:export :*atom-ns*
Modified: trunk/src/isidorus.asd
==============================================================================
--- trunk/src/isidorus.asd (original)
+++ trunk/src/isidorus.asd Fri Apr 10 19:11:32 2009
@@ -1,4 +1,13 @@
;;-*- mode: lisp -*-
+;;+-----------------------------------------------------------------------------
+;;+ 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 :isidorus-system
(:use :asdf :cl))
(in-package :isidorus-system)
@@ -123,25 +132,26 @@
(:module "ajax"
:components ((:static-file "isidorus.html")
(:module "javascripts"
- :components ((:static-file "builder.js")
- (:static-file "controls.js")
- (:static-file "dragdrop.js")
- (:static-file "effects.js")
- (:static-file "prototype.js")
- (:static-file "scriptaculous.js")
- (:static-file "slider.js")
- (:static-file "sound.js")
- (:static-file "unittest.js")
- (:static-file "ajax_constants.js")
- (:static-file "ajax_home.js")
- (:static-file "ajax_navi.js")
- (:static-file "ajax_edit_topic.js")))
+ :components ((:static-file "constants.js")
+ (:static-file "home.js")
+ (:static-file "navi.js")
+ (:static-file "make_fragment_node.js")
+ (:static-file "edit_topic.js")
+ (:module "external"
+ :components ((:module "prototype"
+ :components ((:static-file "prototype.js")))
+ (:module "scriptaculous"
+ :components ((:static-file "builder.js")
+ (:static-file "controls.js")
+ (:static-file "dragdrop.js")
+ (:static-file "effects.js")
+ (:static-file "scriptaculous.js")
+ (:static-file "slider.js")
+ (:static-file "sound.js")
+ (:static-file "unittest.js")))))))
(:module "css"
- :components ((:static-file "create_topics.css")
- (:static-file "edit_topics.css")
- (:static-file "home.css")
+ :components ((:static-file "home.css")
(:static-file "navi.css")
- (:static-file "search_topics.css")
(:static-file "main.css")))))
)
;;(:module "threading"
Modified: trunk/src/json/json_exporter.lisp
==============================================================================
--- trunk/src/json/json_exporter.lisp (original)
+++ trunk/src/json/json_exporter.lisp Fri Apr 10 19:11:32 2009
@@ -1,3 +1,12 @@
+;;+-----------------------------------------------------------------------------
+;;+ 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-exporter
(:use :cl :json :datamodel)
(:export :to-json-string
@@ -267,7 +276,7 @@
(concatenate 'string (subseq j-associations 0 (- (length j-associations) 1)) "]"))
"null")))
(tm-ids
- (concatenate 'string "\"tm-ids\":"
+ (concatenate 'string "\"tmIds\":"
(if (in-topicmaps (topic instance))
(let ((j-tm-ids "["))
(loop for item in (in-topicmaps (topic instance))
Modified: trunk/src/json/json_importer.lisp
==============================================================================
--- trunk/src/json/json_importer.lisp (original)
+++ trunk/src/json/json_importer.lisp Fri Apr 10 19:11:32 2009
@@ -1,3 +1,12 @@
+;;+-----------------------------------------------------------------------------
+;;+ 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-importer
(:use :cl :json :datamodel :xml-importer)
(:export :json-to-elem
@@ -342,7 +351,7 @@
(setf topicStubs (cdr j-elem)))
((string= (car j-elem) :associations)
(setf associations (cdr j-elem)))
- ((string= (car j-elem) :tm-ids)
+ ((string= (car j-elem) :tm-Ids)
(setf tm-ids (cdr j-elem)))
(t
(error "json-importer:get-fragment-values-from-json-string:
Modified: trunk/src/model/changes.lisp
==============================================================================
--- trunk/src/model/changes.lisp (original)
+++ trunk/src/model/changes.lisp Fri Apr 10 19:11:32 2009
@@ -1,3 +1,12 @@
+;;+-----------------------------------------------------------------------------
+;;+ 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.
+;;+-----------------------------------------------------------------------------
+
+
;-*- standard-indent:2; tab-width:2; indent-tabs-mode:nil -*-
(in-package :datamodel)
Modified: trunk/src/model/datamodel.lisp
==============================================================================
--- trunk/src/model/datamodel.lisp (original)
+++ trunk/src/model/datamodel.lisp Fri Apr 10 19:11:32 2009
@@ -1,3 +1,12 @@
+;;+-----------------------------------------------------------------------------
+;;+ 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.
+;;+-----------------------------------------------------------------------------
+
+
;-*- standard-indent: 2; indent-tabs-mode: nil -*-
(defpackage :datamodel
(:use :cl :elephant :constants)
Modified: trunk/src/model/exceptions.lisp
==============================================================================
--- trunk/src/model/exceptions.lisp (original)
+++ trunk/src/model/exceptions.lisp Fri Apr 10 19:11:32 2009
@@ -1,3 +1,12 @@
+;;+-----------------------------------------------------------------------------
+;;+ 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 :exceptions
(:use :common-lisp)
(:export :inconsistent-file-error
Modified: trunk/src/model/model_tools.lisp
==============================================================================
--- trunk/src/model/model_tools.lisp (original)
+++ trunk/src/model/model_tools.lisp Fri Apr 10 19:11:32 2009
@@ -1,3 +1,12 @@
+;;+-----------------------------------------------------------------------------
+;;+ 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.
+;;+-----------------------------------------------------------------------------
+
+
(in-package :datamodel)
(defgeneric equalT (construct1 construct2)
Modified: trunk/src/rest_interface/publish_feeds.lisp
==============================================================================
--- trunk/src/rest_interface/publish_feeds.lisp (original)
+++ trunk/src/rest_interface/publish_feeds.lisp Fri Apr 10 19:11:32 2009
@@ -1,3 +1,12 @@
+;;+-----------------------------------------------------------------------------
+;;+ 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.
+;;+-----------------------------------------------------------------------------
+
+
(in-package :rest-interface)
(defgeneric publish-feed (feed)
Modified: trunk/src/rest_interface/read.lisp
==============================================================================
--- trunk/src/rest_interface/read.lisp (original)
+++ trunk/src/rest_interface/read.lisp Fri Apr 10 19:11:32 2009
@@ -1,3 +1,12 @@
+;;+-----------------------------------------------------------------------------
+;;+ 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.
+;;+-----------------------------------------------------------------------------
+
+
(in-package :rest-interface)
;in the midterm write a reader thread
Modified: trunk/src/rest_interface/rest-interface.lisp
==============================================================================
--- trunk/src/rest_interface/rest-interface.lisp (original)
+++ trunk/src/rest_interface/rest-interface.lisp Fri Apr 10 19:11:32 2009
@@ -1,3 +1,12 @@
+;;+-----------------------------------------------------------------------------
+;;+ 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 :rest-interface
(:nicknames :rest)
(:use :cl :hunchentoot
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 Fri Apr 10 19:11:32 2009
@@ -1,3 +1,12 @@
+;;+-----------------------------------------------------------------------------
+;;+ 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.
+;;+-----------------------------------------------------------------------------
+
+
(in-package :rest-interface)
(defparameter *json-get-prefix* "/json/get/(.+)$") ;the prefix to get a fragment by the psis -> localhost:8000/json/get/<fragment-psi>
Modified: trunk/src/threading/reader-writer.lisp
==============================================================================
--- trunk/src/threading/reader-writer.lisp (original)
+++ trunk/src/threading/reader-writer.lisp Fri Apr 10 19:11:32 2009
@@ -1,3 +1,12 @@
+;;+-----------------------------------------------------------------------------
+;;+ 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 :isidorus-reader-writer
(:use :cl :hunchentoot-mp) ;hunchentoot 0.15.7
(:export :current-readers
Modified: trunk/src/unit_tests/atom-conf.lisp
==============================================================================
--- trunk/src/unit_tests/atom-conf.lisp (original)
+++ trunk/src/unit_tests/atom-conf.lisp Fri Apr 10 19:11:32 2009
@@ -1,3 +1,12 @@
+;;+-----------------------------------------------------------------------------
+;;+ 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.
+;;+-----------------------------------------------------------------------------
+
+
(in-package :atom)
(defsite psi.egovpt.org
;;(base-url "http://london.ztt.fh-worms.de:8000") ;the base-url
Modified: trunk/src/unit_tests/atom_test.lisp
==============================================================================
--- trunk/src/unit_tests/atom_test.lisp (original)
+++ trunk/src/unit_tests/atom_test.lisp Fri Apr 10 19:11:32 2009
@@ -1,3 +1,12 @@
+;;+-----------------------------------------------------------------------------
+;;+ 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 :atom-test
(:use
:common-lisp
Modified: trunk/src/unit_tests/atom_test.xtm
==============================================================================
--- trunk/src/unit_tests/atom_test.xtm (original)
+++ trunk/src/unit_tests/atom_test.xtm Fri Apr 10 19:11:32 2009
@@ -1,4 +1,13 @@
<?xml version="1.0"?>
+<!-- ======================================================================= -->
+<!-- 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. -->
+<!-- ======================================================================= -->
+
+
<topicMap xmlns="http://www.topicmaps.org/xtm/" version="2.0">
<!-- a TM that exists for the sole reason of having completely different topics -->
<itemIdentity href="http://psi.egovpt.org/tm/egov-ontology"/>
@@ -7,4 +16,4 @@
<itemIdentity href="http://psi.egovpt.org/tm/egov-ontology/ii#1"/>
<name><value>Test Topic</value></name>
</topic>
-</topicMap>
\ No newline at end of file
+</topicMap>
Modified: trunk/src/unit_tests/dangling_instanceof.xtm
==============================================================================
--- trunk/src/unit_tests/dangling_instanceof.xtm (original)
+++ trunk/src/unit_tests/dangling_instanceof.xtm Fri Apr 10 19:11:32 2009
@@ -1,4 +1,13 @@
<?xml version="1.0"?>
+<!-- ======================================================================= -->
+<!-- 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. -->
+<!-- ======================================================================= -->
+
+
<topicMap xmlns="http://www.topicmaps.org/xtm/" version="2.0">
<topic id="t1">
<itemIdentity href="http://psi.egovpt.org/itemIdentifiers#t1"/>
Modified: trunk/src/unit_tests/dangling_topicref.xtm
==============================================================================
--- trunk/src/unit_tests/dangling_topicref.xtm (original)
+++ trunk/src/unit_tests/dangling_topicref.xtm Fri Apr 10 19:11:32 2009
@@ -1,4 +1,13 @@
<?xml version="1.0"?>
+<!-- ======================================================================= -->
+<!-- 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. -->
+<!-- ======================================================================= -->
+
+
<topicMap xmlns="http://www.topicmaps.org/xtm/" version="2.0">
<topic id="t-1">
<itemIdentity href="http://psi.egovpt.org/itemIdentifiers#t1"/>
Modified: trunk/src/unit_tests/duplicate_identifier.xtm
==============================================================================
--- trunk/src/unit_tests/duplicate_identifier.xtm (original)
+++ trunk/src/unit_tests/duplicate_identifier.xtm Fri Apr 10 19:11:32 2009
@@ -1,4 +1,13 @@
<?xml version="1.0"?>
+<!-- ======================================================================= -->
+<!-- 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. -->
+<!-- ======================================================================= -->
+
+
<topicMap xmlns="http://www.topicmaps.org/xtm/" version="2.0">
<topic id="t1">
<itemIdentity href="http://psi.egovpt.org/itemIdentifiers#t1"/>
Modified: trunk/src/unit_tests/exporter_xtm1.0_test.lisp
==============================================================================
--- trunk/src/unit_tests/exporter_xtm1.0_test.lisp (original)
+++ trunk/src/unit_tests/exporter_xtm1.0_test.lisp Fri Apr 10 19:11:32 2009
@@ -1,3 +1,12 @@
+;;+-----------------------------------------------------------------------------
+;;+ 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.
+;;+-----------------------------------------------------------------------------
+
+
(in-package :exporter-test)
(in-suite exporter-tests)
Modified: trunk/src/unit_tests/exporter_xtm2.0_test.lisp
==============================================================================
--- trunk/src/unit_tests/exporter_xtm2.0_test.lisp (original)
+++ trunk/src/unit_tests/exporter_xtm2.0_test.lisp Fri Apr 10 19:11:32 2009
@@ -1,3 +1,12 @@
+;;+-----------------------------------------------------------------------------
+;;+ 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 :exporter-test
(:use
:common-lisp
Modified: trunk/src/unit_tests/fixtures.lisp
==============================================================================
--- trunk/src/unit_tests/fixtures.lisp (original)
+++ trunk/src/unit_tests/fixtures.lisp Fri Apr 10 19:11:32 2009
@@ -1,3 +1,12 @@
+;;+-----------------------------------------------------------------------------
+;;+ 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 :fixtures
(:use
:common-lisp
Modified: trunk/src/unit_tests/importer_test.lisp
==============================================================================
--- trunk/src/unit_tests/importer_test.lisp (original)
+++ trunk/src/unit_tests/importer_test.lisp Fri Apr 10 19:11:32 2009
@@ -1,3 +1,12 @@
+;;+-----------------------------------------------------------------------------
+;;+ 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 :importer-test
(:use
:common-lisp
Modified: trunk/src/unit_tests/inconsistent.xtm
==============================================================================
--- trunk/src/unit_tests/inconsistent.xtm (original)
+++ trunk/src/unit_tests/inconsistent.xtm Fri Apr 10 19:11:32 2009
@@ -1,3 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- ======================================================================= -->
+<!-- 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. -->
+<!-- ======================================================================= -->
+
+
<topicMap xmlns="http://www.topicmaps.org/xtm/1.0/" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- === topics ================================================== -->
@@ -303,4 +313,4 @@
</t:subjectIdentity>
</t:topic>
-</topicMap>
\ No newline at end of file
+</topicMap>
Modified: trunk/src/unit_tests/inconsistent_2_0.xtm
==============================================================================
--- trunk/src/unit_tests/inconsistent_2_0.xtm (original)
+++ trunk/src/unit_tests/inconsistent_2_0.xtm Fri Apr 10 19:11:32 2009
@@ -1,4 +1,13 @@
<?xml version="1.0"?>
+<!-- ======================================================================= -->
+<!-- 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. -->
+<!-- ======================================================================= -->
+
+
<topicMap xmlns="http://www.topicmaps.org/xtm/" version="2.0">
<!-- === test object 1 =================================================== -->
Modified: trunk/src/unit_tests/json_test.lisp
==============================================================================
--- trunk/src/unit_tests/json_test.lisp (original)
+++ trunk/src/unit_tests/json_test.lisp Fri Apr 10 19:11:32 2009
@@ -1,3 +1,12 @@
+;;+-----------------------------------------------------------------------------
+;;+ 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-test
(:use
:common-lisp
@@ -127,9 +136,9 @@
(frag-topic
(get-latest-fragment-of-topic "http://www.topicmaps.org/xtm/1.0/core.xtm#topic")))
(let ((frag-t100-string
- (concatenate 'string "{\"topic\":{\"id\":\"" (d:topicid (d:topic frag-t100)) "\",\"itemIdentities\":[\"http://psi.egovpt.org/itemIdentifiers#t100\"],\"subjectLocators\":null,\"subjectIdentifiers\":[\"http://psi.egovpt.org/standard/ISO+19115%3A+Geographic+Information+-+Metada…"],\"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\":\"" (topicid (elt (referenced-topics frag-t100) 0)) "\",\"itemIdentities\":[\"http://psi.egovpt.org/itemIdentifiers#t3a\"],\"subjectLocators\":null,\"subjectIdentifiers\":[\"http://psi.egovpt.org/types/semanticstandard\"]},{\"id\":\"" (topicid (elt (referenced-topics frag-t100) 1)) "\",\"itemIdentities\":null,\"subjectLocators\":null,\"subjectIdentifiers\":[\"http://www.topicmaps.org/xtm/1.0/core.xtm#display\"]},{\"id\":\"" (topicid (elt (referenced-topics frag-t100) 2)) "\",\"itemIdentities\":null,\"subjectLocators\":null,\"subjectIdentifiers\":[\"http://www.topicmaps.org/xtm/1.0/core.xtm#sort\"]},{\"id\":\"" (topicid (elt (referenced-topics frag-t100) 3)) "\",\"itemIdentities\":[\"http://psi.egovpt.org/itemIdentifiers#t51\"],\"subjectLocators\":null,\"subjectIdentifiers\":[\"http://psi.egovpt.org/types/standardHasStatus\"]},{\"id\":\"" (topicid (elt (referenced-topics frag-t100) 4)) "\",\"itemIdentities\":[\"http://psi.egovpt.org/itemIdentifiers#t53\"],\"subjectLocators\":null,\"subjectIdentifiers\":[\"http://psi.egovpt.org/types/description\"]},{\"id\":\"" (topicid (elt (referenced-topics frag-t100) 5)) "\",\"itemIdentities\":[\"http://psi.egovpt.org/itemIdentifiers#t54\"],\"subjectLocators\":null,\"subjectIdentifiers\":[\"http://psi.egovpt.org/types/standardValidFromDate\"]},{\"id\":\"" (topicid (elt (referenced-topics frag-t100) 6)) "\",\"itemIdentities\":[\"http://psi.egovpt.org/itemIdentifiers#t55\"],\"subjectLocators\":null,\"subjectIdentifiers\":[\"http://psi.egovpt.org/types/links\"]},{\"id\":\"" (topicid (elt (referenced-topics frag-t100) 7)) "\",\"itemIdentities\":null,\"subjectLocators\":null,\"subjectIdentifiers\":[\"http://psi.egovpt.org/subject/GeoData\"]},{\"id\":\"" (topicid (elt (referenced-topics frag-t100) 8)) "\",\"itemIdentities\":[\"http://psi.egovpt.org/itemIdentifiers#t60\"],\"subjectLocators\":null,\"subjectIdentifiers\":[\"http://psi.egovpt.org/types/standardIsAboutSubject\"]},{\"id\":\"" (topicid (elt (referenced-topics frag-t100) 9)) "\",\"itemIdentities\":[\"http://psi.egovpt.org/itemIdentifiers#t61\"],\"subjectLocators\":null,\"subjectIdentifiers\":[\"http://psi.egovpt.org/types/SubjectRoleType\"]},{\"id\":\"" (topicid (elt (referenced-topics frag-t100) 10)) "\",\"itemIdentities\":null,\"subjectLocators\":null,\"subjectIdentifiers\":[\"http://psi.egovpt.org/subject/Semantic+Description\"]},{\"id\":\"" (topicid (elt (referenced-topics frag-t100) 11)) "\",\"itemIdentities\":[\"http://psi.egovpt.org/itemIdentifiers#t64\"],\"subjectLocators\":null,\"subjectIdentifiers\":[\"http://psi.egovpt.org/types/serviceUsesStandard\"]},{\"id\":\"" (topicid (elt (referenced-topics frag-t100) 12)) "\",\"itemIdentities\":[\"http://psi.egovpt.org/itemIdentifiers#t63\"],\"subjectLocators\":null,\"subjectIdentifiers\":[\"http://psi.egovpt.org/types/ServiceRoleType\"]},{\"id\":\"" (topicid (elt (referenced-topics frag-t100) 13)) "\",\"itemIdentities\":null,\"subjectLocators\":null,\"subjectIdentifiers\":[\"http://psi.egovpt.org/service/Google+Maps\",\"http://maps.google.com\"]},{\"id\":\"" (topicid (elt (referenced-topics frag-t100) 14)) "\",\"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+-+Metada…"]},{\"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+-+Metada…"]},{\"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+-+Metada…"]}]}],\"tm-ids\":[\"http://www.isidor.us/unittests/testtm\"]}"))
+ (concatenate 'string "{\"topic\":{\"id\":\"" (d:topicid (d:topic frag-t100)) "\",\"itemIdentities\":[\"http://psi.egovpt.org/itemIdentifiers#t100\"],\"subjectLocators\":null,\"subjectIdentifiers\":[\"http://psi.egovpt.org/standard/ISO+19115%3A+Geographic+Information+-+Metada…"],\"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\":\"" (topicid (elt (referenced-topics frag-t100) 0)) "\",\"itemIdentities\":[\"http://psi.egovpt.org/itemIdentifiers#t3a\"],\"subjectLocators\":null,\"subjectIdentifiers\":[\"http://psi.egovpt.org/types/semanticstandard\"]},{\"id\":\"" (topicid (elt (referenced-topics frag-t100) 1)) "\",\"itemIdentities\":null,\"subjectLocators\":null,\"subjectIdentifiers\":[\"http://www.topicmaps.org/xtm/1.0/core.xtm#display\"]},{\"id\":\"" (topicid (elt (referenced-topics frag-t100) 2)) "\",\"itemIdentities\":null,\"subjectLocators\":null,\"subjectIdentifiers\":[\"http://www.topicmaps.org/xtm/1.0/core.xtm#sort\"]},{\"id\":\"" (topicid (elt (referenced-topics frag-t100) 3)) "\",\"itemIdentities\":[\"http://psi.egovpt.org/itemIdentifiers#t51\"],\"subjectLocators\":null,\"subjectIdentifiers\":[\"http://psi.egovpt.org/types/standardHasStatus\"]},{\"id\":\"" (topicid (elt (referenced-topics frag-t100) 4)) "\",\"itemIdentities\":[\"http://psi.egovpt.org/itemIdentifiers#t53\"],\"subjectLocators\":null,\"subjectIdentifiers\":[\"http://psi.egovpt.org/types/description\"]},{\"id\":\"" (topicid (elt (referenced-topics frag-t100) 5)) "\",\"itemIdentities\":[\"http://psi.egovpt.org/itemIdentifiers#t54\"],\"subjectLocators\":null,\"subjectIdentifiers\":[\"http://psi.egovpt.org/types/standardValidFromDate\"]},{\"id\":\"" (topicid (elt (referenced-topics frag-t100) 6)) "\",\"itemIdentities\":[\"http://psi.egovpt.org/itemIdentifiers#t55\"],\"subjectLocators\":null,\"subjectIdentifiers\":[\"http://psi.egovpt.org/types/links\"]},{\"id\":\"" (topicid (elt (referenced-topics frag-t100) 7)) "\",\"itemIdentities\":null,\"subjectLocators\":null,\"subjectIdentifiers\":[\"http://psi.egovpt.org/subject/GeoData\"]},{\"id\":\"" (topicid (elt (referenced-topics frag-t100) 8)) "\",\"itemIdentities\":[\"http://psi.egovpt.org/itemIdentifiers#t60\"],\"subjectLocators\":null,\"subjectIdentifiers\":[\"http://psi.egovpt.org/types/standardIsAboutSubject\"]},{\"id\":\"" (topicid (elt (referenced-topics frag-t100) 9)) "\",\"itemIdentities\":[\"http://psi.egovpt.org/itemIdentifiers#t61\"],\"subjectLocators\":null,\"subjectIdentifiers\":[\"http://psi.egovpt.org/types/SubjectRoleType\"]},{\"id\":\"" (topicid (elt (referenced-topics frag-t100) 10)) "\",\"itemIdentities\":null,\"subjectLocators\":null,\"subjectIdentifiers\":[\"http://psi.egovpt.org/subject/Semantic+Description\"]},{\"id\":\"" (topicid (elt (referenced-topics frag-t100) 11)) "\",\"itemIdentities\":[\"http://psi.egovpt.org/itemIdentifiers#t64\"],\"subjectLocators\":null,\"subjectIdentifiers\":[\"http://psi.egovpt.org/types/serviceUsesStandard\"]},{\"id\":\"" (topicid (elt (referenced-topics frag-t100) 12)) "\",\"itemIdentities\":[\"http://psi.egovpt.org/itemIdentifiers#t63\"],\"subjectLocators\":null,\"subjectIdentifiers\":[\"http://psi.egovpt.org/types/ServiceRoleType\"]},{\"id\":\"" (topicid (elt (referenced-topics frag-t100) 13)) "\",\"itemIdentities\":null,\"subjectLocators\":null,\"subjectIdentifiers\":[\"http://psi.egovpt.org/service/Google+Maps\",\"http://maps.google.com\"]},{\"id\":\"" (topicid (elt (referenced-topics frag-t100) 14)) "\",\"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+-+Metada…"]},{\"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+-+Metada…"]},{\"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+-+Metada…"]}]}],\"tmIds\":[\"http://www.isidor.us/unittests/testtm\"]}"))
(frag-topic-string
- (concatenate 'string "{\"topic\":{\"id\":\"" (topicid (topic frag-topic)) "\",\"itemIdentities\":null,\"subjectLocators\":null,\"subjectIdentifiers\":[\"http://www.topicmaps.org/xtm/1.0/core.xtm#topic\"],\"instanceOfs\":null,\"names\":null,\"occurrences\":null},\"topicStubs\":null,\"associations\":null,\"tm-ids\":[\"http://www.topicmaps.org/xtm/1.0/core.xtm\"]}")))
+ (concatenate 'string "{\"topic\":{\"id\":\"" (topicid (topic frag-topic)) "\",\"itemIdentities\":null,\"subjectLocators\":null,\"subjectIdentifiers\":[\"http://www.topicmaps.org/xtm/1.0/core.xtm#topic\"],\"instanceOfs\":null,\"names\":null,\"occurrences\":null},\"topicStubs\":null,\"associations\":null,\"tmIds\":[\"http://www.topicmaps.org/xtm/1.0/core.xtm\"]}")))
(is (string= frag-t100-string (to-json-string frag-t100)))
(is (string= frag-topic-string (to-json-string frag-topic))))))))
@@ -396,9 +405,9 @@
(elephant:open-store (xml-importer:get-store-spec dir)) ; init-isiodurs closes the store
(let ((json-fragment-t64
- "{\"topic\":{\"id\":\"t396\",\"itemIdentities\":[\"http://psi.egovpt.org/itemIdentifiers#t64\"],\"subjectLocators\":null,\"subjectIdentifiers\":[\"http://psi.egovpt.org/types/serviceUsesStandard\"],\"instanceOfs\":[[\"http://www.networkedplanet.com/psi/npcl/meta-types/association-type\"]],\"names\":[{\"itemIdentities\":null,\"type\":null,\"scopes\":null,\"value\":\"service uses standard\",\"variants\":null}],\"occurrences\":null},\"topicStubs\":[{\"id\":\"t260\",\"itemIdentities\":[\"http://psi.egovpt.org/itemIdentifiers#t7\"],\"subjectLocators\":null,\"subjectIdentifiers\":[\"http://www.networkedplanet.com/psi/npcl/meta-types/association-type\"]}],\"associations\":null,\"tm-ids\":[\"http://www.isidor.us/unittests/testtm\"]}")
+ "{\"topic\":{\"id\":\"t396\",\"itemIdentities\":[\"http://psi.egovpt.org/itemIdentifiers#t64\"],\"subjectLocators\":null,\"subjectIdentifiers\":[\"http://psi.egovpt.org/types/serviceUsesStandard\"],\"instanceOfs\":[[\"http://www.networkedplanet.com/psi/npcl/meta-types/association-type\"]],\"names\":[{\"itemIdentities\":null,\"type\":null,\"scopes\":null,\"value\":\"service uses standard\",\"variants\":null}],\"occurrences\":null},\"topicStubs\":[{\"id\":\"t260\",\"itemIdentities\":[\"http://psi.egovpt.org/itemIdentifiers#t7\"],\"subjectLocators\":null,\"subjectIdentifiers\":[\"http://www.networkedplanet.com/psi/npcl/meta-types/association-type\"]}],\"associations\":null,\"tmIds\":[\"http://www.isidor.us/unittests/testtm\"]}")
(json-fragment-t100
- "{\"topic\":{\"id\":\"t404\",\"itemIdentities\":[\"http://psi.egovpt.org/itemIdentifiers#t100\"],\"subjectLocators\":null,\"subjectIdentifiers\":[\"http://psi.egovpt.org/standard/ISO+19115%3A+Geographic+Information+-+Metada…"],\"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\":\"t228\",\"itemIdentities\":[\"http://psi.egovpt.org/itemIdentifiers#t3a\"],\"subjectLocators\":null,\"subjectIdentifiers\":[\"http://psi.egovpt.org/types/semanticstandard\"]},{\"id\":\"t74\",\"itemIdentities\":null,\"subjectLocators\":null,\"subjectIdentifiers\":[\"http://www.topicmaps.org/xtm/1.0/core.xtm#display\"]},{\"id\":\"t68\",\"itemIdentities\":null,\"subjectLocators\":null,\"subjectIdentifiers\":[\"http://www.topicmaps.org/xtm/1.0/core.xtm#sort\"]},{\"id\":\"t292\",\"itemIdentities\":[\"http://psi.egovpt.org/itemIdentifiers#t51\"],\"subjectLocators\":null,\"subjectIdentifiers\":[\"http://psi.egovpt.org/types/standardHasStatus\"]},{\"id\":\"t308\",\"itemIdentities\":[\"http://psi.egovpt.org/itemIdentifiers#t53\"],\"subjectLocators\":null,\"subjectIdentifiers\":[\"http://psi.egovpt.org/types/description\"]},{\"id\":\"t316\",\"itemIdentities\":[\"http://psi.egovpt.org/itemIdentifiers#t54\"],\"subjectLocators\":null,\"subjectIdentifiers\":[\"http://psi.egovpt.org/types/standardValidFromDate\"]},{\"id\":\"t324\",\"itemIdentities\":[\"http://psi.egovpt.org/itemIdentifiers#t55\"],\"subjectLocators\":null,\"subjectIdentifiers\":[\"http://psi.egovpt.org/types/links\"]},{\"id\":\"t434\",\"itemIdentities\":null,\"subjectLocators\":null,\"subjectIdentifiers\":[\"http://psi.egovpt.org/subject/GeoData\"]},{\"id\":\"t364\",\"itemIdentities\":[\"http://psi.egovpt.org/itemIdentifiers#t60\"],\"subjectLocators\":null,\"subjectIdentifiers\":[\"http://psi.egovpt.org/types/standardIsAboutSubject\"]},{\"id\":\"t372\",\"itemIdentities\":[\"http://psi.egovpt.org/itemIdentifiers#t61\"],\"subjectLocators\":null,\"subjectIdentifiers\":[\"http://psi.egovpt.org/types/SubjectRoleType\"]},{\"id\":\"t422\",\"itemIdentities\":null,\"subjectLocators\":null,\"subjectIdentifiers\":[\"http://psi.egovpt.org/subject/Semantic+Description\"]},{\"id\":\"t396\",\"itemIdentities\":[\"http://psi.egovpt.org/itemIdentifiers#t64\"],\"subjectLocators\":null,\"subjectIdentifiers\":[\"http://psi.egovpt.org/types/serviceUsesStandard\"]},{\"id\":\"t388\",\"itemIdentities\":[\"http://psi.egovpt.org/itemIdentifiers#t63\"],\"subjectLocators\":null,\"subjectIdentifiers\":[\"http://psi.egovpt.org/types/ServiceRoleType\"]},{\"id\":\"t452\",\"itemIdentities\":null,\"subjectLocators\":null,\"subjectIdentifiers\":[\"http://psi.egovpt.org/service/Google+Maps\",\"http://maps.google.com\"]},{\"id\":\"t380\",\"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+-+Metada…"]},{\"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+-+Metada…"]},{\"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+-+Metada…"]}]}],\"tm-ids\":[\"http://www.isidor.us/unittests/testtm\"]}"))
+ "{\"topic\":{\"id\":\"t404\",\"itemIdentities\":[\"http://psi.egovpt.org/itemIdentifiers#t100\"],\"subjectLocators\":null,\"subjectIdentifiers\":[\"http://psi.egovpt.org/standard/ISO+19115%3A+Geographic+Information+-+Metada…"],\"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\":\"t228\",\"itemIdentities\":[\"http://psi.egovpt.org/itemIdentifiers#t3a\"],\"subjectLocators\":null,\"subjectIdentifiers\":[\"http://psi.egovpt.org/types/semanticstandard\"]},{\"id\":\"t74\",\"itemIdentities\":null,\"subjectLocators\":null,\"subjectIdentifiers\":[\"http://www.topicmaps.org/xtm/1.0/core.xtm#display\"]},{\"id\":\"t68\",\"itemIdentities\":null,\"subjectLocators\":null,\"subjectIdentifiers\":[\"http://www.topicmaps.org/xtm/1.0/core.xtm#sort\"]},{\"id\":\"t292\",\"itemIdentities\":[\"http://psi.egovpt.org/itemIdentifiers#t51\"],\"subjectLocators\":null,\"subjectIdentifiers\":[\"http://psi.egovpt.org/types/standardHasStatus\"]},{\"id\":\"t308\",\"itemIdentities\":[\"http://psi.egovpt.org/itemIdentifiers#t53\"],\"subjectLocators\":null,\"subjectIdentifiers\":[\"http://psi.egovpt.org/types/description\"]},{\"id\":\"t316\",\"itemIdentities\":[\"http://psi.egovpt.org/itemIdentifiers#t54\"],\"subjectLocators\":null,\"subjectIdentifiers\":[\"http://psi.egovpt.org/types/standardValidFromDate\"]},{\"id\":\"t324\",\"itemIdentities\":[\"http://psi.egovpt.org/itemIdentifiers#t55\"],\"subjectLocators\":null,\"subjectIdentifiers\":[\"http://psi.egovpt.org/types/links\"]},{\"id\":\"t434\",\"itemIdentities\":null,\"subjectLocators\":null,\"subjectIdentifiers\":[\"http://psi.egovpt.org/subject/GeoData\"]},{\"id\":\"t364\",\"itemIdentities\":[\"http://psi.egovpt.org/itemIdentifiers#t60\"],\"subjectLocators\":null,\"subjectIdentifiers\":[\"http://psi.egovpt.org/types/standardIsAboutSubject\"]},{\"id\":\"t372\",\"itemIdentities\":[\"http://psi.egovpt.org/itemIdentifiers#t61\"],\"subjectLocators\":null,\"subjectIdentifiers\":[\"http://psi.egovpt.org/types/SubjectRoleType\"]},{\"id\":\"t422\",\"itemIdentities\":null,\"subjectLocators\":null,\"subjectIdentifiers\":[\"http://psi.egovpt.org/subject/Semantic+Description\"]},{\"id\":\"t396\",\"itemIdentities\":[\"http://psi.egovpt.org/itemIdentifiers#t64\"],\"subjectLocators\":null,\"subjectIdentifiers\":[\"http://psi.egovpt.org/types/serviceUsesStandard\"]},{\"id\":\"t388\",\"itemIdentities\":[\"http://psi.egovpt.org/itemIdentifiers#t63\"],\"subjectLocators\":null,\"subjectIdentifiers\":[\"http://psi.egovpt.org/types/ServiceRoleType\"]},{\"id\":\"t452\",\"itemIdentities\":null,\"subjectLocators\":null,\"subjectIdentifiers\":[\"http://psi.egovpt.org/service/Google+Maps\",\"http://maps.google.com\"]},{\"id\":\"t380\",\"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+-+Metada…"]},{\"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+-+Metada…"]},{\"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+-+Metada…"]}]}],\"tmIds\":[\"http://www.isidor.us/unittests/testtm\"]}"))
(is (= (length (elephant:get-instances-by-class 'TopicC)) 13))
(is (= (length (elephant:get-instances-by-class 'AssociationC)) 0))
(is (= (length (elephant:get-instances-by-class 'TopicMapC)) 1))
@@ -727,8 +736,8 @@
(elephant:open-store (xml-importer:get-store-spec dir))
(xml-importer:init-isidorus)
(elephant:open-store (xml-importer:get-store-spec dir)) ; init-isiodurs closes the store
- (let ((t100-1 "{\"topic\":{\"id\":\"t970\",\"itemIdentities\":[\"http://www.egovpt.org/itemIdentifiers#t100\"],\"subjectLocators\":null,\"subjectIdentifiers\":[\"http://psi.egovpt.org/standard/Common+Lisp\"],\"instanceOfs\":[[\"http://psi.egovpt.org/types/standard\"]],\"names\":[{\"itemIdentities\":[\"http://www.egovpt.org/itemIdentifiers#t100_n1\",\"http://www.egovpt.org/itemIdentifiers#t100_n1a\"],\"type\":null,\"scopes\":null,\"value\":\"Common Lisp\",\"variants\":[{\"itemIdentities\":[\"http://www.egovpt.org/itemIdentifiers#t100_n_v1\"],\"scopes\":[[\"http://www.topicmaps.org/xtm/1.0/core.xtm#sort\"],[\"http://psi.egovpt.org/types/long-name\"]],\"resourceRef\":null,\"resourceData\":{\"datatype\":\"http://www.w3.org/2001/XMLSchema#string\",\"value\":\"Common-Lisp\"}}]}],\"occurrences\":[{\"itemIdentities\":[\"http://www.egovpt.org/itemIdentifiers#t100_o1\"],\"type\":[\"http://psi.egovpt.org/types/links\"],\"scopes\":null,\"resourceRef\":\"http://www.common-lisp.net/\",\"resourceData\":null}]},\"topicStubs\":[{\"id\":\"t220\",\"itemIdentities\":[\"http://psi.egovpt.org/itemIdentifiers#t3\",\"http://www.egovpt.org/itemIdentifiers#t3\"],\"subjectLocators\":null,\"subjectIdentifiers\":[\"http://psi.egovpt.org/types/standard\"]},{\"id\":\"t68\",\"itemIdentities\":null,\"subjectLocators\":null,\"subjectIdentifiers\":[\"http://www.topicmaps.org/xtm/1.0/core.xtm#sort\"]},{\"id\":\"t284\",\"itemIdentities\":[\"http://psi.egovpt.org/itemIdentifiers#t50a\"],\"subjectLocators\":null,\"subjectIdentifiers\":[\"http://psi.egovpt.org/types/long-name\"]},{\"id\":\"t324\",\"itemIdentities\":[\"http://psi.egovpt.org/itemIdentifiers#t55\",\"http://psi.egovpt.org/itemIdentifiers#t55_1\"],\"subjectLocators\":null,\"subjectIdentifiers\":[\"http://psi.egovpt.org/types/links\"]}],\"associations\":null,\"tm-ids\":[\"http://www.isidor.us/unittests/testtm\"]}")
- (t100-2 "{\"topic\":{\"id\":\"t945\",\"itemIdentities\":[\"http://www.egovpt.org/itemIdentifiers#t100\",\"http://www.egovpt.org/itemIdentifiers#t100_new\"],\"subjectLocators\":null,\"subjectIdentifiers\":[\"http://psi.egovpt.org/standard/Common+Lisp\"],\"instanceOfs\":[[\"http://psi.egovpt.org/types/standard\"]],\"names\":[{\"itemIdentities\":[\"http://www.egovpt.org/itemIdentifiers#t100_n1\"],\"type\":null,\"scopes\":null,\"value\":\"Common Lisp\",\"variants\":[{\"itemIdentities\":[\"http://www.egovpt.org/itemIdentifiers#t100_n_v1\"],\"scopes\":[[\"http://www.topicmaps.org/xtm/1.0/core.xtm#sort\"],[\"http://psi.egovpt.org/types/long-name\"]],\"resourceRef\":null,\"resourceData\":{\"datatype\":\"http://www.w3.org/2001/XMLSchema#string\",\"value\":\"Common-Lisp\"}},{\"itemIdentities\":[\"http://www.egovpt.org/itemIdentifiers#t100_n_v2\"],\"scopes\":[[\"http://www.topicmaps.org/xtm/1.0/core.xtm#display\"]],\"resourceRef\":null,\"resourceData\":{\"datatype\":\"http://www.w3.org/2001/XMLSchema#string\",\"value\":\"CL\"}}]}],\"occurrences\":[{\"itemIdentities\":[\"http://www.egovpt.org/itemIdentifiers#t100_o2\"],\"type\":[\"http://psi.egovpt.org/types/links\"],\"scopes\":null,\"resourceRef\":\"http://www.cliki.net/\",\"resourceData\":null}]},\"topicStubs\":[{\"id\":\"t220\",\"itemIdentities\":[\"http://psi.egovpt.org/itemIdentifiers#t3\",\"http://www.egovpt.org/itemIdentifiers#t3\"],\"subjectLocators\":null,\"subjectIdentifiers\":[\"http://psi.egovpt.org/types/standard\"]},{\"id\":\"t68\",\"itemIdentities\":null,\"subjectLocators\":null,\"subjectIdentifiers\":[\"http://www.topicmaps.org/xtm/1.0/core.xtm#sort\"]},{\"id\":\"t284\",\"itemIdentities\":[\"http://psi.egovpt.org/itemIdentifiers#t50a\"],\"subjectLocators\":null,\"subjectIdentifiers\":[\"http://psi.egovpt.org/types/long-name\"]},{\"id\":\"t74\",\"itemIdentities\":null,\"subjectLocators\":null,\"subjectIdentifiers\":[\"http://www.topicmaps.org/xtm/1.0/core.xtm#display\"]},{\"id\":\"t324\",\"itemIdentities\":[\"http://psi.egovpt.org/itemIdentifiers#t55\"],\"subjectLocators\":null,\"subjectIdentifiers\":[\"http://psi.egovpt.org/types/links\"]}],\"associations\":null,\"tm-ids\":[\"http://www.isidor.us/unittests/testtm\"]}"))
+ (let ((t100-1 "{\"topic\":{\"id\":\"t970\",\"itemIdentities\":[\"http://www.egovpt.org/itemIdentifiers#t100\"],\"subjectLocators\":null,\"subjectIdentifiers\":[\"http://psi.egovpt.org/standard/Common+Lisp\"],\"instanceOfs\":[[\"http://psi.egovpt.org/types/standard\"]],\"names\":[{\"itemIdentities\":[\"http://www.egovpt.org/itemIdentifiers#t100_n1\",\"http://www.egovpt.org/itemIdentifiers#t100_n1a\"],\"type\":null,\"scopes\":null,\"value\":\"Common Lisp\",\"variants\":[{\"itemIdentities\":[\"http://www.egovpt.org/itemIdentifiers#t100_n_v1\"],\"scopes\":[[\"http://www.topicmaps.org/xtm/1.0/core.xtm#sort\"],[\"http://psi.egovpt.org/types/long-name\"]],\"resourceRef\":null,\"resourceData\":{\"datatype\":\"http://www.w3.org/2001/XMLSchema#string\",\"value\":\"Common-Lisp\"}}]}],\"occurrences\":[{\"itemIdentities\":[\"http://www.egovpt.org/itemIdentifiers#t100_o1\"],\"type\":[\"http://psi.egovpt.org/types/links\"],\"scopes\":null,\"resourceRef\":\"http://www.common-lisp.net/\",\"resourceData\":null}]},\"topicStubs\":[{\"id\":\"t220\",\"itemIdentities\":[\"http://psi.egovpt.org/itemIdentifiers#t3\",\"http://www.egovpt.org/itemIdentifiers#t3\"],\"subjectLocators\":null,\"subjectIdentifiers\":[\"http://psi.egovpt.org/types/standard\"]},{\"id\":\"t68\",\"itemIdentities\":null,\"subjectLocators\":null,\"subjectIdentifiers\":[\"http://www.topicmaps.org/xtm/1.0/core.xtm#sort\"]},{\"id\":\"t284\",\"itemIdentities\":[\"http://psi.egovpt.org/itemIdentifiers#t50a\"],\"subjectLocators\":null,\"subjectIdentifiers\":[\"http://psi.egovpt.org/types/long-name\"]},{\"id\":\"t324\",\"itemIdentities\":[\"http://psi.egovpt.org/itemIdentifiers#t55\",\"http://psi.egovpt.org/itemIdentifiers#t55_1\"],\"subjectLocators\":null,\"subjectIdentifiers\":[\"http://psi.egovpt.org/types/links\"]}],\"associations\":null,\"tmIds\":[\"http://www.isidor.us/unittests/testtm\"]}")
+ (t100-2 "{\"topic\":{\"id\":\"t945\",\"itemIdentities\":[\"http://www.egovpt.org/itemIdentifiers#t100\",\"http://www.egovpt.org/itemIdentifiers#t100_new\"],\"subjectLocators\":null,\"subjectIdentifiers\":[\"http://psi.egovpt.org/standard/Common+Lisp\"],\"instanceOfs\":[[\"http://psi.egovpt.org/types/standard\"]],\"names\":[{\"itemIdentities\":[\"http://www.egovpt.org/itemIdentifiers#t100_n1\"],\"type\":null,\"scopes\":null,\"value\":\"Common Lisp\",\"variants\":[{\"itemIdentities\":[\"http://www.egovpt.org/itemIdentifiers#t100_n_v1\"],\"scopes\":[[\"http://www.topicmaps.org/xtm/1.0/core.xtm#sort\"],[\"http://psi.egovpt.org/types/long-name\"]],\"resourceRef\":null,\"resourceData\":{\"datatype\":\"http://www.w3.org/2001/XMLSchema#string\",\"value\":\"Common-Lisp\"}},{\"itemIdentities\":[\"http://www.egovpt.org/itemIdentifiers#t100_n_v2\"],\"scopes\":[[\"http://www.topicmaps.org/xtm/1.0/core.xtm#display\"]],\"resourceRef\":null,\"resourceData\":{\"datatype\":\"http://www.w3.org/2001/XMLSchema#string\",\"value\":\"CL\"}}]}],\"occurrences\":[{\"itemIdentities\":[\"http://www.egovpt.org/itemIdentifiers#t100_o2\"],\"type\":[\"http://psi.egovpt.org/types/links\"],\"scopes\":null,\"resourceRef\":\"http://www.cliki.net/\",\"resourceData\":null}]},\"topicStubs\":[{\"id\":\"t220\",\"itemIdentities\":[\"http://psi.egovpt.org/itemIdentifiers#t3\",\"http://www.egovpt.org/itemIdentifiers#t3\"],\"subjectLocators\":null,\"subjectIdentifiers\":[\"http://psi.egovpt.org/types/standard\"]},{\"id\":\"t68\",\"itemIdentities\":null,\"subjectLocators\":null,\"subjectIdentifiers\":[\"http://www.topicmaps.org/xtm/1.0/core.xtm#sort\"]},{\"id\":\"t284\",\"itemIdentities\":[\"http://psi.egovpt.org/itemIdentifiers#t50a\"],\"subjectLocators\":null,\"subjectIdentifiers\":[\"http://psi.egovpt.org/types/long-name\"]},{\"id\":\"t74\",\"itemIdentities\":null,\"subjectLocators\":null,\"subjectIdentifiers\":[\"http://www.topicmaps.org/xtm/1.0/core.xtm#display\"]},{\"id\":\"t324\",\"itemIdentities\":[\"http://psi.egovpt.org/itemIdentifiers#t55\"],\"subjectLocators\":null,\"subjectIdentifiers\":[\"http://psi.egovpt.org/types/links\"]}],\"associations\":null,\"tmIds\":[\"http://www.isidor.us/unittests/testtm\"]}"))
(is (= (length (elephant:get-instances-by-class 'TopicC)) 13))
(is (= (length (elephant:get-instances-by-class 'AssociationC)) 0))
(is (= (length (elephant:get-instances-by-class 'TopicMapC)) 1))
Modified: trunk/src/unit_tests/multiple_tms_ont.xtm
==============================================================================
--- trunk/src/unit_tests/multiple_tms_ont.xtm (original)
+++ trunk/src/unit_tests/multiple_tms_ont.xtm Fri Apr 10 19:11:32 2009
@@ -1,4 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
+<!-- ======================================================================= -->
+<!-- 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. -->
+<!-- ======================================================================= -->
+
+
<topicMap xmlns="http://www.topicmaps.org/xtm/1.0/"
xmlns:xlink="http://www.w3.org/1999/xlink">
<topic id="t1">
@@ -54,4 +63,4 @@
<topicRef xlink:href="#t3"/>
</member>
</association>
-</topicMap>
\ No newline at end of file
+</topicMap>
Modified: trunk/src/unit_tests/multiple_tms_worms.xtm
==============================================================================
--- trunk/src/unit_tests/multiple_tms_worms.xtm (original)
+++ trunk/src/unit_tests/multiple_tms_worms.xtm Fri Apr 10 19:11:32 2009
@@ -1,4 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
+<!-- ======================================================================= -->
+<!-- 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. -->
+<!-- ======================================================================= -->
+
+
<topicMap xmlns="http://www.topicmaps.org/xtm/1.0/"
xmlns:xlink="http://www.w3.org/1999/xlink">
@@ -13,4 +22,4 @@
<subjectIndicatorRef xlink:href="http://www.egovpt.org/instances/topic-t3"/>
</subjectIdentity>
</topic>
-</topicMap>
\ No newline at end of file
+</topicMap>
Modified: trunk/src/unit_tests/notification_merge1.xtm
==============================================================================
--- trunk/src/unit_tests/notification_merge1.xtm (original)
+++ trunk/src/unit_tests/notification_merge1.xtm Fri Apr 10 19:11:32 2009
@@ -1,4 +1,13 @@
<?xml version="1.0"?>
+<!-- ======================================================================= -->
+<!-- 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. -->
+<!-- ======================================================================= -->
+
+
<topicMap xmlns="http://www.topicmaps.org/xtm/" version="2.0">
<topic id="t1">
<itemIdentity href="http://www.egovpt.org/itemIdentifiers#t1"/>
Modified: trunk/src/unit_tests/notification_merge2.xtm
==============================================================================
--- trunk/src/unit_tests/notification_merge2.xtm (original)
+++ trunk/src/unit_tests/notification_merge2.xtm Fri Apr 10 19:11:32 2009
@@ -1,4 +1,13 @@
<?xml version="1.0"?>
+<!-- ======================================================================= -->
+<!-- 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. -->
+<!-- ======================================================================= -->
+
+
<topicMap xmlns="http://www.topicmaps.org/xtm/" version="2.0">
<topic id="t1">
<itemIdentity href="http://www.egovpt.org/itemIdentifiers#t1"/>
Modified: trunk/src/unit_tests/notificationbase.xtm
==============================================================================
--- trunk/src/unit_tests/notificationbase.xtm (original)
+++ trunk/src/unit_tests/notificationbase.xtm Fri Apr 10 19:11:32 2009
@@ -1,4 +1,13 @@
<?xml version="1.0"?>
+<!-- ======================================================================= -->
+<!-- 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. -->
+<!-- ======================================================================= -->
+
+
<topicMap xmlns="http://www.topicmaps.org/xtm/" version="2.0">
<topic id="t1">
<!-- functions as source locator (does this make a lot of sense
Modified: trunk/src/unit_tests/sample_objects.xtm
==============================================================================
--- trunk/src/unit_tests/sample_objects.xtm (original)
+++ trunk/src/unit_tests/sample_objects.xtm Fri Apr 10 19:11:32 2009
@@ -1,4 +1,13 @@
<?xml version="1.0"?>
+<!-- ======================================================================= -->
+<!-- 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. -->
+<!-- ======================================================================= -->
+
+
<topicMap xmlns="http://www.topicmaps.org/xtm/1.0/" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- === topics ================================================== -->
Modified: trunk/src/unit_tests/sample_objects_2_0.xtm
==============================================================================
--- trunk/src/unit_tests/sample_objects_2_0.xtm (original)
+++ trunk/src/unit_tests/sample_objects_2_0.xtm Fri Apr 10 19:11:32 2009
@@ -1,4 +1,13 @@
<?xml version="1.0"?>
+<!-- ======================================================================= -->
+<!-- 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. -->
+<!-- ======================================================================= -->
+
+
<topicMap xmlns="http://www.topicmaps.org/xtm/" version="2.0">
<!-- === test object 1 =================================================== -->
Modified: trunk/src/unit_tests/t100.xtm
==============================================================================
--- trunk/src/unit_tests/t100.xtm (original)
+++ trunk/src/unit_tests/t100.xtm Fri Apr 10 19:11:32 2009
@@ -1,4 +1,13 @@
<?xml version="1.0"?>
+<!-- ======================================================================= -->
+<!-- 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. -->
+<!-- ======================================================================= -->
+
+
<topicMap xmlns="http://www.topicmaps.org/xtm/" version="2.0">
<!-- main topic "t100" -->
Modified: trunk/src/unit_tests/testing_db.lisp
==============================================================================
--- trunk/src/unit_tests/testing_db.lisp (original)
+++ trunk/src/unit_tests/testing_db.lisp Fri Apr 10 19:11:32 2009
@@ -1,31 +1,11 @@
-;;; file: testing_db.lisp
-;;; author: lukas giessmann
-;;; eMail: inf1045(a)fh-worms.de
-;;; description: contains the following tests in the test-suite "testing-db":
-;;; *test-obj1
-;;; *test-obj2
-;;; *test-obj3
-;;; *test-obj4
-;;; *test-obj5
-;;; *test-obj6
-;;; *test-closing-db
-;;; *test-consistent-file
-;;; notes: *test-inconsistent-file is not implemented (only test body exists)
-;;; *compile warning: ... The symbol "%OID" is not external in the ELEPHANT package ...
-;;; choose: 0: [CONTINUE] Use symbol anyway
-;;; revision 30.04.2008: *(asdf:operate 'asdf:load-op 'isidorus) instead
-;;; of loading all files separately
-;;; *all tests with the to-string method were removed
-;;; *function get-object-by-id was removed
-;;; *definition of equalT(TopicMapConstructC, TopicMapConstructC)
-;;; *definition of equalA(TopicMapConstructC, TopicMapConstructC)
-;;; *definition of equalN(TopicMapConstructC, TopicMapConstructC)
-;;; revision 04.04.2008: *equalT was completely implemented
-;;; *equalA and equalN were removed
-;;; *test-closing-db and test-consistent-file use the macros signals
-;;; and not is (signals type (body) -> is true if the error of the type
-;;; type was thrown)
-;;; date: 20.04.2008 - 04.05.2008
+;;+-----------------------------------------------------------------------------
+;;+ 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.
+;;+-----------------------------------------------------------------------------
+
(asdf:operate 'asdf:load-op 'FiveAM)
(asdf:operate 'asdf:load-op 'cxml)
Modified: trunk/src/unit_tests/unittests-constants.lisp
==============================================================================
--- trunk/src/unit_tests/unittests-constants.lisp (original)
+++ trunk/src/unit_tests/unittests-constants.lisp Fri Apr 10 19:11:32 2009
@@ -1,3 +1,12 @@
+;;+-----------------------------------------------------------------------------
+;;+ 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 :unittests-constants
(:use :common-lisp)
(:import-from :constants
Modified: trunk/src/unit_tests/versions_test.lisp
==============================================================================
--- trunk/src/unit_tests/versions_test.lisp (original)
+++ trunk/src/unit_tests/versions_test.lisp Fri Apr 10 19:11:32 2009
@@ -1,3 +1,12 @@
+;;+-----------------------------------------------------------------------------
+;;+ 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.
+;;+-----------------------------------------------------------------------------
+
+
;-*- standard-indent: 2; indent-tabs-mode: nil -*-
(defpackage :versions-test
(:use
Modified: trunk/src/xml-constants.lisp
==============================================================================
--- trunk/src/xml-constants.lisp (original)
+++ trunk/src/xml-constants.lisp Fri Apr 10 19:11:32 2009
@@ -1,3 +1,12 @@
+;;+-----------------------------------------------------------------------------
+;;+ 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 :xml-constants
(:use :common-lisp
:asdf)
Modified: trunk/src/xml/core_psis.xtm
==============================================================================
--- trunk/src/xml/core_psis.xtm (original)
+++ trunk/src/xml/core_psis.xtm Fri Apr 10 19:11:32 2009
@@ -1,4 +1,13 @@
<?xml version="1.0"?>
+<!-- ======================================================================= -->
+<!-- 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. -->
+<!-- ======================================================================= -->
+
+
<topicMap xmlns="http://www.topicmaps.org/xtm/" version="2.0">
@@ -100,4 +109,4 @@
<value>instance</value>
</name>
</topic>
-</topicMap>
\ No newline at end of file
+</topicMap>
Modified: trunk/src/xml/exporter.lisp
==============================================================================
--- trunk/src/xml/exporter.lisp (original)
+++ trunk/src/xml/exporter.lisp Fri Apr 10 19:11:32 2009
@@ -1,3 +1,12 @@
+;;+-----------------------------------------------------------------------------
+;;+ 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.
+;;+-----------------------------------------------------------------------------
+
+
(in-package :exporter)
Modified: trunk/src/xml/exporter_xtm1.0.lisp
==============================================================================
--- trunk/src/xml/exporter_xtm1.0.lisp (original)
+++ trunk/src/xml/exporter_xtm1.0.lisp Fri Apr 10 19:11:32 2009
@@ -1,3 +1,12 @@
+;;+-----------------------------------------------------------------------------
+;;+ 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 :exporter
(:use :cl :cxml :elephant :datamodel)
(:import-from :constants
Modified: trunk/src/xml/exporter_xtm2.0.lisp
==============================================================================
--- trunk/src/xml/exporter_xtm2.0.lisp (original)
+++ trunk/src/xml/exporter_xtm2.0.lisp Fri Apr 10 19:11:32 2009
@@ -1,3 +1,12 @@
+;;+-----------------------------------------------------------------------------
+;;+ 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.
+;;+-----------------------------------------------------------------------------
+
+
(in-package :exporter)
(defun ref-to-elem (topic)
Modified: trunk/src/xml/importer.lisp
==============================================================================
--- trunk/src/xml/importer.lisp (original)
+++ trunk/src/xml/importer.lisp Fri Apr 10 19:11:32 2009
@@ -1,3 +1,12 @@
+;;+-----------------------------------------------------------------------------
+;;+ 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.
+;;+-----------------------------------------------------------------------------
+
+
;; TODOs (in descending priority):
;; * resolve non-local topicRefs
;; * either check the input document for XTM2.0 conformance in advance or
Modified: trunk/src/xml/importer_xtm1.0.lisp
==============================================================================
--- trunk/src/xml/importer_xtm1.0.lisp (original)
+++ trunk/src/xml/importer_xtm1.0.lisp Fri Apr 10 19:11:32 2009
@@ -1,3 +1,12 @@
+;;+-----------------------------------------------------------------------------
+;;+ 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.
+;;+-----------------------------------------------------------------------------
+
+
(in-package :xml-importer)
(defun get-topic-id-xtm1.0 (topic-elem)
Modified: trunk/src/xml/importer_xtm2.0.lisp
==============================================================================
--- trunk/src/xml/importer_xtm2.0.lisp (original)
+++ trunk/src/xml/importer_xtm2.0.lisp Fri Apr 10 19:11:32 2009
@@ -1,3 +1,12 @@
+;;+-----------------------------------------------------------------------------
+;;+ 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.
+;;+-----------------------------------------------------------------------------
+
+
(in-package :xml-importer)
(defun from-identifier-elem (classsymbol elem start-revision)
Modified: trunk/src/xml/setup.lisp
==============================================================================
--- trunk/src/xml/setup.lisp (original)
+++ trunk/src/xml/setup.lisp Fri Apr 10 19:11:32 2009
@@ -1,3 +1,12 @@
+;;+-----------------------------------------------------------------------------
+;;+ 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.
+;;+-----------------------------------------------------------------------------
+
+
(in-package :xml-importer)
(defun get-uuid ()
Modified: trunk/src/xml/tools.lisp
==============================================================================
--- trunk/src/xml/tools.lisp (original)
+++ trunk/src/xml/tools.lisp Fri Apr 10 19:11:32 2009
@@ -1,3 +1,12 @@
+;;+-----------------------------------------------------------------------------
+;;+ 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 :xml-tools
(:use :cl :cxml)
(:export :get-attribute
1
0

[isidorus-cvs] r25 - in trunk: docs src src/ajax src/ajax/css src/ajax/javascripts src/json src/rest_interface
by Lukas Giessmann 01 Apr '09
by Lukas Giessmann 01 Apr '09
01 Apr '09
Author: lgiessmann
Date: Wed Apr 1 05:41:52 2009
New Revision: 25
Log:
added the general user-interface structure; implemented the home section; and added a summary json-interface to the rest-interface
Added:
trunk/src/ajax/css/
trunk/src/ajax/css/create_topics.css
trunk/src/ajax/css/edit_topics.css
trunk/src/ajax/css/home.css
trunk/src/ajax/css/main.css
trunk/src/ajax/css/navi.css
trunk/src/ajax/css/search_topics.css
trunk/src/ajax/javascripts/ajax_constants.js (contents, props changed)
trunk/src/ajax/javascripts/ajax_edit_topic.js
trunk/src/ajax/javascripts/ajax_home.js
trunk/src/ajax/javascripts/ajax_navi.js
Modified:
trunk/docs/xtm_json.txt
trunk/src/ajax/isidorus.html
trunk/src/isidorus.asd
trunk/src/json/json_exporter.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 Wed Apr 1 05:41:52 2009
@@ -1,11 +1,50 @@
-resourceData:
+//+-----------------------------------------------------------------------------
+//+ Overview:
+//+ *Part 1: XTM - data model
+//+ *Part 2: Object summaries
+//+-----------------------------------------------------------------------------
+
+
+
+
+//+-----------------------------------------------------------------------------
+//+ Part 1: XTM - data model:
+//+ The first part describes the xtm's data model, here will be all elements
+//+ defined in the xtm defined as json objects and finally there will be used
+//+ as json objects in a json-fragment-object.
+//+
+//+ this json model depends on the xtm version 2.0 and contains the following
+//+ objects:
+//+ *resourceData
+//+ *variant
+//+ *name
+//+ *name
+//+ *occurrence
+//+ *topic
+//+ *role
+//+ *association
+//+ *topicStub
+//+ *fragment
+//+
+//+ At the end of this file are some expample json objects, you can also
+//+ validate json data on "http://www.jsonlint.com/".
+//+ Note all values, although they are null values e.g. the "type" field in
+//+ a name object should be set to a value - in this case "null".
+//+-----------------------------------------------------------------------------
+
+
+//+-----------------------------------------------------------------------------
+//+ resourceData
+//+-----------------------------------------------------------------------------
{
"datatype" : "Text",
"value" : "Text"
}
-variant:
+//+-----------------------------------------------------------------------------
+//+ variant
+//+-----------------------------------------------------------------------------
{
"itemIdentities" : [ "Text" , "..." ],
"scopes" : [ [ "PSI-1-t1", "PSI-2-t1", "..." ], [ "PSI-1-t2", "PSI-2-t2", "..." ], [ "..." ] ],
@@ -14,7 +53,9 @@
}
-name:
+//+-----------------------------------------------------------------------------
+//+ name
+//+-----------------------------------------------------------------------------
{
"itemIdentities" : [ "Text", "..." ],
"type" : [ "PSI-1", "PSI-2", "..." ],
@@ -24,7 +65,9 @@
}
-occurrence:
+//+-----------------------------------------------------------------------------
+//+ occurrence
+//+-----------------------------------------------------------------------------
{
"itemIdentities" : [ "Text", "..." ],
"type" : [ "PSI-1", "PSI-2", "..." ],
@@ -34,7 +77,9 @@
}
-topic:
+//+-----------------------------------------------------------------------------
+//+ topic
+//+-----------------------------------------------------------------------------
{
"id" : "Text",
"itemIdentities" : [ "Text", "..." ],
@@ -46,7 +91,9 @@
}
-role:
+//+-----------------------------------------------------------------------------
+//+ role
+//+-----------------------------------------------------------------------------
{
"itemIdentities" : [ "Text", "..." ],
"type" : [ "PSI-1", "PSI-2", "..." ],
@@ -54,7 +101,9 @@
}
-association:
+//+-----------------------------------------------------------------------------
+//+ association
+//+-----------------------------------------------------------------------------
{
"itemIdentities" : [ "Text", "..." ],
"type" : [ "PSI-1", "PSI-2", "..." ],
@@ -63,7 +112,9 @@
}
-topicStub:
+//+-----------------------------------------------------------------------------
+//+ topicStub
+//+-----------------------------------------------------------------------------
{
"id" : "Text",
"itemIdentities" : [ "Text", "..." ],
@@ -72,24 +123,70 @@
}
-fragment
+//+-----------------------------------------------------------------------------
+//+ fragment
+//+ The field tm-ids should have only one tm-id in the list, because
+//+ there will be used only the first, if the fragment is an incoming one
+//+ outgoing fragment have a list with more tm-ids but at least one
+//+-----------------------------------------------------------------------------
{
"topic" : { <topic> },
"topicStubs" : [ { <topicStub> }, { <...> } ],
"associations" : [ { <association> }, { <...> } ],
"tm-ids" : [ "id-1", "id-2", "..." ]
}
-// the field tm-ids should have only one tm-id in the list, because
-// there will be used only the first if the fragment is an incoming one
-// outgoing fragment have a list with more tm-ids but at least one
-a summary of all topic psis within isidorus
-[["topic-1-psi-1","topic-1-psi-2",<...>],["topic-2-psi-1","topic-2-psi-2",<...>],<...>]
+//+-----------------------------------------------------------------------------
+//+ Part 2: Object summaries
+//+ The second part contains object summaries of exisiting objects in
+//+ isidorus.
+//+
+//+ *psiSummary
+//+ *topicSummary
+//+-----------------------------------------------------------------------------
+
+
+//+-----------------------------------------------------------------------------
+//+ psiSummary
+//+ The json list is made of inner json-lists.
+//+ Every inner json list represents one topic with all psis owned by the
+//+ topic. The outer list represents a set of all topics exist in isidorus.
+//+-----------------------------------------------------------------------------
+[ [ "topic-1-psi-1", "topic-1-psi-2", <...> ], [ "topic-2-psi-1", "topic-2-psi-2", <...> ], <...> ]
+
+
+//+-----------------------------------------------------------------------------
+//+ topicSummary
+//+ contains the topic id,subjetcIdentifiers, itemIdentities,
+//+ subjectLocators, nameSummaries and occurrenceSummaries
+//+-----------------------------------------------------------------------------
+{
+ "id" : "Text",
+ "itemIdentities" : [ "Text", "..." ],
+ "subjectLocators" : [ "Text", "..." ],
+ "subjectIdentifiers" : [ "Text", "..." ],
+ "instanceOfs" : [ [ "PSI-1-t1", "PSI-2-t1", "..." ], [ "PSI-1-t2", "PSI-2-t2", "..." ], [ "..." ] ],
+ "names" : [ "name-1", "name-2", <...> ],
+ "occurrences" : [ "occurrence-1", "occurrence-2", <...>]
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-=== example fragment with one topic, a few topicStubs and associations =========
{
"topic" : {
"id" : "t403",
Added: trunk/src/ajax/css/create_topics.css
==============================================================================
Added: trunk/src/ajax/css/edit_topics.css
==============================================================================
Added: trunk/src/ajax/css/home.css
==============================================================================
--- (empty file)
+++ trunk/src/ajax/css/home.css Wed Apr 1 05:41:52 2009
@@ -0,0 +1,32 @@
+.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.topicTable {
+ list-style: none;
+}
+
+div.naviTopicTable {
+ width: 80%;
+ margin-left: auto;
+ margin-right: auto;
+}
+
+select.topicTable {
+ margin-left: 20px;
+}
\ No newline at end of file
Added: trunk/src/ajax/css/main.css
==============================================================================
--- (empty file)
+++ trunk/src/ajax/css/main.css Wed Apr 1 05:41:52 2009
@@ -0,0 +1,11 @@
+.clickable{
+ cursor: pointer;
+}
+
+.clickable:hover{
+ text-decoration: underline;
+}
+
+.clickable:active{
+ color: red;
+}
\ No newline at end of file
Added: trunk/src/ajax/css/navi.css
==============================================================================
--- (empty file)
+++ trunk/src/ajax/css/navi.css Wed Apr 1 05:41:52 2009
@@ -0,0 +1,9 @@
+#navi {
+ border: solid 1px;
+ margin-top: 10px;
+ margin-bottom: 10px;
+}
+
+.naviElem {
+ background-color: silver;
+}
\ No newline at end of file
Added: trunk/src/ajax/css/search_topics.css
==============================================================================
Modified: trunk/src/ajax/isidorus.html
==============================================================================
--- trunk/src/ajax/isidorus.html (original)
+++ trunk/src/ajax/isidorus.html Wed Apr 1 05:41:52 2009
@@ -3,161 +3,36 @@
<head>
<title>isidorus</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
- <link rel="stylesheet" type="text/css" href="main.css"/>
+ <!-- includes all necessary css-files -->
+ <link rel="stylesheet" type="text/css" href="css/main.css"/>
+ <link rel="stylesheet" type="text/css" href="css/home.css"/>
+ <link rel="stylesheet" type="text/css" href="css/search_topics.css"/>
+ <link rel="stylesheet" type="text/css" href="css/edit_topics.css"/>
+ <link rel="stylesheet" type="text/css" href="css/create_topics.css"/>
+ <link rel="stylesheet" type="text/css" href="css/navi.css"/>
+
<!-- includes the prototype and scriptaculous frameworks -->
<script language="JavaScript" type="text/javascript" src="javascripts/prototype.js"></script>
<script language="JavaScript" type="text/javascript" src="javascripts/scriptaculous.js"></script>
- <!-- own javascript code -->
- <script language="JavaScript" type="text/javascript">
- // --- some constants -----------------------------------------------------
- var TIMEOUT = 5000; // const TIMEOUT = 5000 --> "const" doesn't work under IE
- var HOST_PREF = "http://localhost:8000/";
- var GET_PREFIX = HOST_PREF + "json/get/";
- var COMMIT_URL = HOST_PREF + "json/commit/";
- var ALL_PSIS_URL = HOST_PREF + "json/psis/";
- var OWN_URL = HOST_PREF + "isidorus";
-
- // --- some globals -------------------------------------------------------
- var ALL_PSIS = null;
- var CURRENT_FRAGMENT = null;
-
- // --- default error handler for all ajax objects
- function errorHandler(ajaxReq)
- {
- alert("Something went wrong ... -> " + ajaxReq.status);
- }
-
-
- // --- redirects the client to the initial url
- function goBack()
- {
- window.location = OWN_URL;
- $("textArea").value = "";
- }
-
-
- // --- ajax functions -----------------------------------------------------
- function commitPut()
- {
- function commitPutHandler(ajaxReq)
- {
- alert($("textArea").value + "\n\n" + ajaxReq.status);
- }
-
-
- new Ajax.Request(COMMIT_URL,
- {
- method: "post",
- requestHeaders:{ "Content-Type":"application/json"},
- onSuccess: commitPutHandler,
- onFailure: errorHandler,
- postBody: $("textArea").value
- });
- }
-
-
- // --- hides the table with all psis and sends a request to the server for a specific topic-psi
- function selectTopic(psi)
- {
- if(ALL_PSIS !== null && ALL_PSIS.length !== 0){
- // --- handler for the ajax request aobject - if the request was successful
- function getFragment(ajaxReq)
- {
- var response = ajaxReq.responseText;
- try{
- var jsonObj = CURRENT_FRAGMENT = response.evalJSON();
- $("textArea").innerHTML = response; // for safari
- $("textArea").value = response; // for all other browsers
- }catch(err){
- alert("got bad JSON data: " + err);
- }
- }
-
- var url = GET_PREFIX + psi.gsub("#", "%23");
- $("allPsisTable").shrink();
- setTimeout(function(){$("textArea").grow();}, 1500); // an easy way to define events by yourself
- setTimeout(function(){$("allPsisTable").remove();}, 2000);
- $("allPsisButton").insert({after: '<input id="commitPutButton" style="margin-top:10px; margin-bottom:10px;" type="button" onclick="commitPut()" value="commit fragment"/>'});
- // --- ajax request
- new Ajax.Request(url,
- {
- method:'get',
- requestHeaders: ["If-Modified-Since", "Thu, 1 Jan 1970 00:00:00 GMT"], // rfc1945, to make sure that IE does not cache the ajax-response
- onSuccess: getFragment,
- onFailure: errorHandler
- });
- }
- }
-
-
- // --- gets all topic psis are currently contained in isidorus
- function getAllPsis()
- {
- // --- handler for the ajax request aobject - if the request was successful
- function getAllPsisSuccessHandler(ajaxReq)
- {
- var btn= $("commitPutButton");
- if(btn)btn.remove();
-
- if($("allPsisTable") === null){ // avoid duplicates
- var response = ajaxReq.responseText;
- try{
- var jsonObj = ALL_PSIS = response.evalJSON();
- var htmlStr = '<table id="allPsisTable"><tr><th>topic #</th><th>psis</th></tr>';
-
- jsonObj.each(function(topic, idx)
- {
- htmlStr += '<tr><td rowspan="' + topic.length + '">' + idx + '</td>';
- topic.each(function(psi, innerIdx)
- {
- if(innerIdx !== 0)htmlStr += "<tr>";
- htmlStr += '<td><span id="psiRow_' + idx + '_' + innerIdx + '" name="psi">' + psi + '</span></td></tr>';
- });
- if(topic.length !== 1)htmlStr += "</tr>";
- });
- htmlStr += "</table>";
- $("allPsisButton").insert({after: htmlStr});
- $("allPsisTable").hide();
- $("allPsisTable").appear();
-
-
- // --- iterates through the new created DOM-elements and adds to every one a click-event-handler
- jsonObj.each(function(topic, idx)
- {
- topic.each(function(psi, innerIdx)
- {
- $("psiRow_" + idx + "_" + innerIdx).observe("click", function(event){ selectTopic(Event.element(event).innerHTML); });
- $("psiRow_" + idx + "_" + innerIdx).observe("mouseover", function(event){Event.element(event).up().setStyle({"backgroundColor" : "silver", "cursor" : "pointer"}); });
- $("psiRow_" + idx + "_" + innerIdx).observe("mouseout", function(event){ Event.element(event).up().setStyle({"backgroundColor" : "white", "cursor" : "default"}); });
- });
- });
- }catch(err){
- alert("got bad JSON data: " + err);
- }
- }
- }
-
- $("textArea").fade();
-
- // --- ajax request
- new Ajax.Request(ALL_PSIS_URL,
- {
- method:"get",
- requestHeaders: ["If-Modified-Since", "Thu, 1 Jan 1970 00:00:00 GMT"],
- onSuccess: getAllPsisSuccessHandler,
- onFailure: errorHandler
- });
- }
- </script>
+ <!-- includes own javascript files -->
+ <script language="JavaScript" type="text/javascript" src="javascripts/ajax_constants.js"></script>
+ <script language="JavaScript" type="text/javascript" src="javascripts/ajax_edit_topic.js"></script>
+ <script language="JavaScript" type="text/javascript" src="javascripts/ajax_home.js"></script>
+ <script language="JavaScript" type="text/javascript" src="javascripts/ajax_navi.js"></script>
</head>
<body>
- <div id="content" style="margin-top:20px; margin-left:auto; margin-right:auto; border:dashed; width:60%;">
- <input id="allPsisButton" style="margin:10px;" type="button" onclick="getAllPsis()" value="get all psis"/><br/>
- <textarea id="textArea" style="margin-left:10px; margin-bottom:10px;" cols="67" rows="10"></textarea><br/>
- <input id="backButton" style="margin-left:10px; margin-bottom:10px;" type="button" onclick="goBack()" value="clear"/><br/>
+ <div id="page">
+ <div id="navi">
+ <span id="home" class="naviElem clickable">home</span>
+ <span id="searchTopic" class="naviElem clickable">search topic</span>
+ <span id="editTopic" class="naviElem clickable">edit topic</span>
+ <span id="createTopic" class="naviElem clickable">create topic</span>
+ </div>
+ <div id="content" style="border: red solid 1px;">
+ </div>
</div>
</body>
</html>
Added: trunk/src/ajax/javascripts/ajax_constants.js
==============================================================================
--- (empty file)
+++ trunk/src/ajax/javascripts/ajax_constants.js Wed Apr 1 05:41:52 2009
@@ -0,0 +1,11 @@
+var TIMEOUT = 5000; // const TIMEOUT = 5000 --> "const" doesn't work under IE
+var HOST_PREF = "http://localhost:8000/";
+var GET_PREFIX = HOST_PREF + "json/get/";
+var COMMIT_URL = HOST_PREF + "json/commit/";
+var ALL_PSIS_URL = HOST_PREF + "json/psis/";
+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"};
\ No newline at end of file
Added: trunk/src/ajax/javascripts/ajax_edit_topic.js
==============================================================================
--- (empty file)
+++ trunk/src/ajax/javascripts/ajax_edit_topic.js Wed Apr 1 05:41:52 2009
@@ -0,0 +1,4 @@
+function makeEdit(psi)
+{
+ alert("psi: " + psi);
+}
\ No newline at end of file
Added: trunk/src/ajax/javascripts/ajax_home.js
==============================================================================
--- (empty file)
+++ trunk/src/ajax/javascripts/ajax_home.js Wed Apr 1 05:41:52 2009
@@ -0,0 +1,258 @@
+// --- 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,
+ "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); },
+ "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)
+{
+ // --- 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 ? "topicTableSelectTop" : "topicTableSelectBottom"), "class" : "topicTable"});
+ var selectValues = new Array("5", "10", "15", "25", "50", "100", "200", "300", "All");
+ var selectInnerHTML = "";
+ selectValues.each(function(value, idx)
+ {
+ if(Number(value) !== __idx.getTopicsPerPage()){
+ select.insert(new Element("option", {"value" : (value === "All" ? -1 : value)}).update(value), {"position" : "bottom"});
+ }
+ else {
+ select.insert(new Element("option", {"value" : (value === "All" ? -1 : value), "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($("naviDivBottom") !== null)$("naviDivBottom").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));
+ });
+ }
+
+ 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));
+ });
+ }
+
+ 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);
+ 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));
+ });
+ }
+ });
+ }
+
+ 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));
+ });
+ }
+
+ 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));
+ });
+ }
+
+ 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
Added: trunk/src/ajax/javascripts/ajax_navi.js
==============================================================================
--- (empty file)
+++ trunk/src/ajax/javascripts/ajax_navi.js Wed Apr 1 05:41:52 2009
@@ -0,0 +1,49 @@
+// --- 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, ""); });
+
+ // --- necessary for the first call of the page
+ makePage(PAGES.home);
+}
+
+
+// --- generates the current page depending on the variable __currentPage
+function makePage(newPage, psi)
+{
+ // --- removes the old content
+ cleanPage(newPage);
+
+ // --- creates the new content
+ switch(newPage){
+ case PAGES.home:
+ makeHome("content", "topicTable", true);
+ break;
+ case PAGES.search:
+ break;
+ case PAGES.edit:
+ makeEdit(psi);
+ break;
+ case PAGES.create:
+ 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);
+
Modified: trunk/src/isidorus.asd
==============================================================================
--- trunk/src/isidorus.asd (original)
+++ trunk/src/isidorus.asd Wed Apr 1 05:41:52 2009
@@ -131,7 +131,18 @@
(:static-file "scriptaculous.js")
(:static-file "slider.js")
(:static-file "sound.js")
- (:static-file "unittest.js")))))
+ (:static-file "unittest.js")
+ (:static-file "ajax_constants.js")
+ (:static-file "ajax_home.js")
+ (:static-file "ajax_navi.js")
+ (:static-file "ajax_edit_topic.js")))
+ (:module "css"
+ :components ((:static-file "create_topics.css")
+ (:static-file "edit_topics.css")
+ (:static-file "home.css")
+ (:static-file "navi.css")
+ (:static-file "search_topics.css")
+ (:static-file "main.css")))))
)
;;(:module "threading"
;; :components ((:file "reader-writer"))))
Modified: trunk/src/json/json_exporter.lisp
==============================================================================
--- trunk/src/json/json_exporter.lisp (original)
+++ trunk/src/json/json_exporter.lisp Wed Apr 1 05:41:52 2009
@@ -1,14 +1,20 @@
(defpackage :json-exporter
(:use :cl :json :datamodel)
(:export :to-json-string
- :get-all-topic-psis))
+ :get-all-topic-psis
+ :to-json-string-summary
+ :make-topic-summary))
(in-package :json-exporter)
;; the json schema for our datamodel is in ".../docs/xtm_json.txt"
+
+;; =============================================================================
+;; --- main json data model ----------------------------------------------------
+;; =============================================================================
(defgeneric to-json-string (instance &key xtm-id)
- (:documentation "converts the Topic Maps construct instance to a json string"))
+ (:documentation "converts the Topic Map construct instance to a json string"))
(defun identifiers-to-json-string (parent-construct &key (what 'd:psis))
@@ -130,7 +136,7 @@
(defmethod to-json-string ((instance TopicC) &key (xtm-id d:*current-xtm*))
- "transforms an OccurrenceC object to a json string"
+ "transforms an TopicC object to a json string"
(let ((id
(concatenate 'string "\"id\":\"" (topicid instance) "\""))
(itemIdentity
@@ -272,6 +278,9 @@
(concatenate 'string "{" main-topic "," topicStubs "," associations "," tm-ids "}")))
+;; =============================================================================
+;; --- json data summeries -----------------------------------------------------
+;; =============================================================================
(defun get-all-topic-psis()
"returns all topic psis as a json list of the form
[[topic-1-psi-1, topic-1-psi-2],[topic-2-psi-1, topic-2-psi-2],...]"
@@ -279,4 +288,56 @@
(remove-if #'null (map 'list #'(lambda(psi-list)
(when psi-list
(map 'list #'uri psi-list)))
- (map 'list #'psis (elephant:get-instances-by-class 'TopicC))))))
\ No newline at end of file
+ (map 'list #'psis (elephant:get-instances-by-class 'TopicC))))))
+
+
+(defun to-json-string-summary (topic)
+ "creates a json string of called topic element. the following elements are within this
+ summary:
+ *topic id
+ *all identifiers
+ *names (only the real name value)
+ *occurrences (jonly the resourceRef and resourceData elements)"
+ (declare (TopicC topic))
+ (let ((id
+ (concatenate 'string "\"id\":\"" (topicid topic) "\""))
+ (itemIdentity
+ (concatenate 'string "\"itemIdentities\":"
+ (identifiers-to-json-string topic :what 'item-identifiers)))
+ (subjectLocator
+ (concatenate 'string "\"subjectLocators\":"
+ (identifiers-to-json-string topic :what 'locators)))
+ (subjectIdentifier
+ (concatenate 'string "\"subjectIdentifiers\":"
+ (identifiers-to-json-string topic :what 'psis)))
+ (instanceOf
+ (concatenate 'string "\"instanceOfs\":" (ref-topics-to-json-string (list-instanceOf topic))))
+ (name
+ (concatenate 'string "\"names\":"
+ (if (names topic)
+ (json:encode-json-to-string (loop for name in (names topic)
+ when (slot-boundp name 'charvalue)
+ collect (charvalue name)))
+ "null")))
+ (occurrence
+ (concatenate 'string "\"occurrences\":"
+ (if (occurrences topic)
+ (json:encode-json-to-string (loop for occurrence in (occurrences topic)
+ when (slot-boundp occurrence 'charvalue)
+ collect (charvalue occurrence)))
+ "null"))))
+ (concatenate 'string "{" id "," itemIdentity "," subjectLocator "," subjectIdentifier ","
+ instanceOf "," name "," occurrence "}")))
+
+
+(defun make-topic-summary (topic-list)
+ "creates a json list of the produced json-strings by to-json-string-summary"
+ (if topic-list
+ (let ((json-string
+ (let ((inner-string nil))
+ (concatenate 'string
+ (loop for topic in topic-list
+ do (setf inner-string (concatenate 'string inner-string (to-json-string-summary topic) ","))))
+ (subseq inner-string 0 (- (length inner-string) 1)))))
+ (concatenate 'string "[" json-string "]"))
+ "null"))
\ 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 Wed Apr 1 05:41:52 2009
@@ -19,6 +19,7 @@
:*json-get-prefix*
:*json-commit-url*
:*json-get-all-psis*
+ :*json-get-summary-prefix**
:*ajax-user-interface-url*
:*ajax-user-interface-file-path*
:*ajax-javascript-directory-path*
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 Wed Apr 1 05:41:52 2009
@@ -3,7 +3,10 @@
(defparameter *json-get-prefix* "/json/get/(.+)$") ;the prefix to get a fragment by the psis -> localhost:8000/json/get/<fragment-psi>
(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 *ajax-user-interface-url* "/isidorus/?$") ;the url to the user interface -> localhost:8000/isidorus
+(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 *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
(defparameter *ajax-user-interface-file-path* "ajax/isidorus.html") ;the file path to the HTML file implements the user interface
(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
@@ -12,19 +15,31 @@
(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*)
(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*)
+ (ajax-user-interface-css-directory-path *ajax-user-interface-css-directory-path*)
(ajax-javascripts-directory-path *ajax-javascript-directory-path*)
(ajax-javascripts-url-prefix *ajax-javascript-url-prefix*))
"registers the json im/exporter to the passed base-url in hunchentoot's dispatch-table
and also registers a file-hanlder to the html-user-interface"
- (declare (string json-get-prefix json-get-all-psis json-commit-url ajax-user-interface-url ajax-user-interface-file-path))
+ ;; === html and css files ====================================================
(push
(create-regex-dispatcher ajax-user-interface-url
#'(lambda()
(hunchentoot:handle-static-file ajax-user-interface-file-path "text/html")))
hunchentoot:*dispatch-table*)
- ;; === ajax frameworks =======================================================
+
+ (dolist (script-path-and-url (make-file-path-and-url ajax-user-interface-css-directory-path ajax-user-interface-css-prefix))
+ (let ((script-path (getf script-path-and-url :path))
+ (script-url (getf script-path-and-url :url)))
+ (push (create-regex-dispatcher script-url
+ #'(lambda()
+ (hunchentoot:handle-static-file script-path))); "text/javascript")))
+ hunchentoot:*dispatch-table*)))
+
+ ;; === ajax frameworks and javascript files ==================================
(dolist (script-path-and-url (make-file-path-and-url ajax-javascripts-directory-path ajax-javascripts-url-prefix))
(let ((script-path (getf script-path-and-url :path))
(script-url (getf script-path-and-url :url)))
@@ -32,7 +47,8 @@
#'(lambda()
(hunchentoot:handle-static-file script-path))); "text/javascript")))
hunchentoot:*dispatch-table*)))
- ;; === ajax frameworks end ===================================================
+
+ ;; === rest interface ========================================================
(push
(create-regex-dispatcher json-get-all-psis #'return-all-topic-psis)
hunchentoot:*dispatch-table*)
@@ -41,6 +57,9 @@
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*))
@@ -101,15 +120,54 @@
(setf (hunchentoot:return-code*) hunchentoot:+http-bad-request+))))
-(defun make-file-path-and-url (path-to-javascripts url-prefix)
+(defun return-topic-summaries(&optional param)
+ "returns a summary of the requested topics"
+ (declare (ignorable param))
+ (let ((start-idx
+ (handler-case (parse-integer (hunchentoot:get-parameter "start"))
+ (condition () 0)))
+ (end-idx
+ (handler-case (parse-integer (hunchentoot:get-parameter "end"))
+ (condition () nil))))
+
+ (let ((topics (elephant:get-instances-by-class 'd:TopicC)))
+ (let ((end
+ (cond
+ ((not end-idx)
+ (length topics))
+ ((> end-idx (length topics))
+ (length topics))
+ ((< end-idx 0)
+ 0)
+ (t
+ end-idx))))
+ (let ((start
+ (cond
+ ((> start-idx (length topics))
+ end)
+ ((< start-idx 0)
+ 0)
+ (t
+ start-idx))))
+ (let ((topics-in-range
+ (if (<= start end)
+ (subseq topics start end)
+ (reverse (subseq topics end start)))))
+ (setf (hunchentoot:content-type*) "application/json") ;RFC 4627
+ (json-exporter:make-topic-summary topics-in-range)))))))
+
+
+;; =============================================================================
+;; --- some helper functions ---------------------------------------------------
+;; =============================================================================
+(defun make-file-path-and-url (path-to-files-directory url-prefix)
"returns a list of lists which contains an absolute file path and a file-url
concatenated of the url-prefix and the relative path of all all files in the
passed directory and its subdirectories"
- (declare (string path-to-javascripts url-prefix))
(let ((start-position-of-relative-path
- (- (length (write-to-string (com.gigamonkeys.pathnames:file-exists-p path-to-javascripts))) 2)))
+ (- (length (write-to-string (com.gigamonkeys.pathnames:file-exists-p path-to-files-directory))) 2)))
(let ((files-and-urls nil))
- (com.gigamonkeys.pathnames:walk-directory path-to-javascripts
+ (com.gigamonkeys.pathnames:walk-directory path-to-files-directory
#'(lambda(current-path)
(let ((current-path-string
(write-to-string current-path)))
1
0