lineageDiagram.js 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773
  1. /****************************************************************
  2. ** Licensed Materials - Property of IBM
  3. **
  4. ** IBM Cognos Products: mdsrv
  5. **
  6. ** (C) Copyright IBM Corp. 2008, 2014
  7. **
  8. ** US Government Users Restricted Rights - Use, duplication or disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
  9. *****************************************************************/
  10. //***********************************************************************************************
  11. // Copyright (C) 2008 Cognos ULC, an IBM Company. All rights reserved.
  12. // Cognos (R) is a trademark of Cognos ULC, (formerly Cognos Incorporated).
  13. //
  14. // Component: Wrapper classes to support the lineage diagram API needs
  15. //***********************************************************************************************
  16. // Declare the LINEAGE namespace
  17. if ( ! LNS )
  18. var LNS = {};
  19. // Global constants
  20. LNS.typeDataItem = "dataItem";
  21. LNS.typeReportItem = "reportItem";
  22. LNS.typeObjectSubclassRegular = "regular";
  23. LNS.sReportID = "[Report]";
  24. LNS.sPaneReportResId = "report";
  25. LNS.sPanePackageResId = "package";
  26. LNS.sPaneDatabaseResId = "dataSources";
  27. LNS.sPaneReportName = "Report";
  28. LNS.sPanePackageName = "Package";
  29. LNS.sPaneDatabaseName = "Data Sources";
  30. LNS.sObjectLocationByType = [];
  31. LNS.sObjectLocationByType["query"] = 'report';
  32. LNS.sObjectLocationByType["dataItem"] = 'report';
  33. LNS.sObjectLocationByType["reportItem"] = 'report';
  34. LNS.sObjectLocationByType["summaryFilter"] = 'report';
  35. LNS.sObjectLocationByType["detailFilter"] = 'report';
  36. LNS.sObjectLocationByType["dataSource"] = 'datasources';
  37. LNS.mapAllowedParentTypes = [];
  38. LNS.mapAllowedParentTypes["querySubject"] = true;
  39. LNS.mapAllowedParentTypes["dimension"] = true;
  40. LNS.mapAllowedParentTypes["query"] = true;
  41. LNS.mapIgnoreShortcutsByType = [];
  42. LNS.mapIgnoreShortcutsByType["detailFilter"] = true;
  43. LNS.mapIgnoreShortcutsByType["filterDefinition"] = true;
  44. LNS.mapIgnoreShortcutsByType["summaryFilter"] = true;
  45. LNS.mapIgnoreShortcutsByType["slicerMemberSet"] = true;
  46. LNS.mapIgnoreShortcutsByType["reportItem"] = true;
  47. /***************************************************************
  48. * CModelData
  49. ***************************************************************/
  50. function CModelData ( mdsrv_LineageResponseHelper )
  51. {
  52. this.responseHelper = mdsrv_LineageResponseHelper;
  53. this.arrNodes = new Array(); // only the main container object to display in the digram are in this list
  54. this.arrNodes.numberOfRegisteredObjects = 0;
  55. this.mapObjectInclusionById = new Array();
  56. this.arrConnections = new Array();
  57. this.mapConnectionNames = new Array(); // to prevent duplicate connections
  58. this.arrRegisteredObjects = new Array(); // all objects are in this list
  59. this.paneNames = new Array();
  60. this.arrParentModelObjects = new Array();
  61. // walk through the transformations and build up a
  62. // list of diagram node connections. While we visit
  63. // each node we will add the 'query parent' of each
  64. // lineage object to a list and mark it as visited
  65. // We all add a special shortcut node to represent the selected items
  66. var lineageObjs = this.responseHelper.getQueryResults();
  67. for ( var i = 0; i < lineageObjs.length; i++ )
  68. {
  69. this.examineForChildRefs( lineageObjs[i] );
  70. }
  71. // Now add the rest of the child items that were not included in the transformations
  72. this.processChildren ();
  73. }
  74. //This function will check if the given lineage obj has no transformation and contains children
  75. //if so, it will go through all children (including grandchildren), looking for an object
  76. //which has no children, that object will be added to the diagram, via examineLineageObj
  77. //This handles the case where a QuerySubject was selected for lienage, this code will go through
  78. //and get all the query items [also handling the scenario where there may be queryItemFolders]
  79. CModelData.prototype.examineForChildRefs = function( lineageObj )
  80. {
  81. var hasChildren = false;
  82. var childObjIds = lineageObj.getChildRefs();
  83. if ( childObjIds && childObjIds.length > 0 )
  84. {
  85. hasChildren = true;
  86. }
  87. //if it doens't have children, then use that object
  88. if ( ! hasChildren )
  89. {
  90. this.examineLineageObject( lineageObj );
  91. }
  92. else
  93. {
  94. //only go after the children if we don't have a transformation
  95. var hasTrans = false;
  96. var trans = lineageObj.getTransformation();
  97. if ( trans )
  98. {
  99. var sources = trans.getTransformationSourceList();
  100. // alert( "examineForChildRefs: Transformation sources no. = " + sources.length );
  101. if ( sources && sources.length > 0 )
  102. {
  103. hasTrans = true;
  104. }
  105. }
  106. if ( hasTrans )
  107. {
  108. this.examineLineageObject( lineageObj );
  109. }
  110. else
  111. {
  112. //examine the lineage of the child objects
  113. for (var childIdx = 0; childIdx < childObjIds.length; childIdx++)
  114. {
  115. var childObj = this.responseHelper.lookup( childObjIds[childIdx] );
  116. this.examineForChildRefs( childObj );
  117. }
  118. }
  119. }
  120. }
  121. CModelData.prototype.examineLineageObject = function( lineageObj )
  122. {
  123. // alert ( "examineLineageObject: <" + lineageObj.m_name + "> of type <" + lineageObj.m_type + ">" );
  124. var nColumnIndex = 0;
  125. var scObj = this.registerShortcutObject( lineageObj );
  126. if ( scObj )
  127. {
  128. var bAdded = this.addToNodes( scObj );
  129. if ( bAdded )
  130. {
  131. this.addConnection( scObj.getId(), lineageObj.getId() );
  132. scObj.nColumnIndex = nColumnIndex++;
  133. }
  134. }
  135. var modelObj = this.registerObject( lineageObj );
  136. modelObj.setMainObject( nColumnIndex === 0 );
  137. this.visitObject( modelObj, nColumnIndex );
  138. }
  139. /*********************************************************************
  140. * register an object and return a new CModelObject or the
  141. * one previously registered for the lineage objects
  142. * inputs
  143. * lineageObj - type mdsrv_lineageObj
  144. * returns
  145. * type CModelObject
  146. *********************************************************************/
  147. CModelData.prototype.registerObject = function( lineageObj )
  148. {
  149. var bNew = false;
  150. var modelObj = this.arrRegisteredObjects[ lineageObj.getId() ];
  151. if ( ! modelObj )
  152. {
  153. modelObj = new CModelObject( lineageObj );
  154. bNew = true;
  155. this.arrRegisteredObjects[ modelObj.getId() ] = modelObj;
  156. if ( Array.indexOf( this.paneNames, modelObj.getObjLocation() ) === -1 )
  157. this.paneNames[ this.paneNames.length ] = modelObj.getObjLocation();
  158. modelObj.isPackageDataSourceObject();
  159. }
  160. modelObj.bNew = bNew;
  161. return modelObj;
  162. }
  163. /*************************************************************************
  164. * register a shortcut for an object and return a new CModelObject or the
  165. * one previously registered
  166. * inputs
  167. * lineageObj - type mdsrv_lineageObj
  168. * returns
  169. * type CModelObject
  170. ************************************************************************/
  171. CModelData.prototype.registerShortcutObject = function( lineageObj )
  172. {
  173. if ( ! LNS.mapIgnoreShortcutsByType[ lineageObj.m_type ] )
  174. {
  175. var modelObj = this.registerObject( lineageObj );
  176. if ( modelObj.bNew )
  177. {
  178. var shortcutModelObj = new CModelObject( lineageObj, modelObj );
  179. this.arrRegisteredObjects[ shortcutModelObj.getId() ] = shortcutModelObj;
  180. return shortcutModelObj;
  181. }
  182. }
  183. // alert ( "registerShortcutObject: omitted object of type <" + lineageObj.m_type + ">" );
  184. return null;
  185. }
  186. CModelData.prototype.addObject = function( refObjId, origModelObj, bIncrementColumnIndex )
  187. {
  188. var refLinObj = this.responseHelper.lookup( refObjId );
  189. ASSERT ( refLinObj, "responseHelper.lookup: object '" + refObjId + "' is not found in the lineage response !!!" );
  190. if ( refLinObj )
  191. {
  192. this.addConnection( origModelObj.getId(), refObjId );
  193. var refModelObj = this.registerObject( refLinObj );
  194. if ( refModelObj.bNew )
  195. {
  196. var nNewIndex = bIncrementColumnIndex ? origModelObj.nColumnIndex + 1 : origModelObj.nColumnIndex;
  197. // refModelObj.nColumnIndex = nNewIndex; // ??
  198. if ( origModelObj.getObjLocation() != refModelObj.getObjLocation() )
  199. {
  200. // we are making the transition from a report to model or to data source
  201. // so reset the column index
  202. nNewIndex = 0;
  203. }
  204. this.visitObject( refModelObj, nNewIndex );
  205. }
  206. }
  207. }
  208. CModelData.prototype.visitObject = function( modelObj, nColumnIndex )
  209. {
  210. // get the query parent (dimension or query subject) if it has one.
  211. // If there is no query parent then consider it a standalone object
  212. // alert ( "visitObject: " + modelObj.getId() + " of type <" + modelObj.getObjClass() + ">" );
  213. modelObj.nColumnIndex = nColumnIndex;
  214. if ( ! this.visitParent( modelObj ) )
  215. {
  216. this.addToNodes( modelObj );
  217. }
  218. var transformationObj = modelObj.lineageObj.getTransformation();
  219. var bHasReferences = transformationObj && transformationObj.getTransformationSourceList().length > 0;
  220. if ( bHasReferences )
  221. {
  222. var transObjs = transformationObj.getTransformationSourceList();
  223. // alert( "visitObject: Transformation sources no. = " + transObjs.length );
  224. for ( var nIndex = 0; nIndex < transObjs.length; ++nIndex )
  225. {
  226. var refObjId = transObjs[ nIndex ].getObjectRef();
  227. this.addObject ( refObjId, modelObj, true );
  228. }
  229. }
  230. else // only go after the children if the object does not have references
  231. {
  232. var childObjIds = modelObj.lineageObj.getChildRefs();
  233. // traverse the lineage of the child objects
  234. for ( var nIndex = 0; nIndex < childObjIds.length; ++nIndex )
  235. {
  236. var refChildObjId = childObjIds[ nIndex ];
  237. this.addObject ( refChildObjId, modelObj, false );
  238. }
  239. }
  240. }
  241. CModelData.prototype.addConnection = function( leftId, rightId )
  242. {
  243. var sConnName = leftId + "-&&-" + rightId;
  244. if ( ! this.mapConnectionNames[ sConnName ] )
  245. {
  246. this.arrConnections[ this.arrConnections.length ] = [ leftId, rightId ];
  247. this.mapConnectionNames[ sConnName ] = true;
  248. }
  249. }
  250. CModelData.prototype.registerConnections = function ( origModelObj )
  251. {
  252. // alert ( "registerConnections: <" + origModelObj.getId() + "> of type <" + origModelObj.getObjClass() + ">" );
  253. transformationObj = origModelObj.lineageObj.getTransformation();
  254. if ( transformationObj )
  255. {
  256. var transObjs = transformationObj.getTransformationSourceList();
  257. for ( var t = 0; t < transObjs.length; t++)
  258. {
  259. var refObjId = transObjs[t].getObjectRef();
  260. var refModelObj = this.registerObject( this.responseHelper.lookup( refObjId ) );
  261. // alert ( "registerConnections: Ref Object " + refModelObj.getId() + " of type <" + refModelObj.getObjClass() + ">" );
  262. this.addConnection( origModelObj.getId(), refModelObj.getId() );
  263. }
  264. }
  265. }
  266. CModelData.prototype.processChildren = function()
  267. {
  268. for ( var i = 0; i < this.arrParentModelObjects.length; i++ )
  269. {
  270. var parentModelObj = this.arrParentModelObjects[i];
  271. var childObjIds = parentModelObj.lineageObj.getChildRefs();
  272. // Add the children to the Parent (Note: some children may have already been added on transformation unwinding)
  273. for ( var j = 0; j < childObjIds.length; j++ )
  274. {
  275. var lineageObject = this.responseHelper.lookup( childObjIds[j] );
  276. if ( lineageObject )
  277. {
  278. var childModelObj = this.registerObject( lineageObject );
  279. if ( childModelObj.bNew )
  280. {
  281. // alert( childModelObj.getName() + " is NEW object, nColumnIndex = " + parentModelObj.nColumnIndex + ", Parent = " + parentModelObj.getName() );
  282. this.visitObject ( childModelObj, parentModelObj.nColumnIndex );
  283. }
  284. }
  285. }
  286. }
  287. }
  288. CModelData.prototype.visitParent = function( modelObj )
  289. {
  290. var bAddedParent = false;
  291. var currentLinObj = modelObj.lineageObj;
  292. while ( true )
  293. {
  294. var parentObjId = currentLinObj.getParentRef();
  295. if ( ! parentObjId || parentObjId === "null" || parentObjId === LNS.sReportID )
  296. break;
  297. var parentLinObj = this.responseHelper.lookup( parentObjId );
  298. var type = parentLinObj.getType();
  299. if ( LNS.mapAllowedParentTypes[ type ] )
  300. {
  301. var childObjIds = parentLinObj.getChildRefs();
  302. // alert ( "visitParent: <" + parentObjId + "> of type <" + type + "> children = " + childObjIds.length );
  303. var parentModelObj = this.registerObject( parentLinObj );
  304. bAddedParent = true;
  305. if ( parentModelObj.bNew )
  306. {
  307. this.arrParentModelObjects.push( parentModelObj );
  308. this.addToNodes( parentModelObj );
  309. if ( parentModelObj.nColumnIndex === 0 )
  310. {
  311. parentModelObj.nColumnIndex = modelObj.nColumnIndex; // the parent always takes the first child column index
  312. }
  313. }
  314. parentModelObj.addChild( modelObj );
  315. break;
  316. }
  317. currentLinObj = parentLinObj;
  318. }
  319. return bAddedParent;
  320. }
  321. CModelData.prototype.addToNodes = function( modelObj )
  322. {
  323. var bAdded = false;
  324. var objId = modelObj.getId();
  325. if ( ! this.mapObjectInclusionById[ objId ] )
  326. {
  327. this.arrNodes[ objId ] = this.arrRegisteredObjects[ objId ];
  328. this.arrNodes[ this.arrNodes.numberOfRegisteredObjects ] = this.arrRegisteredObjects[ objId ];
  329. this.arrNodes.numberOfRegisteredObjects++;
  330. this.mapObjectInclusionById[ objId ] = true;
  331. bAdded = true;
  332. }
  333. return bAdded;
  334. }
  335. CModelData.prototype.getPaneCount = function()
  336. {
  337. return this.paneNames.length;
  338. }
  339. CModelData.prototype.getPaneName = function( i )
  340. {
  341. return this.paneNames[ i ];
  342. }
  343. /******************************************************
  344. * CModelData public methods
  345. ******************************************************/
  346. CModelData.prototype.getQueryCount = function ()
  347. {
  348. return this.arrNodes.numberOfRegisteredObjects;
  349. //return arrayLen( this.arrNodes );
  350. }
  351. CModelData.prototype.getObjectCount = function ()
  352. {
  353. return this.arrNodes.numberOfRegisteredObjects;
  354. }
  355. CModelData.prototype.getQuery = function ( i )
  356. {
  357. return this.arrNodes[i];
  358. }
  359. CModelData.prototype.getObject = function ( i )
  360. {
  361. return this.arrNodes[i];
  362. }
  363. CModelData.prototype.getConnectionCount = function()
  364. {
  365. return this.arrConnections.length;
  366. }
  367. CModelData.prototype.getConnection = function( i )
  368. {
  369. return this.arrConnections[i];
  370. }
  371. CModelData.prototype.getConnectionLeft = function( i )
  372. {
  373. return this.arrConnections[i][0];
  374. }
  375. CModelData.prototype.getConnectionRight = function( i )
  376. {
  377. return this.arrConnections[i][1];
  378. }
  379. /*******************************************************
  380. * CModelObject
  381. *
  382. * This class is a wrapper for the MDSRV_LineageObject to
  383. * deal with diagram specific requirements
  384. *
  385. ******************************************************/
  386. function CModelObject( mdsrv_LineageObject, modelObject )
  387. {
  388. this.lineageObj = mdsrv_LineageObject;
  389. this.shortcutTo = null;
  390. this.nColumnIndex = 0;
  391. this.bMain = false;
  392. if ( modelObject )
  393. {
  394. // if the modelObject is not NULL then this object is a shortcut to the modelObject
  395. this.shortcutTo = modelObject;
  396. }
  397. }
  398. CModelObject.prototype.getItemCount = function()
  399. {
  400. if ( this.model_data_childList )
  401. {
  402. return this.model_data_childList.numberOfRegisteredObjects;
  403. }
  404. return 0;
  405. }
  406. CModelObject.prototype.getItem = function( i )
  407. {
  408. if ( this.model_data_childList )
  409. {
  410. return this.model_data_childList[i];
  411. }
  412. return null;
  413. }
  414. CModelObject.prototype.addChild = function( childObj )
  415. {
  416. if ( ! this.model_data_childList )
  417. {
  418. this.mapChildInclusionById = new Array();
  419. this.model_data_childList = new Array();
  420. this.model_data_childList.numberOfRegisteredObjects = 0;
  421. }
  422. if ( ! this.mapChildInclusionById[ childObj.getId() ] )
  423. {
  424. this.model_data_childList[ childObj.getId() ] = childObj;
  425. this.model_data_childList[ this.model_data_childList.numberOfRegisteredObjects ] = childObj;
  426. this.model_data_childList.numberOfRegisteredObjects++;
  427. this.mapChildInclusionById[ childObj.getId() ] = true;
  428. }
  429. }
  430. CModelObject.prototype.getPropertyCount = function()
  431. {
  432. var propArray = this.lineageObj.getProperties();
  433. //return arrayLen( propArray );
  434. return propArray.length;
  435. }
  436. //CModelObject.prototype.getProperty = function( i ) {
  437. // return arrayItemAtIndex( this.lineageObj.getProperties(), i );
  438. //}
  439. CModelObject.prototype.getPropertyName = function( nProp )
  440. {
  441. var propArray = this.lineageObj.getProperties();
  442. return propArray[nProp].getName();
  443. //var prop = arrayItemAtIndex( this.lineageObj.getProperties(), nProp );
  444. //return prop.getName();
  445. }
  446. CModelObject.prototype.getPropertyDisplayName = function( nProp )
  447. {
  448. var propArray = this.lineageObj.getProperties();
  449. return propArray[nProp].getDisplayName();
  450. }
  451. CModelObject.prototype.getPropertyValue = function( nProp )
  452. {
  453. var propArray = this.lineageObj.getProperties();
  454. return propArray[nProp].getValue();
  455. }
  456. CModelObject.prototype.findPropertyValue = function ( sPropName )
  457. {
  458. var sPropValue = "";
  459. var cProperties = this.getPropertyCount();
  460. for ( var i = 0; i < cProperties; i++ )
  461. {
  462. // alert ( this.getPropertyDisplayName(i) + ' = ' + this.getPropertyValue(i) );
  463. if ( this.getPropertyName(i) === sPropName )
  464. {
  465. sPropValue = this.getPropertyValue(i);
  466. break;
  467. }
  468. }
  469. return sPropValue;
  470. }
  471. CModelObject.prototype.isPackageDataSourceObject = function ()
  472. {
  473. this.bPackageDataSourceObject = false;
  474. var sPropValue = this.findPropertyValue( 'definitionType' );
  475. if ( sPropValue === 'Data Source' )
  476. {
  477. this.bPackageDataSourceObject = true;
  478. }
  479. else
  480. {
  481. sPropValue = this.findPropertyValue( 'externalName' );
  482. if ( sPropValue.length > 0 )
  483. this.bPackageDataSourceObject = true;
  484. }
  485. // if ( this.bPackageDataSourceObject )
  486. // alert( 'Object "' + this.lineageObj.getName() + '" isPackageDataSourceObject' );
  487. return this.bPackageDataSourceObject;
  488. }
  489. // Return whether the lineage object comes from a report, model or data source
  490. CModelObject.prototype.getObjLocation = function()
  491. {
  492. var sObjectLocation = LNS.sObjectLocationByType[ this.lineageObj.getType() ];
  493. // this is a hack. sObjectLocation can be only "report" or "datasources". For this.lineageObj.getType() = filter
  494. // sObjectLocation = filter() . Looks like it finds a function with this name, but I coudn't find the function??
  495. // so there is the hack.
  496. if (sObjectLocation != "report" && sObjectLocation != "datasources")
  497. sObjectLocation = null;
  498. if ( ! sObjectLocation )
  499. sObjectLocation = LNS.sPanePackageResId;
  500. var sPaneName = MDSRV_techView_StringManager.stringLookup( sObjectLocation );
  501. return sPaneName;
  502. }
  503. CModelObject.prototype.isReportPane = function()
  504. {
  505. return ( this.getObjLocation() === LNS.sPaneReportName );
  506. }
  507. CModelObject.prototype.isModelPane = function()
  508. {
  509. return ( this.getObjLocation() === LNS.sPanePackageName );
  510. }
  511. CModelObject.prototype.isDatabasePane = function()
  512. {
  513. return ( this.getObjLocation() === LNS.sPaneDatabaseName );
  514. }
  515. // XXXXXXXXXXXXX deprecate
  516. CModelObject.prototype.getPaneName = function()
  517. {
  518. return this.getObjLocation();
  519. }
  520. CModelObject.prototype.setMainObject = function( bMain )
  521. {
  522. this.bMain = ( true ? bMain === true : false );
  523. }
  524. CModelObject.prototype.isMainObject = function()
  525. {
  526. var bRet = false;
  527. if ( this.bMain || this.shortcutTo )
  528. {
  529. bRet = true;
  530. }
  531. return bRet;
  532. }
  533. CModelObject.prototype.getColumnIndex = function()
  534. {
  535. var nColumnIndex = 0;
  536. if ( this.nColumnIndex )
  537. {
  538. nColumnIndex = this.nColumnIndex;
  539. }
  540. return nColumnIndex;
  541. }
  542. CModelObject.prototype.isRootObject = function()
  543. {
  544. return ( this.nColumnIndex === 0 );
  545. }
  546. CModelObject.prototype.getObjClass = function()
  547. {
  548. return this.lineageObj.getType();
  549. }
  550. CModelObject.prototype.getObjSubClass = function()
  551. {
  552. return LNS.typeObjectSubclassRegular;
  553. }
  554. CModelObject.prototype.getName = function()
  555. {
  556. return this.lineageObj.getName();
  557. }
  558. CModelObject.prototype.getShortcutTo = function()
  559. {
  560. if ( this.shortcutTo )
  561. {
  562. return this.shortcutTo;
  563. }
  564. return null;
  565. }
  566. CModelObject.prototype.getId = function()
  567. {
  568. var id = this.lineageObj.getId();
  569. if ( this.shortcutTo )
  570. {
  571. id = '_' + id;
  572. }
  573. return id;
  574. }
  575. CModelObject.prototype.findObjectById = function( objectArray, objId )
  576. {
  577. var index = -1;
  578. for ( var i = 0; i < objectArray.length; i++ )
  579. {
  580. if ( objectArray[i].getId() === objId )
  581. {
  582. index = i;
  583. break;
  584. }
  585. }
  586. return index;
  587. }