/**************************************************************** ** Licensed Materials - Property of IBM ** ** IBM Cognos Products: mdsrv ** ** (C) Copyright IBM Corp. 2008, 2014 ** ** 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). // // Component: Wrapper classes to support the lineage diagram API needs //*********************************************************************************************** // Declare the LINEAGE namespace if ( ! LNS ) var LNS = {}; // Global constants LNS.typeDataItem = "dataItem"; LNS.typeReportItem = "reportItem"; LNS.typeObjectSubclassRegular = "regular"; LNS.sReportID = "[Report]"; LNS.sPaneReportResId = "report"; LNS.sPanePackageResId = "package"; LNS.sPaneDatabaseResId = "dataSources"; LNS.sPaneReportName = "Report"; LNS.sPanePackageName = "Package"; LNS.sPaneDatabaseName = "Data Sources"; LNS.sObjectLocationByType = []; LNS.sObjectLocationByType["query"] = 'report'; LNS.sObjectLocationByType["dataItem"] = 'report'; LNS.sObjectLocationByType["reportItem"] = 'report'; LNS.sObjectLocationByType["summaryFilter"] = 'report'; LNS.sObjectLocationByType["detailFilter"] = 'report'; LNS.sObjectLocationByType["dataSource"] = 'datasources'; LNS.mapAllowedParentTypes = []; LNS.mapAllowedParentTypes["querySubject"] = true; LNS.mapAllowedParentTypes["dimension"] = true; LNS.mapAllowedParentTypes["query"] = true; LNS.mapIgnoreShortcutsByType = []; LNS.mapIgnoreShortcutsByType["detailFilter"] = true; LNS.mapIgnoreShortcutsByType["filterDefinition"] = true; LNS.mapIgnoreShortcutsByType["summaryFilter"] = true; LNS.mapIgnoreShortcutsByType["slicerMemberSet"] = true; LNS.mapIgnoreShortcutsByType["reportItem"] = true; /*************************************************************** * CModelData ***************************************************************/ function CModelData ( mdsrv_LineageResponseHelper ) { this.responseHelper = mdsrv_LineageResponseHelper; this.arrNodes = new Array(); // only the main container object to display in the digram are in this list this.arrNodes.numberOfRegisteredObjects = 0; this.mapObjectInclusionById = new Array(); this.arrConnections = new Array(); this.mapConnectionNames = new Array(); // to prevent duplicate connections this.arrRegisteredObjects = new Array(); // all objects are in this list this.paneNames = new Array(); this.arrParentModelObjects = new Array(); // walk through the transformations and build up a // list of diagram node connections. While we visit // each node we will add the 'query parent' of each // lineage object to a list and mark it as visited // We all add a special shortcut node to represent the selected items var lineageObjs = this.responseHelper.getQueryResults(); for ( var i = 0; i < lineageObjs.length; i++ ) { this.examineForChildRefs( lineageObjs[i] ); } // Now add the rest of the child items that were not included in the transformations this.processChildren (); } //This function will check if the given lineage obj has no transformation and contains children //if so, it will go through all children (including grandchildren), looking for an object //which has no children, that object will be added to the diagram, via examineLineageObj //This handles the case where a QuerySubject was selected for lienage, this code will go through //and get all the query items [also handling the scenario where there may be queryItemFolders] CModelData.prototype.examineForChildRefs = function( lineageObj ) { var hasChildren = false; var childObjIds = lineageObj.getChildRefs(); if ( childObjIds && childObjIds.length > 0 ) { hasChildren = true; } //if it doens't have children, then use that object if ( ! hasChildren ) { this.examineLineageObject( lineageObj ); } else { //only go after the children if we don't have a transformation var hasTrans = false; var trans = lineageObj.getTransformation(); if ( trans ) { var sources = trans.getTransformationSourceList(); // alert( "examineForChildRefs: Transformation sources no. = " + sources.length ); if ( sources && sources.length > 0 ) { hasTrans = true; } } if ( hasTrans ) { this.examineLineageObject( lineageObj ); } else { //examine the lineage of the child objects for (var childIdx = 0; childIdx < childObjIds.length; childIdx++) { var childObj = this.responseHelper.lookup( childObjIds[childIdx] ); this.examineForChildRefs( childObj ); } } } } CModelData.prototype.examineLineageObject = function( lineageObj ) { // alert ( "examineLineageObject: <" + lineageObj.m_name + "> of type <" + lineageObj.m_type + ">" ); var nColumnIndex = 0; var scObj = this.registerShortcutObject( lineageObj ); if ( scObj ) { var bAdded = this.addToNodes( scObj ); if ( bAdded ) { this.addConnection( scObj.getId(), lineageObj.getId() ); scObj.nColumnIndex = nColumnIndex++; } } var modelObj = this.registerObject( lineageObj ); modelObj.setMainObject( nColumnIndex === 0 ); this.visitObject( modelObj, nColumnIndex ); } /********************************************************************* * register an object and return a new CModelObject or the * one previously registered for the lineage objects * inputs * lineageObj - type mdsrv_lineageObj * returns * type CModelObject *********************************************************************/ CModelData.prototype.registerObject = function( lineageObj ) { var bNew = false; var modelObj = this.arrRegisteredObjects[ lineageObj.getId() ]; if ( ! modelObj ) { modelObj = new CModelObject( lineageObj ); bNew = true; this.arrRegisteredObjects[ modelObj.getId() ] = modelObj; if ( Array.indexOf( this.paneNames, modelObj.getObjLocation() ) === -1 ) this.paneNames[ this.paneNames.length ] = modelObj.getObjLocation(); modelObj.isPackageDataSourceObject(); } modelObj.bNew = bNew; return modelObj; } /************************************************************************* * register a shortcut for an object and return a new CModelObject or the * one previously registered * inputs * lineageObj - type mdsrv_lineageObj * returns * type CModelObject ************************************************************************/ CModelData.prototype.registerShortcutObject = function( lineageObj ) { if ( ! LNS.mapIgnoreShortcutsByType[ lineageObj.m_type ] ) { var modelObj = this.registerObject( lineageObj ); if ( modelObj.bNew ) { var shortcutModelObj = new CModelObject( lineageObj, modelObj ); this.arrRegisteredObjects[ shortcutModelObj.getId() ] = shortcutModelObj; return shortcutModelObj; } } // alert ( "registerShortcutObject: omitted object of type <" + lineageObj.m_type + ">" ); return null; } CModelData.prototype.addObject = function( refObjId, origModelObj, bIncrementColumnIndex ) { var refLinObj = this.responseHelper.lookup( refObjId ); ASSERT ( refLinObj, "responseHelper.lookup: object '" + refObjId + "' is not found in the lineage response !!!" ); if ( refLinObj ) { this.addConnection( origModelObj.getId(), refObjId ); var refModelObj = this.registerObject( refLinObj ); if ( refModelObj.bNew ) { var nNewIndex = bIncrementColumnIndex ? origModelObj.nColumnIndex + 1 : origModelObj.nColumnIndex; // refModelObj.nColumnIndex = nNewIndex; // ?? if ( origModelObj.getObjLocation() != refModelObj.getObjLocation() ) { // we are making the transition from a report to model or to data source // so reset the column index nNewIndex = 0; } this.visitObject( refModelObj, nNewIndex ); } } } CModelData.prototype.visitObject = function( modelObj, nColumnIndex ) { // get the query parent (dimension or query subject) if it has one. // If there is no query parent then consider it a standalone object // alert ( "visitObject: " + modelObj.getId() + " of type <" + modelObj.getObjClass() + ">" ); modelObj.nColumnIndex = nColumnIndex; if ( ! this.visitParent( modelObj ) ) { this.addToNodes( modelObj ); } var transformationObj = modelObj.lineageObj.getTransformation(); var bHasReferences = transformationObj && transformationObj.getTransformationSourceList().length > 0; if ( bHasReferences ) { var transObjs = transformationObj.getTransformationSourceList(); // alert( "visitObject: Transformation sources no. = " + transObjs.length ); for ( var nIndex = 0; nIndex < transObjs.length; ++nIndex ) { var refObjId = transObjs[ nIndex ].getObjectRef(); this.addObject ( refObjId, modelObj, true ); } } else // only go after the children if the object does not have references { var childObjIds = modelObj.lineageObj.getChildRefs(); // traverse the lineage of the child objects for ( var nIndex = 0; nIndex < childObjIds.length; ++nIndex ) { var refChildObjId = childObjIds[ nIndex ]; this.addObject ( refChildObjId, modelObj, false ); } } } CModelData.prototype.addConnection = function( leftId, rightId ) { var sConnName = leftId + "-&&-" + rightId; if ( ! this.mapConnectionNames[ sConnName ] ) { this.arrConnections[ this.arrConnections.length ] = [ leftId, rightId ]; this.mapConnectionNames[ sConnName ] = true; } } CModelData.prototype.registerConnections = function ( origModelObj ) { // alert ( "registerConnections: <" + origModelObj.getId() + "> of type <" + origModelObj.getObjClass() + ">" ); transformationObj = origModelObj.lineageObj.getTransformation(); if ( transformationObj ) { var transObjs = transformationObj.getTransformationSourceList(); for ( var t = 0; t < transObjs.length; t++) { var refObjId = transObjs[t].getObjectRef(); var refModelObj = this.registerObject( this.responseHelper.lookup( refObjId ) ); // alert ( "registerConnections: Ref Object " + refModelObj.getId() + " of type <" + refModelObj.getObjClass() + ">" ); this.addConnection( origModelObj.getId(), refModelObj.getId() ); } } } CModelData.prototype.processChildren = function() { for ( var i = 0; i < this.arrParentModelObjects.length; i++ ) { var parentModelObj = this.arrParentModelObjects[i]; var childObjIds = parentModelObj.lineageObj.getChildRefs(); // Add the children to the Parent (Note: some children may have already been added on transformation unwinding) for ( var j = 0; j < childObjIds.length; j++ ) { var lineageObject = this.responseHelper.lookup( childObjIds[j] ); if ( lineageObject ) { var childModelObj = this.registerObject( lineageObject ); if ( childModelObj.bNew ) { // alert( childModelObj.getName() + " is NEW object, nColumnIndex = " + parentModelObj.nColumnIndex + ", Parent = " + parentModelObj.getName() ); this.visitObject ( childModelObj, parentModelObj.nColumnIndex ); } } } } } CModelData.prototype.visitParent = function( modelObj ) { var bAddedParent = false; var currentLinObj = modelObj.lineageObj; while ( true ) { var parentObjId = currentLinObj.getParentRef(); if ( ! parentObjId || parentObjId === "null" || parentObjId === LNS.sReportID ) break; var parentLinObj = this.responseHelper.lookup( parentObjId ); var type = parentLinObj.getType(); if ( LNS.mapAllowedParentTypes[ type ] ) { var childObjIds = parentLinObj.getChildRefs(); // alert ( "visitParent: <" + parentObjId + "> of type <" + type + "> children = " + childObjIds.length ); var parentModelObj = this.registerObject( parentLinObj ); bAddedParent = true; if ( parentModelObj.bNew ) { this.arrParentModelObjects.push( parentModelObj ); this.addToNodes( parentModelObj ); if ( parentModelObj.nColumnIndex === 0 ) { parentModelObj.nColumnIndex = modelObj.nColumnIndex; // the parent always takes the first child column index } } parentModelObj.addChild( modelObj ); break; } currentLinObj = parentLinObj; } return bAddedParent; } CModelData.prototype.addToNodes = function( modelObj ) { var bAdded = false; var objId = modelObj.getId(); if ( ! this.mapObjectInclusionById[ objId ] ) { this.arrNodes[ objId ] = this.arrRegisteredObjects[ objId ]; this.arrNodes[ this.arrNodes.numberOfRegisteredObjects ] = this.arrRegisteredObjects[ objId ]; this.arrNodes.numberOfRegisteredObjects++; this.mapObjectInclusionById[ objId ] = true; bAdded = true; } return bAdded; } CModelData.prototype.getPaneCount = function() { return this.paneNames.length; } CModelData.prototype.getPaneName = function( i ) { return this.paneNames[ i ]; } /****************************************************** * CModelData public methods ******************************************************/ CModelData.prototype.getQueryCount = function () { return this.arrNodes.numberOfRegisteredObjects; //return arrayLen( this.arrNodes ); } CModelData.prototype.getObjectCount = function () { return this.arrNodes.numberOfRegisteredObjects; } CModelData.prototype.getQuery = function ( i ) { return this.arrNodes[i]; } CModelData.prototype.getObject = function ( i ) { return this.arrNodes[i]; } CModelData.prototype.getConnectionCount = function() { return this.arrConnections.length; } CModelData.prototype.getConnection = function( i ) { return this.arrConnections[i]; } CModelData.prototype.getConnectionLeft = function( i ) { return this.arrConnections[i][0]; } CModelData.prototype.getConnectionRight = function( i ) { return this.arrConnections[i][1]; } /******************************************************* * CModelObject * * This class is a wrapper for the MDSRV_LineageObject to * deal with diagram specific requirements * ******************************************************/ function CModelObject( mdsrv_LineageObject, modelObject ) { this.lineageObj = mdsrv_LineageObject; this.shortcutTo = null; this.nColumnIndex = 0; this.bMain = false; if ( modelObject ) { // if the modelObject is not NULL then this object is a shortcut to the modelObject this.shortcutTo = modelObject; } } CModelObject.prototype.getItemCount = function() { if ( this.model_data_childList ) { return this.model_data_childList.numberOfRegisteredObjects; } return 0; } CModelObject.prototype.getItem = function( i ) { if ( this.model_data_childList ) { return this.model_data_childList[i]; } return null; } CModelObject.prototype.addChild = function( childObj ) { if ( ! this.model_data_childList ) { this.mapChildInclusionById = new Array(); this.model_data_childList = new Array(); this.model_data_childList.numberOfRegisteredObjects = 0; } if ( ! this.mapChildInclusionById[ childObj.getId() ] ) { this.model_data_childList[ childObj.getId() ] = childObj; this.model_data_childList[ this.model_data_childList.numberOfRegisteredObjects ] = childObj; this.model_data_childList.numberOfRegisteredObjects++; this.mapChildInclusionById[ childObj.getId() ] = true; } } CModelObject.prototype.getPropertyCount = function() { var propArray = this.lineageObj.getProperties(); //return arrayLen( propArray ); return propArray.length; } //CModelObject.prototype.getProperty = function( i ) { // return arrayItemAtIndex( this.lineageObj.getProperties(), i ); //} CModelObject.prototype.getPropertyName = function( nProp ) { var propArray = this.lineageObj.getProperties(); return propArray[nProp].getName(); //var prop = arrayItemAtIndex( this.lineageObj.getProperties(), nProp ); //return prop.getName(); } CModelObject.prototype.getPropertyDisplayName = function( nProp ) { var propArray = this.lineageObj.getProperties(); return propArray[nProp].getDisplayName(); } CModelObject.prototype.getPropertyValue = function( nProp ) { var propArray = this.lineageObj.getProperties(); return propArray[nProp].getValue(); } CModelObject.prototype.findPropertyValue = function ( sPropName ) { var sPropValue = ""; var cProperties = this.getPropertyCount(); for ( var i = 0; i < cProperties; i++ ) { // alert ( this.getPropertyDisplayName(i) + ' = ' + this.getPropertyValue(i) ); if ( this.getPropertyName(i) === sPropName ) { sPropValue = this.getPropertyValue(i); break; } } return sPropValue; } CModelObject.prototype.isPackageDataSourceObject = function () { this.bPackageDataSourceObject = false; var sPropValue = this.findPropertyValue( 'definitionType' ); if ( sPropValue === 'Data Source' ) { this.bPackageDataSourceObject = true; } else { sPropValue = this.findPropertyValue( 'externalName' ); if ( sPropValue.length > 0 ) this.bPackageDataSourceObject = true; } // if ( this.bPackageDataSourceObject ) // alert( 'Object "' + this.lineageObj.getName() + '" isPackageDataSourceObject' ); return this.bPackageDataSourceObject; } // Return whether the lineage object comes from a report, model or data source CModelObject.prototype.getObjLocation = function() { var sObjectLocation = LNS.sObjectLocationByType[ this.lineageObj.getType() ]; // this is a hack. sObjectLocation can be only "report" or "datasources". For this.lineageObj.getType() = filter // sObjectLocation = filter() . Looks like it finds a function with this name, but I coudn't find the function?? // so there is the hack. if (sObjectLocation != "report" && sObjectLocation != "datasources") sObjectLocation = null; if ( ! sObjectLocation ) sObjectLocation = LNS.sPanePackageResId; var sPaneName = MDSRV_techView_StringManager.stringLookup( sObjectLocation ); return sPaneName; } CModelObject.prototype.isReportPane = function() { return ( this.getObjLocation() === LNS.sPaneReportName ); } CModelObject.prototype.isModelPane = function() { return ( this.getObjLocation() === LNS.sPanePackageName ); } CModelObject.prototype.isDatabasePane = function() { return ( this.getObjLocation() === LNS.sPaneDatabaseName ); } // XXXXXXXXXXXXX deprecate CModelObject.prototype.getPaneName = function() { return this.getObjLocation(); } CModelObject.prototype.setMainObject = function( bMain ) { this.bMain = ( true ? bMain === true : false ); } CModelObject.prototype.isMainObject = function() { var bRet = false; if ( this.bMain || this.shortcutTo ) { bRet = true; } return bRet; } CModelObject.prototype.getColumnIndex = function() { var nColumnIndex = 0; if ( this.nColumnIndex ) { nColumnIndex = this.nColumnIndex; } return nColumnIndex; } CModelObject.prototype.isRootObject = function() { return ( this.nColumnIndex === 0 ); } CModelObject.prototype.getObjClass = function() { return this.lineageObj.getType(); } CModelObject.prototype.getObjSubClass = function() { return LNS.typeObjectSubclassRegular; } CModelObject.prototype.getName = function() { return this.lineageObj.getName(); } CModelObject.prototype.getShortcutTo = function() { if ( this.shortcutTo ) { return this.shortcutTo; } return null; } CModelObject.prototype.getId = function() { var id = this.lineageObj.getId(); if ( this.shortcutTo ) { id = '_' + id; } return id; } CModelObject.prototype.findObjectById = function( objectArray, objId ) { var index = -1; for ( var i = 0; i < objectArray.length; i++ ) { if ( objectArray[i].getId() === objId ) { index = i; break; } } return index; }