/********************************************************************************************* * Copyright 2021 - 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 description for Class1. /// 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 _MyROID; public string MyROID { get { return _MyROID; } set { _MyROID = value; } } 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"); 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 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 (comma20) 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 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='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 0); // 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; if (PCApplicability) text = GetPCReturnValues(theDb, pcChildern, elm, PCApplicability, inusename, text); // C2021-026 Get P/C Children return values strbld.Append(text.Replace("{", "&123;").Replace("}", "&125;")); } 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',stindx); // first see if it is within it's own {} if (stindxbrace -1) { rightbrace = retvaltmpl.IndexOf('}',stindxbrace); if ((left>leftbrace&&leftleftbrace&&right -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); defPCROval = end.InnerText; } } } // C2021_026 put out PC children values if (ContainedInArrayList(rof,InUseApplcList)) { XmlNode pcn; int pcChildIdx = 0; foreach (string s in PCChildren) { pcChildIdx++; string pcName = nd.Name + string.Format("_PCCHILD{0}", pcChildIdx); // create child field name string pcField = rof.MakeFieldName(pcName); xmldoc.pushHeader(" "+s); // put out the PC Child name (indented 5 spaces) for complete RO Report // see if it has data in the ro. pcn = this.SelectSingleNode(pcField); if (pcn != null) xmldoc.writeTextValue(pcn.InnerText); // use PC Child value else xmldoc.writeTextValue(defPCROval); // use default value } } 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 DateTime last = DateTime.Now; // use these to control status message output 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) { if (TimeSpan.FromTicks(DateTime.Now.Ticks - last.Ticks).Seconds > 1) { showStat.StatusMessage = TheMenuTitle; last = DateTime.Now; } } 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; } private static string[] PCChildren = null; //C2021-026 holds list of P/C children names public bool HasApplicabilityEnabled { get { return (PCChildren != null && PCChildren.Length > 0); } } // 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, string [] pcChildren) { bool success; PCChildren = pcChildren; // C2021-026 list of P/C children 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; } } }