/******************************************************************************************************************************** * Licensed Materials - Property of IBM * * * * IBM Cognos Products: AGS * * * * (C) Copyright IBM Corp. 2005, 2008 * * * * US Government Users Restricted Rights - Use, duplication or disclosure restricted by GSA ADP Schedule Contract with IBM Corp. * *********************************************************************************************************************************/ function Stack(max_size){ this.max_size = max_size ? max_size : 50; this.members = new Array(); } Stack.prototype.reSize = function(size){ if(this.members.length > size){ var start = this.members.length - size; this.members = this.members.slice(start, this.members.length - 1); } } //add the peek to Stack Stack.prototype.peek = function(){ var top = null; if(this.members.length > 0){ top = this.members[this.members.length - 1]; } return top; } //add the peek to Stack Stack.prototype.isEmpty = function(){ return this.members.length == 0; } //add the push to Stack Stack.prototype.push = function(pushee){ this.members.push(pushee); this.reSize(this.max_size); } //add the peek to Array Stack.prototype.pop = function(){ return this.members.pop(); } //add the peek to Array Stack.prototype.clear = function(){ this.members = new Array(); } // check if a item is in stack Stack.prototype.contains = function(searchid){ var found = false; for(var i = 0; i < this.members.length; i++){ if(searchid == (this.members[i])){ found = true; break; } } return found; } //return an array of members for which the passed objects search method returns true //so the caller has to provide an object that has a search method on it that returns a boolean //hmmm that sounds like an interface Stack.prototype.search = function(filterer){ var found = new Array(); for(var i = 0; i < this.members.length; i++){ if(filterer && filterer.search){ if(filterer.search(this.members[i])){ found.push(this.members[i]); } } } return found; } //similar to search, but if the matchers search method returns true, then the found //member is brought to the top ... any other matches subsequently found will be brought to the //top, but underneath the first found... its lifo so later matches have higher precedence //default search direction bottom up //return whether one was brought to the top or not Stack.prototype.bringToTop = function(matcher){ var new_top = new Array(); var ongoing = new Array(); for(var i = 0; i < this.members.length; i++){ if(matcher && matcher.search){ if(matcher.search(this.members[i])){ new_top.push(this.members[i]); } }else{ ongoing.push(this.members[i]); } } this.members = ongoing.concat(new_top); return new_top.length > 0; } Stack.prototype.executeFilter = function(filter, an_object){ if(filter && filter.search){ if(filter.search(an_object)){ return an_object; } } } /*empty type definition for extension, give it an "execute" method use this to push on the stack for stateful commands eg function makeCommandStackObject(value){ var cmdObject = new CommandStackObject(); cmdObject.state = value; cmdObject.execute = myFunctionRef; return cmdObject; } if you pass in a command.... it will execute that and then call the stack again this should only be used if the command wont take much time */ function CommandStackObject(aCommand){ this.command = aCommand; //lets have some config frame action available this.cf = parent.getConfigFrame ? parent.getConfigFrame() : getConfigFrame(); //this is a do little... diy this.execute = function(){ if(this.command){ eval(this.command); } setTimeout("getCommandStackManager().processCommandStack();", 100); } } /* A generic function to create a command stack object with passing in a function name and it arugments. The function name must always be the last parammeter in the arguments passed to this function. */ function createCommandStackObject(){ var cmdObject = new CommandStackObject(); cmdObject.arguments = arguments; //add the execute method cmdObject.execute = function(){ var argsLength = this.arguments.length-1; var fn = this.arguments[argsLength]; var args = "("; for (var i=0;i < argsLength;i++) { args += "this.arguments[" +i +"]"; if (i < argsLength-1) { args += ","; } } args += ")"; eval(fn + args); setTimeout("getCommandStackManager().processCommandStack();", 100); } return cmdObject; } /* the location id is an xpath into the generated report spec of the condition report */ function createValidateCommandStackObject(location_id, error_div_id){ var cmdObject = new cf.CommandStackObject(); cmdObject.error_div_id = error_div_id; //add the execute method cmdObject.execute = function(){ //put this in cfg to be available to the display page this.cf.cfgSet("ValidateCommandStackObject", this); //cf is defined in CommandStackObject this.cf.validateAgentCondition(this.error_div_id); setTimeout("getCommandStackManager().processCommandStack();", 100); } //add a function to test the location_id passed in against the location from an error message cmdObject.checkLocation = function(location){ if(location_id && location){ return location.indexOf(location_id) != -1; } } return cmdObject; } //extend the stack //pass in either strings to eval, or a CommandStackObject with an execute method //can pass in a fail command function CommandStack(commandArray){ var stack = new Stack(); if(commandArray && commandArray.length){ //a little harsh and non oo but quicker (make sure its an array though) stack.members = commandArray; } stack.doNextCommand = function(){ var command = this.pop(); try{ this.evaluateCommand(command); }catch(ex){ var error_message = ex + " ["+command+"]"; if(ex.message != null){ error_message = ex.message + " ["+command+"]"; } if(this.failCommand){ try{ this.evaluateCommand(this.failCommand); alert(error_message); }catch(ex2){ alert(error_message); } }else{ alert(error_message); } this.clear(); } } stack.evaluateCommand = function(command){ if(command instanceof CommandStackObject){ command.execute(); }else{ eval(command); } } stack.setFailCommand = function(failCommand){ if(failCommand){ this.failCommand = failCommand; } } stack.setCancelCommand = function(cancelCommand){ if(cancelCommand){ this.cancelCommand = cancelCommand; } } stack.concat = function(commandStack){ var concatStack = this.members; if (commandStack && commandStack instanceof Stack) { concatStack = this.members.concat(commandStack.members); } return new CommandStack(concatStack); } stack.doFail = function(){ try{ this.evaluateCommand(this.failCommand); }catch(ex){ } this.clear(); } /** defaul cancel method */ stack.cancel = function(){ try{ if(this.cancelCommand){ this.evaluateCommand(this.cancelCommand); }else{ this.clear(); } }catch(ex){ } } //do a default stack.setFailCommand("hideDialogFrame();this.clear()"); return stack; } ////////////////////////////////// // class (ish) that holds a stack of js commands to be evaluated // this removes the knowledge of what to do next from cmd.js //////////////////////////////// function CommandStackManager(){ } CommandStackManager.prototype.getCommandStack = function(){ var cmdStack = cfgGet("agsCommandStack"); if(!cmdStack){ cmdStack = new CommandStack(); this.setCommandStack(cmdStack); } return cmdStack; } CommandStackManager.prototype.setCommandStack = function(cmdStack){ cfgSet("agsCommandStack", cmdStack); } //repeated code in following methods is hard to factor out due to the use of the "arguments" key word CommandStackManager.prototype.createCommandStack = function(){ var cmds = new Array(); //the arguments to this function var args = arguments; if(arguments && arguments.length){ //push them in reverse order to maintain the order for(var i = args.length - 1; i >= 0; i--){ cmds.push(args[i]); } } return new CommandStack(cmds); } //takes any amount of arguments and creates a command stack CommandStackManager.prototype.initiateCommandStack = function(){ if(applicationActionManager.isBlocked()){ return; } applicationActionManager.blockActions(); var cmds = new Array(); //the arguments to this function var args = arguments; if(arguments && arguments.length){ //push them in reverse order to maintain the order for(var i = args.length - 1; i >= 0; i--){ cmds.push(args[i]); } } this.setCommandStack(new CommandStack(cmds)); //execute the top this.processCommandStack(); } //takes any amount of arguments and creates a command stack CommandStackManager.prototype.doCommandStack = function(cmdStack){ this.setCommandStack(cmdStack); this.processCommandStack(); } CommandStackManager.prototype.processCommandStack = function(){ cmdStack = this.getCommandStack(); if(cmdStack && !cmdStack.isEmpty()){ //alert("cmd stack process: " + cmdStack.peek()); var wasBlocked = applicationActionManager.isBlocked(); // let the user exit, if ES is not usable don't block if(cmdStack.contains('closeAGS()')) { var messageIFrame = getMessageIFrame(); var messageIFrame_doc = getFrameDocument(messageIFrame); wasBlocked = false; var formsArray = messageIFrame_doc.forms; //we cannot find a form, something is awry if (formsArray.length==0) { // we can't save stuff only option is to exit now cmdStack.clear(); cmdStack.push('closeAGS()'); } } applicationActionManager.allowActions(); //open a window for the action cmdStack.doNextCommand(); //only reblock when more commands are available //this needs to be checked because one of the commands //may have cancelled execution by explicitly clearing the stack if(wasBlocked && !cmdStack.isEmpty()){ applicationActionManager.blockActions(); }else{ applicationActionManager.allowActions(); } } } var agsCommandStackManager = new CommandStackManager(); function getCommandStackManager(){ return agsCommandStackManager; }