/****************************************************************
** 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 = '
' + childObj.m_name + '';
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 += '' + prop.m_value + ' | ';
}
var referenceHeader = getHeaderString(this.whitespaceToUnderscore(referencesValue));
str += '';
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 + '';
//create a table for each node
for ( var j = 0; j < numNodes; j++ )
{
var str = '';
var obj = this.GraphTables[this.Graph.m_nodeList[j].nUniqueId].node.modelObject.lineageObj;
var refs = this.removeDuplicates( this.GraphTables[this.Graph.m_nodeList[j].nUniqueId].references );
var properties = obj.getProperties();
var getHeaderString = this.createHeaderStringClosure(obj.m_id);
//create rows for the current table
for ( var i = 0; i < properties.length; i++ )
{
var prop = properties[i];
var currentObjectHeader = getHeaderString(this.whitespaceToUnderscore(prop.m_name));
str += '' + prop.m_value + ' | ';
}
var referencesHeader = getHeaderString(this.whitespaceToUnderscore(referencesValue));
str += '
';
//write the list of references
if(refs.length > 0)
str += '';
str += ' |
'
var childObjIds = obj.getChildRefs();
var childTables = "";
for ( var i = 0; i < childObjIds.length; i++)
{
var childObj = this.lineageResponse.lookup( childObjIds[i] );
if(childObj) //lookup will return null in some cases, so we need to check this
childTables += this.buildQueryItemTable(childObj, this.GraphTables[this.Graph.m_nodeList[j].nUniqueId].queryItemReferences, "", getHeaderString('QueryItems'));
}
//add reference to table of contents
TableOfContents += '- ' + obj.m_id + '
';
//create table
var summary = this.deCamelCaseWord(obj.m_type) + ' ' + obj.m_id;
TableString += '' + obj.m_id + '
' + str;
TableString += '' + childTables + ' |
';
}
TableOfContents += '
';
//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'));
}
}