Author: lgiessmann
Date: Thu Apr 15 13:52:44 2010
New Revision: 279
Log:
docs: fixed some bad ebnf definitions of the json interface; json: currently only active topics are exported, mark-as-deleted topics are not exported; ajax: added the possibility that the ui is able to mark topics, names and occurrences as deleted ---> at the moment there is a problem when recreating occurrences and names that have already existed
Modified:
trunk/docs/json.ebnf
trunk/docs/xtm_json.txt
trunk/src/ajax/css/frame.css
trunk/src/ajax/javascripts/constants.js
trunk/src/ajax/javascripts/datamodel.js
trunk/src/ajax/javascripts/requests.js
trunk/src/json/json_exporter.lisp
trunk/src/json/json_importer.lisp
trunk/src/json/json_tmcl.lisp
trunk/src/json/json_tmcl_validation.lisp
trunk/src/rest_interface/set-up-json-interface.lisp
Modified: trunk/docs/json.ebnf
==============================================================================
--- trunk/docs/json.ebnf (original)
+++ trunk/docs/json.ebnf Thu Apr 15 13:52:44 2010
@@ -194,12 +194,12 @@
DeleteType = "\"type\":" ("Topic" | "Occurrence" | "Name" | "Association" | "Role" | "Variant")
DeleteTopics = "\"topics\":" List
DeleteAssociations = "\"associations\":" Associations
-DeleteParentTopic = "\"parent-topic\":" String
-DeleteParentName = "\"parent-name\":" Name
+DeleteParentTopic = "\"parentTopic\":" String
+DeleteParentName = "\"parentName\":" Name
DeleteNames = "\"names\":" Names
DeleteVariants = "\"variants\":" Variants
DeleteOccurrences = "\"occurrences\":" Occurrences
-DeleteParentAssociation = "\"parent-association\":" Association
+DeleteParentAssociation = "\"parentAssociation\":" Association
DeleteRoles = "\"roles\":" Roles
DeleteObject = "{" DeleteType "," DeleteTopics "," DeleteAssociations ","
Modified: trunk/docs/xtm_json.txt
==============================================================================
--- trunk/docs/xtm_json.txt (original)
+++ trunk/docs/xtm_json.txt Thu Apr 15 13:52:44 2010
@@ -467,11 +467,11 @@
"type":<"Topic" | "Occurrence" | "Name" | "Association" | "Role" | "Variant" >,
"topics": [<psi-top-1>, <psi-top-2>, <...>],
"associations": [<association-1>, <association-2>, <...>],
- "parent-topic": "topic-psi",
- "parent-name": <name>,
+ "parentTopic": "topic-psi",
+ "parentName": <name>,
"names": [<name-1>, <name-2>, <...>],
"variants": [<variant-1>, <variant-2>, <...>],
"occurrences": [<occurrence-1>, <occurrence-2>, <...>],
- "parent-association": <association>,
+ "parentAssociation": <association>,
"roles": [<role-1>, <role-2>, <...>]
}
Modified: trunk/src/ajax/css/frame.css
==============================================================================
--- trunk/src/ajax/css/frame.css (original)
+++ trunk/src/ajax/css/frame.css Thu Apr 15 13:52:44 2010
@@ -27,6 +27,18 @@
background-color: #eaeaee;
}
+tr.removeNameRow {
+ background-color: #eaeaee;
+}
+
+tr.removeOccurrenceRow {
+ background-color: #eaeaee;
+}
+
+tr.removeTopicRow {
+ background-color: #eaeaee;
+}
+
li.errorMessage {
margin-top: 1em;
font-size: 1.2em;
@@ -139,6 +151,17 @@
margin-top: 1px;
}
+span.removeLink {
+ cursor: pointer;
+ font-size: 0.75em;
+ float: right;
+ margin-right: 1em;
+}
+
+span.removeLink:hover {
+ color:#ff7f00;
+}
+
/* === topic frame ========================================================== */
table.topicFrame {
Modified: trunk/src/ajax/javascripts/constants.js
==============================================================================
--- trunk/src/ajax/javascripts/constants.js (original)
+++ trunk/src/ajax/javascripts/constants.js Thu Apr 15 13:52:44 2010
@@ -22,6 +22,7 @@
var INSTANCE_PSIS_URL = HOST_PREF + "json/tmcl/instances/";
var OWN_URL = HOST_PREF + "isidorus";
var SUMMARY_URL = HOST_PREF + "json/summary"
+ var MARK_AS_DELETED_URL = HOST_PREF + "mark-as-deleted";
var TM_OVERVIEW = "/json/tmcl/overview/";
var TIMEOUT = 10000; // const TIMEOUT = 10000 --> "const" doesn't work under IE
@@ -89,5 +90,9 @@
"treeView" : function(){ return "treeView"; },
"instances" : function(){ return "instances"; },
"subtypes" : function(){ return "subtypes"; },
- "topicPsis" : function(){ return "topicPsis"; }
+ "topicPsis" : function(){ return "topicPsis"; },
+ "removeLink" : function(){ return "removeLink"; },
+ "removeNameRow" : function(){ return "removeOccurrenceRow"; },
+ "removeOccurrenceRow" : function(){ return "removeNameRow"; },
+ "removeTopicRow" : function(){ return "removeTopicRow"; }
};
\ No newline at end of file
Modified: trunk/src/ajax/javascripts/datamodel.js
==============================================================================
--- trunk/src/ajax/javascripts/datamodel.js (original)
+++ trunk/src/ajax/javascripts/datamodel.js Thu Apr 15 13:52:44 2010
@@ -1447,6 +1447,11 @@
dblClickHandler(owner, event);
});
}
+
+ var myself = this;
+ this.__table__.insert({"bottom" : makeRemoveLink(function(event){
+ makeDeleteObject("Name", myself);
+ }, "delete Name")});
}
catch(err){
alert("From NameC(): " + err);
@@ -1491,6 +1496,7 @@
this.getFrame().select("tr." + CLASSES.scopeContainer())[0].hide();
this.getFrame().select("tr." + CLASSES.valueFrame())[0].hide();
this.getFrame().select("tr." + CLASSES.variantContainer())[0].hide();
+ this.getFrame().select("tr." + CLASSES.removeNameRow())[0].hide();
this.__isMinimized__ = true;
}
else {
@@ -1500,6 +1506,7 @@
this.getFrame().select("tr." + CLASSES.scopeContainer())[0].show();
this.getFrame().select("tr." + CLASSES.valueFrame())[0].show();
this.getFrame().select("tr." + CLASSES.variantContainer())[0].show();
+ this.getFrame().select("tr." + CLASSES.removeNameRow())[0].show();
this.__isMinimized__ = false;
}
},
@@ -1512,6 +1519,7 @@
this.__variants__.disable();
this.getFrame().writeAttribute({"class" : CLASSES.disabled()});
this.getFrame().writeAttribute({"title" : this.__cssTitle__});
+ this.getFrame().select("tr." + CLASSES.removeNameRow())[0].disable();
this.hideAddButton();
this.__disabled__ = true;
},
@@ -1523,6 +1531,7 @@
this.__variants__.enable();
this.getFrame().writeAttribute({"class" : CLASSES.nameFrame()});
this.getFrame().removeAttribute("title");
+ this.getFrame().select("tr." + CLASSES.removeNameRow())[0].enable();
checkRemoveAddButtons(this.__owner__, 1, this.__max__, this);
this.__disabled__ = false;
}});
@@ -1742,6 +1751,92 @@
}});
+function makeRemoveLink (removeHandler, textContent){
+ var link = new Element("span", {"class" : CLASSES.removeLink()}).update(textContent);
+ var trClass = null;
+ switch(textContent){
+ case "delete Occurrence" : trClass = CLASSES.removeOccurrenceRow(); break;
+ case "delete Topic" : trClass = CLASSES.removeTopicRow(); break;
+ case "delete Name" : trClass = CLASSES.removeNameRow(); break;
+ }
+
+ var tr = new Element("tr", {"class" : trClass}).insert(new Element("td", {"colspan" : 3}).insert(link));
+ if(removeHandler){ link.observe("click", removeHandler); }
+ return tr;
+}
+
+
+function makeDeleteObject(type, objectToDelete){
+ if(type !== "Occurrence" && type !== "Name" && type !== "Variant"
+ && type !== "Topic" && type !== "Association"){
+ throw "From makeDeleteObject(): type must be: \"Occurrence\" || \"Name\" " +
+ "|| \"Variant\" || \"Topic\" || \"Association\" but is " + type;
+ }
+ if (!objectToDelete){
+ throw "From makeDeleteObject(): objectToDelete must be set";
+ }
+
+ var parentTopic = "null";
+ if(type === "Occurrence" || type === "Name"){
+ var psiFrame = objectToDelete.getFrame().parentNode.parentNode.parentNode.parentNode.select("tr." + CLASSES.subjectIdentifierFrame())[0];
+ var psiFields = psiFrame.select("input");
+ for(i = 0; psiFields && i !== psiFields.length; ++i){
+ var psiValue = psiFields[i].value;
+ if(psiValue.strip().length !== 0){
+ parentTopic = psiValue.strip().toJSON();
+ break;
+ }
+ }
+ }
+
+ var topics = "null";
+ if (type === "Topic"){
+ var psiFrame = objectToDelete.getFrame().select("tr." + CLASSES.subjectIdentifierFrame())[0];
+ var psiFields = psiFrame.select("input");
+ for(i = 0; psiFields && i !== psiFields.length; ++i){
+ var psiValue = psiFields[i].value;
+ if(psiValue.strip().length !== 0){
+ topics = new Array(psiValue.strip()).toJSON();
+ break;
+ }
+ }
+ }
+
+ var deletedObjects = null;
+ if(type === "Topic"){ deletedObjects = topics; }
+ else { deletedObjects = "[" + objectToDelete.toJSON() + "]"; }
+
+ var jsonData = "{\"type\":\"" + type + "\"," +
+ "\"topics\":" + topics + "," +
+ "\"associations\":" + "null" + "," +
+ "\"parentTopic\":" + parentTopic + "," +
+ "\"parentName\":" + "null" + "," +
+ "\"names\":" + (type === "Name" ? deletedObjects : "null") + "," +
+ "\"variants\":" + "null" + "," +
+ "\"occurrences\":" + (type === "Occurrence" ? deletedObjects : "null") + "," +
+ "\"parentAssociation\":" + "null" + "," +
+ "\"roles\":" + "null" + "}";
+
+ commitDeletedObject(jsonData, function(xhr){
+ alert("Objected deleted");
+ if(type === "Topic"){
+ $(CLASSES.subPage()).update();
+ makeHome();
+ }
+ else if (type === "Occurrence" || type === "Name"){
+ if(objectToDelete.__owner__.__frames__.length > objectToDelete.__max__
+ && objectToDelete.__owner__.__frames__.length > 1){
+ objectToDelete.remove();
+ }
+ else {
+ if(type === "Occurrence"){ objectToDelete.__value__.setValue(""); }
+ else { objectToDelete.__value__.__frames__[0].__content__.setValue(""); }
+ }
+ }
+ });
+
+}
+
// --- represenation of an occurrence element
var OccurrenceC = Class.create(ContainerC, {"initialize" : function($super, contents, occurrenceTypes, constraint, uniqueConstraints, owner, min, max, cssTitle, dblClickHandler){
$super();
@@ -1826,6 +1921,10 @@
dblClickHandler(owner, event);
});
}
+ var myself = this;
+ this.__table__.insert({"bottom" : makeRemoveLink(function(event){
+ makeDeleteObject("Occurrence", myself);
+ }, "delete Occurrence")});
}
catch(err){
alert("From OccurrenceC(): " + err);
@@ -1894,6 +1993,7 @@
this.getFrame().select("tr." + CLASSES.scopeContainer())[0].hide();
this.getFrame().select("tr." + CLASSES.valueFrame())[0].hide();
this.getFrame().select("tr." + CLASSES.datatypeFrame())[0].hide();
+ this.getFrame().select("tr." + CLASSES.removeOccurrenceRow())[0].hide();
this.__isMinimized__ = true;
}
else {
@@ -1903,6 +2003,9 @@
this.getFrame().select("tr." + CLASSES.scopeContainer())[0].show();
this.getFrame().select("tr." + CLASSES.valueFrame())[0].show();
this.getFrame().select("tr." + CLASSES.datatypeFrame())[0].show();
+ if(this.__disabled__ === false){
+ this.getFrame().select("tr." + CLASSES.removeOccurrenceRow())[0].show();
+ }
this.__isMinimized__ = false;
}
},
@@ -1916,6 +2019,7 @@
this.getFrame().writeAttribute({"class" : CLASSES.disabled()});
this.getFrame().writeAttribute({"title" : this.__cssTitle__});
this.hideAddButton();
+ this.getFrame().select("tr." + CLASSES.removeOccurrenceRow())[0].hide();
this.__disabled__ = true;
},
"enable" : function(){
@@ -1928,6 +2032,7 @@
this.getFrame().removeAttribute("style");
this.getFrame().removeAttribute("title");
checkRemoveAddButtons(this.__owner__, 1, this.__max__, this);
+ this.getFrame().select("tr." + CLASSES.removeOccurrenceRow())[0].show();
this.__disabled__ = false;
}});
@@ -2222,6 +2327,11 @@
_constraints = (constraints ? constraints.topicOccurrenceConstraints : null);
this.__occurrence__ = new OccurrenceContainerC(occurrencesContent, _constraints);
this.__table__.insert({"bottom" : newRow(CLASSES.occurrenceContainer(), "Occurrences", this.__occurrence__.getFrame())});
+
+ var myself = this;
+ this.__table__.insert({"bottom" : makeRemoveLink(function(event){
+ makeDeleteObject("Topic", myself);
+ }, "delete Topic")});
}catch(err){
alert("From TopciC(): " + err);
}
@@ -2261,7 +2371,8 @@
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]);
+ this.getFrame().select("tr." + CLASSES.occurrenceContainer())[0],
+ this.getFrame().select("tr." + CLASSES.removeTopicRow())[0]);
for(var i = 0; i != rows.length; ++i){
if(this.__minimized__ === false) rows[i].hide();
else rows[i].show();
Modified: trunk/src/ajax/javascripts/requests.js
==============================================================================
--- trunk/src/ajax/javascripts/requests.js (original)
+++ trunk/src/ajax/javascripts/requests.js Thu Apr 15 13:52:44 2010
@@ -219,6 +219,27 @@
}
+// --- Sends a POST-Message to the server. The sent message enables the server
+// --- to find the spcified object and mark it as deleted
+function commitDeletedObject(json, onSuccessHandler, onFailureHandler)
+{
+ if(!json || !onSuccessHandler) throw "From commitDeletedObject(): json and onSuccessHandler must be set!";
+ try{
+ var onFailure = onFailureHandler ? onFailureHandler : defaultFailureHandler;
+ var timeFun = setAjaxTimeout(TIMEOUT, COMMIT_URL);
+
+ new Ajax.Request(MARK_AS_DELETED_URL, {
+ "method" : "post",
+ "postBody" : json,
+ "onSuccess" : createXHRHandler(onSuccessHandler, timeFun),
+ "onFailure" : createXHRHandler(onFailure, timeFun)});
+ }
+ catch(err){
+ alert("From commitDeletedObject(): " + err);
+ }
+}
+
+
// --- Requests a JSON-Fragment for the passed psi and calls the onSuccessHandler function
// --- after a succeeded request.
function requestFragment(psi, onSuccessHandler, onFailureHandler)
Modified: trunk/src/json/json_exporter.lisp
==============================================================================
--- trunk/src/json/json_exporter.lisp (original)
+++ trunk/src/json/json_exporter.lisp Thu Apr 15 13:52:44 2010
@@ -8,7 +8,7 @@
(defpackage :json-exporter
- (:use :cl :json :datamodel)
+ (:use :cl :json :datamodel :json-tmcl-constants)
(:export :to-json-string
:get-all-topic-psis
:to-json-string-summary
@@ -298,7 +298,8 @@
(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))))))
+ (json-tmcl::clean-topics
+ (elephant:get-instances-by-class 'TopicC))))))
(defun to-json-string-summary (topic)
@@ -350,4 +351,14 @@
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
+ "null"))
+
+
+(defun clean-topics(isas-or-akos)
+ (remove-if
+ #'null
+ (map 'list
+ #'(lambda(top)
+ (when (d:find-item-by-revision top 0)
+ top))
+ isas-or-akos)))
\ No newline at end of file
Modified: trunk/src/json/json_importer.lisp
==============================================================================
--- trunk/src/json/json_importer.lisp (original)
+++ trunk/src/json/json_importer.lisp Thu Apr 15 13:52:44 2010
@@ -362,7 +362,7 @@
(setf tm-ids (cdr j-elem)))
(t
(error "json-importer:get-fragment-values-from-json-string:
- bad item-specifier found in json-list"))))
+ bad item-specifier found in json-list (~a)" (car j-elem)))))
(unless topic
(error "json-importer:get-fragment-values-from-json-string: the element topic must be set"))
(unless (= (length tm-ids) 1)
Modified: trunk/src/json/json_tmcl.lisp
==============================================================================
--- trunk/src/json/json_tmcl.lisp (original)
+++ trunk/src/json/json_tmcl.lisp Thu Apr 15 13:52:44 2010
@@ -179,7 +179,7 @@
(defun delete-names-from-json (names parent-psi revision)
(declare (list names) (string parent-psi) (integer revision))
(let ((parent-topic (d:get-item-by-psi parent-psi))
- (err "From delete-name-from-json(): "))
+ (err "From delete-names-from-json(): "))
(unless parent-topic
(error "~a~a not found"
err parent-psi))
@@ -235,7 +235,7 @@
(defun delete-occurrences-from-json(occurrences parent-psi revision)
(declare (list occurrences) (string parent-psi) (integer revision))
(let ((parent-topic (d:get-item-by-psi parent-psi))
- (err "From delete-occurrence-from-json(): "))
+ (err "From delete-occurrences-from-json(): "))
(unless parent-topic
(error "~a~a not found" err parent-psi))
(dolist (j-occ occurrences)
@@ -284,7 +284,7 @@
(declare (list associations) (integer revision))
(dolist (j-assoc associations)
(let ((plist (json-importer::get-association-values-from-json-list j-assoc))
- (err "From delete-association-from-json(): "))
+ (err "From delete-associations-from-json(): "))
(let ((assoc (find-association-from-json plist)))
(unless assoc
(error "~a ~a not found" err plist))
@@ -297,7 +297,7 @@
(dolist (uri topics)
(let ((psi (elephant:get-instance-by-value 'd:PersistentIdC 'd:uri uri)))
(unless psi
- (error "From delete-topic-from-json(): PSI ~a not found" uri))
+ (error "From delete-topics-from-json(): PSI ~a not found" uri))
(pushnew psi psis)))
(let ((tops
(remove-duplicates
@@ -1573,33 +1573,9 @@
t))
(get-direct-subtypes-of-topic topic-instance)))))))
(let ((cleaned-isas ;;all constraint topics are removed
- (remove-if #'null (map 'list #'(lambda(top-entry)
- (when (find-if #'(lambda(psi)
- (unless (or (string= (uri psi) *constraint-psi*)
- (string= (uri psi) *occurrencetype-psi*)
- (string= (uri psi) *nametype-psi*)
- (string= (uri psi) *associationtype-psi*)
- (string= (uri psi) *roletype-psi*)
- (string= (uri psi) *scopetype-psi*)
- (string= (uri psi) *schema-psi*))
- top-entry))
- (psis (getf top-entry :topic)))
- top-entry))
- isas-of-this)))
+ (clean-topic-entries isas-of-this))
(cleaned-akos ;;all constraint topics are removed
- (remove-if #'null (map 'list #'(lambda(top-entry)
- (when (find-if #'(lambda(psi)
- (unless (or (string= (uri psi) *constraint-psi*)
- (string= (uri psi) *occurrencetype-psi*)
- (string= (uri psi) *nametype-psi*)
- (string= (uri psi) *associationtype-psi*)
- (string= (uri psi) *roletype-psi*)
- (string= (uri psi) *scopetype-psi*)
- (string= (uri psi) *schema-psi*))
- top-entry))
- (psis (getf top-entry :topic)))
- top-entry))
- akos-of-this))))
+ (clean-topic-entries akos-of-this)))
(list :topic topic-instance
:is-type is-type
:is-instance is-instance
@@ -1610,12 +1586,37 @@
(make-nodes (getf x :topic) (getf x :is-type) (getf x :is-instance)))
cleaned-akos))))))
+(defun clean-topic-entries(isas-or-akos)
+ (remove-if
+ #'null
+ (map 'list
+ #'(lambda(top-entry)
+ (when (and (d:find-item-by-revision (getf top-entry :topic) 0)
+ (find-if
+ #'(lambda(psi)
+ (unless (or (string= (uri psi) *constraint-psi*)
+ (string= (uri psi) *occurrencetype-psi*)
+ (string= (uri psi) *nametype-psi*)
+ (string= (uri psi) *associationtype-psi*)
+ (string= (uri psi) *roletype-psi*)
+ (string= (uri psi) *scopetype-psi*)
+ (string= (uri psi) *schema-psi*))
+ top-entry))
+ (psis (getf top-entry :topic))))
+ top-entry))
+ isas-or-akos)))
+
(defun get-all-tree-roots ()
"Returns all topics that are no instanceOf and no subtype
of any other topic."
(let ((all-topics
- (elephant:get-instances-by-class 'd:TopicC)))
+ (remove-if #'null
+ (map 'list
+ #'(lambda(top)
+ (when (d:find-item-by-revision top 0)
+ top))
+ (elephant:get-instances-by-class 'd:TopicC)))))
(remove-if #'null
(map 'list #'(lambda(x)
(let ((isas-of-x
Modified: trunk/src/json/json_tmcl_validation.lisp
==============================================================================
--- trunk/src/json/json_tmcl_validation.lisp (original)
+++ trunk/src/json/json_tmcl_validation.lisp Thu Apr 15 13:52:44 2010
@@ -375,7 +375,8 @@
(defun return-all-tmcl-types ()
"Returns all topics that are valid tmcl-types"
(let ((all-topics
- (elephant:get-instances-by-class 'd:TopicC))
+ (json-exporter::clean-topics
+ (elephant:get-instances-by-class 'd:TopicC)))
(topictype (get-item-by-psi json-tmcl-constants::*topictype-psi*))
(topictype-constraint (is-type-constrained)))
(let ((all-types
@@ -399,7 +400,8 @@
The validity is only oriented on the typing of topics, e.g.
type-instance or supertype-subtype."
(let ((all-topics
- (elephant:get-instances-by-class 'd:TopicC)))
+ (json-exporter::clean-topics
+ (elephant:get-instances-by-class 'd:TopicC))))
(let ((valid-instances
(remove-if #'null
(map 'list #'(lambda(x)
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 Thu Apr 15 13:52:44 2010
@@ -115,7 +115,7 @@
(create-regex-dispatcher json-get-summary-url #'return-topic-summaries)
hunchentoot:*dispatch-table*)
(push
- (create-regex-dispatcher mark-as-deleted-url #'mark-as-deleted)
+ (create-regex-dispatcher mark-as-deleted-url #'mark-as-deleted-handler)
hunchentoot:*dispatch-table*))
;; =============================================================================
@@ -302,7 +302,12 @@
(condition () nil))))
(handler-case (with-reader-lock
(let ((topics
- (elephant:get-instances-by-class 'd:TopicC)))
+ (remove-if
+ #'null
+ (map 'list #'(lambda(top)
+ (when (d:find-item-by-revision top 0)
+ top))
+ (elephant:get-instances-by-class 'd:TopicC)))))
(let ((end
(cond
((not end-idx)
@@ -372,6 +377,7 @@
(format nil "Condition: \"~a\"" err))))))
(setf (hunchentoot:return-code*) hunchentoot:+http-bad-request+))))
+
;; =============================================================================
;; --- some helper functions ---------------------------------------------------
;; =============================================================================