using System; using System.Collections.Generic; using System.Text; using System.ComponentModel; using System.Text.RegularExpressions; using System.Data; using System.Data.SqlClient; using System.Linq; using System.Threading; using Csla.Data; namespace VEPROMS.CSLA.Library { [Flags] public enum E_ROValueType : uint { All = 0, Text = 1, Table = 2, Graph = 4, Image = 8, Video = 16, Hologram = 32 } [Serializable] [TypeConverter(typeof(ExpandableObjectConverter))] public class ROFSTLookup { #region Log4Net private static readonly log4net.ILog _MyLog = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); #endregion #region Enums [Flags] public enum SearchTypes { StartsWith = 1, EndsWith = 2, Contains = 3, ExactMatch = 4 } public enum HeaderStatuses { Unknown = 0, NotLoaded = 1, InProgress = 2, LoadComplete = 3, LoadFailed = 4 } #endregion #region Structs / Internal Classes [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; }; [Serializable] public struct rogrp { public string value; public string appid; public int ID; public int ParentID; public rochild[] children; }; [Serializable] public struct rochild { public int ID; public int ParentID; public int type; public string title; // gets used for treeview public string roid; // roid unique identifier public string appid; // accessory page id - user specified unique id public string value; // return value, can be multiple values public rochild[] children; }; public class RoExtension { public int Offset; public string RoidExt; public string AccPageExt; } #endregion #region Fields public static Regex regRoKeyHigh = new Regex("( |-|_)(HIGH|HI)([0-9])"); public static Regex regRoKeyLow = new Regex("( |-|_)(LOW|LO)([0-9])"); private List _extensions; private List _baseAccPageKeys; // RofstLookup/Conversion Variables private int _rofstID; private DocVersionInfo _myDocVersionInfo; private int _selectedSlave; private string _otherChild = string.Empty; private string _roMissingDefaultValue = "[TBD]"; private bool _autoCombineSingleRetValues = true; private List _lstRoValues; private List _multiRoValues; private Dictionary _dicRoVars; private ItemInfo _itemInfo; // B2022-107: Display Progress Bar Messages/Statuses when a new ROFST binary file is loaded into the database private frmRofstLoadStatus _frmRofstLoadStatus = null; private Dictionary _dicRoCounts = null; private bool _showLoadingStatus = true; private int _curRoCnt = 0; private int _dbRoCnt = 0; private int _totalRoCnt = 0; private double _pctComplete = 0; #endregion #region Properties public int RofstID { get { return _rofstID; } } public DocVersionInfo MyDocVersionInfo { get { return _myDocVersionInfo; } set { _myDocVersionInfo = value; _selectedSlave = (_myDocVersionInfo == null) ? 0 : _myDocVersionInfo.DocVersionConfig.SelectedSlave; } } // C2021-065 see if we need to get the RO information for the "Other" Child applicability value public int SelectedSlave { get { return (!string.IsNullOrEmpty(_otherChild)) ? Convert.ToInt32(_otherChild) : _selectedSlave; } } //C2021-065 used by Barakah Alarms so that we get ROLookUp for the Other applicability public string OtherChild { get { return _otherChild; } set { _otherChild = value; } } // B2022-020 to pass information into error log if needed public ItemInfo MyItemInfo { get { return _itemInfo; } set { _itemInfo = value; } } // B2022-124: [JPR] Blank RO Values (All Spaces) printing as "?" public string RoMissingDefaultValue { get { return _roMissingDefaultValue; } set { _roMissingDefaultValue = value; } } public List Extensions { get { if (_extensions == null) { _extensions = RofstDataGetExtensions(); } return _extensions; } } public List BaseAccPageKeys { get { if (_baseAccPageKeys == null) { _baseAccPageKeys = GetBaseAccPageKeys(); } return _baseAccPageKeys; } } public bool AutoCombineSingleRetValues { get { return _autoCombineSingleRetValues; } set { _autoCombineSingleRetValues = value; } } public bool ShowLoadingStatus { get { return _showLoadingStatus; } } #endregion #region Constructors public ROFSTLookup(int rofstID, DocVersionInfo dvi, string otherChild, bool showLoadingStatus = true) { // Set Fields/Properties _rofstID = rofstID; MyDocVersionInfo = dvi; _otherChild = otherChild; _showLoadingStatus = showLoadingStatus; // Check if ROFST file is already loaded, if not then parse/load Ro Values if (!RofstDataExists(rofstID)) { Load(rofstID); } } public ROFSTLookup(int rofstID, DocVersionInfo dvi, bool showLoadingStatus = true) { _rofstID = rofstID; MyDocVersionInfo = dvi; _showLoadingStatus = showLoadingStatus; if (!RofstDataExists(rofstID)) { Load(rofstID); } } public ROFSTLookup(int rofstID, bool showLoadingStatus = true) { _rofstID = rofstID; MyDocVersionInfo = null; _showLoadingStatus = showLoadingStatus; if (!RofstDataExists(rofstID)) { Load(rofstID); } } #endregion #region ROTextConvertMethods // B2023-037: Handle <=, >=, +-, -> and <- symbols. Convert to unicode for output, i.e. print and edit/view (when editing // step, will show as 2 characters, not unicode, unless ro inserted when code replaced link text with unicode. public static string ROConvertSymbols(string retval, bool arr1, bool arr2) { if (arr1) { retval = retval.Replace("\\u8209?>", @"\u8594?"); // Right Arrow retval = retval.Replace("<\\u8209?", @"\u8592?"); // Left Arrow retval = retval.Replace("->", @"\u8594?"); // Right Arrow retval = retval.Replace("<-", @"\u8592?"); // Left Arrow } if (arr2) { retval = retval.Replace("<=", @"\u8804?"); // Less than or Equal retval = retval.Replace(">=", @"\u8805?"); // Greater than or Equal retval = retval.Replace("+\\u8209?", @"\'b1"); // plus minus retval = retval.Replace("+-", @"\'b1"); // plus minus } return retval; } #endregion #region Public Methods #region (RO Search / Collections) public Dictionary Search(string value, int searchTypeID, bool onlyRoid16, int? maxNumRecords = null) { if (string.IsNullOrEmpty(value)) return null; return RofstDataSearch(_rofstID, value, searchTypeID, onlyRoid16, maxNumRecords); } public ROFSTLookup.rochild[] GetRoChildrenByID(int id, int dbiID, bool loadChildren = false, bool loadAllChildren = false) { return RofstDataGetChildrenByID(_rofstID, dbiID, id, loadChildren, loadAllChildren); } public ROFSTLookup.rochild[] GetRoChildrenByRoid(string roid, bool loadChildren = false, bool loadAllChildren = false) { return RofstDataGetChildrenByRoid(_rofstID, roid, loadChildren, loadAllChildren); } public ROFSTLookup.rochild[] GetRoChildrenByType(E_ROValueType valueTypes, bool loadChildren = false, bool loadAllChildren = false) { return RofstDataGetRoChildrenByType(_rofstID, valueTypes, loadChildren, loadAllChildren); } #endregion #region (RO Database Info) public int GetRODatabaseTitleIndex(string roid) { return Convert.ToInt32("0x" + roid.Substring(0, 4), 16); } public string GetRODatabaseTitle(int idx) { ROFSTLookup.rodbi rd = RofstDataGetDatabaseByID(_rofstID, idx); return (!string.IsNullOrEmpty(rd.dbiTitle) ? rd.dbiTitle : "RO Database Title Not Found"); } public ROFSTLookup.rodbi GetRODatabase(string roid, bool loadChildren = false, bool loadAllChildren = false) { int idx = GetRODatabaseTitleIndex(roid); ROFSTLookup.rodbi rd = RofstDataGetDatabaseByID(_rofstID, idx, loadChildren, loadAllChildren); return (rd.dbiID > 0) ? rd : RofstDataGetDatabaseByID(_rofstID, 1, loadChildren, loadAllChildren); } public ROFSTLookup.rodbi[] GetRODatabaseList(bool loadChildren = false, bool loadAllChildren = false) { return RofstDataGetDatabases(_rofstID, loadChildren, loadAllChildren); } #endregion #region (RO Info By AccPageID) public string FormatAccPageKey(string accPageID) { string accPageBase = string.Empty; string accPageExt = string.Empty; string spDefault = (MyDocVersionInfo != null && MyDocVersionInfo.DocVersionConfig != null) ? MyDocVersionInfo.DocVersionConfig.RODefaults_setpointprefix : string.Empty; string igDefault = (MyDocVersionInfo != null && MyDocVersionInfo.DocVersionConfig != null) ? MyDocVersionInfo.DocVersionConfig.RODefaults_graphicsprefix : string.Empty; return FormatAccPageKeyWithExt(accPageID, spDefault, igDefault, ref accPageBase, ref accPageExt); } public string FormatAccPageKey(string accPageID, ref string accPageBase, ref string accPageExt) { string spDefault = (MyDocVersionInfo != null && MyDocVersionInfo.DocVersionConfig != null) ? MyDocVersionInfo.DocVersionConfig.RODefaults_setpointprefix : string.Empty; string igDefault = (MyDocVersionInfo != null && MyDocVersionInfo.DocVersionConfig != null) ? MyDocVersionInfo.DocVersionConfig.RODefaults_graphicsprefix : string.Empty; return FormatAccPageKeyWithExt(accPageID, spDefault, igDefault, ref accPageBase, ref accPageExt); } public string FormatAccPageKey(string accPageID, string spDefault, string igDefault) { string accPageBase = string.Empty; string accPageExt = string.Empty; return FormatAccPageKeyWithExt(accPageID, spDefault, igDefault, ref accPageBase, ref accPageExt); } public string FormatAccPageKey(string accPageID, string spDefault, string igDefault, ref string accPageBase, ref string accPageExt) { return FormatAccPageKeyWithExt(accPageID, spDefault, igDefault, ref accPageBase, ref accPageExt); } public ROFSTLookup.rochild GetROChildByAccPageID(string accPageID) { string spDefault = (MyDocVersionInfo != null && MyDocVersionInfo.DocVersionConfig != null) ? MyDocVersionInfo.DocVersionConfig.RODefaults_setpointprefix : string.Empty; string igDefault = (MyDocVersionInfo != null && MyDocVersionInfo.DocVersionConfig != null) ? MyDocVersionInfo.DocVersionConfig.RODefaults_graphicsprefix : string.Empty; return GetROChildByAccPageID(accPageID, spDefault, igDefault); } public ROFSTLookup.rochild GetROChildByAccPageID(string accPageID, string spDefault, string igDefault) { string accPageBase = string.Empty; string accPageExt = string.Empty; // Cleanup accPageID if necessary [Note* This will also handle any UnitInfo Ro Values (ex: "")] string accPageKey = FormatAccPageKeyWithExt(accPageID, spDefault, igDefault, ref accPageBase, ref accPageExt); ROFSTLookup.rochild rc = RofstDataGetChildByAccPageID(_rofstID, accPageBase); //if (rc.ID >=0 && rc.roid.Length < 16 && Regex.IsMatch(accPageKey, @".*\.[A-Z]") && rc.children != null && rc.children.Count() > 0) if (rc.ID >= 0 && rc.roid.Length < 16 && !string.IsNullOrEmpty(accPageExt) && rc.children != null && rc.children.Count() > 0) { // Check if AccPageID/Key has a return value specific extension. Try to find the RoChild record with the specific return value type, // If not found Or the specific extension value is (Null or Empty), then just return the first/default return value type in the list of children var roExt = Extensions.Where(x => x.AccPageExt.Equals(accPageExt)).SingleOrDefault(); return (rc.children.Where(x => x.roid.Substring(12, 4) == roExt.RoidExt && !string.IsNullOrEmpty(x.value)).Any()) ? rc.children.Where(x => x.roid.Substring(12, 4) == roExt.RoidExt).Single() : rc.children.First(); } return rc; // If RoChild is not found, then a default (ROFSTLookup.rochild) object will be returned, but its ID will be -1 } #endregion #region (RO Info By Roid) public static string FormatRoidKey(string roid, bool check16Digits = false) { if (!string.IsNullOrEmpty(roid)) { roid = roid.ToUpper(); roid = roid.Replace("", ""); roid = roid.ToCleanString(); // Removes any spaces if ((!roid.StartsWith(" "FFFF000000020041"] roid = string.Format("{0}00000000", roid).Substring(0, 12) + "0041"; } roid = roid.TrimStart(); //B2022-140 remove any preceding spaces } return roid; } public static string FormatRoidKey(string roid, ref string roid12, ref string roidExt, bool check16Digits = false) { roid = FormatRoidKey(roid, check16Digits); // Default / Initialize Reference Parameters roid12 = string.Empty; roidExt = string.Empty; if (!string.IsNullOrEmpty(roid) && !roid.StartsWith("")] roid = FormatRoidKey(roid); ROFSTLookup.rochild rc = GetRoChild12(roid, loadChildren, loadAllChildren); if (!roid.StartsWith("FFFF") && rc.children != null && rc.children.Length > 0 && roid.Length == 16) { // If specific match exists for multi-return values, then return specified value, otherwise default to the first child if (rc.children.Where(x => x.roid.ToUpper() == roid.ToUpper()).Any()) return rc.children.Where(x => x.roid.ToUpper() == roid.ToUpper()).Single(); else return rc.children.First(); } return rc; } public string GetTranslatedRoValue(string roid, bool DoCaret, bool DoDOSSuperSubScript, bool convertRoSymbols, ItemInfo myiteminfo) { roid = FormatRoidKey(roid, true); string retval = GetRoChild(roid).value; if (string.IsNullOrEmpty(retval)) return "?"; // Returning a "?" character indicates that the selected RO Value no longer exists or has been deleted. retval = ReplaceUnicode(retval, DoCaret); // B2023-037: Handle <=, >=, +-, -> and <- symbols. Convert to unicode for output, i.e. print and edit/view (when editing // step, will show as 2 characters, not unicode, unless ro inserted when code replaced link text with unicode. //(_MyItemInfo.ActiveFormat.PlantFormat.FormatData.SectData.UseDashGreaterLessThenForArrowsInROValue || // _MyItemInfo.ActiveFormat.PlantFormat.FormatData.SectData.ConvertGTELTEPMinROValue)) bool arrows1 = myiteminfo.ActiveFormat.PlantFormat.FormatData.SectData.UseDashGreaterLessThenForArrowsInROValue; bool arrows2 = myiteminfo.ActiveFormat.PlantFormat.FormatData.SectData.ConvertGTELTEPMinROValue; if (convertRoSymbols) retval = ROFSTLookup.ROConvertSymbols(retval, arrows1, arrows2); retval = ConvertFortranFormatToScienctificNotation(retval); // B2019-037 handle the super an sub scripts after getting the RO value from the FST // the corrected RO text is added to the display text in the link info if (DoDOSSuperSubScript) { retval = Regex.Replace(retval, "[#](.*?)[#]", "\\up2 $1\\up0 ");// Superscript retval = Regex.Replace(retval, "[~](.*?)[~]", "\\dn2 $1\\up0 ");// Subscript } return (!string.IsNullOrEmpty(retval)) ? retval.Replace("\r\n", @"\par ") : retval; } public List GetValueDifferences(int originalRofstID, ref List delList) { return RofstDataGetValueDifferences(originalRofstID, _rofstID, ref delList); } public List GetROTitleAndGroupPath(string roid, bool reportMissingROs, bool convertCaretToDelta) { // Return the RO Title in a list of strings. The last item in the list is the actual RO title, // the items preceding it are the titles of the groups and sub-groups containing the RO List titlePath = new List(); roid = FormatRoidKey(roid); ROFSTLookup.rochild roc = GetRoChild12(roid); if (!string.IsNullOrEmpty(roc.appid)) { string tmp = roc.title; if (!string.IsNullOrEmpty(roc.appid) && roc.title.Contains(roc.appid)) { tmp = roc.title.Replace(roc.appid, string.Empty).Trim(); } tmp = string.Format("[{0}] {1}", roc.appid, tmp); tmp = tmp.Replace("`", "\u00B0"); //degree tmp = tmp.Replace("\xF8", "\u00B0"); //degree if (convertCaretToDelta) tmp = tmp.Replace("^", "\u0394"); // delta titlePath.Add(tmp); if (roc.ParentID > 0) { do { string parent = roid.Substring(0, 4) + string.Format("{0:X8}", roc.ParentID); roc = GetRoChild12(parent); if (roc.ID >= 0) titlePath.Add(roc.title.Trim()); } while (roc.ID >= 0); } titlePath.Reverse(); } else if (reportMissingROs) // Missing RO, put a message with the ROID on the report... { titlePath.Add(string.Format("Missing RO for ROID {0}", roid)); } return titlePath; } public string GetROTitle(string roid) { StringBuilder sb = new StringBuilder(); roid = FormatRoidKey(roid); ROFSTLookup.rochild rc = GetRoChild(roid); // B2020-125: View of Consistency check report displaying error message and crashing. And also in 'else' check for null if (rc.ID < 0) { sb.Append("Could not find RO data"); } else { string tmp = string.Empty; if (!string.IsNullOrEmpty(rc.title)) tmp = rc.title; if (!string.IsNullOrEmpty(rc.appid)) tmp = tmp.Replace(rc.appid, string.Empty); if (!string.IsNullOrEmpty(rc.value)) tmp = tmp.Replace(rc.value, string.Empty); sb.Append(tmp.Trim()); } if (rc.ParentID > 0) { do { string parentROID = roid.Substring(0, 4) + string.Format("{0:X8}", rc.ParentID); rc = GetRoChild12(parentROID); if (rc.ID > 0) sb.Insert(0, rc.title + " - "); } while (rc.ID > 0); } return sb.ToString(); } #endregion #region (RO Info Helper Methods) public static byte[] GetRofstLookupBytes(int rofstID) { return RofstDataGetRofstLookupBytes(rofstID); } public static DateTime GetRoFSTdts(int rofstID) { return GetRofstDtsByID(rofstID); } public DateTime GetRoFSTdts() { return GetRoFSTdts(_rofstID); } public bool HasChildren(ref ROFSTLookup.rochild child) { LoadChildren(ref child); return child.children.Any(); } public bool HasChildren(ref ROFSTLookup.rodbi db) { LoadChildren(ref db); return db.children.Any(); } public void LoadChildren(ref ROFSTLookup.rochild child) { // If Children is null then it hasn't been loaded yet if (child.children == null) { if (!string.IsNullOrEmpty(child.appid)) child = GetRoChild12(child.roid, true); else child.children = GetRoChildrenByRoid(child.roid, false); } } public void LoadChildren(ref ROFSTLookup.rodbi db) { // If Children is null then it hasn't been loaded yet if (db.children == null) db.children = GetRoChildrenByID(db.ID, db.dbiID, false); } public static ROFSTLookup.rochild GetEmptyRoChild() { return new ROFSTLookup.rochild() { ID = -1, type = 0 }; } public static string CalculateDuration(DateTime dtStart) { string duration = string.Empty; double totalSecs = TimeSpan.FromTicks(DateTime.Now.Ticks - dtStart.Ticks).TotalSeconds; int minutes = (totalSecs > 60) ? Convert.ToInt32(totalSecs) / 60 : 0; double secs = (minutes <= 0) ? totalSecs : (totalSecs - Convert.ToDouble(minutes * 60)); if (minutes > 0) duration = string.Format("{0} min(s) ", minutes.ToString("n0")); if (secs < 0) secs = 0.00; duration = duration + string.Format("{0,10:#####0.00} sec(s)", secs).Trim(); return duration; //return string.Format("{0,10:#####0.00}", TimeSpan.FromTicks(DateTime.Now.Ticks - dtStart.Ticks).TotalSeconds); } #endregion #endregion #region Private Methods #region (Database Calls) private bool RofstDataExists(int rofstID) { int headerStatusID = RofstDataGetHeaderLoadStatus(rofstID); while (headerStatusID == (int)HeaderStatuses.InProgress) { // Wait 5 sec(s) then Check Header Status Again Thread.Sleep(5000); headerStatusID = RofstDataGetHeaderLoadStatus(rofstID); } return (headerStatusID == (int)HeaderStatuses.LoadComplete); // false includes [NotLoaded = 1 || LoadFailed = 4 || Unknown = 0] } private int RofstDataGetHeaderLoadStatus(int rofstID) { try { using (SqlConnection cn = Database.VEPROMS_SqlConnection) { using (SqlCommand cmd = cn.CreateCommand()) { cmd.CommandTimeout = Database.DefaultTimeout; cmd.CommandType = CommandType.StoredProcedure; cmd.CommandText = "vesp_RofstDataGetHeaderRofstByID"; cmd.Parameters.Add(new SqlParameter("@RofstID", SqlDbType.Int)).Value = rofstID; using (SafeDataReader dr = new SafeDataReader(cmd.ExecuteReader())) { if (dr.Read()) return Convert.ToInt32(dr.GetValue("RofstHeaderStatusID")); } } } return 0; // Unknown Status } catch (Exception ex) { throw new DbCslaException("RofstData.vesp_RofstDataGetHeaderRofstByID", ex); } } private static byte[] RofstDataGetRofstLookupBytes(int rofstID) { try { using (SqlConnection cn = Database.VEPROMS_SqlConnection) { using (SqlCommand cmd = cn.CreateCommand()) { cmd.CommandTimeout = Database.DefaultTimeout; cmd.CommandType = CommandType.StoredProcedure; cmd.CommandText = "vesp_RofstDataGetRofstByID"; cmd.Parameters.Add(new SqlParameter("@RofstID", SqlDbType.Int)).Value = rofstID; cmd.Parameters.Add(new SqlParameter("@IncludeRoLookup", SqlDbType.Bit)).Value = 1; using (SafeDataReader dr = new SafeDataReader(cmd.ExecuteReader())) { if (dr.Read()) return (byte[])dr.GetValue("ROLookup"); } } } return null; } catch (Exception ex) { throw new DbCslaException("RofstData.vesp_RofstDataGetRofstByID", ex); } } private static DateTime GetRofstDtsByID(int rofstID) { try { using (SqlConnection cn = Database.VEPROMS_SqlConnection) { using (SqlCommand cmd = cn.CreateCommand()) { cmd.CommandTimeout = Database.DefaultTimeout; cmd.CommandType = CommandType.StoredProcedure; cmd.CommandText = "vesp_RofstDataGetRofstByID"; cmd.Parameters.Add(new SqlParameter("@RofstID", SqlDbType.Int)).Value = rofstID; cmd.Parameters.Add(new SqlParameter("@IncludeRoLookup", SqlDbType.Bit)).Value = 0; using (SafeDataReader dr = new SafeDataReader(cmd.ExecuteReader())) { if (dr.Read()) return (DateTime)dr.GetValue("DTS"); } } } return new DateTime(); } catch (Exception ex) { throw new DbCslaException("RofstData.vesp_RofstDataGetRofstByID", ex); } } private void RofstHeaderInsert(int rofstID, int hSize, int hMonth, int hDay, int hcYear, int hcMonth, int hcDay, int hcHour, int hcMin, int hcSec, int hcHund, string userID) { try { using (SqlConnection cn = Database.VEPROMS_SqlConnection) { using (SqlCommand cmd = cn.CreateCommand()) { cmd.CommandTimeout = Database.DefaultTimeout; cmd.CommandType = CommandType.StoredProcedure; cmd.CommandText = "vesp_RofstHeaderInsert"; cmd.Parameters.Add(new SqlParameter("@RofstID", SqlDbType.Int)).Value = rofstID; cmd.Parameters.Add(new SqlParameter("@hSize", SqlDbType.Int)).Value = hSize; cmd.Parameters.Add(new SqlParameter("@hMonth", SqlDbType.Int)).Value = hMonth; cmd.Parameters.Add(new SqlParameter("@hDay", SqlDbType.Int)).Value = hDay; cmd.Parameters.Add(new SqlParameter("@hcYear", SqlDbType.Int)).Value = hcYear; cmd.Parameters.Add(new SqlParameter("@hcMonth", SqlDbType.Int)).Value = hcMonth; cmd.Parameters.Add(new SqlParameter("@hcDay", SqlDbType.Int)).Value = hcDay; cmd.Parameters.Add(new SqlParameter("@hcHour", SqlDbType.Int)).Value = hcHour; cmd.Parameters.Add(new SqlParameter("@hcMin", SqlDbType.Int)).Value = hcMin; cmd.Parameters.Add(new SqlParameter("@hcSec", SqlDbType.Int)).Value = hcSec; cmd.Parameters.Add(new SqlParameter("@hcHund", SqlDbType.Int)).Value = hcHund; cmd.Parameters.Add(new SqlParameter("@userID", SqlDbType.VarChar)).Value = userID; cmd.ExecuteNonQuery(); } } } catch (Exception ex) { throw new DbCslaException("ROFSTLookup.RofstHeaderInsert.vesp_RofstHeaderInsert", ex); } } private void RofstHeaderFinalizeLoad(int rofstID) { try { using (SqlConnection cn = Database.VEPROMS_SqlConnection) { using (SqlCommand cmd = cn.CreateCommand()) { cmd.CommandTimeout = Database.DefaultTimeout; cmd.CommandType = CommandType.StoredProcedure; cmd.CommandText = "vesp_RofstHeaderFinalizeLoad"; cmd.Parameters.Add(new SqlParameter("@RofstID", SqlDbType.Int)).Value = rofstID; cmd.ExecuteNonQuery(); } } } catch (Exception ex) { throw new DbCslaException("RofstData.vesp_RofstHeaderFinalizeLoad", ex); } } private void RofstDatabaseInsert(int rofstID, int dbiID, int dbiType, int dbiAW, string dbiTitle, string dbiAP, int id, int parentID) { try { using (SqlConnection cn = Database.VEPROMS_SqlConnection) { using (SqlCommand cmd = cn.CreateCommand()) { cmd.CommandTimeout = Database.DefaultTimeout; cmd.CommandType = CommandType.StoredProcedure; cmd.CommandText = "vesp_RofstDatabaseInsert"; cmd.Parameters.Add(new SqlParameter("@RofstID", SqlDbType.Int)).Value = rofstID; cmd.Parameters.Add(new SqlParameter("@dbiID", SqlDbType.Int)).Value = dbiID; cmd.Parameters.Add(new SqlParameter("@dbiType", SqlDbType.Int)).Value = dbiType; cmd.Parameters.Add(new SqlParameter("@dbiAW", SqlDbType.Int)).Value = dbiAW; cmd.Parameters.Add(new SqlParameter("@dbiTitle", SqlDbType.VarChar)).Value = dbiTitle; cmd.Parameters.Add(new SqlParameter("@dbiAP", SqlDbType.VarChar)).Value = dbiAP; cmd.Parameters.Add(new SqlParameter("@ID", SqlDbType.Int)).Value = id; cmd.Parameters.Add(new SqlParameter("@ParentID", SqlDbType.Int)).Value = parentID; cmd.ExecuteNonQuery(); } } } catch (Exception ex) { throw new DbCslaException("RofstData.vesp_RofstDatabaseInsert", ex); } } private void RofstChildInsert(int rofstID, int id, int parentID, int dbiID, int type, string title, string roid, string appid, string value) { try { using (SqlConnection cn = Database.VEPROMS_SqlConnection) { using (SqlCommand cmd = cn.CreateCommand()) { cmd.CommandTimeout = Database.DefaultTimeout; cmd.CommandType = CommandType.StoredProcedure; cmd.CommandText = "vesp_RofstChildInsert"; cmd.Parameters.Add(new SqlParameter("@RofstID", SqlDbType.Int)).Value = rofstID; cmd.Parameters.Add(new SqlParameter("@ID", SqlDbType.Int)).Value = id; cmd.Parameters.Add(new SqlParameter("@ParentID", SqlDbType.Int)).Value = parentID; cmd.Parameters.Add(new SqlParameter("@dbiID", SqlDbType.Int)).Value = dbiID; cmd.Parameters.Add(new SqlParameter("@type", SqlDbType.Int)).Value = type; cmd.Parameters.Add(new SqlParameter("@title", SqlDbType.VarChar)).Value = title; cmd.Parameters.Add(new SqlParameter("@roid", SqlDbType.VarChar)).Value = roid; if (!string.IsNullOrEmpty(appid)) cmd.Parameters.Add(new SqlParameter("@appid", SqlDbType.VarChar)).Value = appid; if (!string.IsNullOrEmpty(value)) cmd.Parameters.Add(new SqlParameter("@value", SqlDbType.VarChar)).Value = value; // B2022-124: [JPR] Blank RO Values (All Spaces) printing as "?" if (!string.IsNullOrEmpty(this.RoMissingDefaultValue)) cmd.Parameters.Add(new SqlParameter("@missingDefaultValue", SqlDbType.VarChar)).Value = this.RoMissingDefaultValue; cmd.ExecuteNonQuery(); } } } catch (Exception ex) { throw new DbCslaException("RofstData.vesp_RofstChildInsert", ex); } } private ROFSTLookup.rodbi RofstDataGetDatabaseByID(int rofstID, int dbiID, bool loadChildren = false, bool loadAllChildren = false) { try { using (SqlConnection cn = Database.VEPROMS_SqlConnection) { using (SqlCommand cmd = cn.CreateCommand()) { cmd.CommandTimeout = Database.DefaultTimeout; cmd.CommandType = CommandType.StoredProcedure; cmd.CommandText = "vesp_RofstDataGetDatabaseByID"; cmd.Parameters.Add(new SqlParameter("@RofstID", SqlDbType.Int)).Value = rofstID; cmd.Parameters.Add(new SqlParameter("@dbiID", SqlDbType.Int)).Value = dbiID; using (SafeDataReader dr = new SafeDataReader(cmd.ExecuteReader())) { if (dr.Read()) { return ConvertToRodbiObject(dr, loadChildren, loadAllChildren); } } } } return new ROFSTLookup.rodbi(); } catch (Exception ex) { throw new DbCslaException("RofstData.vesp_RofstDataGetDatabaseByID", ex); } } private ROFSTLookup.rodbi[] RofstDataGetDatabases(int rofstID, bool loadChildren = false, bool loadAllChildren = false) { try { List dbs = new List(); using (SqlConnection cn = Database.VEPROMS_SqlConnection) { using (SqlCommand cmd = cn.CreateCommand()) { cmd.CommandTimeout = Database.DefaultTimeout; cmd.CommandType = CommandType.StoredProcedure; cmd.CommandText = "vesp_RofstDataGetDatabases"; cmd.Parameters.Add(new SqlParameter("@RofstID", SqlDbType.Int)).Value = rofstID; using (SafeDataReader dr = new SafeDataReader(cmd.ExecuteReader())) { while (dr.Read()) { dbs.Add(ConvertToRodbiObject(dr, loadChildren, loadAllChildren)); } } } } return dbs.ToArray(); } catch (Exception ex) { throw new DbCslaException("RofstData.vesp_RofstDataGetDatabases", ex); } } private ROFSTLookup.rochild[] RofstDataGetChildrenByID(int rofstID, int dbiID, int id, bool loadChildren = false, bool loadAllChildren = false) { try { List lst = new List(); using (SqlConnection cn = Database.VEPROMS_SqlConnection) { using (SqlCommand cmd = cn.CreateCommand()) { cmd.CommandTimeout = Database.DefaultTimeout; cmd.CommandType = CommandType.StoredProcedure; cmd.CommandText = "vesp_RofstDataGetChildrenByID"; cmd.Parameters.Add(new SqlParameter("@RofstID", SqlDbType.Int)).Value = rofstID; cmd.Parameters.Add(new SqlParameter("@DbiID", SqlDbType.Int)).Value = dbiID; cmd.Parameters.Add(new SqlParameter("@ID", SqlDbType.Int)).Value = id; using (SafeDataReader dr = new SafeDataReader(cmd.ExecuteReader())) { while (dr.Read()) { lst.Add(ConvertToRochildObject(dr, loadChildren, loadAllChildren)); } } } } return lst.ToArray(); } catch (Exception ex) { throw new DbCslaException("RofstData.vesp_RofstDataGetChildrenByID", ex); } } private ROFSTLookup.rochild[] RofstDataGetChildrenByRoid(int rofstID, string roid, bool loadChildren = false, bool loadAllChildren = false) { try { List lst = new List(); using (SqlConnection cn = Database.VEPROMS_SqlConnection) { using (SqlCommand cmd = cn.CreateCommand()) { cmd.CommandTimeout = Database.DefaultTimeout; cmd.CommandType = CommandType.StoredProcedure; cmd.CommandText = "vesp_RofstDataGetChildrenByRoid"; cmd.Parameters.Add(new SqlParameter("@RofstID", SqlDbType.Int)).Value = rofstID; cmd.Parameters.Add(new SqlParameter("@Roid", SqlDbType.VarChar)).Value = roid; using (SafeDataReader dr = new SafeDataReader(cmd.ExecuteReader())) { while (dr.Read()) { lst.Add(ConvertToRochildObject(dr, loadChildren, loadAllChildren)); } } } } return lst.ToArray(); } catch (Exception ex) { throw new DbCslaException("RofstData.vesp_RofstDataGetChildrenByRoid", ex); } } private List RofstDataGetValueDifferences(int originalRofstID, int currentRofstID, ref List delList) { // use this list to see what differences are between the current and the original List modList = new List(); List roidList = new List(); try { using (SqlConnection cn = Database.VEPROMS_SqlConnection) { using (SqlCommand cmd = cn.CreateCommand()) { cmd.CommandTimeout = Database.DefaultTimeout; cmd.CommandType = CommandType.StoredProcedure; cmd.CommandText = "vesp_RofstDataGetValueDifferences"; cmd.Parameters.Add(new SqlParameter("@OriginalRofstID", SqlDbType.Int)).Value = originalRofstID; cmd.Parameters.Add(new SqlParameter("@CurrentRofstID", SqlDbType.Int)).Value = currentRofstID; using (SafeDataReader dr = new SafeDataReader(cmd.ExecuteReader())) { while (dr.Read()) { roidList.Add((string)dr.GetValue("Roid")); } } } } ROFSTLookup.rochild originalRoChild; ROFSTLookup.rochild currentRoChild; Dictionary originalRos = new Dictionary(); Dictionary currentRos = new Dictionary(); foreach (string roid in roidList) { originalRoChild = RofstDataGetChildByRoid(originalRofstID, roid); originalRos.Add(originalRoChild.roid, originalRoChild.value); if (originalRoChild.children != null && originalRoChild.children.Length > 0) { foreach (ROFSTLookup.rochild roc in originalRoChild.children) { originalRos.Add(roc.roid, roc.value); } } currentRoChild = RofstDataGetChildByRoid(currentRofstID, roid); currentRos.Add(currentRoChild.roid, currentRoChild.value); if (currentRoChild.children != null && currentRoChild.children.Length > 0) { foreach (ROFSTLookup.rochild roc in currentRoChild.children) { currentRos.Add(roc.roid, roc.value); } } } string cvalue = string.Empty; string ovalue = string.Empty; foreach (string key in originalRos.Keys) { cvalue = null; ovalue = originalRos[key]; if (currentRos.ContainsKey(key)) cvalue = currentRos[key]; if (cvalue == null && cvalue != ovalue) delList.Add(key); else if (cvalue != ovalue) modList.Add(key); } return modList; } catch (Exception ex) { throw new DbCslaException("RofstData.vesp_RofstDataGetValueDifferences", ex); } } private Dictionary RofstDataSearch(int rofstID, string value, int searchTypeID, bool onlyRoid16, int? maxNumRecords) { // Currently, the RO Value Search only uses the default values for each of the (16) digit Ext Specific RO Return Values // The defaults for each (16) digit Ext Specific RO Return Value are stored separately in the [RofstDefaultValue] table so they can be indexed / optimized // for performance. In the future, the search can easily be modified to also include all unit specific return values as well. All we need to do is // add a new table [RofstReturnValue] in the database to hold all of the different extension specific return values for each unit when applicable. // All of the records in the [RofstReturnValue] will have a Foreign Key reference back to their RO Child Base objects in the [RofstChild] table. Dictionary dic = new Dictionary(); if (string.IsNullOrEmpty(value)) return dic; try { using (SqlConnection cn = Database.VEPROMS_SqlConnection) { using (SqlCommand cmd = cn.CreateCommand()) { cmd.CommandTimeout = Database.DefaultTimeout; cmd.CommandType = CommandType.StoredProcedure; cmd.CommandText = "vesp_RofstDataSearch"; cmd.Parameters.Add(new SqlParameter("@RofstID", SqlDbType.Int)).Value = rofstID; cmd.Parameters.Add(new SqlParameter("@Value", SqlDbType.VarChar)).Value = value; cmd.Parameters.Add(new SqlParameter("@SearchTypeID", SqlDbType.Int)).Value = searchTypeID; cmd.Parameters.Add(new SqlParameter("@OnlyRoid16", SqlDbType.Bit)).Value = (onlyRoid16) ? 1 : 0; if (maxNumRecords != null) cmd.Parameters.Add(new SqlParameter("@MaxNumOfRecords", SqlDbType.Int)).Value = (int)maxNumRecords; using (SafeDataReader dr = new SafeDataReader(cmd.ExecuteReader())) { while (dr.Read()) { dic.Add((string)dr.GetValue("roid"), (string)dr.GetValue("value")); } } } } return dic; } catch (Exception ex) { throw new DbCslaException("RofstData.vesp_RofstDataSearch", ex); } } private ROFSTLookup.rochild[] RofstDataGetRoChildrenByType(int rofstID, E_ROValueType valueTypes, bool loadChildren = false, bool loadAllChildren = false) { try { List lst = new List(); using (SqlConnection cn = Database.VEPROMS_SqlConnection) { using (SqlCommand cmd = cn.CreateCommand()) { cmd.CommandTimeout = Database.DefaultTimeout; cmd.CommandType = CommandType.StoredProcedure; cmd.CommandText = "vesp_RofstDataGetChildrenByType"; cmd.Parameters.Add(new SqlParameter("@RofstID", SqlDbType.Int)).Value = rofstID; cmd.Parameters.Add(new SqlParameter("@ValueTypes", SqlDbType.VarChar)).Value = valueTypes.ToCommaDelimString(); using (SafeDataReader dr = new SafeDataReader(cmd.ExecuteReader())) { while (dr.Read()) { lst.Add(ConvertToRochildObject(dr, loadChildren, loadAllChildren)); } } } } return lst.ToArray(); } catch (Exception ex) { throw new DbCslaException("RofstData.RofstDataGetRoChildrenByType", ex); } } private List RofstDataGetExtensions() { try { List lst = new List(); using (SqlConnection cn = Database.VEPROMS_SqlConnection) { using (SqlCommand cmd = cn.CreateCommand()) { cmd.CommandTimeout = Database.DefaultTimeout; cmd.CommandType = CommandType.StoredProcedure; cmd.CommandText = "vesp_RofstDataGetExtensions"; using (SafeDataReader dr = new SafeDataReader(cmd.ExecuteReader())) { while (dr.Read()) { lst.Add(ConvertToRoExtensionObject(dr)); } } } } return lst; } catch (Exception ex) { throw new DbCslaException("RofstData.vesp_RofstDataGetExtensions", ex); } } private List GetBaseAccPageKeys() { try { List lst = new List(); using (SqlConnection cn = Database.VEPROMS_SqlConnection) { using (SqlCommand cmd = cn.CreateCommand()) { cmd.CommandTimeout = Database.DefaultTimeout; cmd.CommandType = CommandType.StoredProcedure; cmd.CommandText = "vesp_RofstDataGetBaseAccPageKeys"; cmd.Parameters.Add(new SqlParameter("@RofstID", SqlDbType.Int)).Value = _rofstID; using (SafeDataReader dr = new SafeDataReader(cmd.ExecuteReader())) { while (dr.Read()) { lst.Add(dr.GetValue("BaseAccPageID").ToString()); } } } } return lst; } catch (Exception ex) { throw new DbCslaException("RofstData.vesp_RofstDataGetBaseAccPageKeys", ex); } } #endregion #region (Core/Base logic for RO Values & UnitInfo RO Values) private ROFSTLookup.rochild RofstDataGetChildByRoid(int rofstID, string roid, bool loadChildren = false, bool loadAllChildren = false) { try { // Cleanup Roid if necessary (Note* This method also handles the UnitInfo Ro Values. ex: "") roid = FormatRoidKey(roid); // Check if roid is for a Unit Information RO Value Tag if (!string.IsNullOrEmpty(roid) && roid.StartsWith("FFFF")) { return GetUnitInfoRoChild(roid); } // Lookup RO Value in the database based on the roid using (SqlConnection cn = Database.VEPROMS_SqlConnection) { using (SqlCommand cmd = cn.CreateCommand()) { cmd.CommandTimeout = Database.DefaultTimeout; cmd.CommandType = CommandType.StoredProcedure; cmd.CommandText = "vesp_RofstDataGetChildByRoid"; cmd.Parameters.Add(new SqlParameter("@RofstID", SqlDbType.Int)).Value = rofstID; cmd.Parameters.Add(new SqlParameter("@Roid", SqlDbType.VarChar)).Value = roid; using (SafeDataReader dr = new SafeDataReader(cmd.ExecuteReader())) { if (dr.Read()) { return ConvertToRochildObject(dr, loadChildren, loadAllChildren); } } } } return GetEmptyRoChild(); } catch (Exception ex) { throw new DbCslaException("RofstData.vesp_RofstDataGetChildByRoid", ex); } } private ROFSTLookup.rochild RofstDataGetChildByAccPageID(int rofstID, string accPageID) { try { // Check if roid is for a Unit Information RO Value Tag if (!string.IsNullOrEmpty(accPageID) && accPageID.StartsWith("")) accPageID = string.Format("{0}>", accPageID); accPageID = accPageID.Replace("", ""); accPageID = accPageID.ToCleanString(); // Removes any spaces // Clean up the AccPageID before using it to do a lookup if (accPageID.StartsWith("".ToCharArray()); // String < and > // Check the end of the AccPageID to determine if its an extension or part of the base key // If the AccPageID doesn't have an extension then set to default // B2022-121: RO values containing curly braces around values that are NOT multi return values do not resolved in Word Sections. if (!Regex.IsMatch(accPageID.Substring(accPageID.Length - 2, 2), @".*\.[A-Z]") || BaseAccPageKeys.Contains(accPageID)) { // No Extension, set to default accPageID = string.Format("{0}.A", accPageID); } // Set AccPage Base and Extension return values accPageBase = accPageID.Substring(0, (accPageID.Length - 2)); accPageExt = Convert.ToString(accPageID.ToCharArray().LastOrDefault()); } } return (!string.IsNullOrEmpty(accPageID)) ? accPageID.ToUpper() : accPageID; } #endregion #region (Parse/Load) private ROFSTLookup.roHdr ConvertFst2Objects(byte[] ab) { ROFSTLookup.roHdr roh = new ROFSTLookup.roHdr(); roh.hSize = BitConverter.ToInt32(ab, 0); roh.hYear = BitConverter.ToInt16(ab, 4); roh.hMonth = ab[6]; roh.hDay = ab[7]; roh.hcYear = BitConverter.ToInt16(ab, 8); roh.hcMonth = ab[10]; roh.hcDay = ab[11]; roh.hcHour = ab[12]; roh.hcMin = ab[13]; roh.hcSec = ab[14]; roh.hcHund = ab[15]; int hdrOffset = BitConverter.ToInt32(ab, 16); int dbs = BitConverter.ToInt16(ab, hdrOffset + 4); roh.myDbs = new ROFSTLookup.rodbi[dbs]; for (int i = 0; i < dbs; i++) { _dbRoCnt = 0; int offset = hdrOffset + 6 + (i * 30); roh.myDbs[i].dbiID = BitConverter.ToInt16(ab, offset + 0); int tableID = roh.myDbs[i].dbiID; roh.myDbs[i].dbiType = BitConverter.ToInt16(ab, offset + 2); roh.myDbs[i].dbiAW = BitConverter.ToInt16(ab, offset + 4); int iPtr = BitConverter.ToInt32(ab, offset + 22) + hdrOffset + 6; roh.myDbs[i].dbiTitle = Encoding.Default.GetString(ab, iPtr, StringLength(ab, iPtr)); iPtr = BitConverter.ToInt32(ab, offset + 26) + hdrOffset + 6; roh.myDbs[i].dbiAP = Encoding.Default.GetString(ab, iPtr, StringLength(ab, iPtr)); ROFSTLookup.rogrp tmp = LoadGroup(ab, BitConverter.ToInt32(ab, offset + 6), tableID); roh.myDbs[i].ID = tmp.ID; roh.myDbs[i].children = tmp.children; _dicRoCounts.Add(tableID, _dbRoCnt); } return roh; } private ROFSTLookup.rogrp LoadGroup(byte[] ab, int offset, int tableID) { ROFSTLookup.rogrp myGrp = new ROFSTLookup.rogrp(); myGrp.ID = BitConverter.ToInt32(ab, offset); myGrp.ParentID = BitConverter.ToInt32(ab, offset + 4); int numChildren = BitConverter.ToInt16(ab, offset + 8); if (numChildren > 0) { myGrp.children = new ROFSTLookup.rochild[numChildren]; int myOffset = offset + 10; for (int i = 0; i < myGrp.children.Length; i++) { ROFSTLookup.rochild tmp = new ROFSTLookup.rochild(); int childOffset = 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); ROFSTLookup.rogrp tmpg = LoadGroup(ab, childOffset, tableID); tmp.ID = tmpg.ID; tmp.ParentID = tmpg.ParentID; tmp.value = tmpg.value; tmp.appid = tmpg.appid; tmp.roid = tableID.ToString("X4") + tmp.ID.ToString("X8"); tmp.children = tmpg.children; 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); int slen2 = StringLength(ab, offset + 13 + slen); myGrp.appid = Encoding.Default.GetString(ab, offset + 13 + slen, slen2); _dbRoCnt++; } return myGrp; } // B2024-001: Loading of Ros was getting called over and over when ROs are in tables. Added // a flag to only process once until completed, 'currentlyLoading'. static bool currentlyLoading = false; private void Load(int rofstID) { if (currentlyLoading) return; // B2024-001: don't load if in process of loading currentlyLoading = true; _dicRoCounts = new Dictionary(); DateTime dtStart = DateTime.Now; string title = string.Empty; string displayText = string.Empty; try { if (ShowLoadingStatus) { _frmRofstLoadStatus = new frmRofstLoadStatus(); _frmRofstLoadStatus.Show(); _frmRofstLoadStatus.Focus(); } //Get Original ROLookup Bytes OnProgressChanged("Importing ROFST File...", null, 1, 100); byte[] bytes = RofstDataGetRofstLookupBytes(rofstID); //Convert Bytes to Objects OnProgressChanged("Converting RO Values to Objects...", null, 5, 100); ROFSTLookup.roHdr roh = ConvertFst2Objects(bytes); //Save FstObjects to Database string userID = "System"; //Insert Rofst Header OnProgressChanged("Creating Rofst Header...", null, 10, 100); RofstHeaderInsert(rofstID, roh.hSize, roh.hMonth, roh.hDay, roh.hcYear, roh.hcMonth, roh.hcDay, roh.hcHour, roh.hcMin, roh.hcSec, roh.hcHund, userID); _pctComplete = 10.0; _totalRoCnt = Convert.ToInt32(_dicRoCounts.Sum(x => x.Value)); for (int i = 0; i < roh.myDbs.Length; i++) { ROFSTLookup.rodbi rodbi = roh.myDbs[i]; _dbRoCnt = (_dicRoCounts.Where(x => x.Key == rodbi.dbiID).Any()) ? Convert.ToInt32(_dicRoCounts.Where(x => x.Key == rodbi.dbiID).FirstOrDefault().Value) : 0; _curRoCnt = 0; title = string.Format("Loading '{0}' Database... ({1} of {2})", rodbi.dbiTitle, i + 1, roh.myDbs.Length); displayText = string.Format("Processing RO Value... ({0} of {1})", 1, _dbRoCnt.ToString("n0")); //Insert Rofst Database OnProgressChanged(title, displayText, Convert.ToInt32(_pctComplete), 100); RofstDatabaseInsert(rofstID, rodbi.dbiID, rodbi.dbiType, rodbi.dbiAW, rodbi.dbiTitle, rodbi.dbiAP, rodbi.ID, rodbi.ParentID); if (rodbi.children != null && rodbi.children.Length > 0) { for (int j = 0; j < rodbi.children.Length; j++) { //Insert Rofst Child LoadChild(rofstID, rodbi.dbiID, rodbi.children[j]); displayText = string.Format("Processing RO Values... ({0} of {1})", _curRoCnt.ToString("n0"), _dbRoCnt.ToString("n0")); OnProgressChanged(displayText, Convert.ToInt32(_pctComplete), 100); } } // Update Progress Bar Accordingly if (_totalRoCnt > 0) _pctComplete = _pctComplete + ((Convert.ToDouble(_dbRoCnt) / Convert.ToDouble(_totalRoCnt)) * 80.0); OnProgressChanged(displayText, Convert.ToInt32(_pctComplete), 100); } //Finalized Load for Rofst Header / Rebuild Indexes OnProgressChanged("Finalizing Rofst Header and Rebuilding Indexes...", null, 90, 100); RofstHeaderFinalizeLoad(rofstID); title = string.Format("Successfully Loaded ({0}) RO Values... Total Duration {1}", _totalRoCnt.ToString("n0"), CalculateDuration(dtStart)); OnProgressChanged(title, null, 100, 100); } catch (Exception ex) { OnProgressChanged("Error Imported RO Values...", ex.Message, 100, 100); } finally { try { if (_frmRofstLoadStatus != null) { _frmRofstLoadStatus.Close(); _frmRofstLoadStatus.Dispose(); _frmRofstLoadStatus = null; } if (_dicRoCounts != null || _dicRoCounts.Count > 0) { _dicRoCounts = null; } } catch { } } currentlyLoading = false; // B2024-001: done loading } private void LoadChild(int rofstID, int dbiID, ROFSTLookup.rochild child) { //Insert Rofst Child RofstChildInsert(rofstID, child.ID, child.ParentID, dbiID, child.type, child.title, child.roid, child.appid, child.value); //Increment RO Count if RoChild has a return value if (!string.IsNullOrEmpty(child.value)) _curRoCnt++; if (child.children != null && child.children.Length > 0) { for (int i = 0; i < child.children.Length; i++) { //Insert Rofst Child LoadChild(rofstID, dbiID, child.children[i]); } } } #region (Parse/Load - Events/Handlers) protected virtual void OnProgressChanged(string title, string displayText, int curVal = 0, int maxVal = 100) { // If frmRofstLoadStatus is not null then call Update Progress Method if (_frmRofstLoadStatus != null) _frmRofstLoadStatus.UpdateProgress(title, displayText, curVal, maxVal); } protected virtual void OnProgressChanged(string displayText, int curVal = 0, int maxVal = 100) { // If frmRofstLoadStatus is not null then call Update Progress Method if (_frmRofstLoadStatus != null) _frmRofstLoadStatus.UpdateProgress(_frmRofstLoadStatus.Title, displayText, curVal, maxVal); } #endregion #endregion #region (Convert To Objects) private ROFSTLookup.roHdr ConvertToRoHdrObject(SafeDataReader dr, bool loadChildren) { ROFSTLookup.roHdr rh = new ROFSTLookup.roHdr(); rh.hSize = (int)dr.GetValue("hSize"); rh.hYear = (int)dr.GetValue("hYear"); rh.hMonth = (byte)dr.GetValue("hMonth"); rh.hDay = (byte)dr.GetValue("hDay"); rh.hcYear = (int)dr.GetValue("hcYear"); rh.hcMonth = (byte)dr.GetValue("hcMonth"); rh.hcDay = (byte)dr.GetValue("hcDay"); rh.hcHour = (byte)dr.GetValue("hcHour"); rh.hcMin = (byte)dr.GetValue("hcMin"); rh.hcSec = (byte)dr.GetValue("hcSec"); rh.hcHund = (byte)dr.GetValue("hcHund"); if (loadChildren) { rh.myDbs = RofstDataGetDatabases(_rofstID); } return rh; } private ROFSTLookup.rodbi ConvertToRodbiObject(SafeDataReader dr, bool loadChildren, bool loadAllChildren) { ROFSTLookup.rodbi rd = new ROFSTLookup.rodbi(); rd.dbiID = (int)dr.GetValue("dbiID"); rd.dbiType = (int)dr.GetValue("dbiType"); rd.dbiAW = (int)dr.GetValue("dbiAW"); rd.dbiAP = (string)dr.GetValue("dbiAP"); rd.dbiTitle = (string)dr.GetValue("dbiTitle"); rd.ID = (int)dr.GetValue("ID"); rd.ParentID = (int)dr.GetValue("ParentID"); if (loadChildren || loadAllChildren) { rd.children = RofstDataGetChildrenByID(_rofstID, rd.dbiID, rd.ID, false, loadAllChildren); } return rd; } private ROFSTLookup.rochild ConvertToRochildObject(SafeDataReader dr, bool loadChildren, bool loadAllChildren) { ROFSTLookup.rochild rc = new ROFSTLookup.rochild(); rc.ID = (int)dr.GetValue("ID"); rc.ParentID = (int)dr.GetValue("ParentID"); rc.type = (int)dr.GetValue("type"); rc.title = (string)dr.GetValue("title"); rc.roid = (string)dr.GetValue("roid"); if (!string.IsNullOrEmpty((string)dr.GetValue("appid"))) { rc.appid = (string)dr.GetValue("AccPageID"); if (!string.IsNullOrEmpty((string)dr.GetValue("value"))) { rc.value = (string)dr.GetValue("value"); ProcessROReturnValue(ref rc, rc.value, GetRODatabaseTitleIndex(rc.roid)); } } else if (loadChildren || loadAllChildren) { rc.children = RofstDataGetChildrenByRoid(_rofstID, rc.roid, false, loadAllChildren); } return rc; } private ROFSTLookup.RoExtension ConvertToRoExtensionObject(SafeDataReader dr) { ROFSTLookup.RoExtension re = new ROFSTLookup.RoExtension(); re.Offset = (int)dr.GetValue("Offset"); re.RoidExt = (string)dr.GetValue("RoidExt"); re.AccPageExt = (string)dr.GetValue("AccPageExt"); return re; } #endregion #region (RO Values) private ROFSTLookup.rochild GetRoChild12(string roid, bool loadChildren = false, bool loadAllChildren = false) { ROFSTLookup.rochild rc = RofstDataGetChildByRoid(_rofstID, roid, loadChildren, loadAllChildren); if (rc.ID <= 0 && roid.Length == 4) { rc.title = GetRODatabaseTitle(GetRODatabaseTitleIndex(roid)); } // B2023-038: return a "?" if none found - this is used by calling methods to flag none found. if (rc.ID < 0 && rc.value == null) rc.value = "?"; return rc; } private void ProcessROReturnValue(ref ROFSTLookup.rochild child, string rawvalue, int tableID) { // This function will take the raw RO return value and resolve any macros, conditionals, // and generate the return value or a list of multiple return values. List lstValues = GetROReturnValue(rawvalue); if (lstValues.Count > 0) // Single or Multiple Return Values { child.children = new ROFSTLookup.rochild[lstValues.Count]; // Load all extension specific return values (1 to many) for (int i = 0; i < lstValues.Count; i++) { // B2022-110: PC/PC Multi return values are correct in editor but not correct in Step Properties/ROs when selected, or when printed // B2022-110 continued (9/12/22): for lstValues.Count of 1, needed to use code that was there so that value can be used later for // setting appid and roid var roExt = lstValues.Count==1? Extensions.Where(x => x.Offset.Equals(i + 1)).SingleOrDefault() : Extensions.Where(x => x.AccPageExt.Equals(_multiRoValues[i])).SingleOrDefault(); // B2022-124: [JPR] Blank RO Values (All Spaces) printing as "?" string roValue = GetParentChildROValue(lstValues[i], this.SelectedSlave, this.RoMissingDefaultValue); child.children[i].ParentID = child.ID; child.children[i].type = child.type; // Multiple return value inherit type from parent child.children[i].title = roValue; child.children[i].value = roValue; child.children[i].appid = (roExt != null) ? string.Format("{0}.{1}", child.appid, roExt.AccPageExt) : child.appid; child.children[i].roid = string.Format("{0}{1}{2}", tableID.ToString("X4"), child.ID.ToString("X8"), (roExt != null && roExt.RoidExt != null) ? roExt.RoidExt : string.Empty).ToUpper(); child.children[i].children = new List().ToArray(); } if (AutoCombineSingleRetValues && lstValues.Count == 1) { // When the RO object only has only return value and the "AutoCombineSingleRetValues" is set to True. // Instead of returning the RoChildBase object with a single RoReturnVal object attached, just return the single Ro ReturnValue object. var roRetVal = child.children.First(); //child.title = roRetVal.title; child.appid = roRetVal.appid; child.roid = roRetVal.roid; child.value = roRetVal.value; child.children = new List().ToArray(); } else { child.value = null; } } _lstRoValues.Clear(); _multiRoValues.Clear(); return; } private static string GetParentChildROValue(string roval, int selChldIdx, string roMissingDefaultValue) { // C2021-026 Get the child RO value if it exists, otherwise to the default (parent) RO value // C2022-001 new logic to handle new format of Parent/Child RO.FST // The RO.FST will not have a specific child value if that child value is the same as the default value // B2021-093 Don't look for child RO values if "roval" is null // B2022-124: [JPR] Blank RO Values (All Spaces) printing as "?", Added roMissingDefaultValue parameter if (string.IsNullOrEmpty(roval)) return null; // Clean Up RoValue roval = roval.Replace("\xFF", "\xa0"); roval = roval.Replace(@"\u160?", " "); // B2022-020 remove a un-needed question mark that was in the search criteria "(" // B2022-050 change the search string from "(" to "" to handle when RO values have less then sign // B2022-077 Need to use the RegexOption of Single Line to handle cases of an RO Return value having ascii newline characters (\r\n) MatchCollection mm = Regex.Matches(roval, "", RegexOptions.Singleline); // C2022-014 commented write to error log. Keep for debugging purposes. //if (mm.Count == 0) // B2022-020 will now write in error log if there is a problem // _MyLog.WarnFormat("Parent/Child Values not parsable for \r\nItemId={0}\r\nROValue={1} ",MyDocVersionInfo.ItemID,roval); StringBuilder sb = new StringBuilder(); int lastIndex = 0; // Get Selected Child Value foreach (Match m in mm) { sb.Append(roval.Substring(lastIndex, m.Index - lastIndex)); string aplString = m.Value; string chldValStr = string.Format("UnitIdx={0} Value=", selChldIdx); int offsetIdx = aplString.IndexOf(chldValStr); int nextIDX = -1; if (offsetIdx == -1) { offsetIdx = aplString.IndexOf("DefaultVal=") + 11; } else { offsetIdx += chldValStr.Length; } nextIDX = aplString.IndexOf(",UnitIdx", offsetIdx); if (nextIDX == -1) nextIDX = aplString.IndexOf(" /APL>"); sb.Append(aplString.Substring(offsetIdx, nextIDX - offsetIdx)); lastIndex = m.Index + m.Length; } // B2022-018 append any remaining text if (lastIndex < roval.Length) { sb.Append(roval.Substring(lastIndex)); } // If Default Value is selected (selChldIdx = 0), and return value is empty then replace with Standard Missing Default Value // TODO: [JAKE] return (selChldIdx == 0 && sb.ToString().Length <= 0) ? roMissingDefaultValue : sb.ToString(); } private List GetROReturnValue(string roval) { _lstRoValues = new List(); _multiRoValues = new List(); _dicRoVars = new Dictionary(); string tmp = ProcessRO(_myDocVersionInfo == null ? roval : _myDocVersionInfo.ProcessDocVersionSpecificInfo(roval), false); if (!string.IsNullOrEmpty(tmp) && _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 len = roval.Length; while (len > 0) { int ptr = NextDelimiter("{", str); if (ptr == -1) { rtnstr += str; // add remaining text len = 0; // break out of while loop } else { int cnt = ptr; if (cnt > 0) { // add text rtnstr += str.Substring(0, cnt); len -= cnt; str = str.Substring(ptr); } ptr = MatchingBrace(str) + 1; cnt = ptr; bool nfnd = false; string pbstr = ProcessBrace(str.Substring(1, cnt - 2), cnt - 2, ref nfnd, multiRtnVal); if (pbstr == null) return null; if (nfnd) rtnstr += str.Substring(0, cnt); else rtnstr += pbstr; len -= cnt; str = str.Substring(ptr); } } return ProcessMacros(rtnstr); } private string ProcessBrace(string str, int l, ref bool nfnd, bool multiRtnVal) { string rtnstr = ""; int nxt = NextDelimiter("{=", str); if (nxt == -1) // no delimiter found { if (_dicRoVars.ContainsKey(str)) rtnstr = _dicRoVars[str]; else nfnd = true; } else { if (str[nxt] == '{') { if (nxt == 0) // Multiple Return Values { ProcessMultiReturnValues(str, l); } else // Conditional { rtnstr = ProcessConditional(str, str.Substring(nxt), nxt, str.Length - nxt - 1, multiRtnVal); } } else // must be variable definition { // 'l' is the length up to the matching brace of the variable definition string tmpval = ProcessRO(str.Substring(nxt + 1, l - nxt - 1), multiRtnVal); if (string.IsNullOrEmpty(tmpval)) tmpval = " "; // nothing assigned to variable if (!_dicRoVars.ContainsKey(str.Substring(0, nxt))) { _dicRoVars.Add(str.Substring(0, nxt), tmpval); if (nxt == 1) _multiRoValues.Add(str.Substring(0, nxt)); } else { return null; } if (multiRtnVal) rtnstr = tmpval; } } return rtnstr; } private void ProcessMultiReturnValues(string str, int len) { string tstr = (!string.IsNullOrEmpty(str)) ? str.Substring(0, len) : string.Empty; while (tstr.Length > 0) { int idx = MatchingBrace(tstr); string tmpVal = ProcessRO(tstr.Substring(0, idx + 1), true); if (tmpVal != null) _lstRoValues.Add(tmpVal); // duplicates get returned as null tstr = tstr.Substring(idx + 1); } } private string ProcessConditional(string cnd, string opt, int lencnd, int lenopt, bool multiRtnVal) { // Evaluate Condition string stat = (_myDocVersionInfo != null) ? _myDocVersionInfo.Evaluate(cnd, lencnd) : string.Empty; // if evaluation not defined then return an empty string - no matches can be made, look for match - remember default if (stat.Length == 0) return string.Empty; int ls = stat.Length; string match = null; string def = null; int deflen = 0; while (lenopt > 0 && match == null) { int end = MatchingBrace(opt); int eq = opt.IndexOf('='); int len = end + 1; int li = eq - 1; int ld = len - li - 3; if (def == null || eq == 1) { def = opt.Substring(eq + 1); deflen = ld; } if (ls == li && opt.Substring(1).StartsWith(stat + "=")) { match = opt.Substring(eq + 1, ld); } opt = opt.Substring(len); // point to the next piece lenopt -= len; } // if match process option - or process default if (match == null) //(!match) { match = def.Substring(0, deflen); } return ProcessRO(match, multiRtnVal); } private string ProcessMacros(string str) { // Takes the RO text value and sees if a macro has been used. // If so it will perform the macro operation on the substring in the text value // Note** Right now the only macro is @HSP(), where every space between the "(" and ")" will be replaced with a hard space if (string.IsNullOrEmpty(str)) return str; string rtnstr = str; int indx; while ((indx = rtnstr.ToUpper().IndexOf("@HSP(")) > -1) { string resstr = rtnstr.Substring(0, indx); int endHsp = rtnstr.IndexOf(")", indx); string tmpstr = rtnstr.Substring(indx + 5, endHsp - indx - 5); // B2017-012 Don't convert space to hard spaces for XY Plots. if (!tmpstr.Contains("< 0 && idx++ < str.Length) { switch (str[idx]) { case '{': level++; break; case '}': level--; break; } } } return (level != 0) ? -1 : idx; //return -1 if didn't find matching brace otherwise length including end brace } private string ReplaceUnicode(string s2, bool DoCaret) { if (string.IsNullOrEmpty(s2)) return s2; s2 = s2.Replace(@"\u160?", ""); // convert hard spaces bug fix: B2016-206 s2 = s2.Replace(@"\", @"\u9586?"); // convert backslashes to a backslash symbol s2 = s2.Replace("", @"\u160?"); // convert hard spaces bug fix: B2016-206 s2 = s2.Replace("`", @"\'b0"); // convert backquote to degree - left over from DOS days. s2 = s2.Replace("\xf8", @"\'b0"); // convert \xf8 to degree. s2 = s2.Replace("\xa0", @"\u160?"); // hardspace s2 = s2.Replace("\xb0", @"\'b0"); // degree s2 = s2.Replace("\x7f", @"\u916?"); // delta s2 = s2.Replace("\x2265", @"\u8805?"); // greater than or equal s2 = s2.Replace("\x2264", @"\u8804?"); // less than or equal s2 = s2.Replace("\xB1", @"\'b1"); // plus minus s2 = s2.Replace("\x3A3", @"\u931?"); // sigma s2 = s2.Replace("\x3C4", @"\u947?"); // gamma s2 = s2.Replace("\xBD", @"\'bd"); // half s2 = s2.Replace("\x25A0", @"\u9604?"); // accum 2584 s2 = s2.Replace("\x7", @"\u9679?"); // bullet 25CF s2 = s2.Replace("\x2248", @"\u8776?"); // approx eq s2 = s2.Replace("\x2261", @"\u8773?"); // similar eq 2245 s2 = s2.Replace("\xF7", @"\'f7"); // division s2 = s2.Replace("\x221A", @"\u8730?"); // square root s2 = s2.Replace("\x393", @"\u961?"); // rho 3C1 s2 = s2.Replace("\x3C0", @"\u960?"); // pi s2 = s2.Replace("\xb5", @"\u956?"); // micro 3BC (try e6, if not work try 109) s2 = s2.Replace("\x3B4", @"\u948?"); // lower case delta s2 = s2.Replace("\x3C3", @"\u963?"); // lower case sigma s2 = s2.Replace("\xBC", @"\'bc"); // quarter s2 = s2.Replace("\x3C6", @"\'d8"); // dist zero, D8 s2 = s2.Replace("\xC9", @"\u274?"); // energy, 112 s2 = s2.Replace("\xEC", @"\'ec"); // grave s2 = s2.Replace("\x2502", @"\u9474?"); // bar s2 = s2.Replace("\x3B5", @"\u949?"); // epsilon s2 = s2.Replace("\x398", @"\u952?"); // theta, 3B8 s2 = s2.Replace("\x221E", @"\u8857?"); // dot in oval, 2299 s2 = s2.Replace("\xBF", @"\u964?"); // tau, 3C4 s2 = s2.Replace("\x2310", @"\u9830?"); // diamond, 2666 s2 = s2.Replace("\x2192", @"\u8594?"); // Rightwards Arrow s2 = s2.Replace("\x2190", @"\u8592?"); // Leftwards Arrow s2 = s2.Replace("\x2191", @"\u8593?"); // Upwards Arrow s2 = s2.Replace("\x2193", @"\u8595?"); // Downwards Arrow s2 = s2.Replace("\x2207", @"\u8711?"); // Nabla s2 = s2.Replace("\x2591", @"\'b0"); // Degree Symbol s2 = s2.Replace("\xFF", @"\u8593?"); // Up Arrow s2 = s2.Replace("\xD6", @"\u8595?"); // Down Arrow if (DoCaret) s2 = s2.Replace("^", @"\u916?"); // Convert dash to a non-breaking dash. This is a Unicode character. // This character will be used in PROMS rather than a dash. // if the dash is proceeded byte a token remove the space following the token s2 = Regex.Replace(s2, @"(\\[^ \\?]*) \-", @"$1\u8209?"); s2 = s2.Replace("-", @"\u8209?"); return s2; } #endregion #region (Unit Info - RO Values) private ROFSTLookup.rochild GetUnitInfoRoChild(string roid) { ROFSTLookup.rochild rc = GetEmptyRoChild(); if (!string.IsNullOrEmpty(roid)) { rc.roid = FormatRoidKey(roid).Substring(0, 12); DocVersionConfig dvc = (_myDocVersionInfo != null) ? _myDocVersionInfo.DocVersionConfig : null; if (dvc != null) dvc.SelectedSlave = this.SelectedSlave; switch (rc.roid) { case "FFFF00000001": rc.title = "Number"; rc.appid = "U-NUMBER"; rc.value = (dvc != null) ? dvc.Unit_Number : null; break; case "FFFF00000002": rc.title = "Other Number"; rc.appid = "U-OTHERNUMBER"; rc.value = (dvc != null) ? dvc.Other_Unit_Number : null; break; case "FFFF00000003": rc.title = "Text"; rc.appid = "U-TEXT"; rc.value = (dvc != null) ? dvc.Unit_Text : null; break; case "FFFF00000004": rc.title = "Other Text"; rc.appid = "U-OTHERTEXT"; rc.value = (dvc != null) ? dvc.Other_Unit_Text : null; break; case "FFFF00000005": rc.title = "ID"; rc.appid = "U-ID"; rc.value = (dvc != null) ? dvc.Unit_ID : null; break; case "FFFF00000006": rc.title = "Other ID"; rc.appid = "U-OTHERID"; rc.value = (dvc != null) ? dvc.Other_Unit_ID : null; break; case "FFFF00000007": rc.title = "Name"; rc.appid = "U-NAME"; rc.value = (dvc != null) ? dvc.Unit_Name : null; break; case "FFFF00000008": rc.title = "Other Name"; rc.appid = "U-OTHERNAME"; rc.value = (dvc != null) ? dvc.Other_Unit_Name : null; break; } if (!string.IsNullOrEmpty(rc.appid)) { rc.ID = 0; rc.ParentID = 0; rc.type = 1; // Single Text rc.roid = string.Format("{0}0041", rc.roid); rc.children = new List().ToArray(); } } return rc; } private string GetUnitInfoRoidByAccPageID(string accPageID) { string roid = string.Empty; if (!string.IsNullOrEmpty(accPageID)) { string accPageKey = accPageID; // Try to cleanup / standardize the Unit Info Tag before attempting to lookup the associated value if (!accPageKey.StartsWith("<")) accPageKey = string.Format("<{0}", accPageKey); if (!accPageKey.EndsWith(">")) accPageKey = string.Format("{0}>", accPageKey); accPageKey = FormatAccPageKey(accPageKey, null, null); if (accPageKey == "") roid = "FFFF00000001"; if (accPageKey == "") roid = "FFFF00000002"; if (accPageKey == "") roid = "FFFF00000003"; if (accPageKey == "") roid = "FFFF00000004"; if (accPageKey == "") roid = "FFFF00000005"; if (accPageKey == "") roid = "FFFF00000006"; if (accPageKey == "") roid = "FFFF00000007"; if (accPageKey == "") roid = "FFFF00000008"; } return roid; } #endregion #endregion #region Public Static Methods #region (FortranFormat) public static string ConvertFortranFormatToScienctificNotation(string str) { // ([+-]?|\\u8209\?) either an optional single character Plus (+) or Minus (-) or non-breaking dash (\u8209?) // ([0-9]+) a group of at least one digits // [.] a decimal point // ([0-9]*?) a group of zero or more digits // 0*E optional zeros (spare zeros) followed // ([+-]?|\\u8209\?) either an optional single character Plus (+) or Minus (-) or non-breaking dash (\u8209?) // ([0-9]+) a group of at least one digits return Regex.Replace(str, @"([+-]?|\\u8209\?)([0-9]+)[.]([0-9]*?)0*E([+-]?|\\u8209\?)([0-9]+)", new MatchEvaluator(FixFortranNumber)); } public static string FixFortranNumber(Match match) { StringBuilder sb = new StringBuilder(match.Groups[1].Value.Replace("-", @"\u8209?")); if (match.Groups[3].Length == 0) // Nothing to the right of the decimal { if (match.Groups[2].Value != "1") // Other than "1", multiply it times 10 raised to a power { sb.Append(match.Groups[2].Value + "x10"); } else // The number is simply 1 so it can be ignored and 10 can be raised to a power { sb.Append("10"); } } else // A number with a decimal point { sb.Append(match.Groups[2].Value + "." + match.Groups[3].Value + "x10"); } // Add the exponent as superscript return sb.ToString() + "\\up2 " + match.Groups[4].Value.Replace("-", @"\u8209?") + match.Groups[5].Value + "\\up0 "; } #endregion #endregion } }