/**************************************************************** ** Licensed Materials - Property of IBM ** ** IBM Cognos Products: mdsrv ** ** (C) Copyright IBM Corp. 2008, 2010 ** ** US Government Users Restricted Rights - Use, duplication or disclosure restricted by GSA ADP Schedule Contract with IBM Corp. *****************************************************************/ //This object is used to create a table based 'graph' from the Graph object. //This provides a more detailed business view, and lets us meet accessability requirements, as the tables are readable by JAWS CTextGraph = function(Graph, lineageResponse) { this.Graph = Graph; this.lineageResponse = lineageResponse; this.GraphTables = {}; //tables to be written out this.GraphTableNames = {}; //set of table names so we can generate unique ids //turns camel case words back to human words, with spaces and everything! this.deCamelCaseWord = function(word) { if(word === undefined || word === null) { return ""; } var res = ""; for(var i = 0; i < word.length; i++) { var cur = word.charAt(i) if(i == 0) //recapitalize first letter res += cur.toLocaleUpperCase(); else if(cur === cur.toLocaleUpperCase()) //if caps, then insert a space res += " " + cur; else //just copy the current character res += cur; } return res; } //add a table to this.GraphTables for the given node this.addTable = function(node) { this.GraphTables[node.nUniqueId] = { "node": node, "references": [], "queryItemReferences": [] //I'm not crazy about using an array and linearly processing it to get the query item refs, but it works and seems fast enough for now }; this.GraphTableNames[node.modelObject.lineageObj.m_id] = true; } // add a reference (edge) to the table stored in this.GraphTables this.addReferenceToTable = function (connection) { var t = this.GraphTables[connection.m_left.nUniqueId]; t["references"].push(connection.m_right); //try to get the gItem(Left|Right), but fall back to m_(left|right) if it's null var left = connection.gItemLeft === null ? connection.m_left : connection.gItemLeft; var right = connection.gItemRight === null ? connection.m_left : connection.gItemRight; if (left.modelObject.lineageObj.m_id != right.modelObject.lineageObj.m_id) t["queryItemReferences"].push([left.modelObject.lineageObj.m_id, right.modelObject.lineageObj.m_id]) } //remove the duplicate elements from an array and return the array of unique elements this.removeDuplicates = function(array) { var results = []; var elementSet = {}; var len = array.length; for( var i = 0; i < len; i++) { if (elementSet[array[i]] === undefined) { results.push(array[i]); elementSet[array[i]] = true; } } return results; } this.whitespaceToUnderscore = function(str) { var replaceWhitespace = /\s/gi; return str.replace(replaceWhitespace, '_'); } // return a closure (function that saves initial state) that can be used to generate the table header // read http://en.wikipedia.org/wiki/Closure_%28computer_science%29 if you don't understand the concept this.createHeaderStringClosure = function(id) { var whitespaceToUnderscore = this.whitespaceToUnderscore; //save the function ref since the closures 'this' is different return function (str) { return whitespaceToUnderscore(id) + str + 'Header'; } } //recursively process the child objects to generate the references and nested tables for the query items this.buildQueryItemTable = function(childObj, queryItemReferences, idPrefix, parentHeader) { var elementID = idPrefix + childObj.m_id; if( this.GraphTableNames[elementID] !== undefined ) { elementID += "queryItem" } var summary = this.deCamelCaseWord(childObj.m_type) + ' ' + childObj.m_id; var str = ''; var properties = childObj.getProperties(); var refs = childObj.getChildRefs().slice(0); //copy the child refs, since we don't want to overwrite the originals when we add the queryItemReferences var propertyValue = document.getElementById("propertyValue").innerHTML; //load the localized headings from original html var valueValue = document.getElementById("valueValue").innerHTML; var referencesValue = document.getElementById("referenceValue").innerHTML; var getHeaderString = this.createHeaderStringClosure(elementID); //because the levels will point to query item that might also be represented as a top level table, we need to prefix the references to //query items to make them unique if(childObj.getType() == "level") idPrefix += childObj.m_id + "."; for ( var i = 0; i < queryItemReferences.length; i++) { var cur = queryItemReferences[i]; var name = cur[0]; var id = childObj.m_id; if (name === id) //if this child object has the reference/add it to the references array refs.push(cur[1]) } refs = this.removeDuplicates(refs); str += '' for ( var i = 0; i < properties.length; i++ ) { var prop = properties[i]; var currentObjectHeader = getHeaderString(this.whitespaceToUnderscore(prop.m_name)); str += ''; } var referenceHeader = getHeaderString(this.whitespaceToUnderscore(referencesValue)); str += '
' + childObj.m_name + '
' + propertyValue + ''+ valueValue +'
' + prop.m_dispName + '' + prop.m_value + '
' + referencesValue + ''; if(refs.length > 0) str += '
    '; for ( var i = 0; i < refs.length; i++ ) { var ref = refs[i]; //if this is a level datatype, it's references point to a query item, not a top level table var refId = childObj.getType() == "level" ? idPrefix + refs[i] : refs[i] ; str += '
  • ' + ref + '
  • '//write the current reference } if(refs.length > 0) str += '
' str += '
' var recursiveRefs = childObj.getChildRefs(); //we really need to change this to use the "each" method if we ever drop IE 6 for ( var i = 0; i < recursiveRefs.length; i++) { var ref = recursiveRefs[i]; var child = this.lineageResponse.lookup(ref); str += this.buildQueryItemTable(child, queryItemReferences, idPrefix, parentHeader); } return str; } // iterate over the nodes in the list and output the contents to an HTML table at div "textgraph" this.writeGraphTablesToHTML = function() { var numNodes = this.Graph.m_nodeList.length; var propertyValue = document.getElementById("propertyValue").innerHTML; //load the localized headings from original html var valueValue = document.getElementById("valueValue").innerHTML; var referencesValue = document.getElementById("referenceValue").innerHTML; var queryItemValue = document.getElementById("queryItemValue").innerHTML; var contentsValue = document.getElementById("contentsValue").innerHTML; var TableString = ''; var TableOfContents = '

' + contentsValue + '

'; //write table to the DOM document.getElementById("textgraph").innerHTML = TableOfContents + TableString; } //generate the tables and write them to the page this.Init = function() { var numNodes = this.Graph.m_nodeList.length; for ( var j = 0; j < numNodes; j++ ) { this.addTable(this.Graph.m_nodeList[j]) } var numConnections = this.Graph.m_connectionList.length; for ( var i = 0; i < numConnections; i++ ) { this.addReferenceToTable(this.Graph.m_connectionList[i]); } this.writeGraphTablesToHTML(); LNS.replaceBlankTableCells(document.getElementById('id_business_view')); } }