CSelectionContextBuilder.js 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837
  1. /****************************************************************
  2. ** Licensed Materials - Property of IBM
  3. **
  4. ** IBM Cognos Products: drill
  5. **
  6. ** (C) Copyright IBM Corp. 2001, 2010
  7. **
  8. ** US Government Users Restricted Rights - Use, duplication or
  9. ** disclosure restricted by GSA ADP Schedule Contract with
  10. ** IBM Corp.
  11. *****************************************************************/
  12. // Copyright (C) 2008 Cognos ULC, an IBM Company. All rights reserved.
  13. // Cognos (R) is a trademark of Cognos ULC, (formerly Cognos Incorporated).
  14. // JScript source code
  15. //========================== INTERFACE TO THE API =========================================================
  16. //These objects represent the selection.
  17. //CSelectedCell(), CSelectedMeasure() and soHeader() provide an interface to producing a selection context.
  18. /*
  19. INTERFACE CONSTRUCTOR: CSelectionContext() represents the OUTPUT selection context.
  20. It handles output tables and serialization methods that adhere to the selection context schema.
  21. @param rModel The model on which this selection context is based.
  22. */
  23. function CSelectionContext(rModel)
  24. {
  25. //Input selection structure
  26. this.rModel = rModel;
  27. this.selections = new Array();
  28. //Selection context schema object tables (holding selectioncontextSchema_metadataCell, selectioncontextSchema_cell etc.)
  29. this.metadataCells = new Array();
  30. this.cells = new Array();
  31. this.stringTable = new scStringTable();
  32. }
  33. /*
  34. INTERFACE CONSTRUCTOR: CSelectedCell() represents the selection of a particular item and value for that item.
  35. it optionally contains a list of defining cells that give it context.
  36. @param sDataItemName The name of the item being selected (eg: product line)
  37. @param sMetadataModelItem The metadata model item (for olap, this could be a level unique name or hierarchy unique name)
  38. @param sUseValue The use value (for olap members, this would be a member unique name)
  39. @param sUseValueType The use value type (one of string, int, date, memberUniqeName etc.)
  40. @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)
  41. @param sUsage (optional) one of: measure, nonMeasure (identifier, attribute)
  42. @param propertiesObject (optional) The properties object is used to specify additional optional properties for selected cells
  43. that are not part of the interface. It can be initialized using JSON.
  44. Currently, only the queryName property is supported.
  45. sample: propertiesObject = {"queryName":"Query1"};
  46. queryName is the name of the query that contains the data item selected
  47. */
  48. function CSelectedCell(sDataItemName, sMetadataModelItem, sUseValue, sUseValueType, sDisplayValue, sUsage, oPropertiesObject)
  49. {
  50. this.setPropertiesObject(oPropertiesObject);
  51. this.dataItemName = sDataItemName;
  52. this.usage = sUsage;
  53. //alert('sDataItemName' + sDataItemName + '\nusage: ' + sUsage + '\nsMetadataModelItem: ' + sMetadataModelItem + '\nsUseValueType: ' + sUseValueType + '\nsUseValue' + sUseValue);
  54. if (sUsage == 'measure' && sUseValueType == 'memberUniqueName') {
  55. // @TODO: rsvp/viewer measure cell context workaround (updated)
  56. // For dimensional measures, (MSAS, PowerCube), rsvp is not yet passing us the metadataModelItem directly, however;
  57. // it is passing it indirectly as a "MUN" which is actually the metadataModelItem.
  58. // A change to the viewer (for bug 584459) is passing us the "Hierarchy" as the MMI (and not "null" as it was before).
  59. // Unfortunately, the hierarchy (which will always be "[ns].[Measures]") is still not sufficient for scoping.
  60. //
  61. // Temporarily adjust for this case pending an rsvp fix by setting both to the use value for this case.
  62. // Note: A more substantial fix (rsvp/viewer/drill) will be made for the bluesea release and this condition will be removed.
  63. this.metadataModelItem = sUseValue;
  64. } else {
  65. this.metadataModelItem = sMetadataModelItem;
  66. }
  67. this.useValue = sUseValue;
  68. this.useValueType = sUseValueType;
  69. //_memberUniqueName is an acceptable alternative to memberUniqueName
  70. //(it was in the initial version of the interface.)
  71. if (this.useValueType == '_memberUniqueName') {
  72. this.useValueType = 'memberUniqueName';
  73. }
  74. this.displayValue = sDisplayValue;
  75. this.definingCells = new Array(); //array of CSelectedCell
  76. this.dependentCells = new Array(); //array of CSelectedCell
  77. this.nOutputCellId = -1;
  78. //Display value passed is now to be set as a dependent cell of type "_memberCaption"...
  79. if (sDisplayValue != undefined) {
  80. this.addDependentCell('_memberCaption', '', sDisplayValue, '_memberCaption');
  81. }
  82. //special properties (initialized with addProperty)
  83. //LevelUniqueName, ParentUniqueName, HierarchyUniqueName, DimensionUniqueName, ordinal
  84. }
  85. /*
  86. INTERFACE METHOD addSelectedCell()
  87. Add a new cell to the set of selected cells
  88. @param sDataItemName The name of the item being selected (eg: product line)
  89. @param sMetadataModelItem The metadata model item (for olap, this could be a level unique name or hierarchy unique name)
  90. @param sUseValue The use value (for olap members, this would be a member unique name)
  91. @param sUseValueType The use value type (one of string, int, date, memberUniqeName etc.)
  92. @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)
  93. @param sUsage (optional) one of: measure, nonMeasure (identifier, attribute)
  94. @param propertiesObject (optional) The properties object is used to specify additional optional properties for selected cells
  95. that are not part of the interface. It can be initialized using JSON.
  96. Currently, only the queryName property is supported.
  97. sample: propertiesObject = {"queryName":"Query1"};
  98. queryName is the name of the query that contains the data item selected
  99. */
  100. CSelectionContext.prototype.addSelectedCell = function(sDataItemName, sMetadataModelItem, sUseValue, sUseValueType, sDisplayValue, sUsage, oPropertiesObject)
  101. {
  102. var nSelCount = this.selections.length;
  103. // The required items are encoded to make sure if the source values has a special character we will not encounter any xml parsing errors.
  104. //debugger;
  105. this.selections[nSelCount] = new CSelectedCell(sDataItemName, sMetadataModelItem, sUseValue, sUseValueType, sDisplayValue, sUsage, oPropertiesObject);
  106. return this.selections[nSelCount];
  107. }
  108. /*
  109. INTERFACE METHOD addDefiningCell()
  110. Add a new defining cell for this selected cell. A defining cell represents something that contributes to this cell's value.
  111. Examples: The parent cell on a nested crosstab edge or the row edge for a crosstab crosstab fact cell or chart bar (measure).
  112. Defining cells also include sections/master values and possibly burst keys etc.
  113. @param sDataItemName The name of the item being selected (eg: product line)
  114. @param sMetadataModelItem The metadata model item (for olap, this could be a level unique name or hierarchy unique name)
  115. @param sUseValue The use value (for olap members, this would be a member unique name)
  116. @param sUseValueType The use value type (one of string, int, date, memberUniqeName etc.)
  117. @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)
  118. @param sUsage (optional) one of: measure, nonMeasure (identifier, attribute)
  119. @param propertiesObject (optional) The properties object is used to specify additional optional properties for selected cells
  120. that are not part of the interface. It can be initialized using JSON.
  121. Currently, only the queryName property is supported.
  122. sample: propertiesObject = {"queryName":"Query1"};
  123. queryName is the name of the query that contains the data item selected
  124. */
  125. CSelectedCell.prototype.addDefiningCell = function(sDataItemName, sMetadataModelItem, sUseValue, sUseValueType, sDisplayValue, sUsage, oPropertiesObject)
  126. {
  127. var nDefiningCellCount = this.definingCells.length;
  128. // The required items are encoded to make sure if the source values has a special character we will not encounter any xml parsing errors.
  129. this.definingCells[nDefiningCellCount] = new CSelectedCell(sDataItemName, sMetadataModelItem, sUseValue, sUseValueType, sDisplayValue, sUsage, oPropertiesObject);
  130. /**
  131. @todo: add a guard
  132. **/
  133. return this.definingCells[nDefiningCellCount];
  134. }
  135. /*
  136. method setPropertiesObject()
  137. Set the properties object
  138. In addition set the selectedCell properties that are passed in as properties of propertiesObject
  139. Currently this object only support queryName as its property and
  140. sample: oPropertiesObject = {"queryName":"Query1"};
  141. queryName is the name of the query that contains the data item selected
  142. @param oPropertiesObject The object passed in that includes the required properties
  143. *
  144. */
  145. CSelectedCell.prototype.setPropertiesObject = function(oPropertiesObject){
  146. if (typeof oPropertiesObject != "undefined") {
  147. if("queryName" in oPropertiesObject){
  148. this.queryName = oPropertiesObject.queryName;
  149. }
  150. }
  151. }
  152. /*
  153. method setQueryName()
  154. @param sQueryName queryName is the name of the query that contains the data item selected
  155. */
  156. CSelectedCell.prototype.setQueryName = function(sQueryName)
  157. {
  158. this.queryName = sQueryName;
  159. }
  160. /*
  161. method getQueryName()
  162. queryName is the name of the query that contains the data item selected
  163. Return the queryName.
  164. */
  165. CSelectedCell.prototype.getQueryName = function()
  166. {
  167. return this.queryName;
  168. }
  169. /*
  170. method setDataItemName()
  171. Set the name of the item being selected.
  172. @param sDataItemName The name of the item being selected (eg: product line)
  173. */
  174. CSelectedCell.prototype.setDataItemName = function(sDataItemName)
  175. {
  176. this.dataItemName = sDataItemName;
  177. }
  178. /*
  179. method getDataItemName()
  180. Return the name of the item being selected.
  181. */
  182. CSelectedCell.prototype.getDataItemName = function()
  183. {
  184. return this.dataItemName;
  185. }
  186. /*
  187. method setMetadataModelItem()
  188. Set the metadata model item.
  189. @param sMetadataModelItem The metadata model item (for olap, this could be a level unique name or hierarchy unique name)
  190. */
  191. CSelectedCell.prototype.setMetadataModelItem = function(sMetadataModelItem)
  192. {
  193. this.metadataModelItem = sMetadataModelItem;
  194. }
  195. /*
  196. method getMetadataModelItem()
  197. Return the metadata model item.
  198. */
  199. CSelectedCell.prototype.getMetadataModelItem = function()
  200. {
  201. return this.metadataModelItem;
  202. }
  203. /*
  204. method setUseValue()
  205. Set the use value.
  206. @param sUseValue The use value (for olap members, this would be a member unique name)
  207. */
  208. CSelectedCell.prototype.setUseValue = function(sUseValue)
  209. {
  210. this.useValue = sUseValue;
  211. }
  212. /*
  213. method getUseValue()
  214. Return the use value.
  215. */
  216. CSelectedCell.prototype.getUseValue = function()
  217. {
  218. return this.useValue;
  219. }
  220. /*
  221. method setUseValueType()
  222. Set the use value type.
  223. @param sUseValueType The use value type (one of string, int, date, memberUniqeName etc.)
  224. */
  225. CSelectedCell.prototype.setUseValueType = function(sUseValueType)
  226. {
  227. this.useValueType = sUseValueType;
  228. }
  229. /*
  230. method getUseValueType()
  231. Return the use value type.
  232. */
  233. CSelectedCell.prototype.getUseValueType = function()
  234. {
  235. return this.useValueType;
  236. }
  237. /*
  238. method setDisplayValue()
  239. Set the display value.
  240. @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)
  241. */
  242. CSelectedCell.prototype.setDisplayValue = function(sDisplayValue)
  243. {
  244. this.displayValue = sDisplayValue;
  245. }
  246. /*
  247. method getDisplayValue()
  248. Return the display value.
  249. */
  250. CSelectedCell.prototype.getDisplayValue = function()
  251. {
  252. return this.displayValue;
  253. }
  254. /*
  255. method setUsage()
  256. Set the usage.
  257. @param sUsage a usage (eg: measure, nonMeasure (or subtype identifier, attribute), null)
  258. */
  259. CSelectedCell.prototype.setUsage = function(sUsage)
  260. {
  261. this.usage = sUsage;
  262. // @todo: exception handling: check valid types, if not, throw an exception.
  263. }
  264. /*
  265. method getUsate()
  266. Return the usage.
  267. */
  268. CSelectedCell.prototype.getUsage = function()
  269. {
  270. return this.usage;
  271. }
  272. /*
  273. INTERFACE METHOD referenceDefiningCell()
  274. Reference an existing defining cell for this selected cell. A defining cell represents something that contributes to this cell's value.
  275. Examples: The parent cell on a nested crosstab edge or the row edge for a crosstab crosstab fact cell or chart bar (measure).
  276. Defining cells also include sections/master values and possibly burst keys etc.
  277. @param oDefiningCell A defining cell (already created)
  278. */
  279. CSelectedCell.prototype.referenceDefiningCell = function(oDefiningCell)
  280. {
  281. var nDefiningCellCount = this.definingCells.length;
  282. this.definingCells[nDefiningCellCount] = oDefiningCell;
  283. /**
  284. @todo: add a guard
  285. **/
  286. return this.definingCells[nDefiningCellCount];
  287. }
  288. /*
  289. INTERFACE METHOD addProperty()
  290. Add a property for this cell. If the property name is one of the supported "special names", it will be added to the appropriate
  291. table according to the schema, otherwise; the property is considered a "dependent cell" and a metadatamodelItem is expected to be
  292. defined.
  293. @param sPropertyName The property Name to add (eg: LevelUniqueName or Category_Code). The list of special properties (ones that don't
  294. require a dependent cell to be created are generally OLAP member properties (like HierarchyUniqueName,
  295. DimensionUniqueName, ParentUniqueName).
  296. @param sPropertyValue The property Value.
  297. @param sMetadataModelItem If this is NOT a special (usu. OLAP) property, this item is required as part of the dependent cell definition.
  298. @param sUseValueType (optional) The type of this property
  299. TODO: Check and see if similar encoding that we added to addSelectedCell and addDefiningCell is required here
  300. */
  301. CSelectedCell.prototype.addProperty = function(sPropertyName, sPropertyValue, sMetadataModelItem, sUseValueType)
  302. {
  303. if (sPropertyName == 'LevelUniqueName') {
  304. this.LevelUniqueName = sPropertyValue;
  305. } else if (sPropertyName == 'DimensionUniqueName') {
  306. this.DimensionUniqueName = sPropertyValue;
  307. } else if (sPropertyName == 'HierarchyUniqueName') {
  308. this.HierarchyUniqueName = sPropertyValue;
  309. } else if (sPropertyName == 'ordinal') {
  310. this.ordinal = sPropertyValue;
  311. } else {
  312. this.addDependentCell(sPropertyName, sMetadataModelItem, sPropertyValue, sUseValueType);
  313. }
  314. }
  315. /*
  316. Add a dependent cell for this CSelectedCell object
  317. A dependent cell is one that is 'owned' by another cell and represents properties of the parent cell such as level attributes
  318. (Note: these are attributes with independent metadata model items NOT things like role-based properties associated with a member)
  319. @param sPropertyName The name of this property (eg: Population, PPDS_CODE or CategoryCode)
  320. @param sMetadtaModelItem The metadata model item (eg: [outdoors].[countries].[country].[Population])
  321. @param sUseValue The use value (eg: 56,352 for population)
  322. */
  323. CSelectedCell.prototype.addDependentCell = function(sPropertyName, sMetadataModelItem, sUseValue, sUseValueType)
  324. {
  325. var nDependentCellCount = this.dependentCells.length;
  326. this.dependentCells[nDependentCellCount] = new CSelectedCell(sPropertyName, sMetadataModelItem, sUseValue, sUseValueType);
  327. /**
  328. @todo: add a guard
  329. **/
  330. return this.dependentCells[nDependentCellCount];
  331. }
  332. //========================== preparing the selection context for output.
  333. //prepareSchemaObjects is conceptually similar to parsing. Essentially, all of the objects that have been added to the tree structure are prepared
  334. //into the object model representation of a selection context (for serializing).
  335. CSelectionContext.prototype.prepareSchemaObjects = function()
  336. {
  337. for (var i=0; i<this.selections.length; i++) {
  338. //select all the root selection objects.
  339. var objSelectionRoot = this.selections[i];
  340. //Method to recursively create selection context structures for a selection tree branch and its children
  341. objSelectionRoot.prepareSchemaObjects(this);
  342. }
  343. }
  344. /*
  345. CSelectedCell.prepareSchemaObjects
  346. Recursive method to Convert a CSelectedCell and its defining cells into selectioncontext schema objects
  347. @param oSelectionContext The selection context where the schema objects will be created.
  348. */
  349. CSelectedCell.prototype.prepareSchemaObjects = function(oSelectionContext)
  350. {
  351. //Initialize the strings and metadata entries....
  352. var nNewCellId=oSelectionContext.cells.length;
  353. //create the selection context output objects...............................................
  354. //Add a name entry to the string table and keep a reference ID to that name for the metadataCell
  355. var nNewNameId=oSelectionContext.addString('N', this.dataItemName);
  356. //add a metdata entry for it....
  357. var nNewMetadataIdx=oSelectionContext.metadataCells.length;
  358. oSelectionContext.addMetadataCell(nNewMetadataIdx, nNewNameId, this );
  359. //add an entry to the string table for the value and keep a reference to that ID for the schemaCell (ie: the <s:cell rValue=)
  360. var nNewValueIdx=oSelectionContext.addString("V", this.useValue);
  361. //add the output cell object
  362. var oschemaCell = new selectioncontextSchema_Cell(nNewCellId, nNewMetadataIdx, nNewValueIdx, this.displayValue);
  363. oSelectionContext.cells[nNewCellId] = oschemaCell;
  364. /**
  365. @INVESTIGATE: The way this is defined, the cell that has defining cells will be written BEFORE the cells it is referencing
  366. (eg: If Cell C_00 is the cell that has defining cells, it might contain a reference rCell=C_01, then Cell C_01 will be written)
  367. I don't THINK this is a problem .... XML is supposed to be order independent. The function could be changed by processing
  368. defining cells first but it makes the definingCellAxisList list a bit trickier
  369. **/
  370. if (this.definingCells!=undefined && this.definingCells.length > 0) {
  371. for (var i=0; i < this.definingCells.length; i++) {
  372. var odefiningSchemaCell = this.definingCells[i].prepareSchemaObjects(oSelectionContext);
  373. odefiningSchemaCell.rSelectedCell=false; //If something is a defining cell, it shouldn't be in the selected cells list.
  374. nDefiningCellCount = oschemaCell.definingCellAxisList.length;
  375. /**
  376. @TODO: when multiple child cells reference the same parent (ie: siblings under parent "Camping Equipment"), the
  377. 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)
  378. **/
  379. oschemaCell.definingCellAxisList[nDefiningCellCount] = new selectioncontextSchema_Axis(odefiningSchemaCell.nXMLid, this.definingCells[i].ordinal);
  380. }
  381. }
  382. //dependent cells
  383. if (this.dependentCells!=undefined && this.dependentCells.length > 0) {
  384. for (var i=0; i < this.dependentCells.length; i++) {
  385. var odependentSchemaCell = this.dependentCells[i].prepareSchemaObjects(oSelectionContext);
  386. odependentSchemaCell.rSelectedCell=false; //If something is a dependent cell, it shouldn't be in the selected cells list.
  387. oschemaCell.addDependentCell(odependentSchemaCell);
  388. odependentSchemaCell.bDependentCell = true;
  389. }
  390. }
  391. this.nOutputCellId = nNewCellId;
  392. return oschemaCell;
  393. }
  394. //========================== SELECTION CONTEXT SCHEMA OBJECTS =========================================================
  395. //This section defines objects from the selection context schema. They provide a staging area for serializing the XML output.
  396. /*
  397. CONSTRUCTOR: selectioncontextSchema_MetadataCell represents an entry in the <s:metadataCells> table.
  398. @param nXMLid the xmlId of this metadataCell
  399. @param nrName the reference to the name entry in the string table for this metadata cell.
  400. @param nrExpression the reference to the level unique name entry in the string table for this metadata cell.
  401. @param nrUsage a reference to the usage in the string table for this metadata cell.
  402. @param nrQueryName a reference to the queryName in the string table for this metadata cell.
  403. */
  404. function selectioncontextSchema_MetadataCell(/*xml:id="M_#"*/nXMLid, /*N_#*/nrName, /*QI_#*/nrExpression, /*T_#*/nrType, /*U_#*/nrUsage, /*QN_#*/nrQueryName)
  405. {
  406. this.nXMLid = nXMLid;
  407. this.nrName = nrName;
  408. this.nrExpression = nrExpression;
  409. this.nrType = nrType;
  410. this.nrUsage = nrUsage;
  411. this.nrQueryName = nrQueryName;
  412. //special properties that apply to the metadata cell.
  413. this.nrLevelUniqueName = undefined;
  414. this.nrHierarchyUniqueName = undefined;
  415. this.nrDimensionUniqueName = undefined;
  416. }
  417. /*
  418. CONSTRUCTOR: selectionContextSchema_Cell
  419. @param nXMLid the xmlId of this cell
  420. @param nrMetadtaCell the reference ID for this cells metadataCell information.
  421. @param nrValue the reference ID for this cells value.
  422. @param sDisplayValue (optional) the display value for this cell - display=
  423. */
  424. function selectioncontextSchema_Cell(/*xml:id="C_X"*/nXMLid, /*rMetadataCell="M_#"*/ nrMetadataCell, /*rValue="V_#"*/ nrValue, /*display=*/ sDisplayValue)
  425. {
  426. this.rSelectedCell = true; //default this to being part of the rSelectedCells list (it will get updated)
  427. this.bDependentCell = false;
  428. this.nXMLid = nXMLid;
  429. this.nrMetadataCell = nrMetadataCell;
  430. this.nrValue = nrValue;
  431. this.displayValue = sDisplayValue; //Note: not a reference
  432. //an selectioncontextSchema_Cell can contain a list of dependent cells (which store dependent member properties - like ppdscode, caption for this member)
  433. this.dependentCells = new Array();
  434. //and a list of defining cells (which define their position relative to other cells)
  435. this.definingCellAxisList = new Array();
  436. }
  437. /*
  438. CONSTRUCTOR: selectionContextSchema_Axis
  439. @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.)
  440. @param ordinal (optional) The ordinal of this defining cell's axis.
  441. */
  442. function selectioncontextSchema_Axis(/*rCell="C_X"*/nrCell, /*ordinal="X"*/nOrdinal)
  443. {
  444. this.nrCell = nrCell;
  445. this.nOrdinal=nOrdinal;
  446. }
  447. selectioncontextSchema_Cell.prototype.addDependentCell = function(oDependentCell)
  448. {
  449. var nDependentCellCount = this.dependentCells.length;
  450. this.dependentCells[nDependentCellCount] = oDependentCell;
  451. }
  452. /**
  453. @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.
  454. function scString(nXMLid, sValue)
  455. {
  456. }
  457. **/
  458. /*
  459. scOutput::addString()
  460. Adds a string to the named string table.
  461. @param sTable The name of the table to add the string to
  462. @param sValue The value to add
  463. @return the index
  464. */
  465. CSelectionContext.prototype.addString = function(sTable, sValue)
  466. {
  467. if (sValue == undefined) {
  468. return -1;
  469. }
  470. var nStringTableLength=this.stringTable[sTable].length;
  471. for (var i=0; i<nStringTableLength; i++) {
  472. if (sValue == this.stringTable[sTable][i]) {
  473. return i;
  474. }
  475. }
  476. //Didn't find it...insert a new entry
  477. this.stringTable[sTable][nStringTableLength] = sValue;
  478. return nStringTableLength;
  479. }
  480. //class scStringTable constructor
  481. //The string table is made up of a number of named sub-tables
  482. function scStringTable()
  483. {
  484. this.QN = new Array(); // An array of queryName
  485. this.N = new Array(); // An array of DataItemName
  486. this.T = new Array(); // An array of Type
  487. this.V = new Array(); // An array of Value
  488. this.QI = new Array(); // An array of expression
  489. this.L = new Array();
  490. this.SV = new Array();
  491. this.D = new Array();
  492. this.H = new Array();
  493. this.U = new Array(); //An array of usages
  494. this.MP= new Array(); //An array of (one?) model
  495. }
  496. //SERIALIZER OBJECTS AND METHODS FOR SELECTION CONTEXT SCHEMA OBJECTS
  497. /*
  498. produce a string of xml representing the header <s:selection> tag and its contents.
  499. @param objHeader an object representing the header (contains the model reference)
  500. @param objCells The list of all cells. Only the ones that haven't been eliminated from the selected cells (because they
  501. are defining cells) are produced.
  502. */
  503. CSelectionContext.prototype.serializeHeader = function()
  504. {
  505. /*
  506. Add the model reference to the string table
  507. @TODO: Normally, this should go in "prepare" but its easiest to put this here (since its a singleton)
  508. */
  509. var nModelIdx = this.addString('MP', this.rModel);
  510. var sSCHeader = '<s:selection';
  511. sSCHeader+=this.serializeReferenceAttr('rModel', 'MP', nModelIdx);
  512. sSCHeader+=' xmlns:s="http://developer.cognos.com/schemas/selection/1/"';
  513. sSCHeader+=' xmlns:xml="http://www.w3.org/XML/1998/namespace"';
  514. if (this.cells.length > 0) {
  515. var nPrependSpace=0;
  516. sSCHeader+=' rSelectedCells="';
  517. for (var i=0; i<this.cells.length; i++) {
  518. if (this.cells[i].rSelectedCell == true) {
  519. if (nPrependSpace==0) {
  520. nPrependSpace=1;
  521. } else {
  522. sSCHeader+=' ';
  523. }
  524. sSCHeader+='C_';
  525. sSCHeader+=i;
  526. }
  527. }
  528. sSCHeader+='"';
  529. }
  530. sSCHeader+='>';
  531. return sSCHeader;
  532. }
  533. //produce a string of xml representing the footer </s:selection> tag and its contents.
  534. CSelectionContext.prototype.serializeFooter = function()
  535. {
  536. return '</s:selection>';
  537. }
  538. //SelectionContext::serializeStrings()
  539. //Produce a string of xml for the string table of a selection context.
  540. CSelectionContext.prototype.serializeStrings = function()
  541. {
  542. var sStringTable="<s:strings>";
  543. var i=0;
  544. for (var arrayName in this.stringTable) {
  545. for (i=0; i<this.stringTable[arrayName].length; i++) {
  546. sStringTable+='<s:s xml:id="';
  547. sStringTable+=arrayName;
  548. sStringTable+='_';
  549. sStringTable+=i;
  550. sStringTable+='">';
  551. sStringTable+=xml_encode(this.stringTable[arrayName][i]);
  552. sStringTable+='</s:s>';
  553. }
  554. }
  555. sStringTable+="</s:strings>";
  556. return sStringTable;
  557. }
  558. /*
  559. This is a helper method to write a selection context "reference attribute".
  560. The selection context has a large number of properties that are references to items in different tables.
  561. The form of these is r<PROPNAME>="<TYPE>_#" (where # is >= 0)
  562. @param sRefAttrName The name (eg: rName)
  563. @param sAttrType The type (eg: "N")
  564. @param nrAttr The # part of (TYPE_#). Note: If # is not a valid reference (<=0 or undefined), this method returns an empty string.
  565. @return A string <sRefAttrName>=<sAttrType>_<nrAttr> (or "" if # is not a valid reference)
  566. */
  567. CSelectionContext.prototype.serializeReferenceAttr = function(sRefAttrName, sAttrType, nrAttr)
  568. {
  569. var sReturn="";
  570. if (nrAttr != undefined && nrAttr >= 0) {
  571. sReturn = ' ' + sRefAttrName + '="' + sAttrType + "_" + nrAttr + '"';
  572. }
  573. return sReturn;
  574. }
  575. /*
  576. Produce a string of xml for the metadata table: (<s:metadataCells> and the list of its <s:metadataCell> objects)
  577. sample:
  578. <s:metadataCell xml:id="M_0" rQueryName="QN_0" rName="N_0" rExpression="QI_0" rType="T_0"/>
  579. </s:metadataCells>
  580. @param objMetadataTable The metadata table object representation from which the string will be generated.
  581. */
  582. CSelectionContext.prototype.serializeMetadataCells = function(objMetadataTable)
  583. {
  584. var sMetadataTable="<s:metadataCells>";
  585. //serialize each selectioncontextSchema_MetadataCell in the table....
  586. for (x=0; x<objMetadataTable.length; x++) {
  587. oMetadataCell = objMetadataTable[x];
  588. var sMetadataCellXML = '<s:metadataCell';
  589. sMetadataCellXML+=this.serializeReferenceAttr('xml:id', 'M', oMetadataCell.nXMLid);
  590. sMetadataCellXML+=this.serializeReferenceAttr('rQueryName', 'QN', oMetadataCell.nrQueryName);
  591. sMetadataCellXML+=this.serializeReferenceAttr('rName', 'N', oMetadataCell.nrName);
  592. sMetadataCellXML+=this.serializeReferenceAttr('rExpression','QI', oMetadataCell.nrExpression);
  593. sMetadataCellXML+=this.serializeReferenceAttr('rType', 'T', oMetadataCell.nrType);
  594. sMetadataCellXML+=this.serializeReferenceAttr('rUsage', 'U', oMetadataCell.nrUsage);
  595. //special properties for metadataCells....
  596. sMetadataCellXML+=this.serializeReferenceAttr('rDimensionUniqueName', 'D', oMetadataCell.nrDimensionUniqueName);
  597. sMetadataCellXML+=this.serializeReferenceAttr('rHierarchyUniqueName', 'H', oMetadataCell.nrHierarchyUniqueName);
  598. sMetadataCellXML+=this.serializeReferenceAttr('rLevelUniqueName', 'L', oMetadataCell.nrLevelUniqueName);
  599. sMetadataCellXML+="/>";
  600. sMetadataTable+=sMetadataCellXML;
  601. }
  602. sMetadataTable+="</s:metadataCells>";
  603. return sMetadataTable;
  604. }
  605. /*
  606. Serialize the contents of one schema cell, references to cells it is defined by and recursively serialize its dependents
  607. @param oSelectionContext The selection context to which provides helpers for writing reference attributes
  608. @return a string representing the xml for this cell including refernces mentioned above.
  609. */
  610. selectioncontextSchema_Cell.prototype.serialize = function(oSelectionContext)
  611. {
  612. var sCellXML ='<s:cell';
  613. sCellXML+= oSelectionContext.serializeReferenceAttr('xml:id', 'C', this.nXMLid);
  614. sCellXML+= oSelectionContext.serializeReferenceAttr('rMetadataCell', 'M', this.nrMetadataCell);
  615. sCellXML+= oSelectionContext.serializeReferenceAttr('rValue', 'V', this.nrValue);
  616. /**
  617. @TODO: Special properties for cells should be serialized here....
  618. **/
  619. if (this.displayValue != undefined) {
  620. sCellXML += ' display="';
  621. sCellXML += xml_encode(this.displayValue);
  622. sCellXML += '"';
  623. }
  624. //If either dependent or defining cells are defined, we need to close of the opening cell tag to append contents to it.
  625. if (this.definingCellAxisList.length > 0 || this.dependentCells.length > 0) {
  626. sCellXML += '>';
  627. }
  628. //If this cell has dependent cells serialize them...
  629. if (this.dependentCells.length > 0) {
  630. sCellXML += '<s:dependentCells>';
  631. for (var xx=0; xx < this.dependentCells.length; xx++) {
  632. sCellXML+=this.dependentCells[xx].serialize(oSelectionContext);
  633. }
  634. sCellXML += '</s:dependentCells>';
  635. }
  636. //If this cell has defining cells, serialize REFERENCES to them....
  637. if (this.definingCellAxisList.length > 0) {
  638. sCellXML += '<s:definingCells>';
  639. for (var xx=0; xx<this.definingCellAxisList.length; xx++) {
  640. sCellXML+='<s:axis';
  641. sCellXML+= oSelectionContext.serializeReferenceAttr('rCell', 'C', this.definingCellAxisList[xx].nrCell);
  642. if (this.definingCellAxisList[xx].nOrdinal != undefined) {
  643. sCellXML+= (' ordinal="' + this.definingCellAxisList[xx].nOrdinal + '"');
  644. }
  645. sCellXML += '/>';
  646. }
  647. sCellXML += '</s:definingCells>';
  648. }
  649. if (this.definingCellAxisList.length == 0 && this.dependentCells.length == 0) {
  650. sCellXML += "/>";
  651. } else {
  652. sCellXML += "</s:cell>";
  653. }
  654. return sCellXML;
  655. }
  656. /*
  657. CSelectionContext::serializeCells()
  658. Produce selection context XML representing all of the selectioncontextSchema_Cells in the cell table.
  659. Note: only non-dependent cells are written directly by this method. Dependents are written by their parent cells. (see serialize of the schema_Cell)
  660. @param objCells The full array of schema cells.
  661. */
  662. CSelectionContext.prototype.serializeCells = function(objCells)
  663. {
  664. var sCells="<s:cells>";
  665. for (var x=0; x<objCells.length; x++) {
  666. //serialize the main part of the cell
  667. var oscCell = objCells[x];
  668. if (oscCell.bDependentCell == true) {
  669. //dependent cells are serialized as part of the cell that they depend on.
  670. continue;
  671. }
  672. sCells += oscCell.serialize(this);
  673. }
  674. sCells+="</s:cells>";
  675. return sCells;
  676. }
  677. /*
  678. CSelectionContext::serializeSelectionContext
  679. @param objSelectionTree The input selection tree
  680. @return a string of XML that is the selection context corresponding to this tree.
  681. */
  682. CSelectionContext.prototype.toString = function(objSelectionTree)
  683. {
  684. //"select" the objects (by building an object set suitable for serialization as a selection context)
  685. this.prepareSchemaObjects();
  686. var sOutputSelectionContextXML= this.serializeHeader();
  687. sOutputSelectionContextXML+= this.serializeMetadataCells(this.metadataCells);
  688. sOutputSelectionContextXML+= this.serializeCells(this.cells);
  689. sOutputSelectionContextXML+= this.serializeStrings();
  690. sOutputSelectionContextXML+= this.serializeFooter();
  691. return sOutputSelectionContextXML;
  692. }
  693. /*
  694. method: oSelectionContext::addMetadataCell()
  695. Add a metadatacell object to the selection context output structure as well as any related strings to the string table.
  696. @param nNewMetadataIdx The index for this reference (xml:id=M_#)
  697. @param nNewNameIdx The index in the string table where the name for this cell is stored (rName="N_#")
  698. @param sMetadataModelItem The level unique name (for OLAP)
  699. */
  700. CSelectionContext.prototype.addMetadataCell = function(nNewMetadataIdx, nNewNameIdx, oCell)
  701. {
  702. var nNewTypeIdx=this.addString("T", oCell.useValueType);
  703. if (oCell.metadataModelItem != '') {
  704. //Add a new lun entry to the sting table and a reference to that lun in the metadataCell
  705. var nNewQueryNameIdx =this.addString("QN",oCell.queryName);
  706. var nNewQIIdx =this.addString("QI", oCell.metadataModelItem);
  707. var nNewTypeIdx =this.addString("T", oCell.useValueType);
  708. var nNewUsageIdx =this.addString("U", oCell.usage);
  709. this.metadataCells[nNewMetadataIdx]= new selectioncontextSchema_MetadataCell(nNewMetadataIdx, nNewNameIdx, nNewQIIdx, nNewTypeIdx, nNewUsageIdx, nNewQueryNameIdx);
  710. //Add special properties to the metadata cell (if any)
  711. if (oCell.LevelUniqueName != undefined && oCell.LevelUniqueName != null) {
  712. var nNewLunIdx = this.addString("L", oCell.LevelUniqueName);
  713. this.metadataCells[nNewMetadataIdx].nrLevelUniqueName = nNewLunIdx;
  714. }
  715. if (oCell.HierarchyUniqueName != undefined && oCell.HierarchyUniqueName != null ) {
  716. var nNewHunIdx = this.addString("H", oCell.HierarchyUniqueName);
  717. this.metadataCells[nNewMetadataIdx].nrHierarchyUniqueName = nNewHunIdx;
  718. }
  719. if (oCell.DimensionUniqueName != undefined && oCell.DimensionUniqueName != null ) {
  720. var nNewDunIdx = this.addString("D", oCell.DimensionUniqueName);
  721. this.metadataCells[nNewMetadataIdx].nrDimensionUniqueName = nNewDunIdx;
  722. }
  723. } else {
  724. this.metadataCells[nNewMetadataIdx]= new selectioncontextSchema_MetadataCell(nNewMetadataIdx, nNewNameIdx, -1, nNewTypeIdx);
  725. }
  726. }
  727. /*
  728. xml encodes the string that is passed to it
  729. @param str The string to be xml encoded (all non-string values will be returned unaltered.)
  730. @return encoded string
  731. */
  732. function xml_encode(str) {
  733. //Since we call this function for the optional parameters in the interface as wellwe need to have this guard
  734. if (str!=null && typeof str == 'string'){
  735. return str.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&apos;");
  736. }
  737. return str;
  738. }