using System; using System.Collections.Generic; using System.Collections.Specialized; using System.Text; using System.ComponentModel; namespace VEPROMS.CSLA.Library { [Serializable] [TypeConverter(typeof(ExpandableObjectConverter))] public class ROFSTLookup { #region Log4Net private static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); #endregion #region Structs [Serializable] public struct roHdr { public int hSize; public int hYear; public byte hMonth; public byte hDay; public int hcYear; public byte hcMonth; public byte hcDay; public byte hcHour; public byte hcMin; public byte hcSec; public byte hcHund; public rodbi[] myDbs; }; [Serializable] public struct rodbi { public int dbiID; public int dbiType; public int dbiAW; public string dbiTitle; public string dbiAP; public int ID; public int ParentID; public rochild[] children; }; public struct rogrp { public int ID; public int ParentID; public rochild[] children; public string value; public string appid; }; public struct rochild { public int ID; public int ParentID; public int type; public string title; public string roid; public string appid; public string value; public rochild[] children; }; public class roChild { rochild _MyChild; public rochild MyChild { get { return _MyChild; } set { _MyChild = value; } } public roChild(rochild myChild) { _MyChild = myChild; } public override string ToString() { return _MyChild.title; } }; #endregion #region Local Data private string _ROValue = ""; private List lstRoValues; private Dictionary DictROVar = new Dictionary(); #endregion #region Constructors private ROFst _ROFst; private ROFstInfo _ROFstInfo; private DocVersionInfo _DocVersionInfo; public ROFSTLookup(ROFst rofst) { _ROFst = rofst; _ROFstInfo = null; using (ROFstInfo rfi = ROFstInfo.Get(_ROFst.ROFstID)) { _DocVersionInfo = rfi.docVer==null?null: DocVersionInfo.Get(rfi.docVer.VersionID); } ParseIntoDictionary(rofst.ROLookup); } public ROFSTLookup(ROFstInfo rofstinfo) { _ROFstInfo = rofstinfo; _ROFst = null; // docversion will be null if we're working with an ro.fst that is not currently connected // to a docversion. One example of this is when updating ro.fst and comparing the original // with the new to find differences. The docversioninfo is only used to get unit/master // slave info, thus is not needed to compare the raw values. _DocVersionInfo = _ROFstInfo.docVer==null?null: DocVersionInfo.Get(_ROFstInfo.docVer.VersionID); ParseIntoDictionary(rofstinfo.ROLookup); } #endregion #region PropertiesAndData public roHdr myHdr; private int TableID; private Dictionary dicRos; private Dictionary dicRosIntIDs; #endregion #region AppSupport public void Close() { // remove the dictionary if (dicRosIntIDs != null)dicRosIntIDs.Clear(); dicRosIntIDs = null; if (dicRos != null)dicRos.Clear(); dicRos = null; } public List GetValueDifferences(ROFSTLookup origROFst, ref List delList) { // use this list to see what differences are between it and the original List modList = new List(); // assume each rofstlookup has a parsed dictionary foreach (string key in origROFst.dicRos.Keys) { string cvalue = null; string ovalue = origROFst.dicRos[key].value; if (dicRos.ContainsKey(key)) cvalue = dicRos[key].value; if (cvalue == null && cvalue != ovalue) delList.Add(key); else if (cvalue != ovalue) modList.Add(key); } return modList; } //public static ROImageInfo Get(RODbInfo rodbinfo, string filename) //{ // if (rodbinfo.RODbROImageCount != 0) // { // foreach (ROImageInfo ri in rodbinfo.RODbROImages) // { // if (ri.FileName == filename) return ri; // } // } // return null; //} // this only gets rochild values. Later we may want another // dictionary to get groups. public string GetRoValue(string ROID) { if (dicRos == null) ParseIntoDictionary(_ROFst!=null?_ROFst.ROLookup:_ROFstInfo.ROLookup); // Use the ROID to get the value from the dictionary if (dicRos.ContainsKey(ROID)) { rochild rochld = (rochild)dicRos[ROID]; return rochld.value; } return null; } public rochild GetRoChild(string ROID) { if (dicRos == null) ParseIntoDictionary(_ROFst != null ? _ROFst.ROLookup : _ROFstInfo.ROLookup); // Use the ROID to get the value from the dictionary if (dicRos.ContainsKey(ROID)) { rochild rochld = (rochild)dicRos[ROID]; return rochld; } rochild tmp = new rochild(); tmp.ID = -1; return tmp; } public rochild GetRoChildFromID(int id) { if (dicRosIntIDs == null) ParseIntoDictionary(_ROFst != null ? _ROFst.ROLookup : _ROFstInfo.ROLookup); // Use the id to get the value from the dictionary if (dicRosIntIDs.ContainsKey(id)) { rochild rochld = (rochild)dicRosIntIDs[id]; return rochld; } rochild tmp = new rochild(); tmp.ID = -1; return tmp; } public rodbi[] GetRODatabaseList() { return myHdr.myDbs; } //public string GetDefaultROPrefix() //{ // if (docVer != null) // return docVer.DocVersionConfig.RODefaults_setpointprefix; // else // return "SP1"; // Not Sure about this... //} //public string GetDefaultGraphicsPrefix() //{ // if (docVer != null) // return docVer.DocVersionConfig.RODefaults_graphicsprefix; // else // return "IG1"; // Not Sure about this... //} #region Update Ro Values /// /// Updates an ro.fst into a sql database. /// /// /// ROFst: Returns the created rofst object //public static ROFst UpdateRoFst(RODbInfo rdi, DocVersionAssociation dva, DocVersion docver) //{ // // file validity checks are done before getting here - just do the import // // here. // string rofstfilepath = rdi.FolderPath + @"\ro.fst"; // DirectoryInfo di = new DirectoryInfo(rdi.FolderPath); // // There may be more than 1 'ro' as the 'ROName' field (ROName is derived from the ropath). // // Get new name be incrementing, if so. // string newname = NewROName(di.Name); // // Next read in the rofst & make the rofst record. // FileStream fsIn = new FileStream(rofstfilepath, FileMode.Open, FileAccess.Read, FileShare.Read); // // Create an instance of StreamReader that can read characters from the FileStream. // BinaryReader r = new BinaryReader(fsIn); // byte[] ab = r.ReadBytes((int)fsIn.Length); // fsIn.Close(); // using (RODb rd = RODb.Get(rdi.RODbID)) // { // ROFst rofst = ROFst.MakeROFst(rd, ab, null, di.LastWriteTime, rdi.UserID); // // Hook this into the current docversion by replacing the rofstid field in the doc version // // association object: // dva.MyROFst = rofst; // docver.Save(); // // Now load any images in... type 8 - integrated graphics ro type // ROFstInfo rofstInfo = ROFstInfo.Get(rofst.ROFstID); // rofstInfo.ParseIntoDictionary(rofstInfo.ROFST); // for (int i = 0; i < rofstInfo.myHdr.myDbs.Length; i++) // { // // walk through the rofst 'database' searching for all nodes that are integrated graphics, type 8: // if (rofstInfo.myHdr.myDbs[i].children != null) rofstInfo.MigrateRoFstGraphics(rdi, rofstInfo.myHdr.myDbs[i].children); // } // return rofst; // } //} //private static string RoAppConfigExt(string fstPath) //{ // string inipath = fstPath + @"\roapp.ini"; // if (!File.Exists(inipath)) return null; // StreamReader myReader = new StreamReader(inipath); // string sLine; // int indx = -1; // while ((sLine = myReader.ReadLine()) != null) // { // if (sLine.Length > 0 && sLine.Substring(0, 1) != ";") // { // if ((indx = sLine.ToLower().IndexOf("extention")) >= 0) // { // indx = sLine.IndexOf("=", indx + 9); // return sLine.Substring(indx + 1, sLine.Length - indx - 1).Trim(); // } // } // } // myReader.Close(); // return null; //} //private static string NewROName(string roName) //{ // string retval = roName; // int iSuffix = -1; // RODbInfoList rodblist = RODbInfoList.Get(); // foreach (RODbInfo rdi in rodblist) // { // if (rdi.ROName.StartsWith(roName)) // { // if (rdi.ROName == roName) // iSuffix = 0; // else if (Regex.IsMatch(rdi.ROName, roName + "[_][0-9]+")) // { // int ii = int.Parse(rdi.ROName.Substring(1 + roName.Length)); // if (ii > iSuffix) iSuffix = ii; // } // } // } // if (iSuffix >= 0) // retval = string.Format("{0}_{1}", roName, iSuffix + 1); // return retval; //} //private void MigrateRoFstGraphics(RODbInfo rdi, ROFstInfo.rochild[] rochild) //{ // for (int i = 0; i < rochild.Length; i++) // { // if (rochild[i].type == 8) AddGraphic(rdi, rochild[i].value); // if (rochild[i].children != null) MigrateRoFstGraphics(rdi, rochild[i].children); // } //} //private void AddGraphic(RODbInfo rdi, string p) //{ // if (p == null) return; // string imgname = p.Substring(0, p.IndexOf('\n')); // int thedot = imgname.LastIndexOf('.'); // string fname = imgname; // if (thedot == -1 || (thedot != (imgname.Length - 4))) // { // RODbConfig roDbCfg = new RODbConfig(rdi.Config); // fname += string.Format(".{0}", roDbCfg.GetDefaultGraphicExtension()); // } // string imgfile = rdi.FolderPath + @"\" + fname; // ROImage roImg = null; // if (File.Exists(imgfile)) // { // FileInfo fi = new FileInfo(imgfile); // // if the roimage record exists, don't create a new one... // using (roImg = ROImage.GetByRODbID_FileName_DTS(rdi.RODbID, imgname, fi.LastWriteTime)) // { // if (roImg == null) // { // FileStream fsIn = new FileStream(imgfile, FileMode.Open, FileAccess.Read, FileShare.Read); // BinaryReader r = new BinaryReader(fsIn); // byte[] ab = r.ReadBytes((int)fsIn.Length); // r.Close(); // fsIn.Close(); // using (RODb rodb = RODb.Get(rdi.RODbID)) // { // roImg = ROImage.MakeROImage(rodb, imgname, ab, null, fi.LastWriteTime, "Migration"); // } // } // Figure figure = Figure.GetByROFstID_ImageID(this.ROFstID, roImg.ImageID); // if (figure != null) return; // using (ROFst rofst = ROFst.Get(this.ROFstID)) // { // figure = Figure.MakeFigure(rofst, roImg, null); // } // } // } // else // Console.WriteLine(string.Format("{0}", imgfile), "Cannot Find Image File"); //} #endregion #endregion #region LoadStructs private int StringLength(byte[] ab, int offset) { int i = 0; while (ab[i + offset] != 0) i++; return i; } private rogrp LoadGroup(byte[] ab, int offset) { rogrp myGrp = new rogrp(); myGrp.ID = BitConverter.ToInt32(ab, offset); myGrp.ParentID = BitConverter.ToInt32(ab, offset + 4); int howmany = BitConverter.ToInt16(ab, offset + 8); if (howmany > 0) { myGrp.children = new rochild[howmany]; int myOffset = offset + 10; for (int i = 0; i < myGrp.children.Length; i++) { int childOffset = BitConverter.ToInt32(ab, myOffset); rochild tmp = new rochild(); //tmp.offset=BitConverter.ToInt32(ab,myOffset); tmp.type = BitConverter.ToInt16(ab, myOffset + 4); int slen = StringLength(ab, myOffset + 6); tmp.title = Encoding.Default.GetString(ab, myOffset + 6, slen); myOffset += (7 + slen); rogrp tmpg = LoadGroup(ab, childOffset); MultipleReturnValuesInheritType(ref tmpg, tmp.type); tmp.ID = tmpg.ID; tmp.ParentID = tmpg.ParentID; tmp.children = tmpg.children; tmp.value = tmpg.value; tmp.appid = tmpg.appid; tmp.roid = TableID.ToString("X4") + tmp.ID.ToString("X8"); dicRos.Add(tmp.roid, tmp); if (!dicRosIntIDs.ContainsKey(tmp.ID)) dicRosIntIDs.Add(tmp.ID, tmp); int j; for (j = i - 1; j >= 0 && tmp.ID < myGrp.children[j].ID; j--) { myGrp.children[j + 1] = myGrp.children[j]; } myGrp.children[j + 1] = tmp; } } else { int slen = StringLength(ab, offset + 12); //myGrp.value = Encoding.Default.GetString(ab, offset + 12, slen); ProcessROReturnValue(ref myGrp, Encoding.Default.GetString(ab, offset + 12, slen)); int slen2 = StringLength(ab, offset + 13 + slen); myGrp.appid = Encoding.Default.GetString(ab, offset + 13 + slen, slen2); } return myGrp; } /// /// This function will take the raw RO return value and resolve any macros, conditionals, and /// generated the return value or a list of multiple return values. /// /// /// private void ProcessROReturnValue(ref rogrp myGrp, string rawvalue) { if (dicRos == null) ParseIntoDictionary(_ROFst != null ? _ROFst.ROLookup : _ROFstInfo.ROLookup); List lstROVals = GetROReturnValue(rawvalue); if (lstROVals.Count > 1) // mulitple return values { myGrp.children = new rochild[lstROVals.Count]; for (int i = 0; i < lstROVals.Count; i++) { myGrp.children[i].value = lstROVals[i]; myGrp.children[i].roid = TableID.ToString("X4") + myGrp.ID.ToString("X8") + i.ToString("X4"); myGrp.children[i].type = -1; // Multiple return value inherit type from parent myGrp.children[i].title = lstROVals[i]; } } else myGrp.value = lstROVals[0]; return; } /// /// Multiple return values need to get the type from the parent node. /// /// /// private void MultipleReturnValuesInheritType(ref rogrp myGrp, int parenttype) { if (myGrp.children != null) { for (int cnt = 0; cnt < myGrp.children.Length; cnt++) { if (myGrp.children[cnt].type == -1) { myGrp.children[cnt].type = parenttype; myGrp.children[cnt].appid = myGrp.appid; } } } } private void ParseIntoDictionary(byte[] ab) { if (dicRos == null) dicRos = new Dictionary(); if (dicRosIntIDs == null) dicRosIntIDs = new Dictionary(); myHdr.hSize = BitConverter.ToInt32(ab, 0); myHdr.hYear = BitConverter.ToInt16(ab, 4); myHdr.hMonth = ab[6]; myHdr.hDay = ab[7]; myHdr.hcYear = BitConverter.ToInt16(ab, 8); myHdr.hcMonth = ab[10]; myHdr.hcDay = ab[11]; myHdr.hcHour = ab[12]; myHdr.hcMin = ab[13]; myHdr.hcSec = ab[14]; myHdr.hcHund = ab[15]; int hdrOffset = BitConverter.ToInt32(ab, 16); int howbig = BitConverter.ToInt32(ab, hdrOffset); int dbs = BitConverter.ToInt16(ab, hdrOffset + 4); myHdr.myDbs = new rodbi[dbs]; for (int i = 0; i < dbs; i++) { int offset = hdrOffset + 6 + (i * 30); myHdr.myDbs[i].dbiID = BitConverter.ToInt16(ab, offset + 0); TableID = myHdr.myDbs[i].dbiID; myHdr.myDbs[i].dbiType = BitConverter.ToInt16(ab, offset + 2); myHdr.myDbs[i].dbiAW = BitConverter.ToInt16(ab, offset + 4); rogrp tmp = LoadGroup(ab, BitConverter.ToInt32(ab, offset + 6)); myHdr.myDbs[i].ID = tmp.ID; myHdr.myDbs[i].children = tmp.children; int iPtr = BitConverter.ToInt32(ab, offset + 22) + hdrOffset + 6; myHdr.myDbs[i].dbiTitle = Encoding.Default.GetString(ab, iPtr, StringLength(ab, iPtr)); iPtr = BitConverter.ToInt32(ab, offset + 26) + hdrOffset + 6; myHdr.myDbs[i].dbiAP = Encoding.Default.GetString(ab, iPtr, StringLength(ab, iPtr)); } } #endregion #region GetRoValues public List GetROReturnValue(string roval) { lstRoValues = new List(); DictROVar = new Dictionary(); // set up a dictionary of RO defined Variables string tmp = _DocVersionInfo==null?roval:ProcessRO(_DocVersionInfo.ProcessDocVersionSpecificInfo(roval), false); if (lstRoValues.Count == 0) // was not a multiple return value lstRoValues.Add(tmp); return lstRoValues; } private string ProcessRO(string roval, bool multiRtnVal) { string str = roval; string rtnstr = ""; int l = roval.Length; while (l > 0) { int ptr = NextDelimiter("{", str); if (ptr == -1) { // add remaining text //add(new seText(str, l)); rtnstr += str; l = 0; // break out of while loop } else { int cnt = ptr; //(int)(ptr - str); if (cnt > 0) { // add text //add(new seText(str, cnt)); rtnstr += str.Substring(0, cnt); l -= cnt; //str = ptr; str = str.Substring(ptr); } ptr = MatchingBrace(str) + 1; cnt = ptr; //(int)(ptr - str); bool nfnd = false; string pbstr = ProcessBrace(str.Substring(1, cnt - 2), cnt - 2, ref nfnd, multiRtnVal); if (nfnd) rtnstr += str.Substring(0, cnt); // add(new seText(str, cnt)); else rtnstr += pbstr; l -= cnt; //str = ptr; str = str.Substring(ptr); } } //rtnstr = rtnstr.Replace("`", @"\'b0"); // convert backquote to degree - left over from DOS days. return rtnstr; } private string ProcessConditional(string cnd, string opt, int lencnd, int lenopt, bool multiRtnVal) { // equaluate condition string stat = (_DocVersionInfo != null) ? this._DocVersionInfo.Evaluate(cnd, lencnd) : ""; int ls = stat.Length;//strlen(stat); if (ls == 0) return ""; // if evaluation not defined then return an empty string - no matches can be made // look for match - remember default string match = null; int matchlen = 0; string def = null; int deflen = 0; while (lenopt > 0 && match == null) { int end = MatchingBrace(opt); int eq = opt.IndexOf('=');// strchr(opt, '='); int len = end + 1; //(int)((end + 1) - opt); // +1 to include the '}' int li = eq - 1;//(int)(eq - opt) - 1; int ld = len - li - 3;// One for '{', '=' and '}' if (def == null || eq == 1) // (!def || eq == opt+1) { def = opt.Substring(eq + 1); //def=eq+1; deflen = ld; } if (ls == li && (stat.IndexOf(opt.Substring(1), li) > -1)) //(ls == li && !strncmp(stat, opt + 1, li)) { match = opt.Substring(eq + 1, ld);// match = eq + 1; matchlen = ld; } opt = opt.Substring(len); //opt += len;// point to the next piece lenopt -= len; } // if match process option - or process default if (match == null) //(!match) { match = def.Substring(0, deflen); matchlen = deflen; } return ProcessRO(match, multiRtnVal); //process(match, matchlen); } private string ProcessBrace(string str, int l, ref bool nfnd, bool multiRtnVal) { string rtnstr = ""; int nxt = NextDelimiter("{=", str); //nextDelimiter("{=", str, l); if (nxt == -1) // no delimiter found { // VarUse //strList *found=vl->lookFor(str,l); bool found = DictROVar.ContainsKey(str); if (found) rtnstr = DictROVar[str]; //add(new seVarUse(found)); else nfnd = true; } else { if (str[nxt] == '{') { // conditonal or menu if (nxt == 0) // if (nxt == str) { // menu // TODO: implement Menu logic //ml->process(str, l, vl); //add(new seMenuUse(ml)); //lstRoValues.Add(ProcessRO(str.Substring(0,l), true)); ProcessMultiReturnValues(str, l); } else { // conditional rtnstr = ProcessConditional(str, str.Substring(nxt), nxt, str.Length - nxt - 1, multiRtnVal);//processCondition(str, nxt, (int)(nxt - str), l - (int)(nxt - str)); } } else { // must be variable definiton //vl->add(str, nxt+1, (int)(nxt-str), (l - (int)(nxt-str))-1, ml); // 'l' is the lenght up to the matching brace of the variable definition string tmpval = ProcessRO(str.Substring(nxt + 1, l - nxt - 1), multiRtnVal); if (tmpval.Equals(string.Empty)) tmpval = " "; // nothing assinged to variable DictROVar.Add(str.Substring(0, nxt), tmpval); if (multiRtnVal) rtnstr = tmpval; } } return rtnstr; } private Dictionary> _ValueLookupDictionary = null; public List GetRosByValue(string value) { if (_ValueLookupDictionary == null) BuildValueDictionary(); if (value == string.Empty) return null; if(_ValueLookupDictionary.ContainsKey(value.ToUpper())) return _ValueLookupDictionary[value.ToUpper()]; return null; } private void BuildValueDictionary() { _ValueLookupDictionary = new Dictionary>(); if (dicRos == null) ParseIntoDictionary(_ROFst != null ? _ROFst.ROLookup : _ROFstInfo.ROLookup); foreach (rochild child in dicRos.Values) { if (child.value != null) { string value = child.value.ToUpper(); if (_ValueLookupDictionary.ContainsKey(value)) _ValueLookupDictionary[value].Add(new roChild(child)); else { List children = new List(); children.Add(new roChild(child)); _ValueLookupDictionary.Add(value, children); } } } } private void ProcessMultiReturnValues(string str, int len) { string tstr = str.Substring(0, len); while (tstr.Length > 0) { int idx = MatchingBrace(tstr); lstRoValues.Add(ProcessRO(tstr.Substring(0, idx + 1), true)); tstr = tstr.Substring(idx + 1); } } private int MatchingBrace(string str) { int level = 1; int idx = 0; // the while will skip the first position (the first brace) while (level > 0 && idx++ < str.Length) { switch (str[idx]) { case '{': level++; break; case '}': level--; break; } } if (level != 0) idx = -1; // didn't find matching brace return idx; //length including end brace } private int NextDelimiter(string delim, string str) { int idx; idx = str.IndexOfAny(delim.ToCharArray()); return idx; } #endregion } }