1214 lines
34 KiB
C#

/*********************************************************************************************
* Copyright 2002 - Volian Enterprises, Inc. All rights reserved.
* Volian Enterprises - Proprietary Information - DO NOT COPY OR DISTRIBUTE
* ------------------------------------------------------------------------------
* $Workfile: VlnXml.cs $ $Revision: 23 $
* $Author: Jsj $ $Date: 6/20/05 1:29p $
*
* $History: VlnXml.cs $
*
* ***************** Version 23 *****************
* User: Jsj Date: 6/20/05 Time: 1:29p
* Updated in $/LibSource/RODBInterface
* added status message while reading ROs for Complete RO Report.
*
* ***************** Version 22 *****************
* User: Jsj Date: 6/08/05 Time: 4:32p
* Updated in $/LibSource/RODBInterface
* Complete RO Report Bug fix B2001-001
*
* ***************** Version 21 *****************
* User: Jsj Date: 9/27/04 Time: 11:02a
* Updated in $/LibSource/RODBInterface
* upped release number
*
* ***************** Version 20 *****************
* User: Kathy Date: 7/15/04 Time: 11:11a
* Updated in $/LibSource/RODBInterface
* Fix B2004-017
*
* ***************** Version 19 *****************
* User: Kathy Date: 5/06/04 Time: 9:52a
* Updated in $/LibSource/RODBInterface
* B2004-012 fix: skip process of param display data for RO Cmp Rpt
*
* ***************** Version 18 *****************
* User: Jsj Date: 4/08/04 Time: 9:43a
* Updated in $/LibSource/RODBInterface
* Added and commented out calls to VlnProfiler
*
* ***************** Version 17 *****************
* User: Jsj Date: 1/21/04 Time: 12:10p
* Updated in $/LibSource/RODBInterface
* added function to return current selected field type of multi type
* field
*
* ***************** Version 16 *****************
* User: Kathy Date: 5/21/03 Time: 12:41p
* Updated in $/LibSource/RODBInterface
* B2003-035: process ro's with just one field
*
* ***************** Version 15 *****************
* User: Jsj Date: 4/14/03 Time: 2:59p
* Updated in $/LibSource/RODBInterface
* changes resulting from speeding up RO FST creation
*
* ***************** Version 14 *****************
* User: Kathy Date: 3/11/03 Time: 11:24a
* Updated in $/LibSource/RODBInterface
* allow extra text on accpageid template
*
* ***************** Version 13 *****************
* User: Kathy Date: 12/17/02 Time: 12:53p
* Updated in $/LibSource/RODBInterface
* get image data by node for rofst creation
*
* ***************** Version 12 *****************
* User: Kathy Date: 12/10/02 Time: 2:25p
* Updated in $/LibSource/RODBInterface
* fieldname special chars & various bugs
*
* ***************** Version 11 *****************
* User: Kathy Date: 12/02/02 Time: 8:29a
* Updated in $/LibSource/RODBInterface
* fieldname replace chars
*
* ***************** Version 10 *****************
* User: Jsj Date: 11/27/02 Time: 12:47p
* Updated in $/LibSource/RODBInterface
* modifications for RO.FST file creation
*
* ***************** Version 9 *****************
* User: Kathy Date: 11/19/02 Time: 11:32a
* Updated in $/LibSource/RODBInterface
* fields within {} are not required
*
* ***************** Version 8 *****************
* User: Kathy Date: 11/11/02 Time: 7:14a
* Updated in $/LibSource/RODBInterface
* Added complete report methods.
*********************************************************************************************/
using System;
using System.Xml;
using System.Text;
using System.Collections;
using System.IO;
using System.Windows.Forms;
using ROFields;
using VlnStatus;
//using VlnProfiler; //don't forget to add VlnProfiler to the reference list
namespace RODBInterface
{
/// <summary>
/// Summary description for Class1.
/// </summary>
public class VlnXmlDocument:XmlDocument
{
FileStream Rptfs; // for complete report of this document
BinaryWriter RptBW;
public VlnXmlDocument():base()
{
}
public override XmlElement CreateElement( string prefix, string localname, string nsURI)
{
VlnXmlElement elem = new VlnXmlElement(prefix, localname, nsURI, this);
return elem;
}
public bool OpenTemp()
{
try
{
//Rptfs = new FileStream("print.tmp", FileMode.Create);
Rptfs = new FileStream("print.tmp", FileMode.Append);
// Create the writer for data.
RptBW = new BinaryWriter(Rptfs);
}
catch (Exception ex)
{
Console.WriteLine("Open Print.Tmp: {0}", ex.Message);
return false;
}
return true;
}
public void CloseTemp()
{
RptBW.Close();
Rptfs.Close();
}
public void writeInt(short val)
{
RptBW.Write(val);
}
public void writeText(string str)
{
short n = (short) str.Length;
writeInt(n);
// write out char by char. (Using rite
// of entire stirng caused special characters to be
// written as two bytes - which temp file reading code
int i;
for(i =0; i < str.Length; i++)
{
byte WrByte;
WrByte = (byte)str[i];
RptBW.Write(WrByte);
}
}
public void writeTextValue(string str)
{
writeInt(100);
writeText(str);
}
public void writePlot(string str)
{
writeInt(101);
writeText(str);
}
public void writeImage(string str)
{
writeInt(102);
writeText(str);
}
public void pushHeader(string str)
{
writeInt(2);
writeText(str);
}
public void popHeader()
{
writeInt(3);
}
public void doHeader(ArrayList headers)
{
int spaces = -1;
short cnt = (short) headers.Count;
writeInt(255);
writeInt(1);
writeInt(cnt);
for (int i=0; i < cnt ;i++)
{
writeInt(0);
if (spaces>0)
{
string spc = new String(' ',2*(spaces-1));
writeText(spc+headers[i].ToString());
}
else
writeText(headers[i].ToString());
spaces++;
}
}
public void writeRROBegin()
{
writeInt(4);
}
public void writeRROEnd()
{
writeInt(5);
}
public void writeMultiBegin()
{
writeInt(103);
}
public void writeMultiEnd()
{
writeInt(104);
}
}
public class VlnXmlElement:XmlElement
{
public VlnXmlElement( string prefix, string localname, string nsURI, XmlDocument doc ):base( prefix,localname,nsURI, doc )
{
}
private string CvtUserFldToFld(string fldname)
{
if (fldname.Length < 2)
return fldname;
// a digit cannot start an xml fieldname, prepend a "__" to it.
string tmp0;
if (char.IsDigit(fldname,0))
tmp0 = "__" + fldname;
else
tmp0 = fldname;
// an xml fieldname cannot have a space, change it to a "__"
string tmpstr = tmp0.Replace(" ","__");
int len = tmpstr.Length;
int cnt = 0;
// this is also our sequence that tells us the follow 3 digits is the ascii number (base 10)
// of the character we replaced.
string OKpunch = "-._";
string outstr = "";
int decval;
while (cnt < len)
{
char tmpchr = tmpstr[cnt];
if(!char.IsLetterOrDigit(tmpchr)&& (OKpunch.IndexOf(tmpchr) == -1) )
{
decval = tmpchr;
outstr += OKpunch + decval.ToString("D3");
}
else
{
outstr += tmpchr.ToString();
}
cnt++;
}
return outstr;
}
private string CvtFldToUserFld(string fldname)
{
string tmpstr0;
if (fldname.Length < 2) return fldname;
// an xml element name cannot begin with a digit. we had prepended a "__"
if (fldname.Substring(0,2) == "__" && char.IsDigit(fldname,2))
tmpstr0 = fldname.Substring(2,fldname.Length-2);
else
tmpstr0 = fldname;
// an xml element name cannot have a space, we converted to a "__"
string tmpstr = tmpstr0.Replace("__"," ");
int len = tmpstr.Length;
int cur = 0;
// this is also our sequence that tells us the follow 3 digits is the ascii number (base 10)
// of the character we replaced.
string OKpunch = "-._";
string outstr = "";
int decval, indx;
if (tmpstr.Length <6)
indx = -1;
else
indx=tmpstr.IndexOf(OKpunch,cur);
string asc_spchar;
while (indx>=0)
{
outstr += tmpstr.Substring(cur,indx-cur);
asc_spchar = tmpstr.Substring(indx+3,3);
decval = System.Convert.ToInt16(asc_spchar,10);
outstr += System.Convert.ToChar(decval).ToString();
cur = indx+6;
if (cur+6 > len)
indx = -1;
else
indx = tmpstr.IndexOf(OKpunch,cur);
}
if (cur<len) outstr += tmpstr.Substring(cur,len-cur);
return outstr;
}
// for this (VlnXmlElement), get it's accessory page id based on it's data, using
// the passed in template (AccPageID template from the xmlelement's attributes).
// Note that the template represents only 1 field. This was a req/design decision
// made during the development based on engineering review.
public string GetAccPageIDString(string newtmpl)
{
string fld;
// If there aren't properties definied for the group/subgroup - give a message
// rather than crash (B2004-017)
if (newtmpl==null)
{
MessageBox.Show("Missing Accessory Page Information, check Group definition on Properties.");
return null;
}
VlnXmlElement elm = this;
int left = newtmpl.IndexOf("<");
int right= newtmpl.IndexOf(">");
if (left >= 0 && right > 0)
fld = newtmpl.Substring(left+1,right-left-1);
else
return null;
string usefld = CvtUserFldToFld(fld);
XmlNode elmnode = (XmlNode) elm;
XmlNode nd = elmnode.SelectSingleNode(usefld);
// if not found it may be a combination, try this.
if (nd == null)
{
string tmp = usefld + "a";
nd = elmnode.SelectSingleNode(tmp);
}
if (nd == null)
{
string tmp = usefld + "b";
nd = elmnode.SelectSingleNode(tmp);
}
if (nd == null)
{
string tmp = usefld + "c";
nd = elmnode.SelectSingleNode(tmp);
}
if (nd == null)
{
string tmp = usefld + "d";
nd = elmnode.SelectSingleNode(tmp);
}
if(nd != null)
{
StringBuilder strbld = new StringBuilder();
if (left > 0) strbld.Append(newtmpl.Substring(0,left));
strbld.Append(nd.InnerText.ToString());
if (right+1<newtmpl.Length)
strbld.Append(newtmpl.Substring(right+1,newtmpl.Length-right-1));
return strbld.ToString();
}
return null;
}
// for this (VlnXmlElement), get the accessorypageid template by walking up
// the tree, starting at this element.
public string GetAccPageIDTemplate()
{
VlnXmlElement parent;
VlnXmlElement tmp=null;
// get to top node of the ROs & groups to get the accpageID for this tree.
parent = (VlnXmlElement) this;
while(parent.Name != "RO_Root")
{
tmp = parent;
parent = (VlnXmlElement) parent.ParentNode;
}
if (tmp.HasAttribute("AccPageID") == false) return null;
else return tmp.GetAttribute("AccPageID");
}
// check to see if the input string makes a duplicate menu title.
public bool IsDuplicateMenuTitle(string menutitle)
{
// see if this is a duplicate menu, just check ROs at this level except
// myself.
XmlNode parent = this.ParentNode;
XmlNode chld = parent.FirstChild;
while (chld != null)
{
if (chld is VlnXmlElement)
{
VlnXmlElement echld = (VlnXmlElement) chld;
if (this != echld)
{
string chldmenutitle = echld.GetAttribute("MenuTitle");
if (chldmenutitle != null && chldmenutitle == menutitle)return true;
}
}
chld = chld.NextSibling;
}
return false;
}
// for this (VlnXmlElement), get the menu title string. Passed in, menuitm, is the
// template which is used to generate the menu title for this XmlElement. Also
// passed in is a flag to state whether this is a 'Group' menu title.
public string GetMenuString(string menuitm, bool isgrp)
{
VlnXmlElement elm = this;
StringBuilder strbld = new StringBuilder();
// use grpmenuitm, parse for field(s) and generate a string to return
int left = menuitm.IndexOf("<");
int right=0;
int stindx = 0;
if (left > 0) strbld.Append(menuitm.Substring(0,left));
while (left != -1)
{
// get right bracket and then check for valid field & if commas with
// this, check for integer values.
right = menuitm.IndexOf(">",stindx);
string tmpd = menuitm.Substring(left+1,right-left-1);
// do comma parts now.
string inusename;
int comma1 = tmpd.IndexOf(",");
int frmt1=0, frmt2=0;
if (comma1 != -1)
{
// get any numbers for formatting & check for ints.
int comma2 = tmpd.IndexOf(",",comma1+1);
if (comma2 != -1) // two ints.
{
if (comma2-comma1 > 1) // first format field - not empty
{
string int1 = tmpd.Substring(comma1+1,comma2-comma1-1);
frmt1 = System.Convert.ToInt32(int1);
}
if (comma2<tmpd.Length) // second part - not empty
{
string int2 = tmpd.Substring(comma2+1,tmpd.Length-comma2-1);
frmt2 = System.Convert.ToInt32(int2);
}
}
else // just one format
{
string int1 = tmpd.Substring(comma1,comma2-comma1);
frmt1 = System.Convert.ToInt32(int1);
}
inusename = CvtUserFldToFld(tmpd.Substring(0,comma1));
}
else // no commas, it's just a field name.
inusename = CvtUserFldToFld(tmpd);
// get contents of field & append it onto the string builder.
XmlNode elmnode = (XmlNode) elm;
XmlNode nd = elmnode.SelectSingleNode(inusename);
// if not found it may be a combination, try this.
ushort FieldType = 0;
string text;
if (nd == null)
text = GetComboFieldValueAndType(elmnode,inusename,ref FieldType,true);
else
text = nd.InnerText;
if (!text.Equals(""))
{
if (isgrp)
{
if (frmt2 != 0)
strbld.Append(CvtFldToUserFld(text).PadRight(frmt2,' '));
else
strbld.Append(CvtFldToUserFld(text));
}
else
{
if (frmt1 == 0)
{
if (frmt2>0)
strbld.Append(text.PadRight(frmt2,' '));
else
strbld.Append(text);
}
else if (frmt1 != frmt2)
{
int cnt = 0;
// while (cnt < tmp.Length && tmp[cnt] <= '9' && tmp[cnt] >= '0') cnt++; // new RO logic
// int padcnt = (cnt>frmt1)?0:frmt1-cnt;
int padcnt = OldROFSTMenuLogic(text,frmt1,frmt2); // testing!!!!!
StringBuilder strtmp = new StringBuilder();
cnt = 0;
while(cnt<padcnt)
{
strtmp.Append(" ");
cnt++;
}
if ((cnt + text.Length) > frmt2) // longer than the field length?
strtmp.Append(text.Substring(0,frmt2-cnt));
else
strtmp.Append(text);
string tmpstr = strtmp.ToString();
strbld.Append(tmpstr.PadRight(frmt2,' '));
}
else
strbld.Append(text.PadLeft(frmt2,' '));
}
}
stindx = right+1;
left = menuitm.IndexOf("<",left+1);
if (left != -1 && left > right+1) // append any plain text.
strbld.Append(menuitm.Substring(right+1,left-right-1));
}
if (right+1<menuitm.Length)
strbld.Append(menuitm.Substring(right+1,menuitm.Length-right-1));
return strbld.ToString();
}
int OldROFSTMenuLogic(string text,int doff, int wid)
{
int siznum = 0;
int idx =0;
int sps = 0;
int newoff = doff;
int tmpwid;
char[] str = text.ToCharArray();
// skip leading blanks
while (idx < text.Length && str[idx] == ' ') idx++;
int slen = text.Length - idx;
while (idx < text.Length && ((str[idx]<='9' && str[idx]>='0') || str[idx] =='-' || str[idx]=='+'))
{
siznum++;
idx++;
}
if (siznum == 0)
{
newoff= siznum+(wid-slen)/2;
}
else if (((doff-siznum)+slen)> wid)
{
newoff = wid-siznum-slen;
}
tmpwid = wid;
while (tmpwid > 0 && siznum < newoff)
{
sps++;
siznum++;
tmpwid--;
}
return sps;
}
// for this (VlnXmlElement), get it's menu value template. This template is
// used to generate the menu titles. Pass in a string 'GroupMenuItem' or
// 'MenuItem' so that the group level or RRO level menu template is found.
// This walkds up the tree to find the attribute ('GroupMenuItem' or 'MenuItem')
// and returns it.
public string GetMenuValueTemplate(string menuitm)
{
VlnXmlElement parent;
string strmenuitm;
VlnXmlElement tmp;
if (menuitm == "GroupMenuItem")
{
// if at top of tree, use this top GroupMenuItem. but if not,
// the parent node defines the GroupMenuItem for the subgroups.
if (this.ParentNode.Name == "RO_Root")
{
tmp = (VlnXmlElement) this.ParentNode;
strmenuitm=tmp.GetAttribute(menuitm);
return(strmenuitm);
}
else
parent = (VlnXmlElement) this.ParentNode;
while (parent != null)
{
if (parent.HasAttribute(menuitm) == true) break;
if (parent.Name != "RO_Root")
parent = (VlnXmlElement) parent.ParentNode;
else
parent = null;
}
if (parent == null) return null;
strmenuitm = parent.GetAttribute(menuitm);
return strmenuitm;
}
// Now just do 'MenuItem', which is for ROs
parent = (VlnXmlElement) this;
strmenuitm = parent.GetAttribute(menuitm);
while (parent != null && strmenuitm == "")
{
// walk up tree to get parent.
strmenuitm = parent.GetAttribute(menuitm);
parent = (VlnXmlElement) parent.ParentNode;
}
return strmenuitm;
}
// for this (VlnXmlElement), get the Return Value template.
public string GetReturnValueTemplate()
{
VlnXmlElement parent;
VlnXmlElement tmp=null;
// get to top node of the ROs & groups to get the return for this tree.
parent = (VlnXmlElement) this;
tmp = parent;
while((tmp.HasAttribute("RetVal") == false) && parent.Name != "RO_Root")
{
tmp = parent;
parent = (VlnXmlElement) parent.ParentNode;
}
if (tmp.HasAttribute("RetVal") == false) return null;
else return tmp.GetAttribute("RetVal");
}
/*
* return true if the field is a pre defined PROC.INI field name
*/
private bool IsProcIniDef(string fld)
{
bool rtnval = false;
string tmpstr = fld.ToUpper();
rtnval = (tmpstr.Equals("U") ||
tmpstr.Equals("U-") ||
tmpstr.Equals("P") ||
tmpstr.Equals("P-") ||
tmpstr.Equals("S") ||
tmpstr.Equals("S-"));
return rtnval;
}
/*
* This function checks the given field name with the list of fields
* that are "in use" for the current group.
* If the field name is of one of the pre-defined PROC.INI RO fields
* treat that field name as plain text (i.e. NOT in use)
*/
private bool IsAInUseField(ArrayList InUseList, string fld)
{
bool rtnval = false;
int i;
if (IsProcIniDef(fld)) // is this a pre-defined PROC.INI field?
return rtnval; //return false!
string tmpstr = fld.Substring(0,1);
if (tmpstr.Equals("_"))
tmpstr = fld.Substring(1,fld.Length-1);
else
tmpstr = fld;
tmpstr = CvtFldToUserFld(fld);
for(i=0; rtnval == false && i<InUseList.Count; i++)
{
ROField rof = (ROField) InUseList[i];
string fldname = rof.GetFieldname;
if (fldname.Equals(tmpstr))
{
rtnval = true; // found
}
}
return rtnval;
}
public string GetReturnValue(RODB theDb, string TableName,string RtnValTemplate, ArrayList InUseList, ref ushort ValueType)
{
string RtnValStr = "";
VlnXmlElement elm = this;
StringBuilder strbld = new StringBuilder();
// Parse the template for the fields and generate a return string
int left = RtnValTemplate.IndexOf("<"); // look for begining of field
int right = -1;
int stindx = 0;
ushort FldType = 0;
if (left > 0) strbld.Append(RtnValTemplate.Substring(0,left));
while (left != -1)
{
// get right bracket and then check for valid field & if commas with
// this, check for integer values.
right = RtnValTemplate.IndexOf(">",stindx);
string inusename;
string substr = RtnValTemplate.Substring(left+1,right-left-1);
inusename = CvtUserFldToFld(substr);
// get contents of field & append it onto the string builder.
XmlNode elmnode = (XmlNode) elm;
XmlNode nd = elmnode.SelectSingleNode(inusename);
// Check to see if the found field is a "Field In Use"
if (IsAInUseField(InUseList,inusename))
{
string text="";
if (nd == null)
{
text = GetComboFieldValueAndType(elmnode,inusename,ref FldType,false);
if (text.Equals(""))
text = " ";
}
else
{
// Profiler.Start("Grv7");
FldType = theDb.RODB_GetFieldType((VlnXmlElement)nd,TableName,inusename);
// Profiler.End("Grv7");
// Profiler.Start("Grv8");
// for an image, get the filename, height, width, otherwise just use
// data in the node.
if (FldType == 8) // for the '8' see RODBInterface - GetFSTreturntype
{
// get filename, length, width in that order, separated by newlines
XmlNode tmp = nd.SelectSingleNode("Image_Filename");
if (tmp != null && tmp.InnerText != null)
text = tmp.InnerText + "\r\n";
else
text = " \r\n";
tmp = nd.SelectSingleNode("Image_Height");
if (tmp != null && tmp.InnerText != null)
text = text + tmp.InnerText + "\r\n";
else
text = text + " \r\n";
tmp = nd.SelectSingleNode("Image_Width");
if (tmp != null && tmp.InnerText != null)
text = text + tmp.InnerText + "\r\n";
else
text = text + " \r\n";
}
else
{
text = nd.InnerText;
}
// Profiler.End("Grv8");
}
ValueType |= FldType;
strbld.Append(text);
}
else
{
strbld.Append(RtnValTemplate.Substring(left,right-left+1));
}
stindx = right+1;
left = RtnValTemplate.IndexOf("<",left+1);
if (left != -1 && left > right+1) // append any plain text.
strbld.Append(RtnValTemplate.Substring(right+1,left-right-1));
}
right++; // move past the right bracket ('>')
if (right < RtnValTemplate.Length)
strbld.Append(RtnValTemplate.Substring(right,RtnValTemplate.Length-right));
// Bug fix: B2004-044
// If the ValueType is zero, then it will not appear on the list of ROs in the
// procedure editor.
if (ValueType == 0)
ValueType = 1;
RtnValStr = strbld.ToString();
return RtnValStr;
}
public string GetComboFieldValueAndType(XmlNode CurNode, string Fld, ref ushort FldTyp, bool ForMenu)
{
string RtnVal = "";
XmlNode ChildNode = CurNode.FirstChild;
FldTyp = 0;
while (ChildNode != null && FldTyp == 0)
{
if (ChildNode is VlnXmlElement)
{
string ChildName = ChildNode.Name.ToString();
if (ChildName.StartsWith(Fld))
{
char CmboChar = Convert.ToChar(ChildName.Substring(ChildName.Length-1,1));
switch (CmboChar)
{
case 'a': // Fixed Text
case 'b': // Multi Line Text
FldTyp = 1;
RtnVal = ChildNode.InnerText;
break;
case 'c': // Table
FldTyp = 2;
if (ForMenu)
RtnVal = "(Table)";
else
RtnVal = ChildNode.InnerText;
break;
case 'd': // X/Y Plot
FldTyp = 4;
if (ForMenu)
RtnVal = "(Graph)";
else
RtnVal = ChildNode.InnerText;
break;
}
}
}
ChildNode = ChildNode.NextSibling;
}
return RtnVal;
}
// For this (VlnXmlElement), get the list of used fields. Need to find the
// fields from the accessory page id template, the return value template
// and the menu title template or group title template (depends on if a
// group edit or a RRO edit.
public ArrayList GetRequiredFields()
{
ArrayList fldlist = new ArrayList();
string accpagetmpl = GetAccPageIDTemplate();
string retvaltmpl = null;
string menutmpl = null;
if (this.Name == "vlnGroup")
{
menutmpl = GetMenuValueTemplate("GroupMenuItem");
}
else
{
menutmpl = GetMenuValueTemplate("MenuItem");
retvaltmpl = GetReturnValueTemplate();
}
// for each string, add its field names to the list.
// accessory page id's only have a field and only used for ROs.
if (this.Name != "vlnGroup" && accpagetmpl != null)
{
string fld = accpagetmpl.Substring(1,accpagetmpl.Length-2);
fldlist.Add(fld+"\tAccessory Page Value");
}
// menutmpl's may have multiple fields. loop through them.
int left, right, stindx, comma, rdelim;
if (menutmpl != null)
{
left = menutmpl.IndexOf("<");
right = 0;
stindx = 0;
comma = 0;
while (left != -1)
{
// get right bracket and then check for valid field & if commas with
// this, check for integer values.
right = menutmpl.IndexOf(">",stindx);
comma = menutmpl.IndexOf(",",stindx);
rdelim = (comma>-1 && comma>left && comma<right)?comma:right;
string substring = menutmpl.Substring(left+1,rdelim-left-1);
string tmpds = CvtUserFldToFld(substring);
substring = tmpds + "\tMenu Value";
if(fldlist.Contains((Object)substring) == false)fldlist.Add(substring);
left = menutmpl.IndexOf("<",right+1);
stindx = right+1;
}
}
// now add return value's if not a group level.
if (this.Name != "vlnGroup" && retvaltmpl != null)
{
left = retvaltmpl.IndexOf('<');
right = 0;
stindx = 0;
int leftbrace, rightbrace, stindxbrace=0;
bool isreq;
while (left != -1)
{
isreq = true;
// get right bracket and then check for valid field & if commas with
// this, check for integer values. Also, if it's within {}, it isn't
// required.
right = retvaltmpl.IndexOf('>',stindx);
// first see if it is within it's own {}
if (stindxbrace<retvaltmpl.Length)
leftbrace = retvaltmpl.IndexOf('{',stindxbrace);
else
leftbrace=-1;
if (leftbrace > -1)
{
rightbrace = retvaltmpl.IndexOf('}',stindxbrace);
if ((left>leftbrace&&left<rightbrace)&&(right>leftbrace&&right<rightbrace)) // don't do
isreq=false;
stindxbrace=rightbrace+1;
}
if (isreq==true)
{
string substring = retvaltmpl.Substring(left+1,right-left-1);
string tmpds = CvtUserFldToFld(substring);
substring = tmpds + "\tReturn Value";
if(fldlist.Contains((Object)substring) == false)fldlist.Add(substring);
}
left = retvaltmpl.IndexOf("<",right+1);
stindx = right+1;
}
}
return fldlist;
}
/// ******** RO Complete Report methods.
///
/// These methods are called by CmpRpt. They 'show', i.e. write to output
/// file, print.tmp, the fields/data defining the group and Ro.
///
// ShowGroupDetail sends to print.tmp the data for a Group level.
private bool ShowGroupDetail(RODB myrodb)
{
ROField rof;
XmlNode nd;
VlnXmlDocument xmldoc = (VlnXmlDocument) this.OwnerDocument;
string nm;
// First get the fields used for this Group.
string tmp=null; // needed for inuse call
ArrayList AvailList = myrodb.RODB_GetFields(this, 0);
ArrayList InUseList = myrodb.RODB_GetFieldsInUse(this, AvailList, "GroupFieldsInUse", ref tmp, true);
// For each field, print the header (field name) & then print data if it exists.
if (InUseList != null)
{
xmldoc.writeRROBegin();
xmldoc.writeInt(7);
xmldoc.writeText(" ");
for (int i=0; i< InUseList.Count; i++)
{
rof = (ROField) InUseList[i];
if (rof.GetFieldname != null)
{
string nm0 = rof.GetFieldname;
nm = rof.MakeFieldName(nm0);
xmldoc.pushHeader(nm0);
// see if it has data in the ro.
nd = this.SelectSingleNode(nm);
// if not found with just the string, search the tree.
if (nd==null)nd = this.SelectSingleNode("*/"+nm);
if (nd == null) // not found, write out a '0'.
xmldoc.writeInt(0);
else
{
VlnXmlElement end;
end = (VlnXmlElement) nd;
xmldoc.writeTextValue(end.InnerText);
}
xmldoc.popHeader();
}
}
xmldoc.writeRROEnd();
}
return true;
}
public XmlNode GetCurrentOfMultiFields(VlnXmlElement CurElement, string FldName)
{
XmlNode nd = null;
XmlNode grpnd = (XmlNode) CurElement.FirstChild;
string CurFieldName = "";
while (grpnd != null)
{
if (grpnd.Name.Substring(0,grpnd.Name.Length-1) == FldName.Substring(0,FldName.Length))
{
CurFieldName = grpnd.Name;
break;
}
grpnd = grpnd.NextSibling;
}
if (!CurFieldName.Equals(""))
nd = CurElement.SelectSingleNode(CurFieldName);
return nd;
}
// ShowRRO writes data for the input RO.
private bool ShowRRO(RODB myrodb, ArrayList headers)
{
VlnXmlDocument xmldoc = (VlnXmlDocument) this.OwnerDocument;
ROField rof;
XmlNode nd;
bool doingplot;
string nm;
// Get used fields for this RO.
string tmp=null; // needed for inuse call
ArrayList AvailList = myrodb.RODB_GetFields(this, 0);
ArrayList InUseList = myrodb.RODB_GetFieldsInUse(this, AvailList, "FieldsInUse", ref tmp, true);
// put out the stored headers, i.e. the group titles up the tree.
xmldoc.doHeader(headers);
// Put out fields and their associated data.
if (InUseList != null)
{
xmldoc.writeRROBegin();
xmldoc.writeInt(7);
xmldoc.writeText(this.GetAttribute("AccPageID").Trim());
// add items to the InUseList box.
for (int i=0; i< InUseList.Count; i++)
{
doingplot=false;
rof = (ROField) InUseList[i];
if (rof.GetFieldname != null)
{
string nm0 = rof.GetFieldname;
nm = rof.MakeFieldName(nm0);
xmldoc.pushHeader(nm0);
// see if it has data in the ro.
nd = this.SelectSingleNode(nm);
// if not found with just the string, search the tree.
if (nd==null)nd = this.SelectSingleNode("*/"+nm);
if ((uint)rof.GetFieldType == (uint)FieldTypes.Combination && nd==null)
{
nd = GetCurrentOfMultiFields(this,nm);
// nd = this.SelectSingleNode(nm+"a");
// if (nd==null) nd = this.SelectSingleNode(nm+"b");
// if (nd==null) nd = this.SelectSingleNode(nm+"c");
// if (nd==null)
// {
// doingplot=true;
// nd = this.SelectSingleNode(nm+"d");
// }
}
if (nd == null) // not found, write out a '0'.
xmldoc.writeInt(0);
else
{
if (nd.Equals(nm+"d"))
doingplot = true;
VlnXmlElement end;
end = (VlnXmlElement) nd;
if (rof.GetFieldType == (uint) FieldTypes.Image)
{
// get filename.
XmlNode ind = this.SelectSingleNode("*/Image_Filename");
if (ind==null)
xmldoc.writeInt(0);
else
{
// find space & filename is after it.
int indx = ind.InnerText.IndexOf(" ");
if (indx < ind.InnerText.Length && indx > -1)
xmldoc.writeImage(ind.InnerText.Substring(indx+1,ind.InnerText.Length-indx-1));
else
xmldoc.writeImage(ind.InnerText);
// now do height & width??
ind = this.SelectSingleNode("*/Image_Height");
if (ind != null)
{
short iht = (short) System.Convert.ToInt16(ind.InnerText);
xmldoc.writeInt(iht);
}
else
xmldoc.writeInt(0);
ind = this.SelectSingleNode("*/Image_Width");
if (ind != null)
{
short iht = (short) System.Convert.ToInt16(ind.InnerText);
xmldoc.writeInt(iht);
}
else
xmldoc.writeInt(0);
}
}
else
{
if (doingplot)
xmldoc.writePlot(end.InnerText);
else
xmldoc.writeTextValue(end.InnerText);
}
}
xmldoc.popHeader();
}
}
xmldoc.writeRROEnd();
}
return true;
}
// ShowGroup processes the input group node for the complete report by
// using ShowGroupDetail to output data for the group and ShowRRO to
// output data for the RO
private bool ShowGroup(RODB myrodb, ArrayList headers, VlnStatusMessage showStat)
{
XmlNode chldnode;
if (this.ParentNode.Name != "RO_Root")
{
/* Bug fix: B2001-001
* Compete RO Report for All ROs was printing an extra
* page showing just a prameter field. This information
* was not always related to the RO Group being printed at
* this time. Turns out that we don't need to call the
* ShowGroupDetail() at this point, only need to save
* header informat. -jsj 6/8/2005
*
ShowGroupDetail(myrodb);
*/
headers.Add(this.GetAttribute("MenuTitle"));
}
else
{
int bracket = this.InnerXml.IndexOf("<",0);
if (bracket>-1)
headers.Add(this.InnerXml.Substring(0,bracket));
else
headers.Add(this.InnerXml);
}
string haskids, kidsloaded;
haskids = this.GetAttribute("HasChild");
kidsloaded = this.GetAttribute("ChildLoaded");
if (haskids == "True" && kidsloaded == "False" )
{
myrodb.RODB_GetChildData(this,true);
this.SetAttribute("ChildLoaded", "True");
}
// go through all of the children for this node and put them out.
chldnode = (XmlNode) this.FirstChild;
while (chldnode != null)
{
if (chldnode is VlnXmlElement)
{
VlnXmlElement elem = (VlnXmlElement) chldnode;
if (showStat !=null)
showStat.StatusMessage = elem.InnerText;
// if it's a group, recurse through it.
if (chldnode.Name == "vlnGroup")
elem.ShowGroup(myrodb, headers, showStat);
// do RO's too.
else
{
int levelcnt = chldnode.ChildNodes.Count;
bool isParDisData = chldnode.Name == "Parameter__Display__Data";
string TheMenuTitle = elem.GetAttribute("MenuTitle");
if (showStat != null)
showStat.StatusMessage = TheMenuTitle;
if (!isParDisData && ((levelcnt > 1) || (levelcnt==1 && !TheMenuTitle.Equals(""))))
elem.ShowRRO(myrodb, headers);
}
}
chldnode = chldnode.NextSibling;
}
// remove this group from the headers.
headers.RemoveAt(headers.Count-1);
return true;
}
// put this element, and if a group all it's subelements out to the 'print.tmp'
// file for complete reports.
public bool Show(RODB myrodb, ArrayList headers, VlnStatusMessage showStat)
{
bool success;
VlnXmlDocument xmldoc = (VlnXmlDocument) this.OwnerDocument;
success = xmldoc.OpenTemp();
if (success==false) return false;
// if this is the top node, i.e. with name "RO_Root", it is a complete report
// for all Ros, work from the root.
if (this.Name == "RO_Root")
{
// show each 'table' group under the top.
VlnXmlElement group = (VlnXmlElement) this.FirstChild;
VlnXmlElement tmpgroup;
while (group != null)
{
// Now get subgroups for each group.
myrodb.RODB_GetChildData(group,true);
group.ShowGroup(myrodb, headers, showStat);
tmpgroup = group;
group.RemoveAll();
group = (VlnXmlElement) tmpgroup.NextSibling;
}
}
// this is a particular RO or group of ROs.
else
{
if (this.Name == "vlnGroup")
ShowGroup(myrodb, headers, showStat);
else
ShowRRO(myrodb, headers);
}
xmldoc.CloseTemp();
return true;
}
}
}