/* *+------------------------------------------------------------------------+ *| Licensed Materials - Property of IBM *| IBM Cognos Products: Viewer *| (C) Copyright IBM Corp. 2001, 2011 *| *| US Government Users Restricted Rights - Use, duplication or *| disclosure restricted by GSA ADP Schedule Contract with IBM Corp. *| *+------------------------------------------------------------------------+ */ /** * CognosViewerCalculation constructor (base class for all calculation rules) * @constructor */ function CognosViewerCalculation() { this.m_oCV = null; } /** * Sets the cognos viewer object (called by the action factory * @param CCognosViewer object * @private */ CognosViewerCalculation.prototype.setCognosViewer = function(oCV) { this.m_oCV = oCV; }; /** * Returns an instance to the cognos viewer object * @return CCognosViewer object */ CognosViewerCalculation.prototype.getCognosViewer = function() { return this.m_oCV; }; /** * Most calculations require only 2 selected cells */ CognosViewerCalculation.prototype.validSelectionLength = function(selectionController) { try { return selectionController.getAllSelectedObjects().length > 0; } catch (e) { return false; } }; /** * Gets the display value to show in the calculation string. If the current selection is a column title, then * simply use the display from the selection, if not then find the defining cells display value */ CognosViewerCalculation.prototype.getDisplayValueFromSelection = function(selection) { var displayValue = ""; if (!selection) { return displayValue; } if (selection.getLayoutType() == "columnTitle") { displayValue = selection.getDisplayValues()[0]; } else if (selection.getLayoutType() == "datavalue") { // only time we'd be doing a calculation and wouldn't have columnTitles selected // is in a list, so get the column header var viewerAction = this.m_oCV.getAction("CognosViewer"); var selectionController = this.m_oCV.getSelectionController(); var containerId = viewerAction.getContainerId(selectionController); displayValue = selection.getDataItemDisplayValue(viewerAction.getReportInfo(containerId)); } if (displayValue.indexOf("+") != -1 || displayValue.indexOf("-") != -1 || displayValue.indexOf("*") != -1 || displayValue.indexOf("/") != -1) { displayValue = "(" + displayValue + ")"; } return displayValue; }; /** * Need to override this method if your class uses the CognosViewerCalculation getMenuItemString method * +, -, *, / */ CognosViewerCalculation.prototype.getCalcSymbol = function() {}; /** * Generates the menu item string to be displayed in the context menu. Used for simply calculations like * +, -, *, / */ CognosViewerCalculation.prototype.getMenuItemString = function(menuEnabled) { var cognosViewer = this.getCognosViewer(); var selectionController = cognosViewer.getSelectionController(); var sMenuItemString = ""; var selection, index; if (menuEnabled) { try { var selectionLength = selectionController.getAllSelectedObjects().length; if (selectionLength == 1) { selection = selectionController.getAllSelectedObjects()[0]; if(this.m_bFlipSelection) { sMenuItemString = RV_RES.IDS_JS_CALCULATE_NUMBER + " " + this.getCalcSymbol() + " " + this.getDisplayValueFromSelection(selection); } else { sMenuItemString = this.getDisplayValueFromSelection(selection) + " " + this.getCalcSymbol() + " " + RV_RES.IDS_JS_CALCULATE_NUMBER; } } else { if (this.m_bFlipSelection) { selectionLength--; for (index=selectionLength; index >= 0; index--) { selection = selectionController.getAllSelectedObjects()[index]; if (index != selectionLength) { sMenuItemString += " " + this.getCalcSymbol() + " "; } sMenuItemString += this.getDisplayValueFromSelection(selection); } } else { for (index=0; index < selectionLength; index++) { selection = selectionController.getAllSelectedObjects()[index]; if (index > 0) { sMenuItemString += " " + this.getCalcSymbol() + " "; } sMenuItemString += this.getDisplayValueFromSelection(selection); } } } } catch (e) { sMenuItemString = this.getCalcSymbol(); } } else { sMenuItemString = this.getCalcSymbol(); } return sMenuItemString; }; /** * Percent Difference Calculation */ function PercentDifferenceCalculation() {} PercentDifferenceCalculation.prototype = new CognosViewerCalculation(); PercentDifferenceCalculation.prototype.validSelectionLength = function(selectionController) { try { return selectionController.getAllSelectedObjects().length == 2; } catch (e) { return false; } }; /** * Generates the menu item string to be displayed in the context menu */ PercentDifferenceCalculation.prototype.getMenuItemString = function(menuEnabled) { var selectionController = this.getCognosViewer().getSelectionController(); var sMenuItemString = RV_RES.IDS_JS_CALCULATE_PERCENT_DIFFERENCE; if (menuEnabled) { try { var selectionLength = selectionController.getAllSelectedObjects().length; sMenuItemString += " ("; for (var index=0; index < selectionLength; index++) { var selection = selectionController.getAllSelectedObjects()[index]; if (index > 0) { sMenuItemString += ", "; } sMenuItemString += this.getDisplayValueFromSelection(selection); } sMenuItemString += ")"; } catch (e) {} } return sMenuItemString; }; /** * Percent Difference Calculation */ function PercentDifferenceCalculationSwapOrder() { this.m_bFlipSelection = true; } PercentDifferenceCalculationSwapOrder.prototype = new PercentDifferenceCalculation(); /** * Generates the menu item string to be displayed in the context menu */ PercentDifferenceCalculationSwapOrder.prototype.getMenuItemString = function(menuEnabled) { var selectionController = this.getCognosViewer().getSelectionController(); var sMenuItemString = RV_RES.IDS_JS_CALCULATE_PERCENT_DIFFERENCE; if (menuEnabled) { try { var selectionLength = selectionController.getAllSelectedObjects().length; sMenuItemString += " ("; selectionLength--; for (var index=selectionLength; index >= 0; index--) { var selection = selectionController.getAllSelectedObjects()[index]; if (index < selectionLength) { sMenuItemString += ", "; } sMenuItemString += this.getDisplayValueFromSelection(selection); } sMenuItemString += ")"; } catch (e) {} } return sMenuItemString; }; /** * Addition calculation */ function AdditionCalculation() {} AdditionCalculation.prototype = new CognosViewerCalculation(); AdditionCalculation.prototype.getCalcSymbol = function() { return "+"; }; /** * Subtraction calculation */ function SubtractionCalculation() {} SubtractionCalculation.prototype = new CognosViewerCalculation(); SubtractionCalculation.prototype.getCalcSymbol = function() { return "-"; }; /** * Override the validSelectionLength method since additions allows from 1 to 2 selections */ SubtractionCalculation.prototype.validSelectionLength = function(selectionController) { try { var selLength = selectionController.getAllSelectedObjects().length; return selLength > 0 && selLength < 3; } catch (e) { return false; } }; /** * Subtraction calculation when we flip the selection order */ function SubtractionCalculationSwapOrder() { this.m_bFlipSelection = true; } SubtractionCalculationSwapOrder.prototype = new SubtractionCalculation(); /** * Multiplication calculation */ function MultiplicationCalculation() {} MultiplicationCalculation.prototype = new CognosViewerCalculation(); MultiplicationCalculation.prototype.getCalcSymbol = function() { return "*"; }; /** * Division Calculation */ function DivisionCalculation() {} DivisionCalculation.prototype = new CognosViewerCalculation(); DivisionCalculation.prototype.getCalcSymbol = function() { return "/"; }; DivisionCalculation.prototype.validSelectionLength = function(selectionController) { try { var selectionLength = selectionController.getAllSelectedObjects().length; return (selectionLength > 0 && selectionLength < 3); } catch (e) { return false; } }; /** * Division Calculation when we swap the order of selection */ function DivisionCalculationSwapOrder() { this.m_bFlipSelection = true; } DivisionCalculationSwapOrder.prototype = new DivisionCalculation(); /** * Calculation Actions (Addition, Subtraction, Multiplication, Division, PercentDifference etc.) */ function CalculationAction() { this.m_payload = ""; this.m_menuBuilderClass = null; this.m_defaultName = ""; this.m_constant = null; } CalculationAction.prototype = new ModifyReportAction(); CalculationAction.prototype.getUndoHint = function() { return RV_RES.IDS_JS_CALCULATION; }; CalculationAction.prototype.keepRAPCache = function() { return false; }; /** * Specific rules for lists: * 1. No two selections can be on the same column. * 2. Selections have calculation Metadata * @return true if the current selections are valid for calculations */ CalculationAction.prototype.listRules = function() { var selectionController = this.getCognosViewer().getSelectionController(); var aSelectionObjects = selectionController.getSelections(); if (aSelectionObjects.length > 1) { var tmp = {}; for (var i = 0; i < aSelectionObjects.length; ++i) { var columnRef = aSelectionObjects[i].getColumnRef(); if (typeof tmp[columnRef] == "undefined") { tmp[columnRef] = 1; } else { return false; //duplicate found } } } return selectionController.selectionsHaveCalculationMetadata(); }; /** * Specific rules for crosstabs * @return true if the current selections are valid for calculations */ CalculationAction.prototype.crosstabRules = function() { var selectionController = this.getCognosViewer().getSelectionController(); if (!selectionController.areSelectionsColumnRowTitles()) { return false; } if (selectionController.isRelational()) { if (!this.relationalCrosstabRules(selectionController)) { return false; } } else { if (!this.olapCrosstabRules(selectionController)) { return false; } } return true; }; /** * Specific rules for relational data * @return true is the selections meet all the relational crosstab specific rules for allowing calculations */ CalculationAction.prototype.relationalCrosstabRules = function(selectionController) { return selectionController.selectionsHaveCalculationMetadata(); }; /** * Specific rules for OLAP data * @return true if the selections meet all the olap specific crosstab rules for allowing calculations */ CalculationAction.prototype.olapCrosstabRules = function(selectionController) { if (! selectionController.selectionsHaveCalculationMetadata()) { return false; } if (!this.sameDimension(selectionController)) { // Allow calculations between measures of different measure dimensions // Only allow members calcs if all measures return (typeof this.m_oCV.aQoSFunctions != "undefined") && this.m_oCV.aQoSFunctions.toString().indexOf('MULTIPLE_MEASURE_DIMENSION_CALCULATIONS') != -1 && selectionController.selectionsAreMeasures(); } else { if (this.sameHierarchy(selectionController)) { return true; } else { return (typeof this.m_oCV.aQoSFunctions != "undefined") && this.m_oCV.aQoSFunctions.toString().indexOf('VALUE_EXPRESSIONS_REF_MULTIPLE_HIERARCHIES_OF_SAME_DIMENSION') != -1; } } }; /** * Checks to see if the selected cells are from the same hierarchy * @return true if the selections are from the same hierarchy, false otherwise */ CalculationAction.prototype.sameDimension = function(selectionController) { try { var dim = ""; var selLength = selectionController.getAllSelectedObjects().length; for (var selIndex = 0; selIndex < selLength; selIndex++) { if (dim.length == 0) { dim = selectionController.getAllSelectedObjects()[selIndex].getDimensionalItems('dun')[0][0]; } else if (dim != selectionController.getAllSelectedObjects()[selIndex].getDimensionalItems('dun')[0][0]){ return false; } } return true; }catch (e) { return false; } }; CalculationAction.prototype.sameHierarchy = function(selectionController) { try { var dim = ""; var selLength = selectionController.getAllSelectedObjects().length; for (var selIndex = 0; selIndex < selLength; selIndex++) { if (dim.length == 0) { dim = selectionController.getAllSelectedObjects()[selIndex].getDimensionalItems('hun')[0][0]; } else if (dim != selectionController.getAllSelectedObjects()[selIndex].getDimensionalItems('hun')[0][0]){ return false; } } return true; }catch (e) { return false; } }; /** * For calculations, pass the calculation string to the RAP for generating calculation column name. */ CalculationAction.prototype.addActionContextAdditionalParms = function() { var additionalContextParms = ""; if(this.m_constant != null) { additionalContextParms += "" + xml_encode(this.m_constant) + ""; if(this.m_swapSelectionOrder) { additionalContextParms += ""; } } if(this.m_defaultName != "") { additionalContextParms += "" + xml_encode(this.m_defaultName) + ""; } return additionalContextParms; }; CalculationAction.prototype.setRequestParms = function(parms) { if(parms != null) { if(typeof parms.constant != null) { this.m_constant = parms.constant; } } }; CalculationAction.prototype.buildDefaultName = function() { try { var calc = this.getCognosViewer().getCalculation(this.m_menuBuilderClass); this.m_defaultName = calc.getMenuItemString(true); if(this.m_constant != null) { var numberLabel = "" + this.m_constant; var separator = this.getCognosViewer().envParams['contentDecimalSeparator']; if (typeof separator != "undefined" && separator != null && separator != ".") { numberLabel = numberLabel.replace(".", separator); } this.m_defaultName = this.m_defaultName.replace(RV_RES.IDS_JS_CALCULATE_NUMBER, numberLabel); } } catch (e) { this.m_defaultName = ""; } }; CalculationAction.prototype.preProcess = function() { var selectionCount = this.getNumberOfSelections(); this.buildDefaultName(); if(this.m_swapSelectionOrder && selectionCount == 2) { var selectionController = this.getCognosViewer().getSelectionController(); var sel1 = selectionController.getAllSelectedObjects()[0]; var sel2 = selectionController.getAllSelectedObjects()[1]; selectionController.m_aSelectedObjects = [sel2, sel1]; } }; CalculationAction.prototype.isFactCellOnCrosstabOrEmpty = function() { var selectionController = this.m_oCV.getSelectionController(); var selectedObjects = selectionController.getAllSelectedObjects(); if (selectedObjects != null && typeof selectedObjects != "undefined") { if (selectedObjects.length == 0) { return true; } else { var selectedObject = selectedObjects[0]; //If the select object should be disabled when the user selects a fact cell(s). if (selectionController.getDataContainerType() == "crosstab" && selectedObject.getLayoutType() == 'datavalue') { return true; } } } return false; }; CalculationAction.prototype.isSummaryOrAggregateCell = function() { var selectionController = this.m_oCV.getSelectionController(); var selectedObjects = selectionController.getAllSelectedObjects(); if (selectedObjects != null && typeof selectedObjects != "undefined") { var cellRef; var reCrosstabLevel = /\b(ol|il)\b/; for (var i = 0; i < selectedObjects.length; i++) { cellRef = selectedObjects[i].getCellRef(); if (cellRef != null && typeof cellRef != "undefined") { if (selectedObjects[i].getLayoutType() == "summary" || (cellRef != null && reCrosstabLevel.test(cellRef.className))) { return true; } } cellRef =null; } } return false; }; CalculationAction.prototype.isLastSelectionSingleDimensionNested = function() { var selectionController = this.m_oCV.getSelectionController(); var selectedObjects = selectionController.getAllSelectedObjects(); if (selectedObjects != null && typeof selectedObjects != "undefined" && selectedObjects.length) { var lastSelection = selectedObjects[selectedObjects.length - 1]; var dimItemsAxis0 = lastSelection.getDimensionalItems('dun')[0]; //If dimension of this item is same as any of its parents, its SD nested. if (dimItemsAxis0 && dimItemsAxis0.length && dimItemsAxis0[0]) { for(var parent=1; parent