public void ParseToXmlNode(XmlNode parent, string objectName)
{
XmlNode thisNode;
if (!(bool)this._RServer.Evaluate("is.null(" + objectName + ")").AsLogical()[0])//"is.null( tmp )"
{
object data = null;
object executionStat = null; //19Jun2013 for holding the exeution status from return structure
object returnval = null; //20Jun2013 for holding result table value.
string typeName = string.Empty;
string classtype = string.Empty;
try
{
string cmd = "is.na(" + objectName + ")";
LogicalVector tms = this._RServer.Evaluate(cmd).AsLogical();
if (tms == null || tms.Length == 0)//no data to process
{
return;
}
if (tms.Length==1)//single elements !tms.GetType().IsArray)
{
if (tms[0]) //A. to see if NA coming
{
UADataType dataType = getUADataTypeFromName("String");
thisNode = parent.OwnerDocument.CreateElement(getElementTypeName(dataType));
parent.AppendChild(thisNode);
thisNode.InnerText = ".";
return;
}
else
{
object b = this._RServer.Evaluate("class(" + objectName + ")").AsCharacter()[0];
if (true)//factor
data = this._RServer.Evaluate("as.character(" + objectName + ")").AsCharacter()[0];//this lines read factor values ToString numeric
else
data = this._RServer.Evaluate(objectName);//this lines read factor values ToString numeric
if (b != null && b.ToString().ToLower().Equals("matrix"))
typeName = "String[,]";//"Double[,]";
else
typeName = data.GetType().Name;
//Console.WriteLine(b);
}
}
else //For those commands that return multiple tables like BSky return structure. (mainly for analysis command. But not sure.)
{
classtype = this._RServer.Evaluate("class(" + objectName + ")").AsCharacter()[0];
data = this._RServer.Evaluate(objectName).AsList();
if (classtype.Equals("data.frame") && !objectName.Contains("metadatatable"))
{
typeName = "DataFrame";
data = this._RServer.Evaluate(objectName).AsCharacter();
}
else if (classtype.Trim().Equals("matrix"))//"character"
{
typeName = "String[,]";
if (typeName.Equals("String[,]"))
{
data = this._RServer.Evaluate(objectName).AsCharacterMatrix();
}
else if (typeName.Equals("String[]"))
{
data = this._RServer.Evaluate(objectName).AsCharacter();
}
}
else if (classtype.Equals("table") && !objectName.Contains("metadatatable"))
{
classtype = this._RServer.Evaluate("typeof(" + objectName + ")").AsCharacter()[0];
if (classtype.Trim().Equals("double")) //20Sep2013 for 2wayfreq
{
typeName = "Double[,]";
data = this._RServer.Evaluate(objectName).AsNumericMatrix();
}
else if (classtype.Trim().Equals("matrix"))//"character"
{
typeName = "String[,]";
if(typeName.Equals("String[,]"))
{
data = this._RServer.Evaluate(objectName).AsCharacterMatrix();
}
else if (typeName.Equals("String[]"))
{
data = this._RServer.Evaluate(objectName).AsCharacter();
}
}
else
{
typeName = "Int32[,]";//OR "matrix";
data = this._RServer.Evaluate(objectName).AsIntegerMatrix();
}
}
else if (classtype.Equals("data.frame") && objectName.Contains("metadatatable"))
{
typeName = "Object[]";
data = new string[8];
//data = this._RServer.Evaluate(objectName).AsList();
}
else if (classtype.Equals("list") && (data as GenericVector).Length == 13) //bad if condition here. Improve it later. HArd coded for col props
{
typeName = "String[]";
data = this._RServer.Evaluate(objectName).AsCharacter();
}
else if (classtype.Equals("character") || classtype.Equals("numeric")) //bad if condition here. Improve it later. HArd coded for col props
{
typeName = "String[]";
data = this._RServer.Evaluate(objectName).AsCharacter();
}
else
{
typeName = data.GetType().Name;
//data = this._RServer.Evaluate(objectName).AsList();
if (typeName.Equals("GenericVector"))
classtype = "list";
}
}
}
catch (Exception ex)
{
///data = this._RServer.Evaluate(objectName); //for 2d Matrix
if (data != null)
typeName = "Table[]";
}
///////////Fix for One Smpl 13Feb2012 ///////
if (classtype.Equals("list") && parent.Name.Equals("Root"))
{
try
{
data = this._RServer.Evaluate(string.Format("{0}[[7]]", objectName)).AsCharacter()[0];
if (data != null && data.ToString().Length > 0)//str len check for graphic objectName[[7]]
typeName = "Table[]";
}
catch (Exception ee)
{
//data = this._RServer.Evaluate(objectName); //no need of this statement I guess
logService.WriteToLogLevel(ee.Message, LogLevelEnum.Error);
}
}
//////////////13Feb2012///////
if (null != data)
{
UADataType dataType = getUADataTypeFromName(typeName);//datatype will b diff for each datatype. Can be made generic. "DataType"
thisNode = parent.OwnerDocument.CreateElement(getElementTypeName(dataType));
parent.AppendChild(thisNode);
switch (typeName)
{
case "String":
thisNode.InnerText = (string)data;
break;
case "String[]":
string[] sList = (data as CharacterVector).ToArray();
foreach (String r in sList)
{
XmlNode row = thisNode.OwnerDocument.CreateElement("row");
row.InnerText = r;
thisNode.AppendChild(row);
}
returnVal=sList;//added for R.NET
break;
case "Double":
if (((double)data).ToString() == "-2146826246")
thisNode.InnerText = "NA";
else
thisNode.InnerText = ((double)data).ToString();
break;
case "Double[]":
double[] dList = (double[])data;
foreach (double r in dList)
{
XmlNode row = thisNode.OwnerDocument.CreateElement("row");
if (r.ToString() == "-2146826246")
row.InnerText = "NA";
else
row.InnerText = r.ToString();
thisNode.AppendChild(row);
}
break;
case "Double[,]":
GenerateSlicenameAndRowColHeaders(objectName, thisNode);
// Creating DOM using matrix data
NumericMatrix tempNM = (data as NumericMatrix);
long rowCount = tempNM!=null ? tempNM.RowCount:1;
long colCount = tempNM!=null ? tempNM.ColumnCount:1;
double[,] dMatrix = new double[rowCount, colCount];;//String[,] dMatrix = new string[rowCount, colCount];
for (int mi = 0; mi < rowCount; mi++)
{
for (int mj = 0; mj < colCount; mj++)
{
dMatrix[mi, mj] = tempNM != null ? tempNM[mi, mj] : Double.Parse(data.ToString());
}
}
XmlNode rows = thisNode.OwnerDocument.CreateElement("rows");
thisNode.AppendChild(rows);
for (long rIndex = 0; rIndex < rowCount; rIndex++)
{
XmlNode row = rows.OwnerDocument.CreateElement("row");
rows.AppendChild(row);
XmlNode columns = row.OwnerDocument.CreateElement("columns");
row.AppendChild(columns);
for (long cIndex = 0; cIndex < colCount; cIndex++)
{
XmlNode col = columns.OwnerDocument.CreateElement("column");
columns.AppendChild(col);
if (dMatrix[rIndex, cIndex].ToString() == "-2146826246")
{
col.InnerText = "NA";
continue;
}
double val = 0;
double.TryParse(dMatrix[rIndex, cIndex].ToString(), out val);
col.InnerText = val.ToString();
}
}
break;
case "String[,]":
CreateTableRowColumnHeaders(objectName, thisNode);
CharacterMatrix tempCM = (data as CharacterMatrix);//tempCM will be null when there is 1 row 1 col(1 cell only)
int mtxrcount = tempCM!=null ? tempCM.RowCount:1;//multi or single cell
int mtxccount = tempCM!=null ? tempCM.ColumnCount:1; //multi or single cell
String[,] sMatrix = new string[mtxrcount, mtxccount];
for (int mi = 0; mi < mtxrcount; mi++)
{
for (int mj = 0; mj < mtxccount; mj++)
{
sMatrix[mi,mj] = tempCM!=null ? tempCM[mi, mj]:(String)data;
}
}
////////////
rowCount = sMatrix.GetLongLength(0);
colCount = sMatrix.GetLongLength(1);
rows = thisNode.OwnerDocument.CreateElement("rows");
thisNode.AppendChild(rows);
for (long rIndex = 0; rIndex < rowCount; rIndex++)
{
XmlNode row = rows.OwnerDocument.CreateElement("row");
rows.AppendChild(row);
XmlNode columns = row.OwnerDocument.CreateElement("columns");
row.AppendChild(columns);
for (long cIndex = 0; cIndex < colCount; cIndex++)
{
XmlNode col = columns.OwnerDocument.CreateElement("column");
columns.AppendChild(col);
if (sMatrix[rIndex, cIndex].ToString() == "-2146826246")
{
col.InnerText = "NA";
continue;
}
col.InnerText = sMatrix[rIndex, cIndex].ToString();
}
}
break;
case "Object[,]":
GenerateSlicenameAndRowColHeaders(objectName, thisNode);
object[,] oMatrix = (object[,])data;
rowCount = oMatrix.GetLongLength(0);
colCount = oMatrix.GetLongLength(1);
rows = thisNode.OwnerDocument.CreateElement("rows");
thisNode.AppendChild(rows);
for (long rIndex = 0; rIndex < rowCount; rIndex++)
{
XmlNode row = rows.OwnerDocument.CreateElement("row");
rows.AppendChild(row);
XmlNode columns = row.OwnerDocument.CreateElement("columns");
row.AppendChild(columns);
for (long cIndex = 0; cIndex < colCount; cIndex++)
{
XmlNode col = columns.OwnerDocument.CreateElement("column");
columns.AppendChild(col);
if (oMatrix[rIndex, cIndex].ToString() == "-2146826246")
{
col.InnerText = "NA";
continue;
}
col.InnerText = oMatrix[rIndex, cIndex].ToString();
}
}
break;
case "Int16":
case "Int32":
case "Int64":
if (((int)data).ToString() == "-2146826246")
thisNode.InnerText = "NA";
else
thisNode.InnerText = ((int)data).ToString();
break;
case "Int16[]":
case "Int32[]":
case "Int64[]":
int[] iList = (int[])data;
try
{
CreateTableRowColumnHeaders(objectName, thisNode);
//filling data in DOM
rows = thisNode.OwnerDocument.CreateElement("rows");
thisNode.AppendChild(rows);
foreach (double r in iList)
{
XmlNode row = rows.OwnerDocument.CreateElement("row");
if (r.ToString() == "-2146826246")
{
row.InnerText = "NA";
continue;
}
row.InnerText = r.ToString();
rows.AppendChild(row);
}
break;
}
catch { }
//filling data in DOM
///rows = thisNode.OwnerDocument.CreateElement("rows");
///thisNode.AppendChild(rows);
//int[] iList = (int[])data;
foreach (double r in iList)
{
XmlNode row = thisNode.OwnerDocument.CreateElement("row");
if (r.ToString() == "-2146826246")
{
row.InnerText = "NA";
continue;
}
row.InnerText = r.ToString();
thisNode.AppendChild(row);
///rows.AppendChild(row);
}
break;
case "Int16[,]":
case "Int32[,]":
case "Int64[,]":
CreateTableRowColumnHeaders(objectName, thisNode, classtype);
int[,] iMatrix;
//for single row R 'table'. Single Dim array. But we need tp convert it to 2D to print headers for the 1D 'table'
string datatype = data.GetType().Name;
if (datatype.Equals("Int16[]") || datatype.Equals("Int32[]") || datatype.Equals("Int64[]"))
{
int[] tmparr = (int[])data;
int colsize = tmparr.Length;
iMatrix = new int[1, colsize];
int i = 0;
foreach (int v in tmparr)
{
iMatrix[0, i] = tmparr[i];
i++;
}
}
else
{
iMatrix = (int[,])data;
}
////// Creating DOM using matrix data
//28Aug2013. moved above in if else ... int[,] iMatrix = (int[,])data;
rowCount = iMatrix.GetLongLength(0);
colCount = iMatrix.GetLongLength(1);
rows = thisNode.OwnerDocument.CreateElement("rows");
thisNode.AppendChild(rows);
for (long rIndex = 0; rIndex < rowCount; rIndex++)
{
XmlNode row = rows.OwnerDocument.CreateElement("row");
rows.AppendChild(row);
XmlNode columns = row.OwnerDocument.CreateElement("columns");
row.AppendChild(columns);
for (long cIndex = 0; cIndex < colCount; cIndex++)
{
XmlNode col = columns.OwnerDocument.CreateElement("column");
columns.AppendChild(col);
if (iMatrix[rIndex, cIndex].ToString() == "-2146826246")
{
col.InnerText = "NA";
continue;
}
col.InnerText = iMatrix[rIndex, cIndex].ToString();
}
}
break;
case "Object[]":
{
Object[] oList = (Object[])data;
int len = oList.Length;
for (int index = 1; index <= len; index++) //for test make len=8
{
//ParseToXmlNode(thisNode, objectName + "[[" + index.ToString() + "]]"); this commented & following if/else added
if (index == 3 || index == 7 || index == 8)
ParseToXmlNode(thisNode, "as.character(" + objectName + "[[" + index.ToString() + "]])");
else
ParseToXmlNode(thisNode, objectName + "[[" + index.ToString() + "]]");
}
break;
}
case "Table[]":
{
data = this._RServer.Evaluate(string.Format("{0}[[7]]", objectName)).AsCharacter()[0];
int numberOfTables=0;
if (Int32.TryParse(data.ToString(), out numberOfTables))//try converting to number.
{ }
int objectcountintable = 0;
bool isewtable = false;//before ewtable we have BSky stat table and user tables added by BSkyBuildReturnTableStructure
// and have XML output template. Even if template is missing a basic formatting will be done.
//after ewtable we have other user tables for which XML output template is not present.
for (int i = 1; i <= numberOfTables; ++i)
{
tableheader = null;
string tabletype = "resulttable";
/// We can also find tabletype as following (this is now implemented on 21sep2013)
/// Set a flag to one state. assume all the tables those come before type="ewtable" are analytic tables.
/// As soon as type="ewtable" is found, process it and set a flag that will tell that all the other tables
/// are user result tables.
///// finding the table type //////
//if table[[i]]$anyname exists. For result table it should not exists
bool tablepropsnamesexists = this._RServer.Evaluate(string.Format("!is.null(names({0}$tables[[{1}]]))", objectName, i)).AsLogical()[0];
objectcountintable = this._RServer.Evaluate(string.Format("length({0}$tables[[{1}]])", objectName, i)).AsInteger()[0];
if (this._RServer.Evaluate(string.Format("!is.null(names({0}$tables)[[{1}]])", objectName, i)).AsLogical()[0])//01May2014
{
tableheader = this._RServer.Evaluate(string.Format("names({0}$tables)[[{1}]]", objectName, i)).AsCharacter()[0];
}
if (objectcountintable > 1 && tablepropsnamesexists)
{
bool hasType = false;
bool isatomic = this._RServer.Evaluate(string.Format("is.atomic({0}$tables[[{1}]])", objectName, i)).AsLogical()[0];
if (!isatomic)
hasType = this._RServer.Evaluate(string.Format("!is.null({0}$tables[[{1}]]$type)", objectName, i)).AsLogical()[0];
//23Aug2013. this line replaced by abv 4 lines
//bool hasType = this._RServer.Evaluate(string.Format("!is.null({0}$tables[[{1}]]$type)", objectName,i));
if (hasType)
tabletype = this._RServer.Evaluate(string.Format("{0}$tables[[{1}]]$type", objectName, i)).AsCharacter()[0];
//find $columnNames 30apr2015 List of cols to remove( or keep)
bool hasColNames = this._RServer.Evaluate(string.Format("!is.null({0}$tables[[{1}]]$columnNames)", objectName, i)).AsLogical()[0];
if (hasColNames)
{
XmlElement colnames = parent.OwnerDocument.CreateElement("ColNames");//);[0]+metatableId.ToString()// each metadatatable will hv diff name in DOM
colnames.SetAttribute("tablenumber", i.ToString());
ParseToXmlNode(colnames, string.Format("{0}$tables[[{1}]]$columnNames", objectName, i));
thisNode.AppendChild(colnames);
}
}
///Now tabletype is one of "table", "ewtable", "resulttable"
if (tabletype.Equals("table") || tabletype.Equals("ewtable")) // Analytic table or error warning table
{
isewtable = true;//21sep2013
ParseToXmlNode(thisNode, string.Format("{0}$tables[[{1}]]$datatable", objectName, i));
dynamic res = this._RServer.Evaluate(string.Format("{0}$tables[[{1}]]$metadata", objectName, i)).AsCharacter()[0];///tmp[[8]][[1]]$metadata
string isMetadata = res;//(string)res;
if (isMetadata == "yes")
{
int noMetadata = int.Parse(this._RServer.Evaluate(string.Format("{0}$tables[[{1}]]$nometadatatables", objectName, i)).AsInteger()[0].ToString());
string[] Metadatanames = null;
if (noMetadata == 1)
{
Metadatanames = new string[1];
Metadatanames[0] = (string)this._RServer.Evaluate(string.Format("{0}$tables[[{1}]]$metadatatabletype", objectName, i)).AsCharacter()[0];
}
else
{
string str = (string)this._RServer.Evaluate(string.Format("{0}$tables[[{1}]]$metadatatabletype", objectName, i)).AsCharacter()[0];
Metadatanames = new string[noMetadata];
for (int j = 0; j < noMetadata; j++)
Metadatanames[j] = str + (j + 1).ToString();//right now we are assigning same name + index to each matadatatable related to single datatable
}
XmlElement metadatanodes = null;
if (tabletype.Equals("table"))
metadatanodes = parent.OwnerDocument.CreateElement("Metadata");//for analytic
else if (tabletype.Equals("ewtable"))
metadatanodes = parent.OwnerDocument.CreateElement("BSkyErrorWarn");//for error warning
metadatanodes.SetAttribute("tablenumber", i.ToString());
for (int metatableId = 1; metatableId <= noMetadata; ++metatableId)
{
XmlElement metanode = parent.OwnerDocument.CreateElement(Metadatanames[metatableId - 1]);//);[0]+metatableId.ToString()// each metadatatable will hv diff name in DOM
ParseToXmlNode(metanode, string.Format("{0}$tables[[{1}]]$metadatatable[[{2}]]", objectName, i, metatableId));
metadatanodes.AppendChild(metanode);
}
thisNode.AppendChild(metadatanodes);
}
}//tabletype table or ewtable
else
{
// this line puts the direct result. For internal commands from RCommandsString file.
//This line should execute only once. Just after rwtable following retun values will be found.
// We can comment this line and use the DOM thats be being created below to get user resuls.
// Following line is not for users result as its mostly required for internal functions.
//This returnVal value is consumed internally in app functioning rather than pushing it out to output window.
//object r2 = this._RServer.Evaluate(string.Format("names({0}$tables)",objectName));
//if (r2 == null) { }
returnVal = this._RServer.Evaluate(string.Format("{0}$tables[[{1}]]", objectName, i));
if (!isewtable)//21sep2013 For tables added using BSkyBuildReturnTableStructure. Added before "ewtable" in ret struct
{
ParseToXmlNode(thisNode, string.Format("{0}$tables[[{1}]]", objectName, i));
continue;//move to next table
}
////Putting User Results in DOM //class(ostt$tables[[6]]) => character, data.frame etc..
int totalusertables = numberOfTables - i + 1;
XmlElement userresult = null;
userresult = parent.OwnerDocument.CreateElement("UserResult");//for analytic
for (int tno = 1; tno <= totalusertables; ++tno, i++)
{
//Following will check if ewtable exists in between user tables ( this happens when user tables are stacked )
tablepropsnamesexists = this._RServer.Evaluate(string.Format("!is.null(names({0}$tables[[{1}]]))", objectName, i)).AsLogical()[0];
objectcountintable = this._RServer.Evaluate(string.Format("length({0}$tables[[{1}]])", objectName, i)).AsInteger()[0];
if (objectcountintable > 1 && tablepropsnamesexists)
{
bool hasType = false;
bool isatomic = this._RServer.Evaluate(string.Format("is.atomic({0}$tables[[{1}]])", objectName, i)).AsLogical()[0];
if (!isatomic)
hasType = this._RServer.Evaluate(string.Format("!is.null({0}$tables[[{1}]]$type)", objectName, i)).AsLogical()[0];
if (hasType)
{
tabletype = this._RServer.Evaluate(string.Format("{0}$tables[[{1}]]$type", objectName, i)).AsCharacter()[0];
if (tabletype.Equals("ewtable"))
{
i--; // external for loop should increment it again.
break;
}
}
}
////// Processing one of the user tables ////
XmlElement udata = parent.OwnerDocument.CreateElement("UserData");//);[0]+metatableId.ToString()// each metadatatable will hv diff name in DOM
udata.SetAttribute("tablenumber", tno.ToString());
ParseToXmlNode(udata, string.Format("{0}$tables[[{1}]]", objectName, i));
userresult.AppendChild(udata);
}
thisNode.AppendChild(userresult);
}
}// for loop on tables
}
break;
case "DataFrame":
{
rowCount = this._RServer.Evaluate("nrow(" + objectName + ")").AsInteger()[0];
colCount = this._RServer.Evaluate("ncol(" + objectName + ")").AsInteger()[0];
String[,] dfMatrix = new string[rowCount, colCount];
for (int jj = 0; jj < colCount; jj++)
{
string[] coldata = null;
int colscount = this._RServer.Evaluate("length(" + objectName + "[," + (jj + 1) + "])").AsInteger()[0];
if (colscount > 1)
{
CharacterVector cv = this._RServer.Evaluate("as.character(" + objectName + "[," + (jj + 1) + "])").AsCharacter();
int siz = cv.Count();
coldata = new string[siz];
for (int ic = 0; ic < siz; ic++)
{
coldata[ic] = cv[ic];
}
}
else if (colscount == 1)
{
string coname = this._RServer.Evaluate("as.character(" + objectName + "[," + (jj + 1) + "])").AsCharacter()[0];
coldata = new string[1];
coldata[0] = coname;
}
else
{
//no need already set to null
break;
}
for (int ii = 0; ii < coldata.Length; ii++)
{
dfMatrix[ii, jj] = coldata[ii];
}
}
//Creating DOM for row col data, using array from above
rows = thisNode.OwnerDocument.CreateElement("rows");
thisNode.AppendChild(rows);
for (long rIndex = 0; rIndex < rowCount; rIndex++)
{
XmlNode row = rows.OwnerDocument.CreateElement("row");
rows.AppendChild(row);
XmlNode columns = row.OwnerDocument.CreateElement("columns");
row.AppendChild(columns);
for (long cIndex = 0; cIndex < colCount; cIndex++)
{
XmlNode col = columns.OwnerDocument.CreateElement("column");
columns.AppendChild(col);
if (dfMatrix[rIndex, cIndex].ToString() == "-2146826246")
{
col.InnerText = "NA";
continue;
}
col.InnerText = dfMatrix[rIndex, cIndex].ToString();
}
}
}
break;
}//switch
}
}
}