From 33009ef6ad77597f326f72e4c678c7032ea968a2 Mon Sep 17 00:00:00 2001 From: Derrell Lipman Date: Fri, 5 Jan 2007 21:42:49 +0000 Subject: r20574: reorganization of common modules (This used to be commit 5075e008941177d5be1d9471387c9d27aba65f81) --- .../swat/source/class/swat/main/AbstractModule.js | 172 ++++++++ .../source/class/swat/main/AbstractModuleFsm.js | 455 +++++++++++++++++++++ webapps/swat/source/class/swat/main/Gui.js | 2 +- webapps/swat/source/class/swat/main/Main.js | 16 +- webapps/swat/source/class/swat/main/Module.js | 74 ++++ .../source/class/swat/module/AbstractModule.js | 172 -------- .../source/class/swat/module/AbstractModuleFsm.js | 455 --------------------- webapps/swat/source/class/swat/module/Module.js | 74 ---- .../swat/module/documentation/Documentation.js | 6 +- .../source/class/swat/module/documentation/Fsm.js | 6 +- .../swat/source/class/swat/module/ldbbrowse/Fsm.js | 10 +- .../swat/source/class/swat/module/ldbbrowse/Gui.js | 4 +- .../class/swat/module/ldbbrowse/LdbBrowse.js | 6 +- .../source/class/swat/module/statistics/Fsm.js | 8 +- .../source/class/swat/module/statistics/Gui.js | 2 +- .../class/swat/module/statistics/Statistics.js | 6 +- 16 files changed, 734 insertions(+), 734 deletions(-) create mode 100644 webapps/swat/source/class/swat/main/AbstractModule.js create mode 100644 webapps/swat/source/class/swat/main/AbstractModuleFsm.js create mode 100644 webapps/swat/source/class/swat/main/Module.js delete mode 100644 webapps/swat/source/class/swat/module/AbstractModule.js delete mode 100644 webapps/swat/source/class/swat/module/AbstractModuleFsm.js delete mode 100644 webapps/swat/source/class/swat/module/Module.js (limited to 'webapps') diff --git a/webapps/swat/source/class/swat/main/AbstractModule.js b/webapps/swat/source/class/swat/main/AbstractModule.js new file mode 100644 index 0000000000..4533f3d8c6 --- /dev/null +++ b/webapps/swat/source/class/swat/main/AbstractModule.js @@ -0,0 +1,172 @@ +/* + * Copyright: + * (C) 2006 by Derrell Lipman + * All rights reserved + * + * License: + * LGPL 2.1: http://creativecommons.org/licenses/LGPL/2.1/ + */ + +/** + * Abstract Module class. All modules should extend this class. + */ +qx.OO.defineClass("swat.main.AbstractModule", qx.core.Object, +function() +{ + qx.core.Object.call(this); + this.debug("AbstractModule constructor"); +}); + + +/** + * Build the initial finite state machine. + * + * In order to prevent long load times, as minimal as possible of an initial + * FSM should be created. The FSM will receive an "appear" event when the + * module is first selected (and each subsequent time), and the FSM can use + * that event to build the complete FSM. + * + * @param module {swat.main.Module} + * The module descriptor for the module. + */ +qx.Proto.buildInitialFsm = function(module) +{ + // Create a new finite state machine + var fsm = new qx.util.fsm.FiniteStateMachine(module.name); + + // For this simple example application, show all debug messages. + qx.Settings.setCustomOfClass( + "qx.util.fsm.FiniteStateMachine", + "debugFlags", + (qx.util.fsm.FiniteStateMachine.DebugFlags.EVENTS | + qx.util.fsm.FiniteStateMachine.DebugFlags.TRANSITIONS | + qx.util.fsm.FiniteStateMachine.DebugFlags.FUNCTION_DETAIL | + qx.util.fsm.FiniteStateMachine.DebugFlags.OBJECT_NOT_FOUND)); + + /* + * State: Idle + * + * Transition on: + * "appear" on swat.main.canvas + */ + var state = new qx.util.fsm.State( + "State_Idle", + { + "events" : + { + // When we get an appear event the first time, run the transition + // that will load the module's finite state machine and graphical + // user interface. + "appear" : + { + "swat.main.canvas" : + "Transition_Idle_to_Idle_Load_Gui" + } + } + }); + fsm.addState(state); + + /* + * Transition: Idle to (replaced) Idle + * + * Cause: "appear" on canvas for the first time + * + * Action: + * Load module's finite state machine and graphical user interface + */ + var thisModule = this; + var trans = new qx.util.fsm.Transition( + "Transition_Idle_to_Idle_Load_Gui", + { + "nextState" : + qx.util.fsm.FiniteStateMachine.StateChange.CURRENT_STATE, + + "ontransition" : + function(fsm, event) + { + // Make the "Loading" message go away. (We need to learn how to + // remove it entirely. Just doing canvas.removeAll() leaves + // something in the widget queue and we get spurious error + // messages.) + var children = module.canvas.getVisibleChildren(); + for (var child in children) + { + children[child].hide(); + } + + // Call the module's initialAppear function to build FSM and GUI. + // That function should *replace* this state, State_Idle, to which + // we'll transition. + thisModule.initialAppear(module); + } + }); + state.addTransition(trans); + + // Save the finite state machine for this module + module.fsm = fsm; + + // Save the module descriptor in the finite state machine + fsm.addObject("swat.main.module", module); + + // Create an RPC object for use by this module + module.rpc = new qx.io.remote.Rpc(); + module.rpc.setUrl("/services/"); + module.rpc.setTimeout(10000); + module.rpc.setCrossDomain(false); + module.rpc.addEventListener("completed", fsm.eventListener, fsm); + module.rpc.addEventListener("failed", fsm.eventListener, fsm); + module.rpc.addEventListener("timeout", fsm.eventListener, fsm); + module.rpc.addEventListener("aborted", fsm.eventListener, fsm); + fsm.addObject("swat.main.rpc", module.rpc); + + // Start the finite state machine + fsm.start(); +}; + +/** + * Build the initial graphical user interface. + * + * In order to prevent long load times, as minimal as possible of an initial + * GUI should be created. Generally, this is just a "Loading..." message. + * + * @param module {Object} + * An object containing at least the following properties: + * fsm - + * The finite state machine for this module. It should be filled in + * by this function. + * canvas - + * The canvas on which to create the gui for this module + * name - + * The name of this module + * class - + * The class for this module + * + */ +qx.Proto.buildInitialGui = function(module) +{ + // For now, just create the "Loading" text + var o = new qx.ui.basic.Label("Loading module '" + module.name + "'..."); + o.set({ + top: 12, + left: 20 + }); + o.setFont("bold"); + module.canvas.add(o); +}; + +qx.Proto.finalize = function(module) +{ + this.debug("AbstractModule.finalize()"); +}; + + +/* +--------------------------------------------------------------------------- + DEFER SINGLETON INSTANCE +--------------------------------------------------------------------------- +*/ + +/** + * Singleton Instance Getter + */ +qx.Class.getInstance = qx.util.Return.returnInstance; diff --git a/webapps/swat/source/class/swat/main/AbstractModuleFsm.js b/webapps/swat/source/class/swat/main/AbstractModuleFsm.js new file mode 100644 index 0000000000..49222d90d4 --- /dev/null +++ b/webapps/swat/source/class/swat/main/AbstractModuleFsm.js @@ -0,0 +1,455 @@ +/* + * Copyright: + * (C) 2006 by Derrell Lipman + * All rights reserved + * + * License: + * LGPL 2.1: http://creativecommons.org/licenses/LGPL/2.1/ + */ + +/** + * Common facilities for modules' finite state machines. Each module's FSM + * should extend this class. + */ +qx.OO.defineClass("swat.main.AbstractModuleFsm", qx.core.Object, function() +{ + qx.core.Object.call(this); + + // Create an array for pushing request objects + this._requests = [ ]; +}); + + +qx.Proto.buildFsm = function(module) +{ + throw new Error("Module must overload buildFsm() " + + "to build its custom finite state machine."); +}; + +qx.Proto.addAwaitRpcResultState = function(module) +{ + var fsm = module.fsm; + var _this = this; + + /* + * State: AwaitRpcResult + * + * Actions upon entry: + * - enable any objects in group "swat.main.fsmUtils.enable_during_rpc" + * - disable any objects in group "swat.main.fsmUtils.disable_during_rpc" + * + * Actions upon exit: + * - disable any objects in group "swat.main.fsmUtils.enable_during_rpc" + * - enable any objects in group "swat.main.fsmUtils.disable_during_rpc" + * + * Transition on: + * "completed" (on RPC) + * "failed" (on RPC) + * "execute" on swat.main.fsmUtils.abort_rpc + */ + var state = new qx.util.fsm.State( + "State_AwaitRpcResult", + { + "autoActionsBeforeOnentry" : + { + // The name of a function. + "setEnabled" : + [ + { + // We want to enable objects in the group + // swat.main.fsmUtils.enable_during_rpc + "parameters" : [ true ], + + // Call this.getObject().setEnabled(true) on + // state entry, for each in the group called + // "swat.main.fsmUtils.enable_during_rpc". + "groups" : [ "swat.main.fsmUtils.enable_during_rpc" ] + }, + + { + // We want to disable objects in the group + // swat.main.fsmUtils.disable_during_rpc + "parameters" : [ false ], + + // Call this.getObject().setEnabled(false) on + // state entry, for each in the group called + // "swat.main.fsmUtils.disable_during_rpc". + "groups" : [ "swat.main.fsmUtils.disable_during_rpc" ] + } + ] + }, + + "autoActionsBeforeOnexit" : + { + // The name of a function. + "setEnabled" : + [ + { + // We want to re-disable objects we had enabled, in the group + // swat.main.fsmUtils.enable_during_rpc + "parameters" : [ false ], + + // Call this.getObject().setEnabled(false) on + // state entry, for each in the group called + // "swat.main.fsmUtils.enable_during_rpc". + "groups" : [ "swat.main.fsmUtils.enable_during_rpc" ] + }, + + { + // We want to re-enable objects we had disabled, in the group + // swat.main.fsmUtils.disable_during_rpc + "parameters" : [ true ], + + // Call this.getObject().setEnabled(true) on + // state entry, for each in the group called + // "swat.main.fsmUtils.disable_during_rpc". + "groups" : [ "swat.main.fsmUtils.disable_during_rpc" ] + } + ] + }, + + "onentry" : + function(fsm, state) + { + // If we're coming from some other state... + if (fsm.getPreviousState() != "State_AwaitRpcResult") + { + // ... then push the previous state onto the state stack + fsm.pushState(false); + } + }, + + "events" : + { + "execute" : + { + "swat.main.fsmUtils.abort_rpc" : + "Transition_AwaitRpcResult_to_AwaitRpcResult_via_button_abort" + }, + + "completed" : + "Transition_AwaitRpcResult_to_PopStack_via_complete", + + "failed" : + qx.util.fsm.FiniteStateMachine.EventHandling.PREDICATE + } + }); + fsm.addState(state); + + /*** Transitions that use a PREDICATE appear first ***/ + + /* + * Transition: AwaitRpcResult to GetAuthInfo + * + * Cause: "failed" (on RPC) where reason is PermissionDenied + */ + var trans = new qx.util.fsm.Transition( + "Transition_AwaitRpcResult_to_GetAuthInfo", + { + "nextState" : + qx.util.fsm.FiniteStateMachine.StateChange.POP_STATE_STACK, + + "predicate" : + function(fsm, event) + { + var error = event.getData(); // retrieve the JSON-RPC error + + // Did we get get origin=Server, code=PermissionDenied ? + var origins = swat.main.AbstractModuleFsm.JsonRpc_Origin; + var serverErrors = swat.main.AbstractModuleFsm.JsonRpc_ServerError; + if (error.origin == origins.Server && + error.code == serverErrors.PermissionDenied) + { + return true; + } + + // fall through to next transition, also for "failed" + return false; + } + }); + state.addTransition(trans); + + /* + * Transition: AwaitRpcResult to PopStack + * + * Cause: "failed" (on RPC) + */ + var trans = new qx.util.fsm.Transition( + "Transition_AwaitRpcResult_to_PopStack_via_failed", + { + "nextState" : + qx.util.fsm.FiniteStateMachine.StateChange.POP_STATE_STACK, + + "ontransition" : + function(fsm, event) + { + // Get the request object + var rpcRequest = _this.getCurrentRpcRequest(); + + // Generate the result for a completed request + rpcRequest.setUserData("result", + { + type : "failed", + data : event.getData() + }); + } + }); + state.addTransition(trans); + + /*** Remaining transitions are accessed via the jump table ***/ + + /* + * Transition: AwaitRpcResult to AwaitRpcResult + * + * Cause: "execute" on swat.main.fsmUtils.abort_rpc + */ + var trans = new qx.util.fsm.Transition( + "Transition_AwaitRpcResult_to_AwaitRpcResult_via_button_abort", + { + "nextState" : + "State_AwaitRpcResult", + + "ontransition" : + function(fsm, event) + { + // Get the request object + var rpcRequest = _this.getCurrentRpcRequest(); + + // Issue an abort for the pending request + rpcRequest.request.abort(); + } + }); + state.addTransition(trans); + + /* + * Transition: AwaitRpcResult to PopStack + * + * Cause: "complete" (on RPC) + */ + var trans = new qx.util.fsm.Transition( + "Transition_AwaitRpcResult_to_PopStack_via_complete", + { + "nextState" : + qx.util.fsm.FiniteStateMachine.StateChange.POP_STATE_STACK, + + "ontransition" : + function(fsm, event) + { + // Get the request object + var rpcRequest = _this.getCurrentRpcRequest(); + + // Generate the result for a completed request + rpcRequest.setUserData("result", + { + type : "complete", + data : event.getData() + }); + } + }); + state.addTransition(trans); +}; + + +/** + * Issue a remote procedure call. + * + * @param fsm {qx.util.fsm.FiniteStateMachine} + * The finite state machine issuing this remote procedure call. + * + * @param service {string} + * The name of the remote service which provides the specified method. + * + * @param method {string} + * The name of the method within the specified service. + * + * @param params {Array} + * The parameters to be passed to the specified method. + * + * @return {Object} + * The request object for the just-issued RPC request. + */ +qx.Proto.callRpc = function(fsm, service, method, params) +{ + // Create an object to hold a copy of the parameters. (We need a + // qx.core.Object() to be able to store this in the finite state machine.) + var rpcRequest = new qx.core.Object(); + + // Save the service name + rpcRequest.service = service; + + // Copy the parameters; we'll prefix our copy with additional params + rpcRequest.params = params.slice(0); + + // Prepend the method + rpcRequest.params.unshift(method); + + // Prepend the flag indicating to coalesce failure events + rpcRequest.params.unshift(true); + + // Retrieve the RPC object */ + var rpc = fsm.getObject("swat.main.rpc"); + + // Set the service name + rpc.setServiceName(rpcRequest.service); + + // Issue the request, skipping the already-specified service name + rpcRequest.request = + qx.io.remote.Rpc.prototype.callAsyncListeners.apply(rpc, + rpcRequest.params); + + // Make the rpc request object available to the AwaitRpcResult state + this.pushRpcRequest(rpcRequest); + + // Give 'em what they came for + return rpcRequest; +}; + + +/** + * Push an RPC request onto the request stack. + * + * @param request {Object} + * The just-issued rpc request object + */ +qx.Proto.pushRpcRequest = function(rpcRequest) +{ + this._requests.push(rpcRequest); +}; + + +/** + * Retrieve the most recent RPC request from the request stack and pop the + * stack. + * + * @return {Object} + * The rpc request object from the top of the request stack + */ +qx.Proto.popRpcRequest = function() +{ + if (this._requests.length == 0) + { + throw new Error("Attempt to pop an RPC request when list is empty."); + } + + var rpcRequest = this._requests.pop(); + return rpcRequest; +}; + + +/** + * Retrieve the most recent RPC request. + * + * @return {Object} + * The rpc request object at the top of the request stack + */ +qx.Proto.getCurrentRpcRequest = function() +{ + if (this._requests.length == 0) + { + throw new Error("Attempt to retrieve an RPC request when list is empty."); + } + + return this._requests[this._requests.length - 1]; +}; + + +/** + * JSON-RPC error origins + */ +qx.Class.JsonRpc_Origin = +{ + Server : 1, + Application : 2, + Transport : 3, + Client : 4 +}; + + +/** + * JSON-RPC Errors for origin == Server + */ +qx.Class.JsonRpc_ServerError = +{ + /** + * Error code, value 0: Unknown Error + * + * The default error code, used only when no specific error code is passed + * to the JsonRpcError constructor. This code should generally not be used. + */ + Unknown : 0, + + /** + * Error code, value 1: Illegal Service + * + * The service name contains illegal characters or is otherwise deemed + * unacceptable to the JSON-RPC server. + */ + IllegalService : 1, + + /** + * Error code, value 2: Service Not Found + * + * The requested service does not exist at the JSON-RPC server. + */ + ServiceNotFound : 2, + + /** + * Error code, value 3: Class Not Found + * + * If the JSON-RPC server divides service methods into subsets (classes), + * this indicates that the specified class was not found. This is slightly + * more detailed than "Method Not Found", but that error would always also + * be legal (and true) whenever this one is returned. (Not used in this + * implementation) + */ + ClassNotFound : 3, // not used in this implementation + + /** + * Error code, value 4: Method Not Found + * + * The method specified in the request is not found in the requested + * service. + */ + MethodNotFound : 4, + + /* + * Error code, value 5: Parameter Mismatch + * + * If a method discovers that the parameters (arguments) provided to it do + * not match the requisite types for the method's parameters, it should + * return this error code to indicate so to the caller. + * + * This error is also used to indicate an illegal parameter value, in server + * scripts. + */ + ParameterMismatch : 5, + + /** + * Error code, value 6: Permission Denied + * + * A JSON-RPC service provider can require authentication, and that + * authentication can be implemented such the method takes authentication + * parameters, or such that a method or class of methods requires prior + * authentication. If the caller has not properly authenticated to use the + * requested method, this error code is returned. + */ + PermissionDenied : 6, + + /* + * Error code, value 7: Unexpected Output + * + * The called method illegally generated output to the browser, which would + * have preceeded the JSON-RPC data. + */ + UnexpectedOutput : 7, + + /* + * Error code, value 8: Resource Error + * + * Too many resources were requested, a system limitation on the total + * number of resources has been reached, or a resource or resource id was + * misused. + */ + ResourceError : 8 + +}; diff --git a/webapps/swat/source/class/swat/main/Gui.js b/webapps/swat/source/class/swat/main/Gui.js index 8d18f5f38a..2495c31c4d 100644 --- a/webapps/swat/source/class/swat/main/Gui.js +++ b/webapps/swat/source/class/swat/main/Gui.js @@ -125,7 +125,7 @@ qx.Class.buildGui = function(moduleList) canvas.setDisplay(false); // initially not displayed var fsm = moduleList[moduleName].fsm; - fsm.addObject("swat.module.canvas", canvas); + fsm.addObject("swat.main.canvas", canvas); canvas.addEventListener("appear", fsm.eventListener, fsm); canvas.addEventListener("disappear", fsm.eventListener, fsm); diff --git a/webapps/swat/source/class/swat/main/Main.js b/webapps/swat/source/class/swat/main/Main.js index d8cfaac139..7cc6b01736 100644 --- a/webapps/swat/source/class/swat/main/Main.js +++ b/webapps/swat/source/class/swat/main/Main.js @@ -8,8 +8,8 @@ */ /* -#require(swat.module.Module) -#require(swat.module.AbstractModule) +#require(swat.main.Module) +#require(swat.main.AbstractModule) */ /** @@ -26,16 +26,16 @@ function() */ //#require(swat.module.statistics.Statistics) -new swat.module.Module("Status and Statistics", +new swat.main.Module("Status and Statistics", swat.module.statistics.Statistics); //#require(swat.module.ldbbrowse.LdbBrowse) -new swat.module.Module("LDB Browser", +new swat.main.Module("LDB Browser", swat.module.ldbbrowse.LdbBrowse); //#require(swat.module.documentation.Documentation) //#require(api.Viewer) -new swat.module.Module("API Documentation", +new swat.main.Module("API Documentation", swat.module.documentation.Documentation); @@ -54,7 +54,7 @@ qx.Proto.initialize = function() qx.Settings.setCustomOfClass("qx.io.Json", "enableDebug", true); // For each module... - var moduleList = swat.module.Module.getList(); + var moduleList = swat.main.Module.getList(); for (moduleName in moduleList) { // ... call the module's buildInitialFsm() function @@ -66,7 +66,7 @@ qx.Proto.initialize = function() qx.Proto.main = function() { - var moduleList = swat.module.Module.getList(); + var moduleList = swat.main.Module.getList(); // Initialize the gui for the main menu swat.main.Gui.buildGui(moduleList); @@ -84,7 +84,7 @@ qx.Proto.main = function() qx.Proto.finalize = function() { // Call each module's finalization function - var moduleList = swat.module.Module.getList(); + var moduleList = swat.main.Module.getList(); for (moduleName in moduleList) { var module = moduleList[moduleName]["class"].getInstance(); diff --git a/webapps/swat/source/class/swat/main/Module.js b/webapps/swat/source/class/swat/main/Module.js new file mode 100644 index 0000000000..ef71eae625 --- /dev/null +++ b/webapps/swat/source/class/swat/main/Module.js @@ -0,0 +1,74 @@ +/* + * Copyright: + * (C) 2006 by Derrell Lipman + * All rights reserved + * + * License: + * LGPL 2.1: http://creativecommons.org/licenses/LGPL/2.1/ + */ + +/** + * This class defines a module descriptor (the registration of a module) and + * maintains the list of modules that have been registered. + * + * A Module object contains the following public properties which may be + * accessed directly by name: + * + * fsm - + * The finite state machine for this module. + * + * canvas - + * The canvas on which to create the gui for this module + * + * name - + * The name of this module + * + * class - + * The class for this module + * + * @param moduleName {string} + * The name of the module being registered. This is the name that will + * appear in the Modules menu. + * + * @param class {class} + * The class which contains the module implementation. That class must + * extend swat.main.AbstractModule and implement a singleton interface + * that provides a public method called initialAppear() which takes this + * Module object as a parameter, and creates the finite state machine for + * the module (if applicable) and builds the graphical user interface for + * the module. + */ +qx.OO.defineClass("swat.main.Module", qx.core.Object, +function(moduleName, class) +{ + qx.core.Object.call(this); + + // Initialize commonly-used properties of a module + this.canvas = null; + this.fsm = null; + this.gui = null; + + // Save the module name + this.name = moduleName; + + // Save this class name + this.class = class; + + // Add this new module to the module list. + swat.main.Module._list[moduleName] = this; +}); + + +/** + * Return the list of modules + */ +qx.Class.getList = function() +{ + return swat.main.Module._list; +}; + + +/** + * The list of modules which have been registered. + */ +qx.Class._list = { }; diff --git a/webapps/swat/source/class/swat/module/AbstractModule.js b/webapps/swat/source/class/swat/module/AbstractModule.js deleted file mode 100644 index 19bcc88a13..0000000000 --- a/webapps/swat/source/class/swat/module/AbstractModule.js +++ /dev/null @@ -1,172 +0,0 @@ -/* - * Copyright: - * (C) 2006 by Derrell Lipman - * All rights reserved - * - * License: - * LGPL 2.1: http://creativecommons.org/licenses/LGPL/2.1/ - */ - -/** - * Abstract Module class. All modules should extend this class. - */ -qx.OO.defineClass("swat.module.AbstractModule", qx.core.Object, -function() -{ - qx.core.Object.call(this); - this.debug("AbstractModule constructor"); -}); - - -/** - * Build the initial finite state machine. - * - * In order to prevent long load times, as minimal as possible of an initial - * FSM should be created. The FSM will receive an "appear" event when the - * module is first selected (and each subsequent time), and the FSM can use - * that event to build the complete FSM. - * - * @param module {swat.module.Module} - * The module descriptor for the module. - */ -qx.Proto.buildInitialFsm = function(module) -{ - // Create a new finite state machine - var fsm = new qx.util.fsm.FiniteStateMachine(module.name); - - // For this simple example application, show all debug messages. - qx.Settings.setCustomOfClass( - "qx.util.fsm.FiniteStateMachine", - "debugFlags", - (qx.util.fsm.FiniteStateMachine.DebugFlags.EVENTS | - qx.util.fsm.FiniteStateMachine.DebugFlags.TRANSITIONS | - qx.util.fsm.FiniteStateMachine.DebugFlags.FUNCTION_DETAIL | - qx.util.fsm.FiniteStateMachine.DebugFlags.OBJECT_NOT_FOUND)); - - /* - * State: Idle - * - * Transition on: - * "appear" on swat.module.canvas - */ - var state = new qx.util.fsm.State( - "State_Idle", - { - "events" : - { - // When we get an appear event the first time, run the transition - // that will load the module's finite state machine and graphical - // user interface. - "appear" : - { - "swat.module.canvas" : - "Transition_Idle_to_Idle_Load_Gui" - } - } - }); - fsm.addState(state); - - /* - * Transition: Idle to (replaced) Idle - * - * Cause: "appear" on canvas for the first time - * - * Action: - * Load module's finite state machine and graphical user interface - */ - var thisModule = this; - var trans = new qx.util.fsm.Transition( - "Transition_Idle_to_Idle_Load_Gui", - { - "nextState" : - qx.util.fsm.FiniteStateMachine.StateChange.CURRENT_STATE, - - "ontransition" : - function(fsm, event) - { - // Make the "Loading" message go away. (We need to learn how to - // remove it entirely. Just doing canvas.removeAll() leaves - // something in the widget queue and we get spurious error - // messages.) - var children = module.canvas.getVisibleChildren(); - for (var child in children) - { - children[child].hide(); - } - - // Call the module's initialAppear function to build FSM and GUI. - // That function should *replace* this state, State_Idle, to which - // we'll transition. - thisModule.initialAppear(module); - } - }); - state.addTransition(trans); - - // Save the finite state machine for this module - module.fsm = fsm; - - // Save the module descriptor in the finite state machine - fsm.addObject("swat.module.module", module); - - // Create an RPC object for use by this module - module.rpc = new qx.io.remote.Rpc(); - module.rpc.setUrl("/services/"); - module.rpc.setTimeout(10000); - module.rpc.setCrossDomain(false); - module.rpc.addEventListener("completed", fsm.eventListener, fsm); - module.rpc.addEventListener("failed", fsm.eventListener, fsm); - module.rpc.addEventListener("timeout", fsm.eventListener, fsm); - module.rpc.addEventListener("aborted", fsm.eventListener, fsm); - fsm.addObject("swat.module.rpc", module.rpc); - - // Start the finite state machine - fsm.start(); -}; - -/** - * Build the initial graphical user interface. - * - * In order to prevent long load times, as minimal as possible of an initial - * GUI should be created. Generally, this is just a "Loading..." message. - * - * @param module {Object} - * An object containing at least the following properties: - * fsm - - * The finite state machine for this module. It should be filled in - * by this function. - * canvas - - * The canvas on which to create the gui for this module - * name - - * The name of this module - * class - - * The class for this module - * - */ -qx.Proto.buildInitialGui = function(module) -{ - // For now, just create the "Loading" text - var o = new qx.ui.basic.Label("Loading module '" + module.name + "'..."); - o.set({ - top: 12, - left: 20 - }); - o.setFont("bold"); - module.canvas.add(o); -}; - -qx.Proto.finalize = function(module) -{ - this.debug("AbstractModule.finalize()"); -}; - - -/* ---------------------------------------------------------------------------- - DEFER SINGLETON INSTANCE ---------------------------------------------------------------------------- -*/ - -/** - * Singleton Instance Getter - */ -qx.Class.getInstance = qx.util.Return.returnInstance; diff --git a/webapps/swat/source/class/swat/module/AbstractModuleFsm.js b/webapps/swat/source/class/swat/module/AbstractModuleFsm.js deleted file mode 100644 index 2b54b4fab4..0000000000 --- a/webapps/swat/source/class/swat/module/AbstractModuleFsm.js +++ /dev/null @@ -1,455 +0,0 @@ -/* - * Copyright: - * (C) 2006 by Derrell Lipman - * All rights reserved - * - * License: - * LGPL 2.1: http://creativecommons.org/licenses/LGPL/2.1/ - */ - -/** - * Common facilities for modules' finite state machines. Each module's FSM - * should extend this class. - */ -qx.OO.defineClass("swat.module.AbstractModuleFsm", qx.core.Object, function() -{ - qx.core.Object.call(this); - - // Create an array for pushing request objects - this._requests = [ ]; -}); - - -qx.Proto.buildFsm = function(module) -{ - throw new Error("Module must overload buildFsm() " + - "to build its custom finite state machine."); -}; - -qx.Proto.addAwaitRpcResultState = function(module) -{ - var fsm = module.fsm; - var _this = this; - - /* - * State: AwaitRpcResult - * - * Actions upon entry: - * - enable any objects in group "swat.module.fsmUtils.enable_during_rpc" - * - disable any objects in group "swat.module.fsmUtils.disable_during_rpc" - * - * Actions upon exit: - * - disable any objects in group "swat.module.fsmUtils.enable_during_rpc" - * - enable any objects in group "swat.module.fsmUtils.disable_during_rpc" - * - * Transition on: - * "completed" (on RPC) - * "failed" (on RPC) - * "execute" on swat.module.fsmUtils.abort_rpc - */ - var state = new qx.util.fsm.State( - "State_AwaitRpcResult", - { - "autoActionsBeforeOnentry" : - { - // The name of a function. - "setEnabled" : - [ - { - // We want to enable objects in the group - // swat.module.fsmUtils.enable_during_rpc - "parameters" : [ true ], - - // Call this.getObject().setEnabled(true) on - // state entry, for each in the group called - // "swat.module.fsmUtils.enable_during_rpc". - "groups" : [ "swat.module.fsmUtils.enable_during_rpc" ] - }, - - { - // We want to disable objects in the group - // swat.module.fsmUtils.disable_during_rpc - "parameters" : [ false ], - - // Call this.getObject().setEnabled(false) on - // state entry, for each in the group called - // "swat.module.fsmUtils.disable_during_rpc". - "groups" : [ "swat.module.fsmUtils.disable_during_rpc" ] - } - ] - }, - - "autoActionsBeforeOnexit" : - { - // The name of a function. - "setEnabled" : - [ - { - // We want to re-disable objects we had enabled, in the group - // swat.module.fsmUtils.enable_during_rpc - "parameters" : [ false ], - - // Call this.getObject().setEnabled(false) on - // state entry, for each in the group called - // "swat.module.fsmUtils.enable_during_rpc". - "groups" : [ "swat.module.fsmUtils.enable_during_rpc" ] - }, - - { - // We want to re-enable objects we had disabled, in the group - // swat.module.fsmUtils.disable_during_rpc - "parameters" : [ true ], - - // Call this.getObject().setEnabled(true) on - // state entry, for each in the group called - // "swat.module.fsmUtils.disable_during_rpc". - "groups" : [ "swat.module.fsmUtils.disable_during_rpc" ] - } - ] - }, - - "onentry" : - function(fsm, state) - { - // If we're coming from some other state... - if (fsm.getPreviousState() != "State_AwaitRpcResult") - { - // ... then push the previous state onto the state stack - fsm.pushState(false); - } - }, - - "events" : - { - "execute" : - { - "swat.module.fsmUtils.abort_rpc" : - "Transition_AwaitRpcResult_to_AwaitRpcResult_via_button_abort" - }, - - "completed" : - "Transition_AwaitRpcResult_to_PopStack_via_complete", - - "failed" : - qx.util.fsm.FiniteStateMachine.EventHandling.PREDICATE - } - }); - fsm.addState(state); - - /*** Transitions that use a PREDICATE appear first ***/ - - /* - * Transition: AwaitRpcResult to GetAuthInfo - * - * Cause: "failed" (on RPC) where reason is PermissionDenied - */ - var trans = new qx.util.fsm.Transition( - "Transition_AwaitRpcResult_to_GetAuthInfo", - { - "nextState" : - qx.util.fsm.FiniteStateMachine.StateChange.POP_STATE_STACK, - - "predicate" : - function(fsm, event) - { - var error = event.getData(); // retrieve the JSON-RPC error - - // Did we get get origin=Server, code=PermissionDenied ? - var origins = swat.module.AbstractModuleFsm.JsonRpc_Origin; - var serverErrors = swat.module.AbstractModuleFsm.JsonRpc_ServerError; - if (error.origin == origins.Server && - error.code == serverErrors.PermissionDenied) - { - return true; - } - - // fall through to next transition, also for "failed" - return false; - } - }); - state.addTransition(trans); - - /* - * Transition: AwaitRpcResult to PopStack - * - * Cause: "failed" (on RPC) - */ - var trans = new qx.util.fsm.Transition( - "Transition_AwaitRpcResult_to_PopStack_via_failed", - { - "nextState" : - qx.util.fsm.FiniteStateMachine.StateChange.POP_STATE_STACK, - - "ontransition" : - function(fsm, event) - { - // Get the request object - var rpcRequest = _this.getCurrentRpcRequest(); - - // Generate the result for a completed request - rpcRequest.setUserData("result", - { - type : "failed", - data : event.getData() - }); - } - }); - state.addTransition(trans); - - /*** Remaining transitions are accessed via the jump table ***/ - - /* - * Transition: AwaitRpcResult to AwaitRpcResult - * - * Cause: "execute" on swat.module.fsmUtils.abort_rpc - */ - var trans = new qx.util.fsm.Transition( - "Transition_AwaitRpcResult_to_AwaitRpcResult_via_button_abort", - { - "nextState" : - "State_AwaitRpcResult", - - "ontransition" : - function(fsm, event) - { - // Get the request object - var rpcRequest = _this.getCurrentRpcRequest(); - - // Issue an abort for the pending request - rpcRequest.request.abort(); - } - }); - state.addTransition(trans); - - /* - * Transition: AwaitRpcResult to PopStack - * - * Cause: "complete" (on RPC) - */ - var trans = new qx.util.fsm.Transition( - "Transition_AwaitRpcResult_to_PopStack_via_complete", - { - "nextState" : - qx.util.fsm.FiniteStateMachine.StateChange.POP_STATE_STACK, - - "ontransition" : - function(fsm, event) - { - // Get the request object - var rpcRequest = _this.getCurrentRpcRequest(); - - // Generate the result for a completed request - rpcRequest.setUserData("result", - { - type : "complete", - data : event.getData() - }); - } - }); - state.addTransition(trans); -}; - - -/** - * Issue a remote procedure call. - * - * @param fsm {qx.util.fsm.FiniteStateMachine} - * The finite state machine issuing this remote procedure call. - * - * @param service {string} - * The name of the remote service which provides the specified method. - * - * @param method {string} - * The name of the method within the specified service. - * - * @param params {Array} - * The parameters to be passed to the specified method. - * - * @return {Object} - * The request object for the just-issued RPC request. - */ -qx.Proto.callRpc = function(fsm, service, method, params) -{ - // Create an object to hold a copy of the parameters. (We need a - // qx.core.Object() to be able to store this in the finite state machine.) - var rpcRequest = new qx.core.Object(); - - // Save the service name - rpcRequest.service = service; - - // Copy the parameters; we'll prefix our copy with additional params - rpcRequest.params = params.slice(0); - - // Prepend the method - rpcRequest.params.unshift(method); - - // Prepend the flag indicating to coalesce failure events - rpcRequest.params.unshift(true); - - // Retrieve the RPC object */ - var rpc = fsm.getObject("swat.module.rpc"); - - // Set the service name - rpc.setServiceName(rpcRequest.service); - - // Issue the request, skipping the already-specified service name - rpcRequest.request = - qx.io.remote.Rpc.prototype.callAsyncListeners.apply(rpc, - rpcRequest.params); - - // Make the rpc request object available to the AwaitRpcResult state - this.pushRpcRequest(rpcRequest); - - // Give 'em what they came for - return rpcRequest; -}; - - -/** - * Push an RPC request onto the request stack. - * - * @param request {Object} - * The just-issued rpc request object - */ -qx.Proto.pushRpcRequest = function(rpcRequest) -{ - this._requests.push(rpcRequest); -}; - - -/** - * Retrieve the most recent RPC request from the request stack and pop the - * stack. - * - * @return {Object} - * The rpc request object from the top of the request stack - */ -qx.Proto.popRpcRequest = function() -{ - if (this._requests.length == 0) - { - throw new Error("Attempt to pop an RPC request when list is empty."); - } - - var rpcRequest = this._requests.pop(); - return rpcRequest; -}; - - -/** - * Retrieve the most recent RPC request. - * - * @return {Object} - * The rpc request object at the top of the request stack - */ -qx.Proto.getCurrentRpcRequest = function() -{ - if (this._requests.length == 0) - { - throw new Error("Attempt to retrieve an RPC request when list is empty."); - } - - return this._requests[this._requests.length - 1]; -}; - - -/** - * JSON-RPC error origins - */ -qx.Class.JsonRpc_Origin = -{ - Server : 1, - Application : 2, - Transport : 3, - Client : 4 -}; - - -/** - * JSON-RPC Errors for origin == Server - */ -qx.Class.JsonRpc_ServerError = -{ - /** - * Error code, value 0: Unknown Error - * - * The default error code, used only when no specific error code is passed - * to the JsonRpcError constructor. This code should generally not be used. - */ - Unknown : 0, - - /** - * Error code, value 1: Illegal Service - * - * The service name contains illegal characters or is otherwise deemed - * unacceptable to the JSON-RPC server. - */ - IllegalService : 1, - - /** - * Error code, value 2: Service Not Found - * - * The requested service does not exist at the JSON-RPC server. - */ - ServiceNotFound : 2, - - /** - * Error code, value 3: Class Not Found - * - * If the JSON-RPC server divides service methods into subsets (classes), - * this indicates that the specified class was not found. This is slightly - * more detailed than "Method Not Found", but that error would always also - * be legal (and true) whenever this one is returned. (Not used in this - * implementation) - */ - ClassNotFound : 3, // not used in this implementation - - /** - * Error code, value 4: Method Not Found - * - * The method specified in the request is not found in the requested - * service. - */ - MethodNotFound : 4, - - /* - * Error code, value 5: Parameter Mismatch - * - * If a method discovers that the parameters (arguments) provided to it do - * not match the requisite types for the method's parameters, it should - * return this error code to indicate so to the caller. - * - * This error is also used to indicate an illegal parameter value, in server - * scripts. - */ - ParameterMismatch : 5, - - /** - * Error code, value 6: Permission Denied - * - * A JSON-RPC service provider can require authentication, and that - * authentication can be implemented such the method takes authentication - * parameters, or such that a method or class of methods requires prior - * authentication. If the caller has not properly authenticated to use the - * requested method, this error code is returned. - */ - PermissionDenied : 6, - - /* - * Error code, value 7: Unexpected Output - * - * The called method illegally generated output to the browser, which would - * have preceeded the JSON-RPC data. - */ - UnexpectedOutput : 7, - - /* - * Error code, value 8: Resource Error - * - * Too many resources were requested, a system limitation on the total - * number of resources has been reached, or a resource or resource id was - * misused. - */ - ResourceError : 8 - -}; diff --git a/webapps/swat/source/class/swat/module/Module.js b/webapps/swat/source/class/swat/module/Module.js deleted file mode 100644 index e7180d2895..0000000000 --- a/webapps/swat/source/class/swat/module/Module.js +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright: - * (C) 2006 by Derrell Lipman - * All rights reserved - * - * License: - * LGPL 2.1: http://creativecommons.org/licenses/LGPL/2.1/ - */ - -/** - * This class defines a module descriptor (the registration of a module) and - * maintains the list of modules that have been registered. - * - * A Module object contains the following public properties which may be - * accessed directly by name: - * - * fsm - - * The finite state machine for this module. - * - * canvas - - * The canvas on which to create the gui for this module - * - * name - - * The name of this module - * - * class - - * The class for this module - * - * @param moduleName {string} - * The name of the module being registered. This is the name that will - * appear in the Modules menu. - * - * @param class {class} - * The class which contains the module implementation. That class must - * extend swat.module.AbstractModule and implement a singleton interface - * that provides a public method called initialAppear() which takes this - * Module object as a parameter, and creates the finite state machine for - * the module (if applicable) and builds the graphical user interface for - * the module. - */ -qx.OO.defineClass("swat.module.Module", qx.core.Object, -function(moduleName, class) -{ - qx.core.Object.call(this); - - // Initialize commonly-used properties of a module - this.canvas = null; - this.fsm = null; - this.gui = null; - - // Save the module name - this.name = moduleName; - - // Save this class name - this.class = class; - - // Add this new module to the module list. - swat.module.Module._list[moduleName] = this; -}); - - -/** - * Return the list of modules - */ -qx.Class.getList = function() -{ - return swat.module.Module._list; -}; - - -/** - * The list of modules which have been registered. - */ -qx.Class._list = { }; diff --git a/webapps/swat/source/class/swat/module/documentation/Documentation.js b/webapps/swat/source/class/swat/module/documentation/Documentation.js index 03191cacc2..acd7e90400 100644 --- a/webapps/swat/source/class/swat/module/documentation/Documentation.js +++ b/webapps/swat/source/class/swat/module/documentation/Documentation.js @@ -11,10 +11,10 @@ * Swat statistics class */ qx.OO.defineClass("swat.module.documentation.Documentation", - swat.module.AbstractModule, + swat.main.AbstractModule, function() { - swat.module.AbstractModule.call(this); + swat.main.AbstractModule.call(this); }); @@ -25,7 +25,7 @@ function() * appear. Creation of the module's GUI has been deferred until it was * actually needed (now), so we need to create it. * - * @param module {swat.module.Module} + * @param module {swat.main.Module} * The module descriptor for the module. */ qx.Proto.initialAppear = function(module) diff --git a/webapps/swat/source/class/swat/module/documentation/Fsm.js b/webapps/swat/source/class/swat/module/documentation/Fsm.js index 9df878b4f1..184b438520 100644 --- a/webapps/swat/source/class/swat/module/documentation/Fsm.js +++ b/webapps/swat/source/class/swat/module/documentation/Fsm.js @@ -11,10 +11,10 @@ * Swat statistics class finite state machine */ qx.OO.defineClass("swat.module.documentation.Fsm", - swat.module.AbstractModuleFsm, + swat.main.AbstractModuleFsm, function() { - swat.module.AbstractModuleFsm.call(this); + swat.main.AbstractModuleFsm.call(this); }); @@ -36,7 +36,7 @@ qx.Proto.buildFsm = function(module) // We need at least one event listed due to FSM requirements "appear" : { - "swat.module.canvas" : + "swat.main.canvas" : "Transition_Idle_to_Idle_via_appear" } } diff --git a/webapps/swat/source/class/swat/module/ldbbrowse/Fsm.js b/webapps/swat/source/class/swat/module/ldbbrowse/Fsm.js index 6b5ae695bf..0abb3454c8 100644 --- a/webapps/swat/source/class/swat/module/ldbbrowse/Fsm.js +++ b/webapps/swat/source/class/swat/module/ldbbrowse/Fsm.js @@ -10,10 +10,10 @@ /** * Swat LDB Browser class finite state machine */ -qx.OO.defineClass("swat.module.ldbbrowse.Fsm", swat.module.AbstractModuleFsm, +qx.OO.defineClass("swat.module.ldbbrowse.Fsm", swat.main.AbstractModuleFsm, function() { - swat.module.AbstractModuleFsm.call(this); + swat.main.AbstractModuleFsm.call(this); }); @@ -106,7 +106,7 @@ qx.Proto.buildFsm = function(module) function(fsm, event) { // Get our module descriptor - var module = fsm.getObject("swat.module.module"); + var module = fsm.getObject("swat.main.module"); // Retrieve the database handle var dbHandle = module.dbHandle; @@ -203,7 +203,7 @@ qx.Proto.buildFsm = function(module) var searchExpr = "(objectclass=*)"; // Get our module descriptor - var module = fsm.getObject("swat.module.module"); + var module = fsm.getObject("swat.main.module"); // Retrieve the database handle var dbHandle = module.dbHandle; @@ -299,7 +299,7 @@ qx.Proto.buildFsm = function(module) var searchExpr = "(objectclass=*)"; // Get our module descriptor - var module = fsm.getObject("swat.module.module"); + var module = fsm.getObject("swat.main.module"); // Retrieve the database handle var dbHandle = module.dbHandle; diff --git a/webapps/swat/source/class/swat/module/ldbbrowse/Gui.js b/webapps/swat/source/class/swat/module/ldbbrowse/Gui.js index 52db8fdd88..38d10768ee 100644 --- a/webapps/swat/source/class/swat/module/ldbbrowse/Gui.js +++ b/webapps/swat/source/class/swat/module/ldbbrowse/Gui.js @@ -107,7 +107,7 @@ qx.Proto.buildGui = function(module) /** * Populate the graphical user interface with the specified data * - * @param module {swat.module.Module} + * @param module {swat.main.Module} * The module descriptor for the module. * * @result {Object} @@ -296,7 +296,7 @@ qx.Proto._buildPageSearch = function(module, page) find.addEventListener("execute", fsm.eventListener, fsm); // We'll be receiving events on the find object, so save its friendly name - fsm.addObject("find", find, "swat.module.fsmUtils.disable_during_rpc"); + fsm.addObject("find", find, "swat.main.fsmUtils.disable_during_rpc"); hlayout.add(find); diff --git a/webapps/swat/source/class/swat/module/ldbbrowse/LdbBrowse.js b/webapps/swat/source/class/swat/module/ldbbrowse/LdbBrowse.js index 45a4c48930..abccbff2d0 100644 --- a/webapps/swat/source/class/swat/module/ldbbrowse/LdbBrowse.js +++ b/webapps/swat/source/class/swat/module/ldbbrowse/LdbBrowse.js @@ -11,10 +11,10 @@ * Swat LDB Browser class */ qx.OO.defineClass("swat.module.ldbbrowse.LdbBrowse", - swat.module.AbstractModule, + swat.main.AbstractModule, function() { - swat.module.AbstractModule.call(this); + swat.main.AbstractModule.call(this); }); @@ -25,7 +25,7 @@ function() * appear. Creation of the module's actual FSM and GUI have been deferred * until they were actually needed (now) so we need to create them. * - * @param module {swat.module.Module} + * @param module {swat.main.Module} * The module descriptor for the module. */ qx.Proto.initialAppear = function(module) diff --git a/webapps/swat/source/class/swat/module/statistics/Fsm.js b/webapps/swat/source/class/swat/module/statistics/Fsm.js index 5e4843691c..3083fed42a 100644 --- a/webapps/swat/source/class/swat/module/statistics/Fsm.js +++ b/webapps/swat/source/class/swat/module/statistics/Fsm.js @@ -10,10 +10,10 @@ /** * Swat statistics class finite state machine */ -qx.OO.defineClass("swat.module.statistics.Fsm", swat.module.AbstractModuleFsm, +qx.OO.defineClass("swat.module.statistics.Fsm", swat.main.AbstractModuleFsm, function() { - swat.module.AbstractModuleFsm.call(this); + swat.main.AbstractModuleFsm.call(this); }); @@ -105,14 +105,14 @@ qx.Proto.buildFsm = function(module) // When we get an appear event, start our timer "appear" : { - "swat.module.canvas" : + "swat.main.canvas" : "Transition_Idle_to_Idle_via_appear" }, // When we get a disappear event, stop our timer "disappear" : { - "swat.module.canvas" : + "swat.main.canvas" : "Transition_Idle_to_Idle_via_disappear" } } diff --git a/webapps/swat/source/class/swat/module/statistics/Gui.js b/webapps/swat/source/class/swat/module/statistics/Gui.js index 28b21aa46d..5968785e07 100644 --- a/webapps/swat/source/class/swat/module/statistics/Gui.js +++ b/webapps/swat/source/class/swat/module/statistics/Gui.js @@ -303,7 +303,7 @@ qx.Proto.buildGui = function(module) /** * Populate the graphical user interface with the specified data * - * @param module {swat.module.Module} + * @param module {swat.main.Module} * The module descriptor for the module. * * @result {Object} diff --git a/webapps/swat/source/class/swat/module/statistics/Statistics.js b/webapps/swat/source/class/swat/module/statistics/Statistics.js index 1618ab73c5..f15e180cba 100644 --- a/webapps/swat/source/class/swat/module/statistics/Statistics.js +++ b/webapps/swat/source/class/swat/module/statistics/Statistics.js @@ -11,10 +11,10 @@ * Swat statistics class */ qx.OO.defineClass("swat.module.statistics.Statistics", - swat.module.AbstractModule, + swat.main.AbstractModule, function() { - swat.module.AbstractModule.call(this); + swat.main.AbstractModule.call(this); }); @@ -25,7 +25,7 @@ function() * appear. Creation of the module's actual FSM and GUI have been deferred * until they were actually needed (now) so we need to create them. * - * @param module {swat.module.Module} + * @param module {swat.main.Module} * The module descriptor for the module. */ qx.Proto.initialAppear = function(module) -- cgit