776 lines
22 KiB
C#

// ========================================================================
// 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 VEPROMS.Properties;
namespace VEPROMS.CSLA.Library
{
public partial class DocVersion: IVEDrillDown
{
public bool NewerRoFst
{
get
{
if (DocVersionAssociations == null || DocVersionAssociations.Count == 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;
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.
if (fiRofst.Length != roFstInfo.ROLookup.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. If
ROFstInfoList fstList = ROFstInfoList.GetBySize(rdi.RODbID, (int)fiRofst.Length);
if (fstList.Count > 0)
{
FileStream fsIn = new FileStream(rofstPath, FileMode.Open, FileAccess.Read, FileShare.Read);
// Create an instance of StreamReader that can read characters from the FileStream.
BinaryReader r = new BinaryReader(fsIn);
byte[] ab = r.ReadBytes((int)fsIn.Length);
fsIn.Close();
foreach (ROFstInfo irofst in fstList)
{
// compare contents by comparing each byte.
for (int i = 0; i < fiRofst.Length; i++)
if (ab[i] != irofst.ROLookup[i]) return true;
}
}
return false;
}
}
#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;
}
public bool NewerRoFst
{
get
{
if (DocVersionAssociations == null) 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.
if (roFstInfo.DTS >= fiRofst.LastWriteTimeUtc) return false;
TimeSpan ts = roFstInfo.DTS - fiRofst.LastWriteTimeUtc;
if (ts.TotalSeconds > -1F) 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.
if (fiRofst.Length != roFstInfo.ROLookup.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. If
ROFstInfoList fstList = ROFstInfoList.GetBySize(rdi.RODbID, (int)fiRofst.Length);
if (fstList.Count > 0)
{
FileStream fsIn = new FileStream(rofstPath, FileMode.Open, FileAccess.Read, FileShare.Read);
// Create an instance of StreamReader that can read characters from the FileStream.
BinaryReader r = new BinaryReader(fsIn);
byte[] ab = r.ReadBytes((int)fsIn.Length);
fsIn.Close();
foreach (ROFstInfo irofst in fstList)
{
// compare contents by comparing each byte.
for (int i = 0; i < fiRofst.Length; i++)
if (ab[i] != irofst.ROLookup[i]) return true;
}
}
return false;
}
}
#region SearchPaths
public string _SearchDVPath;
public string SearchDVPath
{
get
{
if (_SearchDVPath == null)
_SearchDVPath = ActiveParent.SearchDVPath + "\u0007" + Name;
return _SearchDVPath;
}
}
public string SearchPath { get { return ""; } }
#endregion
#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;
}
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] == '!')
{
// look for mstr in SET.INI
// GetPrivateProfileString("replace", mstr, mstr, tonum, 24, "set.ini");
// TODO: NOT SURE IF SET.INI AND PROC.INI HAVE UNIQUE GROUP NAMES!!!!!!!
//mstr = GetProfile("Replace", mstr);
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 inwhich to check */
string pn;
if (str.Length > 1 && str[1] == '-')
{
int swptr = swhir.IndexOf((str.ToUpper())[0]);
//char swchar = '';
//if (swptr != -1)
// swchar = swhir[swptr];
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) //retval.Equals(string.Empty))
{
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;
//retval = this.DocVersionConfig.Other_Unit_ID;
//retval = this.DocVersionConfig.Other_Unit_Name;
//retval = this.DocVersionConfig.Other_Unit_Number;
//retval = this.DocVersionConfig.Other_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 the return value is empty, then the resulting
// evaluation should repeat the token string including
// the braces. - the beginning brace is not passed in.
//if (retval.Equals(string.Empty))
//{
// retval = (char*)mallocq(len + 3);
// strncpy(retval, str - 1, len + 2);
//}
if (retval == null)
retval = string.Format("<{0}>", str.Substring(0, len));
return retval;
}
public string ProcessDocVersionSpecificInfo(string rawvalue)
{
string str = rawvalue;
string rtnstr = "";
int l = rawvalue.Length;
while (l > 0)
{
int ptr = str.IndexOf('<'); //nextDelimiter("<", str, l);
int cptr = (ptr == -1) ? -1 : str.IndexOf('>'); //nextDelimiter(">", ptr, strlen(ptr));
// 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))))
{
//add(new seText(str, l));
//str += l;
rtnstr += str;
l = 0; // jump out of while loop
}
else
{
int cnt = ptr;
if (cnt > 0)
{
//add(new seText(str, cnt));
rtnstr += str.Substring(0, cnt);
l -= cnt;
str = str.Substring(ptr);
}
ptr = str.IndexOf('>')+1; //nextDelimiter(">", str, l) + 1;
cnt = ptr; //(int)(ptr - str);
//add(new seUser(str + 1, cnt - 2));
rtnstr += Evaluate(str.Substring(1, cnt - 2),cnt-2);
l -= cnt;
str = str.Substring(ptr); //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 Get().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 document version 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) return null;
foreach (AssociationInfo dva in DocVersionAssociations)
{
if (dva.MyROFst.RODbID == rodbid)
return dva.MyROFst;
}
return null;
}
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 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
}
}