1214 lines
34 KiB
C#
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);
|
|
// Create the writer for data.
|
|
RptBW = new BinaryWriter(Rptfs);
|
|
}
|
|
catch (Exception )
|
|
{
|
|
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;
|
|
// 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");
|
|
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)
|
|
{
|
|
bool success;
|
|
VlnStatusMessage showStat = new VlnStatusMessage("Reading ROs");
|
|
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);
|
|
}
|
|
showStat.Dispose();
|
|
xmldoc.CloseTemp();
|
|
return true;
|
|
}
|
|
}
|
|
}
|