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 --------------------------------------------------- ;; =============================================================================