mschill 378653c536 C2025-011 PROMS – RO Update Admin Tool Memory Enhancements
The purpose of this upgrade is to improve the user experience when using the Admin tool to Update ROs. Currently for larger RO dbs (like Barakah) we can run up against memory constraints that do not allow all the ROs to be updated at one time. This is based upon some initial resource where some places were identified where we could improve memory usage.  Some of these should benefit PROMS as a whole while others will be specific to the RO Update option in Admin Tools.
2025-02-04 13:23:21 -05:00

1162 lines
37 KiB
C#
Raw Blame History

// ========================================================================
// Copyright 2006 - Volian Enterprises, Inc. All rights reserved.
// Volian Enterprises - Proprietary Information - DO NOT COPY OR DISTRIBUTE
// ------------------------------------------------------------------------
// $Workfile: $ $Revision: $
// $Author: $ $Date: $
//
// $History: $
// ========================================================================
using System;
using System.Data;
using System.Data.SqlClient;
using Csla;
using Csla.Data;
using System.Collections.Generic;
using System.IO;
using System.Threading;
using System.Xml;
using System.Text.RegularExpressions;
//using VEPROMS.Properties;
namespace VEPROMS.CSLA.Library
{
public partial class DocVersion : IVEDrillDown
{
public static DocVersion GetFromDB(int versionID) // get data from database (don't look in cache first)
{
if (!CanGetObject())
throw new System.Security.SecurityException("User not authorized to view a DocVersion");
try
{
DocVersion tmp = DataPortal.Fetch<DocVersion>(new PKCriteria(versionID));
if (tmp.ErrorMessage == "No Record Found")
{
tmp.Dispose(); // Clean-up DocVersion
tmp = null;
}
return tmp;
}
catch (Exception ex)
{
throw new DbCslaException("Error on DocVersion.Get", ex);
}
}
public bool NewerRoFst
{
get
{
if (DocVersionAssociations == null || DocVersionAssociations.Count == 0) return false;
using (ROFstInfo roFstInfo = ROFstInfo.GetJustROFst(DocVersionAssociations[0].ROFstID))
{
using (RODbInfo rdi = RODbInfo.GetJustRODB(roFstInfo.RODbID))
{
string rofstPath = rdi.FolderPath + @"\ro.fst";
if (!File.Exists(rofstPath)) return false;
FileInfo fiRofst = new FileInfo(rofstPath);
// if the database Ro.Fst is newer or if the files have identical DTS,
// assume that they are the same file.
if (roFstInfo.DTS >= fiRofst.LastWriteTimeUtc) return false;
// next see if the data is the same size, i.e. byte count of record and byte count
// of file. If different sizes, the date/time stamp check will hold.
// B2022-026 RO Memory reduction - new logic
var bytes = ROFSTLookup.GetRofstLookupBytes(roFstInfo.ROFstID);
if (bytes != null && fiRofst.Length != bytes.Length)
return fiRofst.LastWriteTimeUtc > roFstInfo.DTS;
// if we can't tell by the DTS or size, compare the contents. Get all of the rodb's
// rofsts of the size of the file & compare bytes.
return ROFstInfoList.ROFstDiffBySize(rofstPath, rdi.RODbID, (int)fiRofst.Length);
}
}
}
}
public bool ROfstLastCompleted
{
get
{
if (DocVersionAssociations == null || DocVersionAssociationCount == 0) return true; // no ROs associated this will turn off the update ROs button
if (LastCompleted(DocVersionAssociations[0]) == string.Empty) return false;
return true;
}
}
// return the date/time of the last time the RO Update was done and ran all the way through completion
private string LastCompleted(DocVersionAssociation dva)
{
XmlDocument xd = new XmlDocument();
if (dva.Config == null || dva.Config.Length == 0) return string.Empty;
xd.LoadXml(dva.Config);
XmlNode xn = xd.DocumentElement.SelectSingleNode("//ROUpdate");
if (xn == null) return string.Empty;
XmlAttribute att = xn.Attributes["LastCompleted"];
if (att == null) return string.Empty;
return att.InnerText;
}
// B2017-125 put info in the config as to the status of loading RO Figures during the Update RO Values
// This will help us determine if the Update RO Values was terminated during the loading of the RO Figures
public bool ROfstLoadingFigures
{
get
{
if (DocVersionAssociations == null || DocVersionAssociationCount == 0) return true; // no ROs associated this will turn off the update ROs button
if (ROLoadingFigures(DocVersionAssociations[0]) == string.Empty) return false;
return true;
}
}
// B2017-125 return the loading figures status
private string ROLoadingFigures(DocVersionAssociation dva)
{
XmlDocument xd = new XmlDocument();
if (dva.Config == null || dva.Config.Length == 0) return string.Empty;
xd.LoadXml(dva.Config);
XmlNode xn = xd.DocumentElement.SelectSingleNode("//ROUpdate");
if (xn == null) return string.Empty;
XmlAttribute att = xn.Attributes["LoadingFigures"];
if (att == null) return string.Empty;
return att.InnerText;
}
#region VersionType
public VersionTypeEnum eVersionType
{
get { return (VersionTypeEnum)_VersionType; }
set { _VersionType = (int)value; }
}
#endregion
#region DocVersion Config
[NonSerialized]
private DocVersionConfig _DocVersionConfig;
public DocVersionConfig DocVersionConfig
{
get
{
if (_DocVersionConfig == null)
{
_DocVersionConfig = new DocVersionConfig(this);
_DocVersionConfig.PropertyChanged += new System.ComponentModel.PropertyChangedEventHandler(_DocVersionConfig_PropertyChanged);
}
return _DocVersionConfig;
}
}
private void _DocVersionConfig_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
Config = _DocVersionConfig.ToString();
}
#endregion
#region UserSettings
/// <summary>
/// These settings are set on the user interface side.
/// This is used to control whether the Name and/or Title is displayed
/// next to the tree nodes in the user interface
/// </summary>
private bool _DisplayTreeNodeNames = true;
public bool DisplayTreeNodeNames
{
get { return _DisplayTreeNodeNames; }
set { _DisplayTreeNodeNames = value; }
}
private bool _DisplayTreeNodeTitles = false;
public bool DisplayTreeNodeTitles
{
get { return _DisplayTreeNodeTitles; }
set { _DisplayTreeNodeTitles = value; }
}
#endregion
public override string ToString()
{
// assume that at least one of the two options was selected
string rtnstr = "";
if (_DisplayTreeNodeNames) rtnstr = Name;
if (_DisplayTreeNodeTitles)
{
if (rtnstr.Length > 0) rtnstr += " - ";
rtnstr += Title;
}
return rtnstr;
//return string.Format("{0} - {1}", Name, Title);
}
#region IVEDrillDown
//public System.Collections.IList GetChildren()
//{
// return null;
//}
//public bool HasChildren
//{
// get { return _ItemID > 0; }
//}
//public IVEDrillDown ActiveParent
//{
// get
// {
// return MyFolder;
// }
//}
//private Format _ActiveFormat = null;
//public Format ActiveFormat
//{
// get
// {
// if (_ActiveFormat == null)
// _ActiveFormat = LocalFormat != null ? LocalFormat : ActiveParent.ActiveFormat;
// return _ActiveFormat;
// }
// set
// {
// _ActiveFormat = null;
// }
//}
//public Format LocalFormat
//{
// get { return MyFormat; }
//}
public ConfigDynamicTypeDescriptor MyConfig
{
get { return DocVersionConfig; }
}
#endregion
public DocVersionInfo MyDocVersionInfo
{ get { return DocVersionInfo.Get(VersionID); } }
}
public partial class DocVersionInfo : IVEDrillDownReadOnly
{
public TimeSpan tsTimeOut = TimeSpan.FromSeconds(6);
public bool pathExists(string path)
{
bool exists = true;
Thread t = new Thread(
new ThreadStart(delegate()
{
exists = System.IO.File.Exists(path);
})
);
t.Start();
bool completed = t.Join(tsTimeOut); //wait 6 seconds then 3 then 1.5 then .75 seconds
if (!completed)
{
exists = false;
t.Abort();
if (tsTimeOut > TimeSpan.FromSeconds(1))
tsTimeOut = TimeSpan.FromTicks(tsTimeOut.Ticks / 2);
}
return exists;
}
// The following dictionary is used to store the state of the ro.fst check so that it is
// not made repeatedly in NewerRoFst. (B2017-050)
private static Dictionary<string, bool> NewerRoFstLookup = new Dictionary<string, bool>();
private static bool AddToRoFstLookup(string key, bool result)
{
if (!NewerRoFstLookup.ContainsKey(key)) NewerRoFstLookup.Add(key, result);
return result;
}
public bool NewerRoFst
{
get
{
if (DocVersionAssociations == null || DocVersionAssociationCount==0) return false;
ROFstInfo roFstInfo = ROFstInfo.GetJustROFst(DocVersionAssociations[0].ROFstID);
RODbInfo rdi = RODbInfo.GetJustRODB(roFstInfo.RODbID);
string rofstPath = rdi.FolderPath + @"\ro.fst";
//if (!File.Exists(rofstPath)) return false;
if (!pathExists(rofstPath))
{
_MyLog.WarnFormat("RO Path '{0}' could not be found", rofstPath);
return false;
}
FileInfo fiRofst = new FileInfo(rofstPath);
// if the database Ro.Fst is newer or if the files have identical DTS,
// assume that they are the same file.
// put this in a dictionary so we don't have to keep testing to see if the file version of ro.fst is newer than database version
string key = string.Format("{0}-{1}", DocVersionAssociations[0].ROFstID, fiRofst.LastWriteTimeUtc);
if (NewerRoFstLookup.ContainsKey(key)) return NewerRoFstLookup[key];
if (roFstInfo.DTS >= fiRofst.LastWriteTimeUtc) return AddToRoFstLookup(key, false);
TimeSpan ts = roFstInfo.DTS - fiRofst.LastWriteTimeUtc;
if (ts.TotalSeconds > -1F) return AddToRoFstLookup(key, false);
// next see if the data is the same size, i.e. byte count of record and byte count
// of file. If different sizes, the date/time stamp check will hold.
// B2022-026 RO Memory reduction - new logic
var bytes = ROFSTLookup.GetRofstLookupBytes(roFstInfo.ROFstID);
if (bytes != null && fiRofst.Length != bytes.Length)
return AddToRoFstLookup(key, fiRofst.LastWriteTimeUtc > roFstInfo.DTS);
// if we can't tell by the DTS or size, compare the contents. Get all of the rodb's
// rofsts of the size of the file & compare bytes.
return AddToRoFstLookup(key, ROFstInfoList.ROFstDiffBySize(rofstPath, rdi.RODbID, (int)fiRofst.Length));
}
}
public bool ROfstLastCompleted
{
get
{
if (DocVersionAssociations == null || DocVersionAssociationCount == 0) return true; // no ROs associated this will turn off the update ROs button
if (LastCompleted(DocVersionAssociations[0]) == string.Empty) return false; // the AssociatinoConfig does not have completed date for update ROs - this will turn on the update ROs button
return true;
}
}
// return the date/time of the last time the RO Update was done and ran all the way through completion
private string LastCompleted(AssociationInfo associationInfo)
{
AssociationConfig ac = new AssociationConfig(associationInfo);
return ac.ROUpdate_LastCompleted;
}
// B2017-125 return the loading figures status
private string ROLoadingFigures(AssociationInfo associationInfo)
{
AssociationConfig ac = new AssociationConfig(associationInfo);
return ac.ROUpdate_LoadingFigures;
}
#region Enhanced
// B2022-148: cannot insert outside transition in a background document that references a related EOP <20> transition is converted to text
// Check if the 2 doc versions are linked, i.e. one is source and the other is enhanced linked to the source
public static bool Linked(DocVersionInfo dv1, DocVersionInfo dv2)
{
DocVersionConfig dvc1 = dv1.DocVersionConfig;
DocVersionConfig dvc2 = dv2.DocVersionConfig;
bool isLinked1 = dvc1 != null && (dvc1.MyEnhancedDocuments != null && dvc1.MyEnhancedDocuments.Count > 0);
bool isLinked2 = dvc2 != null && (dvc2.MyEnhancedDocuments != null && dvc2.MyEnhancedDocuments.Count > 0);
bool relatedEnh = false;
if (isLinked1 && isLinked2)
{
// does source point to this docversion as enhanced, and does this enhanced point to this source:
bool isSource1 = dvc1.MyEnhancedDocuments.Count == 1 && dvc1.MyEnhancedDocuments[0].Type == 0 && dvc1.MyEnhancedDocuments[0].VersionID == dv2.VersionID;
bool isSource2 = dvc2.MyEnhancedDocuments.Count == 1 && dvc2.MyEnhancedDocuments[0].Type == 0 && dvc2.MyEnhancedDocuments[0].VersionID == dv1.VersionID;
if (isSource1 || isSource2)
{
int sourceVersionID = isSource1 ? dv1.VersionID : dv2.VersionID;
DVEnhancedDocuments enhList = isSource1 ? dvc2.MyEnhancedDocuments : dvc1.MyEnhancedDocuments;
if (enhList != null)
{
foreach (DVEnhancedDocument ded in enhList)
{
if (ded.Type != 0 && ded.VersionID == sourceVersionID) // found it.
{
relatedEnh = true;
break;
}
}
}
}
}
return relatedEnh;
}
#endregion
#region SearchPaths
public string _SearchDVPath;
public string SearchDVPath
{
get
{
if (_SearchDVPath == null)
_SearchDVPath = ActiveParent.SearchDVPath + "\u0007" + Name;
return _SearchDVPath;
}
}
public string SearchPath { get { return ""; } }
// B2021-076: Proms search results are not presented in order when printed to PDF
public string SearchDefaultSort { get { return string.Empty; } }
#endregion
#region UnlinkEnhancedDocVersion
// Unlink (clear) enhanced from source for this docversion. Refresh all related cache items.
public void DoUnlinkEnhancedDocVersion()
{
try
{
// get source docversion id for refresh - used later (check for null, just in case):
int sdvid = DocVersionConfig != null && DocVersionConfig.MyEnhancedDocuments.Count > 0 ? DocVersionConfig.MyEnhancedDocuments[0].VersionID : -1;
using (ContentInfoList cil = ContentInfoList.DoEnhancedDocVersionUnlink(this.VersionID))
{
foreach (ContentInfo ci in cil)
{
using (Content c = ci.Get())
{
// first refresh configs because the ContentInfo.Refresh causes events to occur that refresh screen
// and if configs aren't done first, the screen refresh, if based on config data, will not be correct.
foreach (ItemInfo ii in ci.ContentItems) ii.RefreshConfig();
ContentInfo.Refresh(c);
}
}
}
// Refresh this docversioninfo. Note that this and below refresh use a docversion retrieved from the
// database, i.e. 'GetFromDB'. This was necessary since this dialog is working with docversion writable
// objects.
DocVersionInfo.Refresh(DocVersion.GetFromDB(this.VersionID));
// Refresh the source document's docversioninfo
if (sdvid > -1)
{
using (DocVersion dv = DocVersion.GetFromDB(sdvid))
{
DocVersionInfo.Refresh(dv);
}
}
}
catch (Exception ex)
{
throw new DbCslaException("Error on DocVersionInfo:DoUnlinkEnhancedDocVersion", ex);
}
}
#endregion UnlinkEnhanced
#region DocVersion Config
[NonSerialized]
private DocVersionConfig _DocVersionConfig;
public DocVersionConfig DocVersionConfig
{ get { return (_DocVersionConfig != null ? _DocVersionConfig : _DocVersionConfig = new DocVersionConfig(this)); } }
private void DocVersionConfigRefresh()
{
_DocVersionConfig = null;
}
#endregion
#region MOVE TO DOCVERSION CONFIG
private string GetProfile(string grp, string nam)
{
return GetProfile(grp, nam, false);
}
private string GetProfile(string grp, string nam, bool flag)
{
DocVersionConfig dvcfg = DocVersionConfig;
string buff = null;
if (grp != null && !grp.Equals(string.Empty))
{
buff = dvcfg.GetValue(grp, nam); // get the value of 'nam' in 'grp'
if (buff == null || buff.Equals(string.Empty))
{
if (!flag)
buff = string.Format("<{0}-{1}>", grp, nam);
else
buff = null;
}
}
return buff;
}
// B2021-066: Procedure PC/PC resolve procedure number with Unit Specific info
public string UnitSpecific(string str, int len, ItemInfo ii)
{
ProcedureInfo pi = ii as ProcedureInfo;
if (pi == null) // B2022-004: Don't crash if Proc PC/PC (ii is from a list, so wasn't an ItemInfo)
{
pi = ProcedureInfo.Get(ii.ItemID);
}
if (pi == null) return "";
// B2023-035 for save the current select child (selectedSlave) and use the child number
// that was selected when printed. This is needed for when "Other" applicability
// values are referenced. For BNPP Alarms, sometimes the SelectedSlave value was set
// to the corresponding "Other" value, but we needed to use the selected child that was
// selected from the print button/menu in order to get the correct "Other" value.
int docVerSelectedSlave = DocVersionConfig.SelectedSlave;
int procInfoSelectedChildToPrint = pi.SelectedChildToPrint;
if (procInfoSelectedChildToPrint != 0)
{
DocVersionConfig.SelectedSlave = procInfoSelectedChildToPrint;
}
string unitdes = "ID";
string prefix = null;
string fromunitdes = null;
str = ItemInfo.ConvertToDisplayText(pi.MyContent.Number);
bool hastoken = false;
// Determine if there is a token in the procedure number data, default is ID
if (str.ToUpper().Contains(@"<U"))
{
hastoken = true;
if (str.ToUpper().IndexOf(@"<U-") > -1)
{
try
{
int sindx = str.ToUpper().IndexOf(@"<U-");
int eindx = str.IndexOf(@">", sindx + 1);
unitdes = str.Substring(sindx + 3, eindx - (sindx + 3));
unitdes = unitdes.ToUpper();
}
catch
{
unitdes = "ID";
}
}
}
if (unitdes == "NUMBER")
fromunitdes = DocVersionConfig.Unit_Number;
else if (unitdes == "ID")
fromunitdes = DocVersionConfig.Unit_ID;
else if (unitdes == "NAME")
fromunitdes = DocVersionConfig.Unit_Name;
else if (unitdes == "TEXT")
fromunitdes = DocVersionConfig.Unit_Text;
// B2021-145: For applicability, the tree view & pdf file name are not getting resolved when using any of the <20>OTHER<45> tokens
// B2022-023 also check for other followed by a space
else if (unitdes == "OTHERTEXT" || unitdes == "OTHER TEXT")
fromunitdes = DocVersionConfig.Other_Unit_Text;
else if (unitdes == "OTHERNUMBER" || unitdes == "OTHER NUMBER")
fromunitdes = DocVersionConfig.Other_Unit_Number;
else if (unitdes == "OTHERNAME" || unitdes == "OTHER NAME")
fromunitdes = DocVersionConfig.Other_Unit_Name;
else if (unitdes == "OTHERID" || unitdes == "OTHER ID")
fromunitdes = DocVersionConfig.Other_Unit_ID;
else
fromunitdes = DocVersionConfig.Unit_ID;
DocVersionConfig.SelectedSlave = docVerSelectedSlave; //B2023-035 reset the selected Slave
// adjustments to the procedure number for applicability can be defined in 2 places:
// 1) mstr below: working draft properties/Applicability/Procedure number field for each unit can have text. The '#' in this
// field represents the procdure number & any text prefixing it, will be used to prefix the procedure number
// 2) fromunitdes above: this is defined on the procedure number, seen on procedure properties, and is a token <U> with
// optional '-xxx' after the U, see above for possible tokens.
string mstr = (MyConfig as DocVersionConfig).Unit_ProcedureNumber;
string[] units = mstr.Split(",".ToCharArray());
string[] fromdata = fromunitdes.Split(",".ToCharArray());
// SelectedSlave is > 0 if a unit has been selected, for example from print or approve. It represents that index into the list of units.
// F2023-098: depending on where this is called from & how data is set, the DocVersionConfig.SelectedSlave may be 0, but the
// procInfoSelectedChildToPrint will always have the correct value, i.e. 0 if not printing & the selected slave from the print selection.
// Check for procInfoSelectedChildToPrint > 0 also:
if (DocVersionConfig.SelectedSlave > 0 || procInfoSelectedChildToPrint > 0)
{
prefix = units[0].Replace("#", "");
if (str.ToUpper().IndexOf(@"<U-") > -1) return prefix + Regex.Replace(str, @"\<[uU]-[a-zA-Z]+\>", fromunitdes);
return prefix + Regex.Replace(str, @"\<[uU]\>", fromunitdes);
}
// The following code is used to handle the treeview/tree node representation of the procedure number with any appropriate
// unit specifications resolved, as follows:
// 1) [] (square brackets) are placed around any prefixes determined from the <U> token or the Procedure Number data on
// the working draft properties. If None, i.e. no units, are applicable, as selected from the Step Properties/Applicability tab.
// there will be no text between the brackets to represent no applicability
// 2) , (commas) are used as a delimiter. Only have 1 comma separating the prefix, there may be no text if some units are
// not applicable, but code exists here so that ',,,' does not appear in the treenode
// 3) don't duplicate resolved text, for example if NUMBER is used, and prefix text would be '[A,A,B,C,C]', only show '[A,B,C]'
bool sometext = false; // flag to use since don't want ',,,,,' before number
List<string> prefs = new List<string>();
for (int i = 1; i <= UnitNames.Length; i++)
{
bool procAppl = pi.ApplInclude(i);
string tokRepAndPrefix = units[i - 1].Replace("#", "") + (hastoken ? fromdata[i - 1] : "");
if (tokRepAndPrefix != "")
{
sometext = true;
if (prefs.Count > 0 && prefs.Contains(tokRepAndPrefix))
tokRepAndPrefix = "";
else
if (procAppl) prefs.Add(tokRepAndPrefix);
}
if (procAppl && tokRepAndPrefix != "") prefix = prefix + (prefix == null ? tokRepAndPrefix : (prefix != null && prefix.Length > 0 && prefix[prefix.Length - 1] != ',' ? "," : "") + tokRepAndPrefix);
}
str = Regex.Replace(str, @"\<[uU]-[a-zA-Z]+\>", "");
str = Regex.Replace(str, @"\<[uU]\>", "");
return (!sometext) ? str: "[" + prefix + "]" + str;
}
public string UnitSpecific(string str, int len)
{
// This routine retrieves the procedure number format from the
// current directory and uses it to adjust the procedure number
// in the specified string
string retvalu = "";
string asis = "#";
if (str == null || str.Equals(string.Empty)) return retvalu; // return a null (empty) string
/*
* Bug fix: B2005-017 3/2/2005
* Need to use the largest procedure number length that's in the
* SET.DFF file. "LargestNumber" is the largest length after the
* procedure number is replaced via the SET.INI file "replace" list.
*
if(len==0)len=LargestNumber;
*/
// TODO: Do we need this line?-->>> if(len==0)len=LargestRawSetNumber;
//GetPrivateProfileString("unit", "procedure number", asis, mstr, MAXPATH, "proc.ini");
string pnum = asis;
//rhm/jcb stuff 20120511
//string mstr = GetProfile("Unit", "ProcedureNumber", true);
string mstr = DocVersionConfig.Unit_ProcedureNumber;
if (mstr != null && !mstr.Equals(string.Empty))
pnum = mstr;
if (pnum.Equals(asis))
retvalu = str;
else if (pnum[0] == '!')
{
mstr = GetProfile("Replace", mstr, true); // true allow it to return a null if not found
if (mstr == null) retvalu = str; // no replacement, use procedure number as is
}
else
{
retvalu = "";
string[] pnumsplit = pnum.Split(new Char[] { '#' });
int cnt = 0;
foreach (string s in pnumsplit)
{
if (!s.Equals(string.Empty))
{
if ((cnt == 0) && (str.StartsWith(" ")))
{
string padding = new string(' ', s.Length);
retvalu += padding;
}
else
retvalu += s;
}
else
retvalu += str.Trim();
cnt++;
}
// append trailing blanks or procedure number (str)
if (str.EndsWith(" "))
{
// count number of trailing blanks and append them to retvalu
cnt = str.Length - 1;
while (cnt > 0 && str[cnt] == ' ') cnt--;
retvalu += new string(' ', str.Length - cnt - 1);
}
}
return retvalu;
}
public string Evaluate(string str, int len)
{
string retval = null;
string swhir = "PSU"; /* order in which to check */
string pn;
if (str.Length > 1 && str[1] == '-')
{
int swptr = swhir.IndexOf((str.ToUpper())[0]);
string sav = str.Substring(len);
str = str.Substring(0, len);
string substr = str.Substring(2);
substr = substr.Replace(" ", "");
while (swptr >= 0 && swptr < swhir.Length && retval == null)
{
switch (swhir[swptr])
{
case 'U':
//retval = GetProfile("Unit", substr, true);
if (substr.ToLower() == "id")
retval = this.DocVersionConfig.Unit_ID;
if (substr.ToLower() == "name")
retval = this.DocVersionConfig.Unit_Name;
if (substr.ToLower() == "number")
retval = this.DocVersionConfig.Unit_Number;
if (substr.ToLower() == "text")
retval = this.DocVersionConfig.Unit_Text;
break;
case 'S':
//retval = GetProfile("Procedure_Set", substr, true);
if (substr.ToLower() == "id")
retval = this.DocVersionConfig.Unit_ProcedureSetID;
if (substr.ToLower() == "name")
retval = this.DocVersionConfig.Unit_ProcedureSetName;
break;
case 'P':
//TODO: THIS IS A GLOBAL IN THE 16 BIT CODE!!!!
string procnumber = "";
pn = UnitSpecific(procnumber, 0);
retval = GetProfile(pn, substr, true);
break;
}
if (retval == null) // .Equals(string.Empty))
swptr++;
}
str += sav;
}
else if (len == 1 && (str.ToUpper())[0] == 'U')
{
retval = this.DocVersionConfig.Unit_Number;
}
else if (len == 2 && str.StartsWith("ID"))
{
retval = this.DocVersionConfig.Unit_ID;
}
if (retval == null)
retval = string.Format("<{0}>", str.Substring(0, len));
return retval;
}
public string ProcessDocVersionSpecificInfo(string rawvalue)
{
string str = rawvalue;
string rtnstr = string.Empty;
int l = rawvalue.Length;
while (l > 0)
{
int ptr = str.IndexOf('<');
int cptr = (ptr == -1) ? -1 : str.IndexOf('>');
// jsj 2/5/10 added "|| (ptr > cptr)" to fix bug where rawvalue = "Insert token for ->Step<- to transition back to."
if (ptr == -1 || (ptr > -1 && ((cptr == -1) || (ptr > cptr))))
{
rtnstr += str;
l = 0; // jump out of while loop
}
else
{
int cnt = ptr;
if (cnt > 0)
{
rtnstr += str.Substring(0, cnt);
l -= cnt;
str = str.Substring(ptr);
}
ptr = str.IndexOf('>') + 1;
cnt = ptr;
rtnstr += Evaluate(str.Substring(1, cnt - 2), cnt - 2);
l -= cnt;
str = str.Substring(ptr);
}
}
return rtnstr;
}
#endregion
ItemInfoList _Procedures = null;
public ItemInfoList Procedures
{ get { return (_Procedures != null ? _Procedures : _Procedures = ItemInfoList.GetList(_ItemID, (int)E_FromType.Procedure)); } }
public void ResetProcedures()
{
_Procedures = null;
}
public static void ResetProcedures(int versionID)
{
string key = versionID.ToString();
if (_CacheByPrimaryKey.ContainsKey(key))
foreach (DocVersionInfo dvi in _CacheByPrimaryKey[key])
dvi.ResetProcedures();
}
#region IVEReadOnlyItem
public System.Collections.IList GetChildren()
{
return Procedures;
}
//public bool ChildrenAreLoaded
//{
// get { return _iil == null; }
//}
public bool HasChildren
{
get { return _ItemID > 0; }
}
public IVEDrillDownReadOnly ActiveParent
{
get
{
return MyFolder;
}
}
public FormatInfo ActiveFormat
{
get { return LocalFormat != null ? LocalFormat : ActiveParent.ActiveFormat; }
}
public FormatInfo LocalFormat
{
get
{
//Console.WriteLine("DV Local {0} {1} {2}", (MyFormat == null) ? "MYformat is null" : MyFormat.Name,FormatID,(MyFormat == null)?0:MyFormat.FormatID);
return MyFormat;
}
}
public ConfigDynamicTypeDescriptor MyConfig
{
get { return DocVersionConfig; }
}
//public bool HasStandardSteps()
//{ return false; }
#region PasteChild
public ItemInfo PasteChild(int copyStartID) // pastes into an 'empty' docversion
{
ItemInfo cpItem = ItemInfo.Get(copyStartID);
try
{
DocVersionInfo dvi = DataPortal.Fetch<DocVersionInfo>(new VersionPastingPartCriteria(VersionID, copyStartID, DateTime.Now, Volian.Base.Library.VlnSettings.UserID));
ItemInfo tmp = dvi.Procedures[0] as ItemInfo;
if (tmp != null)
{
tmp.UpdateTransitionText();
tmp.UpdatePastedStepTransitionText();
}
return tmp;
}
catch (Exception ex)
{
System.Windows.Forms.MessageBox.Show("Details were written to the Error Log.", "Paste Failed", System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Error);
return null;
}
}
#endregion
#region UserSettings
/// <summary>
/// These settings are set on the user interface side.
/// This is used to control whether the Name and/or Title is displayed
/// next to the tree nodes in the user interface
/// </summary>
private bool _DisplayTreeNodeNames = true;
public bool DisplayTreeNodeNames
{
get { return _DisplayTreeNodeNames; }
set { _DisplayTreeNodeNames = value; }
}
private bool _DisplayTreeNodeTitles = false;
public bool DisplayTreeNodeTitles
{
get { return _DisplayTreeNodeTitles; }
set { _DisplayTreeNodeTitles = value; }
}
#endregion
public override string ToString()
{
// assume that at least one of the two options was selected
string rtnstr = "";
if (_DisplayTreeNodeNames) rtnstr = Name;
if (_DisplayTreeNodeTitles)
{
if (rtnstr.Length > 0) rtnstr += " - ";
rtnstr += Title;
}
return rtnstr;
//return string.Format("{0} - {1}", Name, Title);
}
//public string ToString(string str,System.IFormatProvider ifp)
//{
// return ToString();
//}
public ItemInfo LastChild()
{
return MyItem.LastSibling;
}
public ItemInfo FirstChild()
{
return MyItem;
}
#endregion
#region DataPortal
private void DataPortal_Fetch(VersionPastingPartCriteria criteria)
{
if (_MyLog.IsDebugEnabled) _MyLog.DebugFormat("[{0}] DocVersionInfo.DataPortal_Fetch", GetHashCode());
try
{
using (SqlConnection cn = Database.VEPROMS_SqlConnection)
{
ApplicationContext.LocalContext["cn"] = cn;
using (SqlCommand cm = cn.CreateCommand())
{
cm.CommandType = CommandType.StoredProcedure;
cm.Parameters.AddWithValue("@VersionID", criteria.VersionID);
cm.Parameters.AddWithValue("@StartItemID", criteria.StartItemID);
cm.Parameters.AddWithValue("@DTS", criteria.DTS); //ABC
cm.Parameters.AddWithValue("@UserID", criteria.UserID); //ABC
SqlParameter param_ContentID = new SqlParameter("@ThisVersionID", SqlDbType.Int);
param_ContentID.Direction = ParameterDirection.Output;
cm.Parameters.Add(param_ContentID);
cm.CommandText = "PasteDocVersionChild";
cm.CommandTimeout = Database.DefaultTimeout;
using (SafeDataReader dr = new SafeDataReader(cm.ExecuteReader()))
{
if (!dr.Read())
{
_ErrorMessage = "No Record Found";
return;
}
ReadData(dr);
}
}
// removing of item only needed for local data portal
if (ApplicationContext.ExecutionLocation == ApplicationContext.ExecutionLocations.Client)
ApplicationContext.LocalContext.Remove("cn");
}
}
catch (Exception ex)
{
if (!ex.Message.Contains("This working draft has been deleted") && !ex.Message.Contains("This current step has been deleted in another session"))
{
if (_MyLog.IsErrorEnabled) _MyLog.Error("DocVersion.DataPortal_Fetch", ex);
}
_ErrorMessage = ex.Message;
throw new DbCslaException("DocVersion.DataPortal_Fetch", ex);
}
}
#endregion
#region Extension
partial class DocVersionInfoExtension : extensionBase
{
public override void Refresh(DocVersionInfo tmp)
{
tmp.DocVersionConfigRefresh();
}
}
#endregion
public ROFstInfo GetROFst(int rodbid)
{
if (DocVersionAssociations == null || DocVersionAssociations.Count == 0) // No RO Association for this Data
{
if (FirstBadRODBIDProblemDetected)
_MyLog.ErrorFormat("<<<ERROR>>> - Missing RO Association\r\nMissing RO Association for this Folder ([{0}] - {1})", VersionID, MyFolder.Name);
return null;
}
foreach (AssociationInfo dva in DocVersionAssociations)
{
if (dva.MyROFst.RODbID == rodbid)
return dva.MyROFst;
}
if (DocVersionAssociations.Count == 1) // Different Association and ROUsage values for RODBID - default to asssociation value
{
if (FirstBadRODBIDProblemDetected)
_MyLog.ErrorFormat("<<<ERROR>>> - ROUsage Does Not match Association\r\nROUsage (RODBID = {0}) does not match Association Information (RODBID = {1}) for this Folder ([2] - {3})",
rodbid, DocVersionAssociations[0].MyROFst.RODbID, VersionID, MyFolder.Name);
return DocVersionAssociations[0].MyROFst;
}
// More than one association record - Cannot guess which to return
if (FirstBadRODBIDProblemDetected)
_MyLog.ErrorFormat("<<<ERROR>>> - More than One Association Record\r\nROUsage (RODBID = {0}) does not match any of the {1} Associations for this Folder ([{2}] -{3})",
rodbid, DocVersionAssociations.Count, VersionID, MyFolder.Name);
return null;
}
private static List<int> _HasBadRODBIDProblem = new List<int>();
private bool FirstBadRODBIDProblemDetected
{
get
{
if (_HasBadRODBIDProblem.Contains(VersionID)) return false;
_HasBadRODBIDProblem.Add(VersionID);
return true;
}
}
public bool IsFolder
{
get
{
return false;
}
}
public bool IsDocVersion
{
get
{
return true;
}
}
public bool IsProcedure
{
get
{
return false;
}
}
public bool IsSection
{
get
{
return false;
}
}
public bool IsStep
{
get
{
return false;
}
}
public int MultiUnitCount
{
get
{
return DocVersionConfig.Unit_Count;
}
}
private string[] _UnitNames;
public string[] UnitNames
{
get
{
if (_UnitNames == null)
{
_UnitNames = DocVersionConfig.Unit_Name.Split(',');
_UnitNames = new string[DocVersionConfig.Unit_Count];
int j = 0;
for (int k = 1; k <= DocVersionConfig.MaxSlaveIndex; k++)
{
DocVersionConfig.SelectedSlave = k;
try
{
_UnitNames[j] = DocVersionConfig.Unit_Name;
j++;
}
catch
{
}
}
DocVersionConfig.SelectedSlave = 0;
}
return _UnitNames;
}
}
#region Proc Set Specific info support
public static string GetInheritedSIValue(ProcedureInfo pi, string fieldName)
{
string val = null;
DocVersionConfig dvConfig = new DocVersionConfig(pi.MyDocVersion.Config);
if (dvConfig != null)
{
val = dvConfig.GetValue("SI", fieldName);
if (val != null && val != "") return val; // the value exists within the docversion level
}
FolderInfo fi = pi.MyDocVersion.MyFolder;
while (fi != null)
{
FolderConfig folderConfig = new FolderConfig(fi.Config);
if (folderConfig != null)
{
val = folderConfig.GetValue("SI", fieldName);
if (val != null && val != "") return val; // the value exists within this folder
}
fi = fi.ActiveParent as FolderInfo;
}
return val;
}
#endregion
}
#region VersionPastingPartCriteria
[Serializable()]
public class VersionPastingPartCriteria
{
#region Properties
private int _VersionID;
public int VersionID
{
get { return _VersionID; }
set { _VersionID = value; }
}
private int _StartItemID;
public int StartItemID
{
get { return _StartItemID; }
set { _StartItemID = value; }
}
private DateTime _DTS;
public DateTime DTS
{
get { return _DTS; }
set { _DTS = value; }
}
private string _UserID;
public string UserID
{
get { return _UserID; }
set { _UserID = value; }
}
#endregion
#region Constructor
public VersionPastingPartCriteria(int versionID, int startItemID, DateTime dts, string userID)
{
_VersionID = versionID;
_StartItemID = startItemID;
_DTS = dts;
_UserID = userID;
}
#endregion
}
#endregion
public enum VersionTypeEnum : int
{
WorkingDraft = 0, Temporary = 1, Revision = 128, Approved = 129
}
public partial class DocVersionInfoList
{
public static DocVersionInfoList GetNonEnhancedDocVersions()
{
try
{
DocVersionInfoList tmp = DataPortal.Fetch<DocVersionInfoList>(new DocVersionNonEnhancedListCriteria());
DocVersionInfo.AddList(tmp);
tmp.AddEvents();
return tmp;
}
catch (Exception ex)
{
throw new DbCslaException("Error on DocVersionInfoList.GetNonEnhancedDocVersions", ex);
}
}
[Serializable()]
protected class DocVersionNonEnhancedListCriteria
{
public DocVersionNonEnhancedListCriteria() { ;}
}
private void DataPortal_Fetch(DocVersionNonEnhancedListCriteria criteria)
{
this.RaiseListChangedEvents = false;
try
{
using (SqlConnection cn = Database.VEPROMS_SqlConnection)
{
using (SqlCommand cm = cn.CreateCommand())
{
cm.CommandType = CommandType.StoredProcedure;
cm.CommandText = "vesp_GetNonEnhancedDocVersions";
cm.CommandTimeout = Database.DefaultTimeout;
using (SafeDataReader dr = new SafeDataReader(cm.ExecuteReader()))
{
IsReadOnly = false;
while (dr.Read())
{
DocVersionInfo dvInfo = new DocVersionInfo(dr);
this.Add(dvInfo);
}
IsReadOnly = true;
}
}
}
}
catch (Exception ex)
{
Database.LogException("DocVersionInfoList.DataPortal_Fetch", ex);
throw new DbCslaException("DocVersionInfoList.DataPortal_Fetch", ex);
}
this.RaiseListChangedEvents = true;
}
}
}