/**************************************************************** ** Licensed Materials - Property of IBM ** ** IBM Cognos Products: drill ** ** (C) Copyright IBM Corp. 2001, 2010 ** ** US Government Users Restricted Rights - Use, duplication or ** disclosure restricted by GSA ADP Schedule Contract with ** IBM Corp. *****************************************************************/ // Copyright (C) 2008 Cognos ULC, an IBM Company. All rights reserved. // Cognos (R) is a trademark of Cognos ULC, (formerly Cognos Incorporated). // JScript source code //========================== INTERFACE TO THE API ========================================================= //These objects represent the selection. //CSelectedCell(), CSelectedMeasure() and soHeader() provide an interface to producing a selection context. /* INTERFACE CONSTRUCTOR: CSelectionContext() represents the OUTPUT selection context. It handles output tables and serialization methods that adhere to the selection context schema. @param rModel The model on which this selection context is based. */ function CSelectionContext(rModel) { //Input selection structure this.rModel = rModel; this.selections = new Array(); //Selection context schema object tables (holding selectioncontextSchema_metadataCell, selectioncontextSchema_cell etc.) this.metadataCells = new Array(); this.cells = new Array(); this.stringTable = new scStringTable(); } /* INTERFACE CONSTRUCTOR: CSelectedCell() represents the selection of a particular item and value for that item. it optionally contains a list of defining cells that give it context. @param sDataItemName The name of the item being selected (eg: product line) @param sMetadataModelItem The metadata model item (for olap, this could be a level unique name or hierarchy unique name) @param sUseValue The use value (for olap members, this would be a member unique name) @param sUseValueType The use value type (one of string, int, date, memberUniqeName etc.) @param sDisplayValue (optional) A string value that is presented to the user in place of the use value (for olap members, that would be the memberCaption) @param sUsage (optional) one of: measure, nonMeasure (identifier, attribute) @param propertiesObject (optional) The properties object is used to specify additional optional properties for selected cells that are not part of the interface. It can be initialized using JSON. Currently, only the queryName property is supported. sample: propertiesObject = {"queryName":"Query1"}; queryName is the name of the query that contains the data item selected */ function CSelectedCell(sDataItemName, sMetadataModelItem, sUseValue, sUseValueType, sDisplayValue, sUsage, oPropertiesObject) { this.setPropertiesObject(oPropertiesObject); this.dataItemName = sDataItemName; this.usage = sUsage; //alert('sDataItemName' + sDataItemName + '\nusage: ' + sUsage + '\nsMetadataModelItem: ' + sMetadataModelItem + '\nsUseValueType: ' + sUseValueType + '\nsUseValue' + sUseValue); if (sUsage == 'measure' && sUseValueType == 'memberUniqueName') { // @TODO: rsvp/viewer measure cell context workaround (updated) // For dimensional measures, (MSAS, PowerCube), rsvp is not yet passing us the metadataModelItem directly, however; // it is passing it indirectly as a "MUN" which is actually the metadataModelItem. // A change to the viewer (for bug 584459) is passing us the "Hierarchy" as the MMI (and not "null" as it was before). // Unfortunately, the hierarchy (which will always be "[ns].[Measures]") is still not sufficient for scoping. // // Temporarily adjust for this case pending an rsvp fix by setting both to the use value for this case. // Note: A more substantial fix (rsvp/viewer/drill) will be made for the bluesea release and this condition will be removed. this.metadataModelItem = sUseValue; } else { this.metadataModelItem = sMetadataModelItem; } this.useValue = sUseValue; this.useValueType = sUseValueType; //_memberUniqueName is an acceptable alternative to memberUniqueName //(it was in the initial version of the interface.) if (this.useValueType == '_memberUniqueName') { this.useValueType = 'memberUniqueName'; } this.displayValue = sDisplayValue; this.definingCells = new Array(); //array of CSelectedCell this.dependentCells = new Array(); //array of CSelectedCell this.nOutputCellId = -1; //Display value passed is now to be set as a dependent cell of type "_memberCaption"... if (sDisplayValue != undefined) { this.addDependentCell('_memberCaption', '', sDisplayValue, '_memberCaption'); } //special properties (initialized with addProperty) //LevelUniqueName, ParentUniqueName, HierarchyUniqueName, DimensionUniqueName, ordinal } /* INTERFACE METHOD addSelectedCell() Add a new cell to the set of selected cells @param sDataItemName The name of the item being selected (eg: product line) @param sMetadataModelItem The metadata model item (for olap, this could be a level unique name or hierarchy unique name) @param sUseValue The use value (for olap members, this would be a member unique name) @param sUseValueType The use value type (one of string, int, date, memberUniqeName etc.) @param sDisplayValue (optional) A string value that is presented to the user in place of the use value (for olap members, that would be the memberCaption) @param sUsage (optional) one of: measure, nonMeasure (identifier, attribute) @param propertiesObject (optional) The properties object is used to specify additional optional properties for selected cells that are not part of the interface. It can be initialized using JSON. Currently, only the queryName property is supported. sample: propertiesObject = {"queryName":"Query1"}; queryName is the name of the query that contains the data item selected */ CSelectionContext.prototype.addSelectedCell = function(sDataItemName, sMetadataModelItem, sUseValue, sUseValueType, sDisplayValue, sUsage, oPropertiesObject) { var nSelCount = this.selections.length; // The required items are encoded to make sure if the source values has a special character we will not encounter any xml parsing errors. //debugger; this.selections[nSelCount] = new CSelectedCell(sDataItemName, sMetadataModelItem, sUseValue, sUseValueType, sDisplayValue, sUsage, oPropertiesObject); return this.selections[nSelCount]; } /* INTERFACE METHOD addDefiningCell() Add a new defining cell for this selected cell. A defining cell represents something that contributes to this cell's value. Examples: The parent cell on a nested crosstab edge or the row edge for a crosstab crosstab fact cell or chart bar (measure). Defining cells also include sections/master values and possibly burst keys etc. @param sDataItemName The name of the item being selected (eg: product line) @param sMetadataModelItem The metadata model item (for olap, this could be a level unique name or hierarchy unique name) @param sUseValue The use value (for olap members, this would be a member unique name) @param sUseValueType The use value type (one of string, int, date, memberUniqeName etc.) @param sDisplayValue (optional) A string value that is presented to the user in place of the use value (for olap members, that would be the memberCaption) @param sUsage (optional) one of: measure, nonMeasure (identifier, attribute) @param propertiesObject (optional) The properties object is used to specify additional optional properties for selected cells that are not part of the interface. It can be initialized using JSON. Currently, only the queryName property is supported. sample: propertiesObject = {"queryName":"Query1"}; queryName is the name of the query that contains the data item selected */ CSelectedCell.prototype.addDefiningCell = function(sDataItemName, sMetadataModelItem, sUseValue, sUseValueType, sDisplayValue, sUsage, oPropertiesObject) { var nDefiningCellCount = this.definingCells.length; // The required items are encoded to make sure if the source values has a special character we will not encounter any xml parsing errors. this.definingCells[nDefiningCellCount] = new CSelectedCell(sDataItemName, sMetadataModelItem, sUseValue, sUseValueType, sDisplayValue, sUsage, oPropertiesObject); /** @todo: add a guard **/ return this.definingCells[nDefiningCellCount]; } /* method setPropertiesObject() Set the properties object In addition set the selectedCell properties that are passed in as properties of propertiesObject Currently this object only support queryName as its property and sample: oPropertiesObject = {"queryName":"Query1"}; queryName is the name of the query that contains the data item selected @param oPropertiesObject The object passed in that includes the required properties * */ CSelectedCell.prototype.setPropertiesObject = function(oPropertiesObject){ if (typeof oPropertiesObject != "undefined") { if("queryName" in oPropertiesObject){ this.queryName = oPropertiesObject.queryName; } } } /* method setQueryName() @param sQueryName queryName is the name of the query that contains the data item selected */ CSelectedCell.prototype.setQueryName = function(sQueryName) { this.queryName = sQueryName; } /* method getQueryName() queryName is the name of the query that contains the data item selected Return the queryName. */ CSelectedCell.prototype.getQueryName = function() { return this.queryName; } /* method setDataItemName() Set the name of the item being selected. @param sDataItemName The name of the item being selected (eg: product line) */ CSelectedCell.prototype.setDataItemName = function(sDataItemName) { this.dataItemName = sDataItemName; } /* method getDataItemName() Return the name of the item being selected. */ CSelectedCell.prototype.getDataItemName = function() { return this.dataItemName; } /* method setMetadataModelItem() Set the metadata model item. @param sMetadataModelItem The metadata model item (for olap, this could be a level unique name or hierarchy unique name) */ CSelectedCell.prototype.setMetadataModelItem = function(sMetadataModelItem) { this.metadataModelItem = sMetadataModelItem; } /* method getMetadataModelItem() Return the metadata model item. */ CSelectedCell.prototype.getMetadataModelItem = function() { return this.metadataModelItem; } /* method setUseValue() Set the use value. @param sUseValue The use value (for olap members, this would be a member unique name) */ CSelectedCell.prototype.setUseValue = function(sUseValue) { this.useValue = sUseValue; } /* method getUseValue() Return the use value. */ CSelectedCell.prototype.getUseValue = function() { return this.useValue; } /* method setUseValueType() Set the use value type. @param sUseValueType The use value type (one of string, int, date, memberUniqeName etc.) */ CSelectedCell.prototype.setUseValueType = function(sUseValueType) { this.useValueType = sUseValueType; } /* method getUseValueType() Return the use value type. */ CSelectedCell.prototype.getUseValueType = function() { return this.useValueType; } /* method setDisplayValue() Set the display value. @param sDisplayValue (optional) A string value that is presented to the user in place of the use value (for olap members, that would be the memberCaption) */ CSelectedCell.prototype.setDisplayValue = function(sDisplayValue) { this.displayValue = sDisplayValue; } /* method getDisplayValue() Return the display value. */ CSelectedCell.prototype.getDisplayValue = function() { return this.displayValue; } /* method setUsage() Set the usage. @param sUsage a usage (eg: measure, nonMeasure (or subtype identifier, attribute), null) */ CSelectedCell.prototype.setUsage = function(sUsage) { this.usage = sUsage; // @todo: exception handling: check valid types, if not, throw an exception. } /* method getUsate() Return the usage. */ CSelectedCell.prototype.getUsage = function() { return this.usage; } /* INTERFACE METHOD referenceDefiningCell() Reference an existing defining cell for this selected cell. A defining cell represents something that contributes to this cell's value. Examples: The parent cell on a nested crosstab edge or the row edge for a crosstab crosstab fact cell or chart bar (measure). Defining cells also include sections/master values and possibly burst keys etc. @param oDefiningCell A defining cell (already created) */ CSelectedCell.prototype.referenceDefiningCell = function(oDefiningCell) { var nDefiningCellCount = this.definingCells.length; this.definingCells[nDefiningCellCount] = oDefiningCell; /** @todo: add a guard **/ return this.definingCells[nDefiningCellCount]; } /* INTERFACE METHOD addProperty() Add a property for this cell. If the property name is one of the supported "special names", it will be added to the appropriate table according to the schema, otherwise; the property is considered a "dependent cell" and a metadatamodelItem is expected to be defined. @param sPropertyName The property Name to add (eg: LevelUniqueName or Category_Code). The list of special properties (ones that don't require a dependent cell to be created are generally OLAP member properties (like HierarchyUniqueName, DimensionUniqueName, ParentUniqueName). @param sPropertyValue The property Value. @param sMetadataModelItem If this is NOT a special (usu. OLAP) property, this item is required as part of the dependent cell definition. @param sUseValueType (optional) The type of this property TODO: Check and see if similar encoding that we added to addSelectedCell and addDefiningCell is required here */ CSelectedCell.prototype.addProperty = function(sPropertyName, sPropertyValue, sMetadataModelItem, sUseValueType) { if (sPropertyName == 'LevelUniqueName') { this.LevelUniqueName = sPropertyValue; } else if (sPropertyName == 'DimensionUniqueName') { this.DimensionUniqueName = sPropertyValue; } else if (sPropertyName == 'HierarchyUniqueName') { this.HierarchyUniqueName = sPropertyValue; } else if (sPropertyName == 'ordinal') { this.ordinal = sPropertyValue; } else { this.addDependentCell(sPropertyName, sMetadataModelItem, sPropertyValue, sUseValueType); } } /* Add a dependent cell for this CSelectedCell object A dependent cell is one that is 'owned' by another cell and represents properties of the parent cell such as level attributes (Note: these are attributes with independent metadata model items NOT things like role-based properties associated with a member) @param sPropertyName The name of this property (eg: Population, PPDS_CODE or CategoryCode) @param sMetadtaModelItem The metadata model item (eg: [outdoors].[countries].[country].[Population]) @param sUseValue The use value (eg: 56,352 for population) */ CSelectedCell.prototype.addDependentCell = function(sPropertyName, sMetadataModelItem, sUseValue, sUseValueType) { var nDependentCellCount = this.dependentCells.length; this.dependentCells[nDependentCellCount] = new CSelectedCell(sPropertyName, sMetadataModelItem, sUseValue, sUseValueType); /** @todo: add a guard **/ return this.dependentCells[nDependentCellCount]; } //========================== preparing the selection context for output. //prepareSchemaObjects is conceptually similar to parsing. Essentially, all of the objects that have been added to the tree structure are prepared //into the object model representation of a selection context (for serializing). CSelectionContext.prototype.prepareSchemaObjects = function() { for (var i=0; i 0) { for (var i=0; i < this.definingCells.length; i++) { var odefiningSchemaCell = this.definingCells[i].prepareSchemaObjects(oSelectionContext); odefiningSchemaCell.rSelectedCell=false; //If something is a defining cell, it shouldn't be in the selected cells list. nDefiningCellCount = oschemaCell.definingCellAxisList.length; /** @TODO: when multiple child cells reference the same parent (ie: siblings under parent "Camping Equipment"), the parent reference should be to the same ID not a new cell with all the same values (its still a valid S/C but less compact) **/ oschemaCell.definingCellAxisList[nDefiningCellCount] = new selectioncontextSchema_Axis(odefiningSchemaCell.nXMLid, this.definingCells[i].ordinal); } } //dependent cells if (this.dependentCells!=undefined && this.dependentCells.length > 0) { for (var i=0; i < this.dependentCells.length; i++) { var odependentSchemaCell = this.dependentCells[i].prepareSchemaObjects(oSelectionContext); odependentSchemaCell.rSelectedCell=false; //If something is a dependent cell, it shouldn't be in the selected cells list. oschemaCell.addDependentCell(odependentSchemaCell); odependentSchemaCell.bDependentCell = true; } } this.nOutputCellId = nNewCellId; return oschemaCell; } //========================== SELECTION CONTEXT SCHEMA OBJECTS ========================================================= //This section defines objects from the selection context schema. They provide a staging area for serializing the XML output. /* CONSTRUCTOR: selectioncontextSchema_MetadataCell represents an entry in the table. @param nXMLid the xmlId of this metadataCell @param nrName the reference to the name entry in the string table for this metadata cell. @param nrExpression the reference to the level unique name entry in the string table for this metadata cell. @param nrUsage a reference to the usage in the string table for this metadata cell. @param nrQueryName a reference to the queryName in the string table for this metadata cell. */ function selectioncontextSchema_MetadataCell(/*xml:id="M_#"*/nXMLid, /*N_#*/nrName, /*QI_#*/nrExpression, /*T_#*/nrType, /*U_#*/nrUsage, /*QN_#*/nrQueryName) { this.nXMLid = nXMLid; this.nrName = nrName; this.nrExpression = nrExpression; this.nrType = nrType; this.nrUsage = nrUsage; this.nrQueryName = nrQueryName; //special properties that apply to the metadata cell. this.nrLevelUniqueName = undefined; this.nrHierarchyUniqueName = undefined; this.nrDimensionUniqueName = undefined; } /* CONSTRUCTOR: selectionContextSchema_Cell @param nXMLid the xmlId of this cell @param nrMetadtaCell the reference ID for this cells metadataCell information. @param nrValue the reference ID for this cells value. @param sDisplayValue (optional) the display value for this cell - display= */ function selectioncontextSchema_Cell(/*xml:id="C_X"*/nXMLid, /*rMetadataCell="M_#"*/ nrMetadataCell, /*rValue="V_#"*/ nrValue, /*display=*/ sDisplayValue) { this.rSelectedCell = true; //default this to being part of the rSelectedCells list (it will get updated) this.bDependentCell = false; this.nXMLid = nXMLid; this.nrMetadataCell = nrMetadataCell; this.nrValue = nrValue; this.displayValue = sDisplayValue; //Note: not a reference //an selectioncontextSchema_Cell can contain a list of dependent cells (which store dependent member properties - like ppdscode, caption for this member) this.dependentCells = new Array(); //and a list of defining cells (which define their position relative to other cells) this.definingCellAxisList = new Array(); } /* CONSTRUCTOR: selectionContextSchema_Axis @param nrCell a reference to its parent cell object (ie: an s:axis is a node under s:definingCells under an s:cell. nrCell would be the xml:id of the s:cell.) @param ordinal (optional) The ordinal of this defining cell's axis. */ function selectioncontextSchema_Axis(/*rCell="C_X"*/nrCell, /*ordinal="X"*/nOrdinal) { this.nrCell = nrCell; this.nOrdinal=nOrdinal; } selectioncontextSchema_Cell.prototype.addDependentCell = function(oDependentCell) { var nDependentCellCount = this.dependentCells.length; this.dependentCells[nDependentCellCount] = oDependentCell; } /** @TODO: probably should have a string object but its so simple, we just use the addString method and fill in the xml directly for now. function scString(nXMLid, sValue) { } **/ /* scOutput::addString() Adds a string to the named string table. @param sTable The name of the table to add the string to @param sValue The value to add @return the index */ CSelectionContext.prototype.addString = function(sTable, sValue) { if (sValue == undefined) { return -1; } var nStringTableLength=this.stringTable[sTable].length; for (var i=0; i tag and its contents. @param objHeader an object representing the header (contains the model reference) @param objCells The list of all cells. Only the ones that haven't been eliminated from the selected cells (because they are defining cells) are produced. */ CSelectionContext.prototype.serializeHeader = function() { /* Add the model reference to the string table @TODO: Normally, this should go in "prepare" but its easiest to put this here (since its a singleton) */ var nModelIdx = this.addString('MP', this.rModel); var sSCHeader = ' 0) { var nPrependSpace=0; sSCHeader+=' rSelectedCells="'; for (var i=0; i tag and its contents. CSelectionContext.prototype.serializeFooter = function() { return ''; } //SelectionContext::serializeStrings() //Produce a string of xml for the string table of a selection context. CSelectionContext.prototype.serializeStrings = function() { var sStringTable=""; var i=0; for (var arrayName in this.stringTable) { for (i=0; i="_#" (where # is >= 0) @param sRefAttrName The name (eg: rName) @param sAttrType The type (eg: "N") @param nrAttr The # part of (TYPE_#). Note: If # is not a valid reference (<=0 or undefined), this method returns an empty string. @return A string =_ (or "" if # is not a valid reference) */ CSelectionContext.prototype.serializeReferenceAttr = function(sRefAttrName, sAttrType, nrAttr) { var sReturn=""; if (nrAttr != undefined && nrAttr >= 0) { sReturn = ' ' + sRefAttrName + '="' + sAttrType + "_" + nrAttr + '"'; } return sReturn; } /* Produce a string of xml for the metadata table: ( and the list of its objects) sample: @param objMetadataTable The metadata table object representation from which the string will be generated. */ CSelectionContext.prototype.serializeMetadataCells = function(objMetadataTable) { var sMetadataTable=""; //serialize each selectioncontextSchema_MetadataCell in the table.... for (x=0; x 0 || this.dependentCells.length > 0) { sCellXML += '>'; } //If this cell has dependent cells serialize them... if (this.dependentCells.length > 0) { sCellXML += ''; for (var xx=0; xx < this.dependentCells.length; xx++) { sCellXML+=this.dependentCells[xx].serialize(oSelectionContext); } sCellXML += ''; } //If this cell has defining cells, serialize REFERENCES to them.... if (this.definingCellAxisList.length > 0) { sCellXML += ''; for (var xx=0; xx/g, ">").replace(/"/g, """).replace(/'/g, "'"); } return str; }