2617 lines
105 KiB
C#
Raw Blame History

using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
using System.Data.SqlClient;
using System.Text.RegularExpressions;
using Csla;
using Csla.Data;
using System.Windows.Forms;
using JR.Utils.GUI.Forms;
namespace VEPROMS.CSLA.Library
{
public delegate void ItemInfoInsertEvent(object sender, ItemInfoInsertEventArgs args);
public class ItemInfoInsertEventArgs
{
private ItemInfo _ItemInserted;
public ItemInfo ItemInserted
{
get { return _ItemInserted; }
set { _ItemInserted = value; }
}
private ItemInfo.EAddpingPart _AddingPart;
public ItemInfo.EAddpingPart AddingPart
{
get { return _AddingPart; }
set { _AddingPart = value; }
}
public ItemInfoInsertEventArgs(ItemInfo itemInserted,ItemInfo.EAddpingPart addingPart)
{
_ItemInserted = itemInserted;
_AddingPart = addingPart;
}
}
public partial class ItemInfo
{
public ItemInfo HandleSqlExceptionOnDelete(Exception ex)
{
// C2020-033: The dialog message has been changed to reference the Tools/Search/Incoming Transitions tab and
// the return value was changed to return null (this was returning first in list, but now user gets all
// listed in the search dialog). This comment is for each of the dialogs below.
string itemDesc = this.GetTypeDescription(); // C2020-018 made the message more accurate when deleting a Procedure, Section, or Step
if (ex.Message.Contains("has External Transitions and has no next step"))
{
using (TransitionInfoList exTrans = TransitionInfoList.GetExternalTransitionsToChildren(ItemID))
{
//C2020-018 build the message based on the type description
string msg1 = string.Format("Transitions exist to this {0} and cannot be adjusted automatically.", itemDesc);
DialogResult ans = FlexibleMessageBox.Show(msg1 +
"\r\n\r\nThe list of all locations are shown in the Tools/Search/Incoming Transitions tab.",
"Cannot Delete This " + itemDesc, MessageBoxButtons.OK, MessageBoxIcon.Information);
}
}
else if (ex.Message.Contains("has External Transitions to Procedure"))
{
using (TransitionInfoList exTrans = TransitionInfoList.GetExternalTransitionsToChildren(ItemID))
{
DialogResult ans = FlexibleMessageBox.Show("Transitions exist to this procedure and cannot be adjusted automatically." +
"\r\n\r\nThe list of all locations are shown in the Tools/Search/Incoming Transitions tab.",
"Cannot Delete This Procedure", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
}
// B2020-091: If deleting a section that has transitions pointing to it, show list:
else if (ex.Message.Contains("has External Transitions to Section"))
{
using (TransitionInfoList exTrans = TransitionInfoList.GetExternalTransitionsToChildren(ItemID))
{
DialogResult ans = FlexibleMessageBox.Show("Transitions exist to this section and cannot be adjusted automatically." +
"\r\n\r\nThe list of all locations are shown in the Tools/Search/Incoming Transitions tab.",
"Cannot Delete This Section", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
}
else if (ex.Message.Contains("has External Transitions to it's children"))
{
using (TransitionInfoList exTrans = TransitionInfoList.GetExternalTransitionsToChildren(ItemID))
{
//C2020-018 build the message based on the type description
string msg1 = string.Format("Transitions exist to {0} this {1} and cannot be adjusted automatically.", (this.IsSection) ? "steps in" : "children of", itemDesc);
DialogResult ans = FlexibleMessageBox.Show(msg1 +
"\r\n\r\nThe list of all locations are shown in the Tools/Search/Incoming Transitions tab.",
"Cannot Delete This " + itemDesc, MessageBoxButtons.OK, MessageBoxIcon.Information);
}
}
else
FlexibleMessageBox.Show(ex.Message, "SQL Exception", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
return null;
}
#region Old Insert
//public ItemInfo InsertSiblingBeforeOld(string text)
//{
// return InsertSiblingBefore(text, null);
//}
//public ItemInfo InsertSiblingBeforeOld(string text, string number)
//{
// ItemInfo prevItemInfo = MyPrevious;
// ItemInfo newItemInfo = null;
// PartInfoList partInfoList = null;
// if (MyParent != null && MyParent.MyContent != null)
// {
// MyParent.MyContent.RefreshContentParts();
// partInfoList = MyParent.MyContent.ContentParts;
// }
// using (Item prevItem = prevItemInfo == null ? null : prevItemInfo.Get()) // Get the previous Item
// {
// using (Item newItem = Item.MakeItem(prevItem, Content.MakeContent(number, text, MyContent.Type, null, null))) // Create the new Item
// {
// using (Item thisItem = Get()) // Get the next item in the list
// {
// thisItem.MyPrevious = newItem; // Point to the new item
// thisItem.Save(); // Save Changes
// if (prevItem == null)
// {
// PartInfo partInfo = partInfoList.Find(this);
// using (Part part = partInfo.Get())
// {
// part.MyItem = newItem;
// part.Save();
// }
// }
// }
// // ToDo: Need change PartInfo in PartInfoList
// newItemInfo = ItemInfo.Get(newItem.ItemID);
// newItemInfo.ResetOrdinal();
// }
// }
// return newItemInfo;
//}
//public ItemInfo InsertSiblingAfterOld(string text)
//{
// return InsertSiblingAfter(text, null);
//}
//public ItemInfo InsertSiblingAfterOld(string text, string number)
//{
// return InsertSiblingAfter(text, number, MyContent.Type);
//}
//public ItemInfo InsertSiblingAfterOld(string text, string number, int? type)
//{
// ItemInfo nextItemInfo = NextItem;
// ItemInfo newItemInfo = null;
// using (Item thisItem = Get()) // Get the Current Item
// {
// using (Item newItem = Item.MakeItem(thisItem, Content.MakeContent(number, text, type, null, null))) // Create the new Item
// {
// if (nextItemInfo != null) // Simple case, adding to end of list:
// using (Item nextItem = nextItemInfo.Get()) // Get the next item in the list
// {
// nextItem.MyPrevious = newItem; // Point to the new item
// nextItem.Save(); // Save Changes
// }
// // ToDo: Need change PartInfo in PartInfoList
// newItemInfo = ItemInfo.Get(newItem.ItemID);
// newItemInfo.ResetOrdinal();
// }
// }
// return newItemInfo;
//}
//public ItemInfo InsertChildOld(E_FromType fromType, int type, string text)
//{
// return InsertChild(fromType, type, text, null);
//}
//public ItemInfo InsertChildOld(E_FromType fromType, int type, string text, string number)
//{
// ItemInfo newItemInfo = null;
// using (Item thisItem = Get()) // Get the Current Item
// {
// using (Item newItem = Item.MakeItem(null, Content.MakeContent(number, text, type, null, null))) // Create the new Item
// {
// PartInfo partInfo = MyContent.ContentParts == null ? null : MyContent.ContentParts.Find(fromType);
// if (partInfo != null)
// {
// //this could be equivalent to adding a sibling with a specific type
// using (Part part = partInfo.Get())
// {
// part.MyItem.MyPrevious = newItem;
// part.MyItem.Save();
// part.MyItem = newItem;
// part.Save();
// }
// }
// else
// {
// // This means that a part needs to be added to point to the new item
// //using (Part part = Part.MakePart(thisItem.MyContent, ))
// //{ ;}
// thisItem.MyContent.ContentParts.Add((int)fromType, newItem);
// thisItem.Save();
// }
// newItemInfo = ItemInfo.Get(newItem.ItemID);
// }
// }
// ResetParts();
// return newItemInfo;
//}
#endregion
#region Events
public event ItemInfoEvent BeforeDelete;
public void OnBeforeDelete()
{
OnBeforeDelete(ItemID);
if (MyContent.ContentPartCount > 0)
{
foreach (PartInfo pi in MyContent.ContentParts)
{
foreach (ItemInfo ii in pi.MyItems)
{
ii.OnBeforeDelete();
}
}
}
//if (ItemPartCount > 0)
//{
// foreach (PartInfo pi in ItemParts)
// {
// foreach (ItemInfo ii in pi.MyItems)
// {
// ii.OnBeforeDelete();
// }
// }
//}
}
private void OnBeforeDelete(int ItemID)
{
if (_CacheByPrimaryKey.ContainsKey(ItemID.ToString()))
{
List<ItemInfo> itmlst = _CacheByPrimaryKey[ItemID.ToString()];
foreach (ItemInfo itm in itmlst)
if (itm.BeforeDelete != null)
{
itm.BeforeDelete(itm);
}
}
}
public static event ItemInfoEvent ItemDeleted;
public event ItemInfoEvent Deleted;
internal void OnDeleted(object sender)
{
if (Deleted != null) Deleted(sender);
if (ItemDeleted != null) ItemDeleted(sender);
if (MyParent != null)
{
MyParent.OnChildrenDeleted(sender);
MyParent.MyContent.RefreshContentParts();
}
}
//internal void OnDeleted(object sender, Volian.Base.Library.VlnTimer tmr)
//{
//tmr.ActiveProcess = "Deleted";
//if (Deleted != null) Deleted(sender);
//tmr.ActiveProcess = "ItemDeleted";
//if (ItemDeleted != null) ItemDeleted(sender);
//if (MyParent != null)
//{
//tmr.ActiveProcess = "OnChildrenDeleted";
//MyParent.OnChildrenDeleted(sender);
//tmr.ActiveProcess = "RefreshContentParts";
//MyParent.MyContent.RefreshContentParts();
//}
//}
public event ItemInfoEvent ChildrenDeleted;
internal void OnChildrenDeleted(object sender)
{
if (_CacheByPrimaryKey.ContainsKey(ItemID.ToString()))
{
List<ItemInfo> itmlst = _CacheByPrimaryKey[ItemID.ToString()];
foreach (ItemInfo itm in itmlst)
if (itm.ChildrenDeleted != null)
{
itm.ChildrenDeleted(itm);
}
}
}
public event ItemInfoInsertEvent NewSiblingAfter;
internal void OnNewSiblingAfter(object sender, ItemInfoInsertEventArgs args)
{
if (NewSiblingAfter != null) NewSiblingAfter(sender,args);
if (MyParent != null)
MyParent.MyContent.RefreshContentParts();
}
internal void OnNewSiblingAfter(ItemInfoInsertEventArgs args)
{
string key = ItemID.ToString();
if (_CacheByPrimaryKey.ContainsKey(key))
{
ItemInfo[] items = _CacheByPrimaryKey[key].ToArray();
foreach (ItemInfo item in items)
{
item.OnNewSiblingAfter(item,args);
}
}
}
public event ItemInfoInsertEvent NewSiblingBefore;
internal void OnNewSiblingBefore(object sender, ItemInfoInsertEventArgs args)
{
if (NewSiblingBefore != null) NewSiblingBefore(sender,args);
if (MyParent != null)
MyParent.MyContent.RefreshContentParts();
}
internal void OnNewSiblingBefore(ItemInfoInsertEventArgs args)
{
string key = ItemID.ToString();
if (_CacheByPrimaryKey.ContainsKey(key))
{
ItemInfo[] items = _CacheByPrimaryKey[key].ToArray();
foreach (ItemInfo item in items)
{
item.OnNewSiblingBefore(item,args);
}
}
}
public event ItemInfoInsertEvent NewChild;
internal void OnNewChild(object sender, ItemInfoInsertEventArgs args)
{
if (NewChild != null) NewChild(sender, args);
MyContent.RefreshContentParts();
}
internal void OnNewChild(ItemInfoInsertEventArgs args)
{
string key = ItemID.ToString();
if (_CacheByPrimaryKey.ContainsKey(key))
{
ItemInfo[] items = _CacheByPrimaryKey[key].ToArray();
foreach (ItemInfo item in items)
{
item.OnNewChild(item, args);
}
}
}
#endregion
#region Insert Before
public ItemInfo InsertSiblingBefore(string text)
{
return InsertSiblingBefore(text, null);
}
public ItemInfo InsertSiblingBefore(string text, string number)
{
return InsertSiblingBefore(text, number, null);
}
public ItemInfo InsertSiblingBefore(string text, string number,int? type)
{
ItemInfo tmp = null;
if (!IsSection && (FormatStepData.UseSmartTemplate || (MyHLS != null && MyHLS.FormatStepData.UseSmartTemplate) || FormatStepData.UseOldTemplate))
tmp = InsertSmartTemplateSteps(text, number, tmp, EAddpingPart.Before, (int)((type == null) ? MyContent.Type : type)); // B2018-051 use the type passed in instead of current step type
if (tmp == null)
tmp = NewItemInfoFetch(ItemID, EAddpingPart.Before, number, text, type, null, null, null, DateTime.Now, Volian.Base.Library.VlnSettings.UserID);
// this item is updated in SQL so we have to manually force the iteminfo updates
// Refresh ItemInfo to update Previous
using (Item item = Get()) ItemInfo.Refresh(item);
// Update all of the content records that have transitions that point to the Siblings or Sibling Children of the new item
tmp.ResetOrdinal(); // B2020-043: Fix transition text (was updatetransitiontext)
tmp.UpdateROText();
OnNewSiblingBefore(new ItemInfoInsertEventArgs(tmp, EAddpingPart.Before));
((ItemInfo)ActiveParent).MyContent.RefreshContentParts();
return tmp;
}
public ItemInfo InsertSmartTemplateSubStep(string text, string number, ItemInfo tmp, EAddpingPart adPart, int type, E_FromType fromTypeTop)
{
int newItemID = 0;
int topType = GetSmartTemplateTopLevelIndxOfThisType(type);
if (topType == -1) return null;
int tpIndx = GetSmartTemplateIndex(topType, type);
if (tpIndx != -1)
{
ItemInfo siblingSmart = null;
ItemInfo firstSmart = null;
int level = ActiveFormat.PlantFormat.FormatData.Templates[tpIndx].level;
string tmptext = ActiveFormat.PlantFormat.FormatData.NewTemplateFormat ? text : ActiveFormat.PlantFormat.FormatData.Templates[tpIndx].text;
int prevlevel = level;
while (level > 0)
{
if (firstSmart == null)
{
firstSmart = NewItemInfoFetch(ItemID, adPart, number, tmptext, type, (int ?)fromTypeTop, null, null, DateTime.Now, Volian.Base.Library.VlnSettings.UserID);
//firstSmart = NewItemInfoFetch(ItemID, adPart, number, tmptext, type, null, null, null, DateTime.Now, Volian.Base.Library.VlnSettings.UserID);
siblingSmart = firstSmart;
newItemID = firstSmart.ItemID;
}
else
{
E_FromType fromType = E_FromType.Step;
EAddpingPart addPart = EAddpingPart.Child; // level > previous, add a child.
if (level == prevlevel) addPart = EAddpingPart.After;
if (level < prevlevel)
{
if (ActiveFormat.PlantFormat.FormatData.Templates[tpIndx].type == 39)
{
fromType = E_FromType.RNO;
addPart = EAddpingPart.Child;
}
else
{
addPart = EAddpingPart.After;
}
newItemID = siblingSmart.ItemID;
}
tmptext = /*ActiveFormat.PlantFormat.FormatData.NewTemplateFormat ? " ": */ActiveFormat.PlantFormat.FormatData.Templates[tpIndx].text;
tmp = NewItemInfoFetch(newItemID, addPart, null, tmptext, ActiveFormat.PlantFormat.FormatData.Templates[tpIndx].type + 20001, (int?)fromType, null, null, DateTime.Now, Volian.Base.Library.VlnSettings.UserID);
newItemID = tmp.ItemID;
if (level < prevlevel) siblingSmart = tmp;
}
tpIndx++;
prevlevel = level;
level = tpIndx < ActiveFormat.PlantFormat.FormatData.Templates.Count ?
ActiveFormat.PlantFormat.FormatData.Templates[tpIndx].level : -1;
}
tmp = firstSmart;
}
return tmp;
}
public ItemInfo InsertSmartTemplateSteps(string text, string number, ItemInfo tmp, EAddpingPart adPart, int type)
{
int newItemID = 0;
int topType = GetSmartTemplateTopLevelIndx();
if (topType == -1) return null;
int tpIndx = GetSmartTemplateIndex(topType, (int)MyContent.Type);
if (tpIndx != -1)
{
ItemInfo siblingSmart = null; // keep track of sibling
ItemInfo firstSmart = null; // hls or top template step
ItemInfo parentSmart = null; // keep track of parent as creating children
int level = ActiveFormat.PlantFormat.FormatData.Templates[tpIndx].level;
string tmptext = ActiveFormat.PlantFormat.FormatData.NewTemplateFormat ? text : ActiveFormat.PlantFormat.FormatData.Templates[tpIndx].text;
int prevlevel = level;
while (level > 0)
{
if (firstSmart == null)
{
firstSmart = NewItemInfoFetch(ItemID, adPart, number, tmptext, type, null, null, null, DateTime.Now, Volian.Base.Library.VlnSettings.UserID);
siblingSmart = parentSmart = firstSmart;
newItemID = firstSmart.ItemID;
}
else
{
E_FromType fromType = E_FromType.Step;
EAddpingPart addPart = EAddpingPart.Child; // level > previous, add a child.
if (level == prevlevel) addPart = EAddpingPart.After; // level = previous, add a sibling
if (level < prevlevel) // level < previous, go up to previous level's id
{
if (ActiveFormat.PlantFormat.FormatData.Templates[tpIndx].type == 39)
{
fromType = E_FromType.RNO;
addPart = EAddpingPart.Child;
newItemID = firstSmart.ItemID;
}
else
{
addPart = EAddpingPart.After;
newItemID = parentSmart.ItemID;
}
}
tmptext = ActiveFormat.PlantFormat.FormatData.Templates[tpIndx].text;
tmp = NewItemInfoFetch(newItemID, addPart, null, tmptext, ActiveFormat.PlantFormat.FormatData.Templates[tpIndx].type + 20001, (int?)fromType, null, null, DateTime.Now, Volian.Base.Library.VlnSettings.UserID);
newItemID = tmp.ItemID;
if (level < prevlevel) siblingSmart = parentSmart;
else if (level > prevlevel) parentSmart = siblingSmart;
if (level == prevlevel) siblingSmart = tmp;
}
tpIndx++;
prevlevel = level;
level = tpIndx < ActiveFormat.PlantFormat.FormatData.Templates.Count ?
ActiveFormat.PlantFormat.FormatData.Templates[tpIndx].level : -1;
}
tmp = firstSmart;
}
return tmp;
}
#endregion
#region PasteChangeId
public static void PasteSetChangeId(ItemInfo ii, string chgid)
{
if (!ii.ActiveFormat.PlantFormat.FormatData.ProcData.ChangeBarData.ChangeIds) return;
if (ii.IsProcedure)
{
return; // copy over change bars & change ids as they exist.
}
else if (ii.IsSection)
{
// don't save change id for section. DON'T return though because code below sets
// change ids for steps within section.
}
else if (ii.IsStep)
{
StepConfig sc = ii.MyConfig as StepConfig;
if (chgid != null && sc.Step_ChangeID != chgid)
{
sc.Step_ChangeID = chgid;
using (Item itm = ii.Get())
{
itm.MyContent.Config = sc.ToString();
itm.MyContent.DTS = DateTime.Now;
itm.MyContent.UserID = Volian.Base.Library.VlnSettings.UserID;
itm.Save();
}
}
}
// handle all of the children
if (ii.Cautions != null) foreach (ItemInfo chldc in ii.Cautions) PasteSetChangeId(chldc, chgid);
if (ii.Notes != null) foreach (ItemInfo chldn in ii.Notes) PasteSetChangeId(chldn, chgid);
if (ii.RNOs != null) foreach (ItemInfo chldr in ii.RNOs) PasteSetChangeId(chldr, chgid);
if (ii.Tables != null) foreach (ItemInfo chldt in ii.Tables) PasteSetChangeId(chldt, chgid);
if (ii.Sections != null) foreach (ItemInfo chldsc in ii.Sections) PasteSetChangeId(chldsc, chgid);
if (ii.Steps != null) foreach (ItemInfo chlds in ii.Steps) PasteSetChangeId(chlds, chgid);
}
#endregion
#region Paste
public ItemInfo PasteChild(int copyStartID, string chgid)
{
// To determine 'type' of pasted item, if it's a step (type >=20000), use the originating
// item, i.e. item inserting after. If it's a section or procedure, use the copied item's type.
ItemInfo cpItem = ItemInfo.Get(copyStartID);
int? type = MyContent.Type >= 20000 ? MyContent.Type : cpItem.MyContent.Type;
int? fromtype = MyContent.Type >= 20000 ? MyContent.Type
: ((int?)(IsProcedure ? E_FromType.Section
: (cpItem.IsSection ? E_FromType.Section : E_FromType.Step)));
try
{
ItemInfo tmp = CopyPasteItemInfoFetch(copyStartID, this.ItemID, type, fromtype, EAddpingPart.Child);
using (Item item = Get()) ItemInfo.Refresh(item);
if (tmp.NextItem != null) using (Item item = tmp.NextItem.Get()) ItemInfo.Refresh(item);
RefreshNextItems();
tmp.UpdateTransitionText();
tmp.UpdatePastedStepTransitionText();
PasteSetChangeId(tmp, chgid);
PasteClearEnhanced(tmp);
OnNewChild(new ItemInfoInsertEventArgs(tmp, EAddpingPart.Child));
return tmp;
}
catch (Exception ex)
{
if (!HandleSqlExceptionOnCopy(ex))
FlexibleMessageBox.Show("Details were written to the Error Log.", "Paste Failed", System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Error);
return this;
}
}
// F2021-009 Get the number of children levels the passed in parent has
private static int GetMaxSubStepLevel(ItemInfo parent)
{
int maxStepLevel = parent.StepLevel-1; // subtract one to account for HLS - we want the sub-step level
if (parent.Steps != null) // B2021-033: check for null
{
foreach (ItemInfo kid in parent.Steps)
{
if (kid.Steps != null)
maxStepLevel = Math.Max(maxStepLevel, GetMaxSubStepLevel(kid));
else
maxStepLevel = Math.Max(maxStepLevel, kid.StepLevel - 1); // subtract one to account for HLS because we are counting only sub-step levels
}
}
return maxStepLevel;
}
// F2021-009 Find the number of sub-step levels that the Copied Step has.
// This is used to determin if the Paste will result in exesssive sub-step levels
private static int GetCopyStepMaxLevels(int copyStartID)
{
ItemInfo cpyItem = ItemInfo.Get(copyStartID);
return GetMaxSubStepLevel(cpyItem);
}
// F2021-009 Find the number of defined sequential tabs. We use this to determin the number of defined sub-step levels
public int GetDefinedSubStepCount()
{
return GetDefinedSubStepCount(this);
}
// F2021-009 Find the number of defined sequential tabs. We use this to determin the number of defined sub-step levels
public static int GetDefinedSubStepCount(ItemInfo curStep)
{
int cnt = 0;
cnt = curStep.ActiveFormat.PlantFormat.FormatData.SectData.StepSectionData.SeqTabFmtList.Count;
return cnt-1; // -1 to account for the high level step level
}
// F2021-009 for PROMS Express, display a message if the Paste of a CopyStep will results in sub-step levels
// greater than what is defined in the format
public static bool PasteStepIsWithinDefinedSubStepLevels(int copyStartID, ItemInfo pasteTarget, bool doingReplace)
{
int largestSubStepLevel = GetCopyStepMaxLevels(copyStartID);
int numDefinedSubstepLevels = GetDefinedSubStepCount(pasteTarget);
largestSubStepLevel += (pasteTarget.StepLevel-((doingReplace)?1:0));// subtract one because HLS is level one, results in actual sub-step level
if (largestSubStepLevel > numDefinedSubstepLevels && pasteTarget.ActiveFormat.PlantFormat.FormatData.Express)
{
string mbMsg = "This will result with more sub-step levels than are defined in" +
"\nthe format and could result in a step that is difficult to follow." +
"\n\nConsider rewriting the step using less sub-steps levels.";
MessageBox.Show(mbMsg, "Paste Step Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
return false;
}
return true;
}
// B2016-009 - added a message box explaining to the user that the copyed step will take on the destination type. 16-bit PROMS had also done this way.
// - this one is used for Paste Replace with copyed step
// C2022-017 Added a Cancel button to the message box to allow the user to cancel the paste operation
public static bool CheckSourceDestinationType(int copyStartID, ItemInfo itemInfo)
{
ItemInfo cpyItem = ItemInfo.Get(copyStartID);
// B2023-049: crash when copied step is no longer available (may have been deleted in previous operation)
if (cpyItem == null)
{
DialogResult msgBoxResult = FlexibleMessageBox.Show("The step you are pasting no longer exists - it may have been deleted as part of a previous operation.", "Paste Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
return false;
}
// B2017-065 use MyContent instead of _Mycontent so that if null it will get the needed content
int? SourceType = cpyItem.MyContent.Type;
int? DestType = itemInfo.MyContent.Type;
if (DestType >= 20000 && DestType != SourceType)
{
string msg = "The step you are copying TO is a different type than the step you are copying FROM.\n\nThe copied step will inherit the destination step type.\n\nOnce copied, the step type can be changed from the Tags tab on the Step Properties panel.";
DialogResult msgBoxResult = FlexibleMessageBox.Show(msg, "Different Step Types", MessageBoxButtons.OKCancel, MessageBoxIcon.Information);
if (msgBoxResult == DialogResult.Cancel)
return false;
}
return true;
}
// B2016-009 - added a message box explaining to the user that the copyed step will take on the destination type. 16-bit PROMS had also done this way.
// - this one is used for Insert Copyed step Before or After
// C2022-017 Added a Cancel button to the message box to allow the user to cancel the paste operation
private bool CheckSourceDestinationType(int? DestType, int? SourceType)
{
if (DestType >= 20000 && DestType != SourceType)
{
string msg = "The step you are copying TO is a different type than the step you are copying FROM.\n\nThe copied step will inherit the destination step type.\n\nOnce copied, the step type can be changed from the Tags tab on the Step Properties panel.";
DialogResult msgBoxResult = FlexibleMessageBox.Show(msg, "Different Step Types", MessageBoxButtons.OKCancel, MessageBoxIcon.Information);
if (msgBoxResult == DialogResult.Cancel)
return false;
}
return true;
}
public ItemInfo PasteSiblingBefore(int copyStartID, string chgid)
{
// To determine 'type' of pasted item, if it's a step (type >=20000), use the originating
// item, i.e. item inserting after. If it's a section or procedure, use the copied item's type.
ItemInfo cpItem = ItemInfo.Get(copyStartID);
// B2016-009 check source and desintation types and display message box if needed
// C2022-017 moved the CheckSourceDestinationType call to btnPasteReplace_Click in StepTabRibbon
int? type = MyContent.Type >= 20000 ? MyContent.Type : cpItem.MyContent.Type;
try
{
ItemInfo tmp = CopyPasteItemInfoFetch(copyStartID, this.ItemID, type, type, EAddpingPart.Before);
using (Item item = Get()) ItemInfo.Refresh(item);
tmp.UpdateTransitionText();
tmp.UpdateROText();
tmp.UpdatePastedStepTransitionText();
PasteSetChangeId(tmp, chgid);
PasteClearEnhanced(tmp);
OnNewSiblingBefore(new ItemInfoInsertEventArgs(tmp, EAddpingPart.Before));
return tmp;
}
catch (Exception ex)
{
if (!HandleSqlExceptionOnCopy(ex))
FlexibleMessageBox.Show("Details were written to the Error Log.", "Paste Failed", System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Error);
return this;
}
}
public ItemInfo PasteSiblingAfter(int copyStartID, string chgid)
{
// To determine 'type' of pasted item, if it's a step (type >=20000), use the originating
// item, i.e. item inserting after. If it's a section or procedure, use the copied item's type.
ItemInfo cpItem = ItemInfo.Get(copyStartID);
// B2016-009 check source and desintation types and display message box if needed
// C2022-017 moved the CheckSourceDestinationType call to btnPasteReplace_Click in StepTabRibbon
int? type = MyContent.Type >= 20000 ? MyContent.Type : cpItem.MyContent.Type;
try
{
ItemInfo tmp = CopyPasteItemInfoFetch(copyStartID, this.ItemID, type, type, EAddpingPart.After);
using (Item item = Get()) ItemInfo.Refresh(item);
if (tmp.NextItem != null) using (Item item = tmp.NextItem.Get()) ItemInfo.Refresh(item);
RefreshNextItems();
// if inserting after a caution or note, refreshes tabs. This will adjust bullets
// of any previous cautions or notes.
if (tmp.IsCaution || tmp.IsNote) ResetOrdinal();
tmp.UpdateTransitionText();
tmp.UpdateROText();
tmp.UpdatePastedStepTransitionText();
PasteSetChangeId(tmp, chgid);
PasteClearEnhanced(tmp);
OnNewSiblingAfter(new ItemInfoInsertEventArgs(tmp, EAddpingPart.After));
return tmp;
}
catch (Exception ex)
{
if(!HandleSqlExceptionOnCopy(ex))
FlexibleMessageBox.Show("Details were written to the Error Log.", "Paste Failed", System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Error);
return this;
}
}
private bool HandleSqlExceptionOnCopy(Exception ex)
{
if (ex.Message.Contains("Collection was modified;"))
{
_MyLog.WarnFormat(ex.Message);
return true;
}
if (ex.Message.Contains("This step has been deleted"))
{
FlexibleMessageBox.Show("The step being pasted has been deleted!", "Cannot Paste Deleted Step"
, System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Hand);
return true;
}
if(ex.Message.Contains("This current step has been deleted in another session"))
{
FlexibleMessageBox.Show("The highlighted step has been deleted by another user!", "Cannot Paste Step"
, System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Hand);
return true;
}
return false;
}
private ItemInfo CopyPasteItemInfoFetch(int copyStartID, int itemID, int? type, int? fromType, EAddpingPart addType)
{
ItemInfo tmp=null;
if (addType == EAddpingPart.Child) // has to add in child relationship - uses 'fromtype'
{
// adding children. Type is based on 'fromType'
switch ((E_FromType)fromType)
{
case E_FromType.Procedure:
tmp = DataPortal.Fetch<ProcedureInfo>(new PastingPartCriteria(copyStartID, itemID, addType, type, fromType, DateTime.Now, Volian.Base.Library.VlnSettings.UserID));
break;
case E_FromType.Section:
tmp = DataPortal.Fetch<SectionInfo>(new PastingPartCriteria(copyStartID, itemID, addType, type, fromType, DateTime.Now, Volian.Base.Library.VlnSettings.UserID));
break;
default:
tmp = DataPortal.Fetch<StepInfo>(new PastingPartCriteria(copyStartID, itemID, addType, type, fromType, DateTime.Now, Volian.Base.Library.VlnSettings.UserID));
break;
}
}
else
{
if (GetType() == typeof(ProcedureInfo) || MyContent.Type < 10000)
tmp = DataPortal.Fetch<ProcedureInfo>(new PastingPartCriteria(copyStartID, itemID, addType, type, fromType, DateTime.Now, Volian.Base.Library.VlnSettings.UserID));
else if (GetType() == typeof(SectionInfo) || (MyContent.Type < 20000))
tmp = DataPortal.Fetch<SectionInfo>(new PastingPartCriteria(copyStartID, itemID, addType, type, fromType, DateTime.Now, Volian.Base.Library.VlnSettings.UserID));
else
tmp = DataPortal.Fetch<StepInfo>(new PastingPartCriteria(copyStartID, itemID, addType, type, fromType, DateTime.Now, Volian.Base.Library.VlnSettings.UserID));
}
AddToCache(tmp);
return tmp;
}
#endregion
#region Insert After
public ItemInfo InsertSiblingAfter(string text)
{
return InsertSiblingAfter(text, null);
}
public ItemInfo InsertSiblingAfter(string text, string number)
{
return InsertSiblingAfter(text, number, MyContent.Type);
}
public ItemInfo InsertSiblingAfter(string text, string number, int? type)
{
ItemInfo tmp = null; // KBR need template code in tree view?
if (!IsSection && (FormatStepData.UseSmartTemplate || (MyHLS != null && MyHLS.FormatStepData.UseSmartTemplate) || FormatStepData.UseOldTemplate))
tmp = InsertSmartTemplateSteps(text, number, tmp, EAddpingPart.After, (int)((type == null)? MyContent.Type : type)); // B2018-051 use the type passed in instead of current step type
if (tmp == null)
tmp = NewItemInfoFetch(ItemID, EAddpingPart.After, number, text, type, null, null, null, DateTime.Now, Volian.Base.Library.VlnSettings.UserID);
// if next exists, it is updated in SQL so we have to manually force the iteminfo updates
// Refresh ItemInfo to update PreviousID field
if (tmp.NextItem != null) using (Item item = tmp.NextItem.Get()) ItemInfo.Refresh(item);
RefreshNextItems();
// if inserting after a caution or note, refreshes tabs. This will adjust bullets
// of any previous cautions or notes.
if (tmp.IsCaution || tmp.IsNote) ResetOrdinal();
// Update all of the content records that have transitions that point to the Siblings or Sibling Children of the new item
tmp.UpdateTransitionText();
tmp.UpdateROText();
OnNewSiblingAfter(new ItemInfoInsertEventArgs(tmp, EAddpingPart.After));
return tmp;
}
private ItemInfo NewItemInfoFetch(int itemID, EAddpingPart addType, string number, string text, int? type, int? fromType, int? formatID, string config, DateTime dts, string userID)
{
ItemInfo tmp;
if (addType == EAddpingPart.Child)
{
// adding children. Type is based on 'fromType'
switch ((E_FromType)fromType)
{
case E_FromType.Procedure:
tmp = DataPortal.Fetch<ProcedureInfo>(new AddingPartCriteria(itemID, addType, number, text, type, fromType, formatID, config, dts, userID));
break;
case E_FromType.Section:
tmp = DataPortal.Fetch<SectionInfo>(new AddingPartCriteria(itemID, addType, number, text, type, fromType, formatID, config, dts, userID));
break;
default:
tmp = DataPortal.Fetch<StepInfo>(new AddingPartCriteria(itemID, addType, number, text, type, fromType, formatID, config, dts, userID));
break;
}
}
else
{
if (GetType() == typeof(ProcedureInfo) || MyContent.Type < 10000)
tmp = DataPortal.Fetch<ProcedureInfo>(new AddingPartCriteria(itemID, addType, number, text, type, fromType, formatID, config, dts, userID));
else if (GetType() == typeof(SectionInfo) || (MyContent.Type < 20000))
tmp = DataPortal.Fetch<SectionInfo>(new AddingPartCriteria(itemID, addType, number, text, type, fromType, formatID, config, dts, userID));
else
tmp = DataPortal.Fetch<StepInfo>(new AddingPartCriteria(itemID, addType, number, text, type, fromType, formatID, config, dts, userID));
}
AddToCache(tmp);
return tmp;
}
public void UpdateTransitionText()
{
// Update Ordinals from here down for Steps
//if (!IsStep) return;
ResetOrdinal();
// This returns a list of all of the transitions that may have been affected
using(TransitionInfoList trans = TransitionInfoList.GetAffected(this.ItemID))
{
#region B2012-071 fix JCB
foreach (TransitionInfo tran in trans)
{
using (Transition trn = tran.Get())
TransitionInfo.Refresh(trn);
Content oldContent = null;
using (Content content = tran.MyContent.Get())
{
if (oldContent != null && content.ContentID != oldContent.ContentID)
{
if (oldContent.IsDirty)
{
oldContent.DTS = DateTime.Now;
#region B2012-079 fix JCB
oldContent.UserID = Volian.Base.Library.VlnSettings.UserID + " - Renumber";
#endregion B2012-079 fix JCB
oldContent.Save();
}
else // Update ContentInfo objects to reflect the change in the transition
ContentInfo.Refresh(oldContent);
oldContent = content;
}
if (oldContent == null) oldContent = content;
//check to see if noneditable
bool forceConvertToText = false;
if (tran.MyItemToID.ActiveSection != null)
{
SectionConfig sc = tran.MyItemToID.ActiveSection.MyConfig as SectionConfig;
//SectionConfig sc = new SectionConfig(tran.MyItemToID.ActiveSection.MyConfig.ToString());
forceConvertToText = (sc.SubSection_Edit == "N" && tran.MyItemToID.IsStep); // Bug fix B2016-081 also check if transition is to a step element
}
if (!forceConvertToText) //check to see if external with internal format
{
tran.MyContent.RefreshContentItems(); // B2020-132: Proms crashing when attempting to restore a deleted step
if (tran.MyContent.ContentItems[0].MyProcedure.ItemID != tran.MyItemToID.MyProcedure.ItemID)
if (tran.MyContent.ContentItems[0].ActiveFormat != null)
if (!tran.MyContent.ContentItems[0].ActiveFormat.PlantFormat.FormatData.TransData.TransTypeList[tran.TranType].TransMenu.Contains("Proc"))
if (!tran.MyContent.ContentItems[0].ActiveFormat.PlantFormat.FormatData.TransData.TransTypeList[tran.TranType].TransMenu.Contains("other proc"))
forceConvertToText = true;
}
oldContent.FixTransitionText(tran, forceConvertToText);
//if (content.IsDirty)
//{
// content.DTS = DateTime.Now;
// content.Save();
//}
if (oldContent != null)
{
if (oldContent.IsDirty)
{
oldContent.DTS = DateTime.Now;
#region B2012-079 fix JCB
oldContent.UserID = Volian.Base.Library.VlnSettings.UserID + " - Renumber";
#endregion B2012-079 fix JCB
oldContent.Save();
}
else // Update ContentInfo objects to reflect the change in the transition
ContentInfo.Refresh(oldContent);
}
}
}
#endregion B2012-071 fix JCB
}
}
public void UpdatePastedStepTransitionText()
{
// Get a list of all of the transitions included in this step & its children.
// Their transition text may have been affected, i.e. depending on the format, etc
using (TransitionInfoList trans = TransitionInfoList.GetPastedAffected(this.ItemID))
{
foreach (TransitionInfo tran in trans)
{
using (Content content = tran.MyContent.Get())
{
//check to see if noneditable
bool forceConvertToText = false;
if (tran.MyItemToID.ActiveSection != null)
{
SectionConfig sc = tran.MyItemToID.ActiveSection.MyConfig as SectionConfig;
//SectionConfig sc = new SectionConfig(tran.MyItemToID.ActiveSection.MyConfig.ToString());
forceConvertToText = (sc.SubSection_Edit == "N" && tran.MyItemToID.IsStep); // Bug fix B2016-081 also check if transition is to a step element
}
if (!forceConvertToText) //check to see if external with internal format
{
if (tran.MyContent.ContentItems[0].MyProcedure.ItemID != tran.MyItemToID.MyProcedure.ItemID)
if (!tran.MyContent.ContentItems[0].ActiveFormat.PlantFormat.FormatData.TransData.TransTypeList[tran.TranType].TransMenu.Contains("Proc"))
if (!tran.MyContent.ContentItems[0].ActiveFormat.PlantFormat.FormatData.TransData.TransTypeList[tran.TranType].TransMenu.Contains("other proc")) //B2017-068 paste with transition fix
forceConvertToText = true;
}
if (!forceConvertToText)
{
// bug fix B2016-148 added check if transition had procedure information in which case we do not want to convert it to text
if (tran.MyContent.ContentItems[0].MyDocVersion.VersionID != tran.MyItemToID.MyDocVersion.VersionID &&
!tran.MyContent.ContentItems[0].ActiveFormat.PlantFormat.FormatData.TransData.TransTypeList[tran.TranType].TransMenu.Contains("Proc") &&
!tran.MyContent.ContentItems[0].ActiveFormat.PlantFormat.FormatData.TransData.TransTypeList[tran.TranType].TransMenu.Contains("other proc")) //B2017-068 paste with transition fix
forceConvertToText = true;
}
if (!forceConvertToText)
{
// C2016-023 Convert Transition to Text is the transtion is to a different procedure set
// and the destination proedure number matches a procedure number in the current set
if (tran.MyContent.ContentItems[0].MyDocVersion.VersionID != tran.MyItemToID.MyDocVersion.VersionID &&
(tran.MyContent.ContentItems[0].ActiveFormat.PlantFormat.FormatData.TransData.TransTypeList[tran.TranType].TransMenu.Contains("Proc") ||
tran.MyContent.ContentItems[0].ActiveFormat.PlantFormat.FormatData.TransData.TransTypeList[tran.TranType].TransMenu.Contains("other proc")))
{
// B2022-148: cannot insert outside transition in a background document that references a related EOP <20> transition is converted to text
bool dvsLinked = DocVersionInfo.Linked(tran.MyItemToID.MyDocVersion, tran.MyContent.ContentItems[0].MyDocVersion);
if (!dvsLinked)
{
string destProcNumber = tran.MyItemToID.MyProcedure.DisplayNumber;
foreach (ProcedureInfo prci in tran.MyContent.ContentItems[0].MyDocVersion.Procedures)
{
if (prci.DisplayNumber == destProcNumber)
{
forceConvertToText = true;
break;
}
}
}
}
}
content.FixTransitionText(tran, forceConvertToText);
if (content.IsDirty)
content.Save();
else // Update ContentInfo objects to reflect the change in the transition
ContentInfo.Refresh(content);
}
}
}
}
public static void PasteClearEnhanced(ItemInfo pasteItem)
{
// B2017-045: if a copied step has enhanced link config data and pasted step should not have it, clear it:
// check if the pasted item should have enhanced data. If the copied data has enhanced config data and
// it is pasted into a section without enhanced data, then clear it.
// config data can only be on hls/notes/cautions for pasted steps.
if (!pasteItem.IsHigh && !pasteItem.IsCaution && !pasteItem.IsNote) return;
// See if the pasted step's section is enhanced with enhanced steps, and if not, clear it
// Also, if pasting into a source section, don't clear (B2017-225), the 'isSourceSection' portion of the code.
bool isSourceSection = false;
EnhancedDocuments eds = pasteItem.ActiveSection.GetMyEnhancedDocuments();
if (eds != null)
{
foreach (EnhancedDocument ed in eds)
{
if (ed.Type != 0)
{
isSourceSection = true;
break;
}
}
}
if (!pasteItem.ActiveSection.IsEnhancedSection && !pasteItem.ActiveSection.IsEnhancedSectionTitleOnly && !isSourceSection)
{
// the RemoveEnhancedFromConfig method clears from the pasted step and any cautions/notes that may be off
// of the pasted step.
if (pasteItem.HasEnhancedLinkedStep) pasteItem.RemoveEnhancedFromConfig();
}
}
#endregion
#region Insert Child
public ItemInfo InsertChild(E_FromType fromType, int type, string text)
{
return InsertChild(fromType, type, text, null);
}
public ItemInfo InsertChild(E_FromType fromType, int type, string text, string number)
{
ItemInfo tmp = null;
tmp = InsertSmartTemplateSubStep(text, number, tmp, EAddpingPart.Child, type, fromType);
//tmp = InsertSmartTemplateSubStep(text, number, tmp, EAddpingPart.After, type);
if (tmp == null)
tmp = NewItemInfoFetch(ItemID, EAddpingPart.Child, number, text, type, (int?)fromType, null, null, DateTime.Now, Volian.Base.Library.VlnSettings.UserID);
// if next exists, it is updated in SQL so we have to manually force the iteminfo updates
// Refresh ItemInfo to update PreviousID field
if (tmp.NextItem != null) using (Item item = tmp.NextItem.Get()) ItemInfo.Refresh(item);
// Update all of the content records that have transitions that point to the Siblings or Sibling Children of the new item
tmp.UpdateTransitionText();
tmp.UpdateROText();
MyContent.RefreshContentParts();
ResetParts();
OnNewChild(new ItemInfoInsertEventArgs(tmp, EAddpingPart.Child));
return tmp;
}
#endregion
#region Enhanced Document Support
public ItemInfo DoAddEnhancedSteps(int enhType, int enhItemID, EAddpingPart addpart)
{
// get the item object in the enhanced document so that inserting of the new enhanced item and
// its children can be done:
ItemInfo existingEnhancedItemInfo = ItemInfo.Get(enhItemID);
int type = GetEnhancedTypeForAdd(); // B2018-115: use the correct step type for the add.
ItemInfo newEnhancedItemInfo = existingEnhancedItemInfo.InsertEnhancedSteps(MyContent.Text, null, addpart, type, enhType, ItemID);
if (newEnhancedItemInfo == null) return null;
StepConfig sc = new StepConfig(MyContent.Config);
sc.AddEnhancedDocument(enhType, newEnhancedItemInfo.ItemID);
SaveConfig(sc.ToString());
return newEnhancedItemInfo;
}
// this method handles inserting new procedures & sections for enhanced documents.
// It also handles the case of inserting a step within an EMPTY section. In this case, the template steps
public ItemInfo InsertEnhancedItems(string text, string number, EAddpingPart addType, int? type, int eDocType, int newSourceID)
{
ItemInfo tmp = null;
if (this.IsProcedure && addType == EAddpingPart.Child) // Created a section off a procedure
{
string scng = null;
ProcedureConfig pc = new ProcedureConfig("<Config/>");
pc.AddEnhancedDocument(0, newSourceID);
scng = pc.ToString();
tmp = InsertChild(E_FromType.Section, 10000, "New Section", null);
tmp.SaveConfig(scng);
}
else if (this.IsSection && addType == EAddpingPart.Child) // Created a HLS off a section, note that the template gets added for the HLS
{
string scng = null;
StepConfig sc = new StepConfig("<Config/>");
sc.AddEnhancedDocument(0, newSourceID);
scng = sc.ToString();
tmp = InsertChild(E_FromType.Step, 20002, "New Step", null);
tmp.SaveConfig(scng);
}
else // the following code is used for inserting before/after.
{
string scng = null;
if (IsSection)
{
SectionConfig sc = new SectionConfig();
sc.AddEnhancedDocument(0, newSourceID);
scng = sc.ToString();
}
else
{
ProcedureConfig sc = new ProcedureConfig("<Config/>");
sc.AddEnhancedDocument(0, newSourceID);
scng = sc.ToString();
}
tmp = NewItemInfoFetch(ItemID, addType, number, text, type, null, null, scng, DateTime.Now, Volian.Base.Library.VlnSettings.UserID);
// B2017-083: first child - adjust the docversion itemid to point to this new one:
if (IsProcedure && tmp != null && tmp.MyPrevious == null)
{
if (this.MyDocVersion != null)
{
using (DocVersion parentItemDV = MyDocVersion.Get())
{
using (Item tmpi = tmp.Get())
{
parentItemDV.MyItem = tmpi;
parentItemDV.Save();
}
}
}
}
}
if (tmp == null) return null;
// if next exists, it is updated in SQL so we have to manually force the iteminfo updates
// Refresh ItemInfo to update PreviousID field
if (tmp.NextItem != null) using (Item item = tmp.NextItem.Get()) ItemInfo.Refresh(item);
RefreshNextItems();
if (addType == EAddpingPart.Child)
OnNewChild(new ItemInfoInsertEventArgs(tmp, EAddpingPart.Child));
else if (addType == EAddpingPart.After)
OnNewSiblingAfter(new ItemInfoInsertEventArgs(tmp, EAddpingPart.After));
else if (addType == EAddpingPart.Before)
OnNewSiblingBefore(new ItemInfoInsertEventArgs(tmp, EAddpingPart.Before));
return tmp;
}
public ItemInfo InsertEnhancedSteps(string text, string number, EAddpingPart addType, int? type, int eDocType, int newSourceID)
{
ItemInfo tmp = null;
if (addType == EAddpingPart.Child)
{
E_FromType fromType = E_FromType.Caution;
if (this.IsSection) fromType = E_FromType.Step;
else if (ActiveFormat.PlantFormat.FormatData.StepDataList[(int)type - 20000].Type.ToUpper() == "NOTE") fromType = E_FromType.Note;
tmp = InsertEnhancedSmartTemplateSubStep(text, number, this, addType, (int)type, fromType, newSourceID);
}
else
{
tmp = InsertEnhancedSmartTemplateSteps(text, number, this, addType, (int)type, newSourceID);
}
if (tmp == null) return null;
// if next exists, it is updated in SQL so we have to manually force the iteminfo updates
// Refresh ItemInfo to update PreviousID field
if (tmp.NextItem != null) using (Item item = tmp.NextItem.Get()) ItemInfo.Refresh(item);
RefreshNextItems();
// if inserting after a caution or note, refreshes tabs. This will adjust bullets
// of any previous cautions or notes.
if (tmp.IsCaution || tmp.IsNote) ResetOrdinal();
tmp.UpdateTransitionText(); // even though enhanced does not have transitions, this is needed to refresh tabs
// Note that non-enhanced update transition and ro text at this point. But since
// transitions and ro's are converted to text, this is not needed.
if (addType == EAddpingPart.Child)
OnNewChild(new ItemInfoInsertEventArgs(tmp, EAddpingPart.Child));
else if (addType == EAddpingPart.After)
{
OnNewSiblingAfter(new ItemInfoInsertEventArgs(tmp, EAddpingPart.After));
}
else if (addType == EAddpingPart.Before)
OnNewSiblingBefore(new ItemInfoInsertEventArgs(tmp, EAddpingPart.Before));
return tmp;
}
private ItemInfo InsertEnhancedSmartTemplateSubStep(string text, string number, ItemInfo tmp, EAddpingPart addType, int type, E_FromType fromTypeTop, int newSourceID)
{
int newItemID = 0;
int topType = GetSmartTemplateTopLevelIndxOfThisType(type);
if (topType == -1) return null;
int tpIndx = GetSmartTemplateIndex(topType, type);
if (tpIndx != -1)
{
ItemInfo siblingSmart = null;
ItemInfo firstSmart = null;
int level = ActiveFormat.PlantFormat.FormatData.Templates[tpIndx].level;
string tmptext = ActiveFormat.PlantFormat.FormatData.NewTemplateFormat ? text : ActiveFormat.PlantFormat.FormatData.Templates[tpIndx].text;
int prevlevel = level;
while (level > 0)
{
if (firstSmart == null)
{
StepConfig sc = new StepConfig("");
sc.AddEnhancedDocument(0, newSourceID);
firstSmart = NewItemInfoFetch(ItemID, addType, number, tmptext, type, (int?)fromTypeTop, null, sc.ToString(), DateTime.Now, Volian.Base.Library.VlnSettings.UserID);
siblingSmart = firstSmart;
newItemID = firstSmart.ItemID;
}
else
{
E_FromType fromType = E_FromType.Step;
EAddpingPart addPart = EAddpingPart.Child; // level > previous, add a child.
if (level == prevlevel) addPart = EAddpingPart.After;
if (level < prevlevel)
{
if (ActiveFormat.PlantFormat.FormatData.Templates[tpIndx].type == 39)
{
fromType = E_FromType.RNO;
addPart = EAddpingPart.Child;
}
else
{
addPart = EAddpingPart.After;
}
newItemID = siblingSmart.ItemID;
}
tmptext = /*ActiveFormat.PlantFormat.FormatData.NewTemplateFormat ? " ": */ActiveFormat.PlantFormat.FormatData.Templates[tpIndx].text;
tmp = NewItemInfoFetch(newItemID, addPart, null, tmptext, ActiveFormat.PlantFormat.FormatData.Templates[tpIndx].type + 20001, (int?)fromType, null, null, DateTime.Now, Volian.Base.Library.VlnSettings.UserID);
newItemID = tmp.ItemID;
if (level < prevlevel) siblingSmart = tmp;
}
tpIndx++;
prevlevel = level;
level = tpIndx < ActiveFormat.PlantFormat.FormatData.Templates.Count ?
ActiveFormat.PlantFormat.FormatData.Templates[tpIndx].level : -1;
}
tmp = firstSmart;
}
return tmp;
}
private ItemInfo InsertEnhancedSmartTemplateSteps(string text, string number, ItemInfo tmp, EAddpingPart eAddpingPart, int type, int newSourceID)
{
int newItemID = 0;
int topType = GetSmartTemplateTopLevelIndx();
if (topType == -1) return null;
int tpIndx = GetSmartTemplateIndex(topType, (int)MyContent.Type);
if (tpIndx != -1)
{
ItemInfo siblingSmart = null; // keep track of sibling
ItemInfo firstSmart = null; // hls or top template step
ItemInfo parentSmart = null; // keep track of parent as creating children
int level = ActiveFormat.PlantFormat.FormatData.Templates[tpIndx].level;
string tmptext = text;
int prevlevel = level;
while (level > 0)
{
if (firstSmart == null)
{
// set stepconfig for this new enhanced item:
StepConfig sc = new StepConfig("");
sc.AddEnhancedDocument(0, newSourceID);
firstSmart = NewItemInfoFetch(ItemID, eAddpingPart, number, tmptext, type, null, null, sc.ToString(), DateTime.Now, Volian.Base.Library.VlnSettings.UserID);
siblingSmart = parentSmart = firstSmart;
newItemID = firstSmart.ItemID;
}
else
{
E_FromType fromType = E_FromType.Step;
EAddpingPart addPart = EAddpingPart.Child; // level > previous, add a child.
if (level == prevlevel) addPart = EAddpingPart.After; // level = previous, add a sibling
if (level < prevlevel) // level < previous, go up to previous level's id
{
if (ActiveFormat.PlantFormat.FormatData.Templates[tpIndx].type == 39)
{
fromType = E_FromType.RNO;
addPart = EAddpingPart.Child;
newItemID = firstSmart.ItemID;
}
else
{
addPart = EAddpingPart.After;
newItemID = parentSmart.ItemID;
}
}
tmptext = ActiveFormat.PlantFormat.FormatData.Templates[tpIndx].text;
tmp = NewItemInfoFetch(newItemID, addPart, null, tmptext, ActiveFormat.PlantFormat.FormatData.Templates[tpIndx].type + 20001, (int?)fromType, null, null, DateTime.Now, Volian.Base.Library.VlnSettings.UserID);
newItemID = tmp.ItemID;
if (level < prevlevel) siblingSmart = parentSmart;
else if (level > prevlevel) parentSmart = siblingSmart;
if (level == prevlevel) siblingSmart = tmp;
}
tpIndx++;
prevlevel = level;
level = tpIndx < ActiveFormat.PlantFormat.FormatData.Templates.Count ?
ActiveFormat.PlantFormat.FormatData.Templates[tpIndx].level : -1;
}
tmp = firstSmart;
}
return tmp;
}
public ItemInfo EnhancedPasteItem(int copyStartID, ItemInfo pasteFromItem, EAddpingPart addType, string chgid)
{
EnhancedDocuments pasteFromItemsEnhancedDocuments = pasteFromItem.GetMyEnhancedDocuments();
if (pasteFromItemsEnhancedDocuments == null || pasteFromItemsEnhancedDocuments.Count == 0) return null;
ItemInfo newItemInfo = this;
ItemInfo newEnhancedItemInfo = null;
// need to save the original item ids in the copied item so that they can be
// changed to the new enhanced ids in 'config'. The oldid/newid pairs will
// be stored in a dictionary & the update will be made after the loop.
Dictionary<int, int> oldToNewEnhancedIds = new Dictionary<int, int>();
// tmpCopyStartSourceItem is the item that was copied in source.
ItemInfo tmpCopyStartSourceItem = ItemInfo.Get(copyStartID);
if (tmpCopyStartSourceItem.IsStep)
{
// if the copied step is not a 'source', then this really needs to be more of an insert for the enhanced steps.
StepConfig stepFromCfg = tmpCopyStartSourceItem.MyConfig as StepConfig;
if (stepFromCfg.MyEnhancedDocuments == null || stepFromCfg.MyEnhancedDocuments.Count == 0)
{
// Insert the enhanced steps. Loop through all enhanced document types, insert from
// the paste item's linked step.
ItemInfo newEnh = null;
foreach (EnhancedDocument edSource in pasteFromItem.GetMyEnhancedDocuments())
{
// create a new enhanced step and link it to this new source step.
// the new source step's item is used to know what type & what to link to.
// The ed.Type & ed.itemid show what type of enhanced document (use to create new
// config Type).
ItemInfo exEnh = ItemInfo.Get(edSource.ItemID);
newEnh = exEnh.InsertEnhancedSteps(tmpCopyStartSourceItem.MyContent.Text, null, addType, MyContent.Type, edSource.Type, this.ItemID);
if (newEnh == null) return null;
StepConfig sc = new StepConfig(MyContent.Config);
sc.AddEnhancedDocument(edSource.Type, newEnh.ItemID);
SaveConfig(sc.ToString());
}
return newEnh;
}
}
// loop through all enhanced document types, pasting in the copied item(s).
// Note that the copy/paste finds the enhanced items that relate to source,
// i.e. copied item & paste from, and uses those to do the copy/paste.
// sc is the config (passed in) for the item that we are pasting around.
foreach (EnhancedDocument edSource in pasteFromItem.GetMyEnhancedDocuments())
{
if (edSource.Type != 0)
{
ItemInfo tmpPasteItemFrom = ItemInfo.Get(edSource.ItemID); // here is problem
// get the 'enhanced' item to copy. To do this, get the enhanced link
// from source's config that matches this 'type'. Use that Id to get the enhanced
// Item that is to be copied:
int tmpCopyEnhancedID = 0;
foreach (EnhancedDocument edCopy in tmpCopyStartSourceItem.GetMyEnhancedDocuments())
{
if (edSource.Type == edCopy.Type)
{
tmpCopyEnhancedID = edCopy.ItemID;
break;
}
}
if (tmpCopyEnhancedID == 0) break; // no connected copied item.
if (addType == EAddpingPart.Before)
newEnhancedItemInfo = tmpPasteItemFrom.PasteSiblingBefore(tmpCopyEnhancedID, chgid);
else if (addType == EAddpingPart.After)
newEnhancedItemInfo = tmpPasteItemFrom.PasteSiblingAfter(tmpCopyEnhancedID, chgid);
else if (addType == EAddpingPart.Child)
newEnhancedItemInfo = tmpPasteItemFrom.PasteChild(tmpCopyEnhancedID, chgid);
else if (addType == EAddpingPart.Replace) // what about user interface for enhanced pasted steps?
{
ItemInfo enhReplaceItem = ItemInfo.Get(edSource.ItemID);
newEnhancedItemInfo = Item.PasteReplace(enhReplaceItem, tmpCopyEnhancedID, chgid);
}
// update the config data for the new enhanced item (procedure, section or step) to point back to the correct source
string cfgEnhStr = null;
if (newEnhancedItemInfo.IsStep)
{
StepConfig scnewenh = newEnhancedItemInfo.MyConfig as StepConfig;
if (scnewenh == null) break; //error here, i.e. should have a related enhanced step
scnewenh.MyEnhancedDocuments[0].ItemID = newItemInfo.ItemID;
scnewenh.SaveEnhancedDocuments();
cfgEnhStr = scnewenh.ToString();
}
else if (newEnhancedItemInfo.IsSection)
{
SectionConfig secnewenh = newEnhancedItemInfo.MyConfig as SectionConfig;
if (secnewenh == null) break; //error here, i.e. should have a related enhanced step
secnewenh.MyEnhancedDocuments[0].ItemID = newItemInfo.ItemID;
secnewenh.SaveEnhancedDocuments();
cfgEnhStr = secnewenh.ToString();
}
else if (newEnhancedItemInfo.IsProcedure)
{
ProcedureConfig pnewenh = newEnhancedItemInfo.MyConfig as ProcedureConfig;
if (pnewenh == null) break; //error here, i.e. should have a related enhanced step
pnewenh.MyEnhancedDocuments[0].ItemID = newItemInfo.ItemID;
pnewenh.SaveEnhancedDocuments();
cfgEnhStr = pnewenh.ToString();
}
if (cfgEnhStr != null) newEnhancedItemInfo.SaveConfig(cfgEnhStr);
// save the new enhanced step ids to set in the new source's config (to relate steps)
foreach (EnhancedDocument edNew in newItemInfo.GetMyEnhancedDocuments())
{
if (edNew.ItemID == tmpCopyEnhancedID) oldToNewEnhancedIds.Add(edNew.ItemID, newEnhancedItemInfo.ItemID);
}
}
}
// update the config to point to new enhanced document steps for the new source item
if (oldToNewEnhancedIds.Count > 0)
{
// save the updated config info on the newly pasted source: step, section or procedure:
string cfgNewSrc = null;
if (newItemInfo.IsStep)
{
StepConfig scnewpst1 = newItemInfo.MyConfig as StepConfig;
foreach (EnhancedDocument edOrig in scnewpst1.MyEnhancedDocuments)
edOrig.ItemID = oldToNewEnhancedIds[edOrig.ItemID];
scnewpst1.SaveEnhancedDocuments();
cfgNewSrc = scnewpst1.ToString();
}
else if (newItemInfo.IsSection)
{
SectionConfig secnewpst1 = newItemInfo.MyConfig as SectionConfig;
foreach (EnhancedDocument edOrig in secnewpst1.MyEnhancedDocuments)
edOrig.ItemID = oldToNewEnhancedIds[edOrig.ItemID];
secnewpst1.SaveEnhancedDocuments();
cfgNewSrc = secnewpst1.ToString();
}
else if (newItemInfo.IsProcedure)
{
ProcedureConfig pnewpst1 = newItemInfo.MyConfig as ProcedureConfig;
foreach (EnhancedDocument edOrig in pnewpst1.MyEnhancedDocuments)
edOrig.ItemID = oldToNewEnhancedIds[edOrig.ItemID];
pnewpst1.SaveEnhancedDocuments();
cfgNewSrc = pnewpst1.ToString();
}
if (cfgNewSrc != null) newItemInfo.SaveConfig(cfgNewSrc);
}
// if this is a HLS, then need to adjust links between any associated notes/cautions too:
if (newItemInfo.IsStep)
{
StepConfig scForNC = newItemInfo.MyConfig as StepConfig;
foreach (EnhancedDocument ed in scForNC.MyEnhancedDocuments) EnhancedSetNoteCautionLinks(newItemInfo, ed.Type);
}
return newEnhancedItemInfo;
}
#region HandleEnhancedNoteCautionConfigLinks
private static void EnhancedSetNoteCautionLinks(ItemInfo newItemInfo, int enhType)
{
// For this enhanced document type, adjust all of the ids to link between source & enhanced if there are
// notes & cautions. Notes first. There may be some source notes that aren't linked and some enhanced
// that are not linked, so account for this.
// get the high level enhanced step, this will be used for both note & caution code:
ItemInfo enhHls = null;
foreach (EnhancedDocument enh in newItemInfo.GetMyEnhancedDocuments())
{
if (enh.Type == enhType)
{
enhHls = ItemInfo.Get(enh.ItemID);
break;
}
}
if (newItemInfo.IsHigh && enhHls != null && newItemInfo.Notes != null && newItemInfo.Notes.Count > 0)
{
int srcIndxNt = 0;
int enhIndxNt = 0;
// for each note association between the source & enhanced document, update
// the config items to link them.
ItemInfo srcNtItem = newItemInfo.Notes[srcIndxNt];
while (srcNtItem != null)
{
StepConfig scSourceNote = newItemInfo.Notes[srcIndxNt].MyConfig as StepConfig;
if (scSourceNote.MyEnhancedDocuments.Count > 0)
{
// Loop through for each enhanced document related to the pasted source HLS
foreach (EnhancedDocument enh in srcNtItem.GetMyEnhancedDocuments())
{
if (enh.Type == enhType)
{
// Find hls in enhanced in order to get its notes to set their config to
// point back to the new source's note itemid. There may be enhanced items that
// don't connect back, so find one that does based on Enhance HLS note list &
// the notes' links back to source.
ItemInfo enhNtItem = null;
while (enhNtItem == null && enhHls.Notes != null && enhIndxNt < enhHls.Notes.Count) // B2017-065 added a null check for Notes
{
ItemInfo enhTstNote = enhHls.Notes[enhIndxNt];
StepConfig enhTstNoteCfg = enhTstNote.MyConfig as StepConfig;
if (enhTstNoteCfg.MyEnhancedDocuments.Count > 0)
{
foreach (EnhancedDocument enhNt in enhTstNote.GetMyEnhancedDocuments())
{
if (enhNt.Type == 0) // found it:
{
enhNtItem = enhTstNote;
break;
}
}
}
if (enhNtItem == null) enhIndxNt++;
}
if (enhNtItem != null)
{
StepConfig scNewEnhancedNote = enhNtItem.MyConfig as StepConfig;
scNewEnhancedNote.MyEnhancedDocuments[0].ItemID = newItemInfo.Notes[srcIndxNt].ItemID;
scNewEnhancedNote.SaveEnhancedDocuments();
enhNtItem.SaveConfig(scNewEnhancedNote.ToString());
foreach (EnhancedDocument noteEnh in scSourceNote.MyEnhancedDocuments)
{
if (noteEnh.Type == enhType)
{
noteEnh.ItemID = enhHls.Notes[enhIndxNt].ItemID;
scSourceNote.SaveEnhancedDocuments();
newItemInfo.Notes[srcIndxNt].SaveConfig(scSourceNote.ToString());
break;
}
}
enhIndxNt++;
}
}
}
}
srcIndxNt++;
srcNtItem = srcIndxNt>=newItemInfo.Notes.Count?null:newItemInfo.Notes[srcIndxNt];
}
}
// now do any cautions.
if (newItemInfo.IsHigh && newItemInfo.Cautions != null && newItemInfo.Cautions.Count > 0)
{
int srcIndxCt = 0;
int enhIndxCt = 0;
// for each caution association between the source & enhanced document, update
// the config items to link them.
ItemInfo srcCtItem = newItemInfo.Cautions[srcIndxCt];
while (srcCtItem != null)
{
StepConfig scSourceCaution = newItemInfo.Cautions[srcIndxCt].MyConfig as StepConfig;
if (scSourceCaution.MyEnhancedDocuments.Count > 0)
{
// Loop through for each enhanced document related to the pasted source HLS
foreach (EnhancedDocument enh in srcCtItem.GetMyEnhancedDocuments())
{
if (enh.Type == enhType)
{
// Find hls in enhanced in order to get its notes to set their config to
// point back to the new source's note itemid.
ItemInfo enhCtItem = null;
// B2022-049: Copy/paste of enhanced procedure and bad links between source and enhanced. Null reference check
if (enhHls.Cautions != null)
{
while (enhCtItem == null && enhIndxCt < enhHls.Cautions.Count)
{
ItemInfo enhTstCaut = enhHls.Cautions[enhIndxCt];
StepConfig enhTstCautCfg = enhTstCaut.MyConfig as StepConfig;
if (enhTstCautCfg.MyEnhancedDocuments.Count > 0)
{
foreach (EnhancedDocument enhCt in enhTstCaut.GetMyEnhancedDocuments())
{
if (enhCt.Type == 0)
{
enhCtItem = enhTstCaut;
break;
}
}
}
if (enhCtItem == null) enhIndxCt++;
}
}
if (enhCtItem != null)
{
StepConfig scNewEnhancedCaution = enhCtItem.MyConfig as StepConfig;
scNewEnhancedCaution.MyEnhancedDocuments[0].ItemID = newItemInfo.Cautions[srcIndxCt].ItemID;
scNewEnhancedCaution.SaveEnhancedDocuments();
enhCtItem.SaveConfig(scNewEnhancedCaution.ToString());
foreach (EnhancedDocument cautionEnh in scSourceCaution.MyEnhancedDocuments)
{
if (cautionEnh.Type == enh.Type)
{
cautionEnh.ItemID = enhHls.Cautions[enhIndxCt].ItemID;
scSourceCaution.SaveEnhancedDocuments();
newItemInfo.Cautions[srcIndxCt].SaveConfig(scSourceCaution.ToString());
break;
}
}
enhIndxCt++;
}
}
}
}
srcIndxCt++;
srcCtItem = srcIndxCt >= newItemInfo.Cautions.Count ? null : newItemInfo.Cautions[srcIndxCt];
}
}
}
#endregion
#region HandleEnhancedStepConfigLinks
private void EnhancedSetStepLinks(ItemInfo newSourceSectionInfo, int enhType)
{
//for the input source section, link all HLS to enhanced HLS (and any associated cautions/notes). Note that
// this assumes that all source steps are linked, but there may be 'deleted' steps in enhanced that may not be linked back.
ItemInfo newEnhSectionInfo = null;
ItemInfo enhStep = null; // in enhanced document, find first step that has links (there may be enhanced steps that don't have links)
SectionConfig newSectCfg = newSourceSectionInfo.MyConfig as SectionConfig;
foreach (EnhancedDocument ed in newSectCfg.MyEnhancedDocuments)
{
if (ed.Type == enhType)
{
newEnhSectionInfo = ItemInfo.Get(ed.ItemID);
// B2020-009 if section does not have steps (empty step section) then skip it.
if (newEnhSectionInfo.Steps != null)
{
StepConfig cfg = newEnhSectionInfo.Steps[0].MyConfig as StepConfig;
if (cfg.MyEnhancedDocuments.Count > 0) enhStep = newEnhSectionInfo.Steps[0];
else enhStep = GetNextEnhancedStep(newEnhSectionInfo.Steps[0]);
}
break;
}
}
if (enhStep == null) return;
// now adjust all of the ids to link between source & enhanced for this section's steps.
// The enhType represents which enhanced document we are working with, for example, backgrounds or deviations.
for (int iStp = 0; iStp < newSourceSectionInfo.Steps.Count; iStp++)
{
StepConfig scSourceStep = newSourceSectionInfo.Steps[iStp].MyConfig as StepConfig;
if (scSourceStep.MyEnhancedDocuments.Count > 0)
{
// Loop through for each enhanced document related to the pasted source HLS
foreach (EnhancedDocument enh in scSourceStep.MyEnhancedDocuments)
{
if (enh.Type == enhType)
{
// Find hls in enhanced in order to set the config to point back to the new source's itemid.
ItemInfo enhHls = enhStep;
StepConfig scNewEnhancedStep = enhHls.MyConfig as StepConfig;
scNewEnhancedStep.MyEnhancedDocuments[0].ItemID = newSourceSectionInfo.Steps[iStp].ItemID;
scNewEnhancedStep.SaveEnhancedDocuments();
enhHls.SaveConfig(scNewEnhancedStep.ToString());
// set the source to go to this enh.
enh.ItemID = enhHls.ItemID;
scSourceStep.SaveEnhancedDocuments();
newSourceSectionInfo.Steps[iStp].SaveConfig(scSourceStep.ToString());
EnhancedSetNoteCautionLinks(newSourceSectionInfo.Steps[iStp], enhType);
}
}
enhStep = GetNextEnhancedStep(enhStep); // B2017-271: this needs to be within the condition where the enhanced step is linked.
}
}
}
private ItemInfo GetNextEnhancedStep(ItemInfo itemInfo)
{
if (itemInfo==null) return null;
ItemInfo curStep = itemInfo.NextItem;
while (curStep != null)
{
StepConfig cfg = curStep.MyConfig as StepConfig;
if (cfg.MyEnhancedDocuments.Count > 0) return curStep;
curStep = curStep.NextItem;
}
return null;
}
private ItemInfo GetNextEnhancedSection(ItemInfo itemInfo)
{
if (itemInfo == null) return null;
ItemInfo curSect = itemInfo.NextItem;
while (curSect != null)
{
SectionConfig cfg = curSect.MyConfig as SectionConfig;
if (cfg.MyEnhancedDocuments.Count > 0) return curSect;
curSect = curSect.NextItem;
}
return null;
}
#endregion
public ItemInfo PasteEnhancedItems(int copyStartID, ItemInfo pasteFromItem, EAddpingPart addType, string chgid)
{
ItemInfo retItem = null;
if (IsProcedure) // newly Pasted Item is a procedure.
{
// the following pastes each type of enhanced procedure, including its sections/steps
EnhancedPasteItem(copyStartID, pasteFromItem, addType, chgid);
// for each enhanced type for this procedure, adjust the config data for its sections/steps:
ProcedureConfig sourceProcConfig = this.MyConfig as ProcedureConfig;
foreach (EnhancedDocument enhProc in sourceProcConfig.MyEnhancedDocuments)
{
if (enhProc.Type != 0)
{
ItemInfo pastedEnhancedProc = ItemInfo.Get(enhProc.ItemID);
// get the first enhanced section, there may be non-linked sections before first linked section:
SectionConfig firstEnhSectionConfig = pastedEnhancedProc.Sections == null ? null : pastedEnhancedProc.Sections[0].MyConfig as SectionConfig;
ItemInfo pastedEnhancedCurrentSection = null;
if (firstEnhSectionConfig.MyEnhancedDocuments.Count > 0) pastedEnhancedCurrentSection = pastedEnhancedProc.Sections[0];
else pastedEnhancedCurrentSection = GetNextEnhancedSection(pastedEnhancedProc.Sections[0]);
// newly pasted procedure has sections/steps, need to adjust 'MyEnhancedDocuments' config items to point to correct
if (Sections != null)
{
foreach (ItemInfo sourceSect in Sections)
{
SectionConfig srcCfg = sourceSect.MyConfig as SectionConfig;
if (srcCfg != null && (srcCfg.Section_LnkEnh=="Y" || srcCfg.Section_LnkEnh=="T") && srcCfg.MyEnhancedDocuments != null && srcCfg.MyEnhancedDocuments.Count > 0)
{
// use pastedEnhancedCurrentSection to link to:
foreach (EnhancedDocument ed in srcCfg.MyEnhancedDocuments)
{
if (ed.Type == enhProc.Type)
{
ed.ItemID = pastedEnhancedCurrentSection.ItemID;
srcCfg.SaveEnhancedDocuments();
sourceSect.SaveConfig(srcCfg.ToString());
break;
}
}
SectionConfig enhSectCfg = pastedEnhancedCurrentSection.MyConfig as SectionConfig;
enhSectCfg.MyEnhancedDocuments[0].ItemID = sourceSect.ItemID;
enhSectCfg.SaveEnhancedDocuments();
pastedEnhancedCurrentSection.SaveConfig(enhSectCfg.ToString());
if (srcCfg.Section_LnkEnh == "Y") EnhancedSetStepLinks(sourceSect, enhProc.Type); //if steps, do them for this type
pastedEnhancedCurrentSection = GetNextEnhancedSection(pastedEnhancedCurrentSection);
}
}
}
}
}
retItem = null;
}
else if (IsSection)
{
ItemInfo pastedSect = EnhancedPasteItem(copyStartID, pasteFromItem, addType, chgid);
SectionConfig sourceSectConfig = this.MyConfig as SectionConfig;
foreach (EnhancedDocument enhSect in sourceSectConfig.MyEnhancedDocuments)
if (enhSect.Type != 0) EnhancedSetStepLinks(this, enhSect.Type);
retItem = pastedSect;
}
else if (pasteFromItem.IsStep || (pasteFromItem.IsSection && addType == EAddpingPart.Child))
{
ItemInfo pastedStep = EnhancedPasteItem(copyStartID, pasteFromItem, addType, chgid);
retItem = pastedStep;
}
return retItem;
}
private void SaveConfig(string cfg)
{
using (Content c1 = Content.Get(ContentID))
{
c1.Config = cfg;
c1.Save();
}
RefreshConfig();
}
public ItemInfo DoAddMissingEnhancedItems(int enhtype)
{
// from this item, need to find an insertion point in the enhanced procedure/section. Look for an item that has enhanced
// links in its config: first go through previous items, then if none found in previous go through next, if none found
// go to parent
ItemInfo newEnh = null;
// look through pervious first:
ItemInfo iiCur = this.MyPrevious;
EAddpingPart addtype = EAddpingPart.After;
// C2019-045: For enhanced procedures, allow modifications of number & text. When a procedure is inserted, if allowing updates, the number/text doesn't
// get set to the existing source because this was done automatically in the contentinfo code that sets the enhanced text to the source and this code
// isn't run if modifications are allowed. Thus, use the number/text here for this case. If the changes in this method aren't made the number is emtpy
// and the procedure text (title) is 'New Procedure'
string pnum = null;
string ptext = null;
if (IsProcedure)
{
pnum = MyContent.Number;
ptext = MyContent.Text;
}
while (iiCur != null && newEnh == null)
{
foreach (EnhancedDocument edSource in iiCur.GetMyEnhancedDocuments())
{
if (edSource.Type == enhtype) // found one to use:
{
ItemInfo exEnh = ItemInfo.Get(edSource.ItemID);
int enhType = (int)MyContent.Type;
// B2017-272 did not need the if-check to set the enhanced type (commented it out)
//if (iiCur.MyContent.Type == MyContent.Type) // B2017-134 the enhanced section was being created with the wrong document type creating new enhanced section from EOP (bryon data)
enhType = (int)exEnh.MyContent.Type;
if (exEnh.IsStep)
{
// B2018-115: use the correct step type for the add.
// if coming from a HLS, note or caution, the enhanced type should be the base hls/note/caution type (from GetEnhancedTypeForAdd)
enhType = GetEnhancedTypeForAdd();
newEnh = exEnh.InsertEnhancedSteps(MyContent.Text, null, addtype, enhType, edSource.Type, this.ItemID);
}
else
{
if (!IsProcedure || !exEnh.MyDocVersion.DocVersionConfig.Enhanced_AllowMods)
newEnh = exEnh.InsertEnhancedItems(MyContent.Text, MyContent.Number, addtype, enhType, edSource.Type, this.ItemID);
else
newEnh = exEnh.InsertEnhancedItems(ptext, pnum, addtype, enhType, edSource.Type, this.ItemID);
}
}
}
iiCur = iiCur.MyPrevious;
}
// no previous have enhanced links. now go through next:
ItemInfo iiNxt = this.NextItem;
addtype = EAddpingPart.Before;
while (iiNxt != null && newEnh == null)
{
foreach (EnhancedDocument edSource in iiNxt.GetMyEnhancedDocuments())
{
if (edSource.Type == enhtype) // found one to use:
{
ItemInfo exEnh = ItemInfo.Get(edSource.ItemID);
int enhType = (int)MyContent.Type;
// B2017-272 did not need the if-check to set the enhanced type (commented it out)
//if (iiNxt != null && iiNxt.MyContent.Type == MyContent.Type) // B2017-134 the enhanced section was being created with the wrong document type creating new enhanced section from EOP (byron data) (B2017-174: added null check)
enhType = (int)exEnh.MyContent.Type;
if (exEnh.IsStep)
{
// B2018-115: use the correct step type for the add.
// if coming from a HLS, note or caution, the enhanced type should be the base hls/note/caution type (from GetEnhancedTypeForAdd)
enhType = GetEnhancedTypeForAdd();
newEnh = exEnh.InsertEnhancedSteps(MyContent.Text, null, addtype, enhType, edSource.Type, this.ItemID);
}
else
{
if (!IsProcedure || !exEnh.MyDocVersion.DocVersionConfig.Enhanced_AllowMods)
newEnh = exEnh.InsertEnhancedItems(MyContent.Text, MyContent.Number, addtype, enhType, edSource.Type, this.ItemID);
else
newEnh = exEnh.InsertEnhancedItems(ptext, pnum, addtype, enhType, edSource.Type, this.ItemID);
}
}
}
iiNxt = iiNxt.GetNextItem();
}
// no next either, try the parent.
if (this.IsProcedure && newEnh == null) // procedure is a special case since it has to be added from the doc version:
{
// need to make a new procedure off working draft of enhanced set:
DocVersionConfig dvc = this.MyDocVersion.MyConfig as DocVersionConfig;
ProcedureInfo pi = ProcedureInfo.Get(this.ItemID);
ProcedureConfig sourcecfg = pi.ProcedureConfig;
if (dvc != null)
{
foreach (DVEnhancedDocument ded in dvc.MyEnhancedDocuments)
{
if (ded.Type == enhtype)
{
// get the enhaced docversioninfo:
DocVersionInfo enhDVInfo = DocVersionInfo.Get(ded.VersionID);
string epnum = MyContent.Number;
string eptext = "New Procedure";
if (enhDVInfo.DocVersionConfig.Enhanced_AllowMods)
eptext = MyContent.Text;
using (Procedure newenhProcedure = Procedure.MakeProcedure(enhDVInfo, enhDVInfo.Procedures.Count != 0 ? enhDVInfo.Procedures[enhDVInfo.Procedures.Count - 1] :null, MyContent.Number, eptext, 0))
{
newEnh = ItemInfo.Get(newenhProcedure.ItemID);
string scng = null;
ProcedureConfig sc = new ProcedureConfig("<Config/>");
sc.AddEnhancedDocument(0, pi.ItemID);
scng = sc.ToString();
newEnh.SaveConfig(scng);
enhDVInfo.ResetProcedures();
break;
}
}
}
}
}
else
{
ItemInfo iiPar = this.MyParent;
addtype = EAddpingPart.Child;
while (iiPar != null && newEnh == null)
{
foreach (EnhancedDocument edSource in iiPar.GetMyEnhancedDocuments())
{
if (edSource.Type == enhtype) // found one to use:
{
ItemInfo exEnh = ItemInfo.Get(edSource.ItemID);
if (exEnh.IsStep)
{
// B2018-115: use the correct step type for the add.
// if coming from a HLS, note or caution, the enhanced type should be the base hls/note/caution type (from GetEnhancedTypeForAdd)
int enhType = GetEnhancedTypeForAdd();
newEnh = exEnh.InsertEnhancedSteps(MyContent.Text, null, addtype, enhType, edSource.Type, this.ItemID);
}
else
newEnh = exEnh.InsertEnhancedItems(MyContent.Text, MyContent.Number, addtype, MyContent.Type, edSource.Type, this.ItemID);
break;
}
}
iiPar = iiPar.MyParent;
}
}
// Now set the config in the source to link to the newly created enhanced item:
if (newEnh != null)
{
if (IsStep)
{
StepConfig sc = new StepConfig(MyContent.Config);
sc.AddEnhancedDocument(enhtype, newEnh.ItemID);
SaveConfig(sc.ToString());
}
else if (IsSection)
{
SectionConfig sc = new SectionConfig(SectionInfo.Get(this.ItemID));
sc.AddEnhancedDocument(enhtype, newEnh.ItemID);
sc.Section_LnkEnh = "Y";
SaveConfig(sc.ToString());
}
else if (IsProcedure)
{
ProcedureConfig sc = new ProcedureConfig(MyContent.Config);
sc.AddEnhancedDocument(enhtype, newEnh.ItemID);
SaveConfig(sc.ToString());
}
}
return newEnh;
}
private int GetEnhancedTypeForAdd()
{
// B2018-115: use the correct step type for the add.
// When creating steps in the enhanced, use the type from the source & then get the 'base' (non-herited) type for HLS/Caution/Note
int enhType = 20002;
if (IsNote) enhType = 20007;
if (IsCaution) enhType = 20006;
return enhType;
}
public void DoCreateLinksEnhancedSingleItem(ItemInfo enhii, int enhtype)
{
// Link the 2 items, srcII & enhii:
if (IsStep)
{
using (Item ii = this.Get())
{
StepConfig sc = this.MyConfig as StepConfig;
sc.AddEnhancedDocument(enhtype, enhii.ItemID);
sc.SaveEnhancedDocuments();
ii.MyContent.Config = sc.ToString();
ii.Save();
RefreshConfig();
}
using (Item ei = Item.Get(enhii.ItemID))
{
StepConfig sc = enhii.MyConfig as StepConfig;
sc.AddEnhancedDocument(0, this.ItemID);
sc.SaveEnhancedDocuments();
ei.MyContent.Text = DisplayText;
ei.MyContent.Config = sc.ToString();
ei.Save();
enhii.RefreshConfig();
}
}
else if (IsSection)
{
using (Item ii = this.Get())
{
SectionConfig sc = this.MyConfig as SectionConfig;
sc.AddEnhancedDocument(enhtype, enhii.ItemID);
sc.SaveEnhancedDocuments();
sc.Section_LnkEnh = "Y";
ii.MyContent.Config = sc.ToString();
ii.Save();
RefreshConfig();
}
using (Item ei = Item.Get(enhii.ItemID))
{
SectionConfig sc = enhii.MyConfig as SectionConfig;
sc.AddEnhancedDocument(0, this.ItemID);
sc.SaveEnhancedDocuments();
ei.MyContent.Text = DisplayText;
ei.MyContent.Config = sc.ToString();
ei.Save();
enhii.RefreshConfig();
}
}
else if (IsProcedure)
{
// To fix B2017-268 the order of the following 2 'usings' had to be changed and the
// Content.Number had to be set in the enhanced.
using (Item ei = Item.Get(enhii.ItemID))
{
ProcedureConfig sc = enhii.MyConfig as ProcedureConfig;
sc.AddEnhancedDocument(0, this.ItemID);
sc.SaveEnhancedDocuments();
ei.MyContent.Number = MyContent.Number;
ei.MyContent.Text = DisplayText;
ei.MyContent.Config = sc.ToString();
ei.Save();
enhii.RefreshConfig();
}
using (Item ii = this.Get())
{
ProcedureConfig sc = this.MyConfig as ProcedureConfig;
sc.AddEnhancedDocument(enhtype, enhii.ItemID);
sc.SaveEnhancedDocuments();
ii.MyContent.Config = sc.ToString();
ii.Save();
RefreshConfig();
}
}
}
#endregion
#region DataPortal
private void DataPortal_Fetch(PastingPartCriteria criteria)
{
if (_MyLog.IsDebugEnabled) _MyLog.DebugFormat("[{0}] ItemInfo.DataPortal_Fetch", GetHashCode());
try
{
using (SqlConnection cn = Database.VEPROMS_SqlConnection)
{
Csla.ApplicationContext.LocalContext["cn"] = cn;
using (SqlCommand cm = cn.CreateCommand())
{
cm.CommandType = CommandType.StoredProcedure;
cm.Parameters.AddWithValue("@StartItemID", criteria.StartItemID);
cm.Parameters.AddWithValue("@ItemID", criteria.ItemID); //ABC After Before Child
cm.Parameters.AddWithValue("@Type", criteria.Type); //ABC
cm.Parameters.AddWithValue("@DTS", criteria.DTS); //ABC
cm.Parameters.AddWithValue("@UserID", criteria.UserID); //ABC
SqlParameter param_ContentID = new SqlParameter("@NewItemID", SqlDbType.Int);
param_ContentID.Direction = ParameterDirection.Output;
cm.Parameters.Add(param_ContentID);
switch (criteria.AddType)
{
case EAddpingPart.Child:
cm.CommandText = "PasteItemChild";
cm.Parameters.AddWithValue("@FromType", criteria.FromType); //--C
break;
case EAddpingPart.Before:
cm.CommandText = "PasteItemSiblingBefore";
break;
case EAddpingPart.After:
cm.CommandText = "PasteItemSiblingAfter";
break;
case EAddpingPart.Replace:
cm.CommandText = "PasteItemReplace";
break;
}
cm.CommandTimeout = Database.DefaultTimeout;
using (SafeDataReader dr = new SafeDataReader(cm.ExecuteReader()))
{
//newItemID = (int)cm.Parameters["@newContentID"].Value;
if (!dr.Read())
{
_ErrorMessage = "No Record Found";
return;
}
ReadData(dr);
}
}
// removing of item only needed for local data portal
if (Csla.ApplicationContext.ExecutionLocation == Csla.ApplicationContext.ExecutionLocations.Client)
Csla.ApplicationContext.LocalContext.Remove("cn");
}
}
catch (Exception ex)
{
if (!ex.Message.Contains("This step has been deleted") && !ex.Message.Contains("This current step has been deleted in another session"))
{
if (_MyLog.IsErrorEnabled) _MyLog.Error("ItemInfo.DataPortal_Fetch", ex);
}
_ErrorMessage = ex.Message;
throw new DbCslaException("ItemInfo.DataPortal_Fetch", ex);
}
}
private void DataPortal_Fetch(AddingPartCriteria criteria)
{
if (_MyLog.IsDebugEnabled) _MyLog.DebugFormat("[{0}] ItemInfo.DataPortal_Fetch", GetHashCode());
try
{
using (SqlConnection cn = Database.VEPROMS_SqlConnection)
{
Csla.ApplicationContext.LocalContext["cn"] = cn;
using (SqlCommand cm = cn.CreateCommand())
{
cm.CommandType = CommandType.StoredProcedure;
cm.Parameters.AddWithValue("@ItemID", criteria.ItemID); //ABC After Before Child
cm.Parameters.AddWithValue("@Number", criteria.Number); //ABC
cm.Parameters.AddWithValue("@Text", criteria.Text); //ABC
cm.Parameters.AddWithValue("@FormatID", criteria.FormatID); //ABC
cm.Parameters.AddWithValue("@Config", criteria.Config); //ABC
cm.Parameters.AddWithValue("@Type", criteria.Type); //ABC
cm.Parameters.AddWithValue("@DTS", criteria.DTS); //ABC
cm.Parameters.AddWithValue("@UserID", criteria.UserID); //ABC
SqlParameter param_ContentID = new SqlParameter("@newItemID", SqlDbType.Int);
param_ContentID.Direction = ParameterDirection.Output;
cm.Parameters.Add(param_ContentID);
switch (criteria.AddType)
{
case EAddpingPart.Child:
cm.CommandText = "addItemChild";
cm.Parameters.AddWithValue("@FromType", criteria.FromType); //--C
break;
case EAddpingPart.Before:
cm.CommandText = "addItemSiblingBefore";
break;
case EAddpingPart.After:
cm.CommandText = "addItemSiblingAfter";
break;
}
cm.CommandTimeout = Database.DefaultTimeout;
using (SafeDataReader dr = new SafeDataReader(cm.ExecuteReader()))
{
//newItemID = (int)cm.Parameters["@newContentID"].Value;
if (!dr.Read())
{
_ErrorMessage = "No Record Found";
return;
}
ReadData(dr);
}
}
// removing of item only needed for local data portal
if (Csla.ApplicationContext.ExecutionLocation == Csla.ApplicationContext.ExecutionLocations.Client)
Csla.ApplicationContext.LocalContext.Remove("cn");
}
}
catch (Exception ex)
{
if (_MyLog.IsErrorEnabled) _MyLog.Error("ItemInfo.DataPortal_Fetch", ex);
_ErrorMessage = ex.Message;
throw new DbCslaException("ItemInfo.DataPortal_Fetch", ex);
}
}
#endregion
#region PastingPartCriteria
[Serializable()]
public class PastingPartCriteria
{
#region Properties
private int _StartItemID;
public int StartItemID
{
get { return _StartItemID; }
set { _StartItemID = value; }
}
//private int _CopyEndID;
//public int CopyEndID
//{
// get { return _CopyEndID; }
// set { _CopyEndID = value; }
//}
private int _ItemID; // paste relative to this itemid
public int ItemID
{
get { return _ItemID; }
set { _ItemID = value; }
}
private EAddpingPart _AddType;
public EAddpingPart AddType
{
get { return _AddType; }
set { _AddType = value; }
}
private int? _FromType = null;
public int? FromType
{
get { return _FromType; }
set { _FromType = value; }
}
private int? _Type = null;
public int? Type
{
get { return _Type; }
set { _Type = 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 PastingPartCriteria(int startItemid, int itemID, EAddpingPart addType, int? type, int? fromType, DateTime dts, string userID)
{
_StartItemID = startItemid;
_ItemID = itemID;
_AddType = addType;
_Type = type;
_FromType = fromType;
_DTS = dts;
_UserID = userID;
}
#endregion
}
#endregion
[Serializable()]
protected class AddingPartCriteria
{
#region Properties
private int _ItemID;
public int ItemID
{
get { return _ItemID; }
set { _ItemID = value; }
}
private EAddpingPart _AddType;
public EAddpingPart AddType
{
get { return _AddType; }
set { _AddType = value; }
}
private string _Number=null;
public string Number
{
get { return _Number; }
set { _Number = value; }
}
private string _Text=null;
public string Text
{
get { return _Text; }
set { _Text = value; }
}
private int? _FromType = null;
public int? FromType
{
get { return _FromType; }
set { _FromType = value; }
}
private int? _Type=null;
public int? Type
{
get { return _Type; }
set { _Type = value; }
}
private int? _FormatID=null;
public int? FormatID
{
get { return _FormatID; }
set { _FormatID = value; }
}
private string _Config=null;
public string Config
{
get { return _Config; }
set { _Config = 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 AddingPartCriteria(int itemID, EAddpingPart addType, string number, string text, int? type, int? fromType, int? formatID, string config, DateTime dts, string userID)
{
_ItemID = itemID;
_AddType = addType;
_Number = number;
_Text = text;
_Type = type;
_FromType = fromType;
_FormatID = formatID;
_Config = config;
_DTS = dts;
_UserID = userID;
}
#endregion
}
public enum EAddpingPart
{
Child=0,
Before=1,
After=2,
Replace=3
}
public ItemInfo NextItem
{
get
{
if (PrintAllAtOnce) return GetNextItem();
return GetNext();
}
}
private static void ResetOrdinal(int itemID)
{
ConvertListToDictionary();
string key = itemID.ToString();
while (key != null && _CacheByPrimaryKey.ContainsKey(key))
{
ItemInfo[] items = _CacheByPrimaryKey[key].ToArray();
key = null;
foreach (ItemInfo item in items)
{
item._Ordinal = null;
item._TagsSetup = false;
//item.MyContent.ShowChange(); // Replaced with OnOrdinalChange below
if (key == null && item.NextItem != null)
key = item.NextItem.ItemID.ToString();
}
ItemInfo.OnOrdinalChange(items[0].ItemID); // After _Ordinal reset trigger event
}
}
public void ResetOrdinal()
{
ResetOrdinal(ItemID);
Application.DoEvents(); // B2020-043: Fix transition text
}
public static void DeleteItemInfoAndChildren(int itemID)
{
//Volian.Base.Library.VlnTimer _MyTimer = new Volian.Base.Library.VlnTimer();
//_MyTimer.ActiveProcess = "ConvertListToDictionary";
ConvertListToDictionary();
string key = itemID.ToString();
if(_CacheByPrimaryKey.ContainsKey(key))
{
ItemInfo [] items = _CacheByPrimaryKey[key].ToArray();
ItemInfo parent = items[0].ActiveParent as ItemInfo;
//_MyTimer.ActiveProcess = "ResetParts";
if (parent != null)
ItemInfo.ResetParts(parent.ItemID);
//Console.WriteLine("\r\n\r\n'Deleting Item {0}'\r\n{0}'Type ','ParentID','ParentUnique','ItemID','Unique'",itemID);
foreach (ItemInfo item in items)
{
//_MyTimer.ActiveProcess = "IsDeleted";
item.IsDeleted = true;
//_MyTimer.ActiveProcess = string.Format("OnDeleted {0}", items.Length);
item.OnDeleted(item);
//item.OnDeleted(item, _MyTimer);
//_MyTimer.ActiveProcess = "DeleteItemInfoAndChildren";
item.DeleteItemInfoAndChildren(" ");
}
//Console.WriteLine("\r\n'Item Deleted'");
}
//_MyTimer.ShowElapsedTimes("DeleteItemInfoAndChildren");
}
private void DeleteItemInfoAndChildren(string depth)
{
if (MyContent.LocalContentParts != null)
{
foreach (PartInfo part in MyContent.LocalContentParts)
{
if (part._MyItems != null)
{
int whereami = 1;
try
{
List<ItemInfo> items = new List<ItemInfo>();
foreach (ItemInfo item in part._MyItems)
{
items.Add(item);
}
foreach (ItemInfo item in items)
{
string key = item.ItemID.ToString();
if (_CacheByPrimaryKey.ContainsKey(key))
{
ItemInfo[] itemz = _CacheByPrimaryKey[key].ToArray();
foreach (ItemInfo itm in itemz)
{
//Console.WriteLine("'{0}cache ',{1},{2},{3},{4}", depth + depth, this.ItemID, this._MyItemInfoUnique, itm.ItemID, itm._MyItemInfoUnique);
//whereami = 2;
itm.OnDeleted(itm);
//whereami = 4;
itm.DeleteItemInfoAndChildren(depth + " ");
//whereami = 3;
}
}
else
{
//Console.WriteLine("'{0}noncache',{1},{2},{3},{4}", depth + depth, this.ItemID, this._MyItemInfoUnique, item.ItemID, item._MyItemInfoUnique);
//whereami = 5;
item.OnDeleted(item);
//whereami = 7;
item.DeleteItemInfoAndChildren(depth + " ");
//whereami = 6;
}
}
}
catch (Exception ex)
{
Console.WriteLine("where = {0}, type = {1}, msg = {2}", whereami, ex.GetType().Name, ex.Message);
}
}
}
}
Dispose();
}
public static void RefreshPrevious(int? itemID, int? previousID)
{
if (itemID == null) return;
string key = itemID.ToString();
ConvertListToDictionary();
if (_CacheByPrimaryKey.ContainsKey(key))
foreach (ItemInfo tmpInfo in _CacheByPrimaryKey[key])
tmpInfo.RefreshPrevious(previousID);
}
private void RefreshPrevious(int? previousID)
{
if (_PreviousID != previousID)
{
if (MyPrevious != null) MyPrevious.RefreshNextItems(); // Update List for old value
_PreviousID = previousID; // Update the value
}
_MyPrevious = null; // Reset list so that the next line gets a new list
if (MyPrevious != null) MyPrevious.RefreshNextItems(); // Update List for new value
}
internal static ItemInfo CopyPasteReplaceItemInfoFetch(int copyStartID, ItemInfo itemInfo) // int itemID, int? type, int? fromType)
{
ItemInfo tmp = null;
if (itemInfo.GetType() == typeof(ProcedureInfo) || itemInfo.MyContent.Type < 10000)
tmp = DataPortal.Fetch<ProcedureInfo>(new ItemInfo.PastingPartCriteria(copyStartID, itemInfo.ItemID, ItemInfo.EAddpingPart.Replace, itemInfo.MyContent.Type, itemInfo.MyContent.Type, DateTime.Now, Volian.Base.Library.VlnSettings.UserID));
else if (itemInfo.GetType() == typeof(SectionInfo) || itemInfo.MyContent.Type < 20000)
tmp = DataPortal.Fetch<SectionInfo>(new ItemInfo.PastingPartCriteria(copyStartID, itemInfo.ItemID, ItemInfo.EAddpingPart.Replace, itemInfo.MyContent.Type, itemInfo.MyContent.Type, DateTime.Now, Volian.Base.Library.VlnSettings.UserID));
else
tmp = DataPortal.Fetch<StepInfo>(new ItemInfo.PastingPartCriteria(copyStartID, itemInfo.ItemID, ItemInfo.EAddpingPart.Replace, itemInfo.MyContent.Type, itemInfo.MyContent.Type, DateTime.Now, Volian.Base.Library.VlnSettings.UserID));
AddToCache(tmp);
return tmp;
}
}
public partial class Item
{
#region DeleteItemAndChildren
public static void DeleteItemAndChildren(ItemInfo item)
{
//Volian.Base.Library.VlnTimer _MyTimer = new Volian.Base.Library.VlnTimer();
if (!CanDeleteObject())
throw new System.Security.SecurityException("User not authorized to remove a Item");
try
{
ItemInfo nextItem = item.NextItem;
ItemInfo prevItem = item.MyPrevious;
DocVersionInfo docVersion = item.ItemDocVersionCount == 1 ? item.ItemDocVersions[0] : null;
item.OnBeforeDelete();
//_MyTimer.ActiveProcess = "DataPortal.Delete";
DataPortal.Delete(new DeleteCriteria(item.ItemID, Volian.Base.Library.VlnSettings.UserID));
if (nextItem != null) // Adjust PreviousID for NextItem
{
if (docVersion != null)
using (DocVersion dv = docVersion.Get())
DocVersionInfo.Refresh(dv);
//_MyTimer.ActiveProcess = "RefreshPrevious";
ItemInfo.RefreshPrevious(nextItem.ItemID, item.PreviousID);
// The order of the next two methods was required to fix a null reference
// when getting myparent. This bug was found when deleting a node from the
// tree when the RTBItem was not open (i.e. in the step editor window).
//_MyTimer.ActiveProcess = "RefreshItemParts";
nextItem.RefreshItemParts();
//nextItem.ResetOrdinal(); - UpdateTransitionText calls ResetOrdinal
//_MyTimer.ActiveProcess = "UpdateTransitionText";
}
else if (prevItem != null)
{
//_MyTimer.ActiveProcess = "RefreshNextItems";
prevItem.RefreshNextItems();
//_MyTimer.ActiveProcess = "ResetOrdinal";
if (prevItem.IsCaution || prevItem.IsNote) prevItem.ResetOrdinal();
//_MyTimer.ActiveProcess = "UpdateTransitionText";
}
//_MyTimer.ActiveProcess = "DeleteItemInfoAndChildren";
ItemInfo.DeleteItemInfoAndChildren(item.ItemID); // Dispose ItemInfo and Children
if (prevItem != null)
prevItem.UpdateTransitionText();
else if (nextItem != null) // B2020-050 needed check for null nextItem - found when deleting empty equation sub-step
nextItem.ResetOrdinal(); // B2020-043: Fix transition text, code moved from above, so that DeleteItemInfoAndChildren is called first.
}
catch (Exception ex)
{
ClearDelProcReason(item); // C2020-038: reason was added when procedure was deleted, but delete failed so remove it
System.Data.SqlClient.SqlException exSQL = SqlException(ex);
if (exSQL != null && exSQL.Message.Contains("###Cannot Delete Item###"))
throw exSQL;
Console.WriteLine("ItemInsertExt: Stacktrace = {0}", ex.StackTrace);
throw new DbCslaException("Error on Item.DeleteItemAndChildren", ex);
}
//_MyTimer.ShowElapsedTimes("DeleteItemAndChildren");
}
// C2020-038: reason was added when procedure was deleted, provide a way to remove it if delete failed
public static void ClearDelProcReason(ItemInfo ii)
{
if (!ii.IsProcedure) return;
ProcedureConfig prc = ii.MyConfig as ProcedureConfig;
prc.General_DelProcReason = string.Empty;
using (Item itm = Item.Get(ii.ItemID))
{
itm.MyContent.Config = prc.ToString();
itm.UserID = Volian.Base.Library.VlnSettings.UserID;
itm.Save();
}
}
private static System.Data.SqlClient.SqlException SqlException(Exception ex)
{
Type sqlExType = typeof(System.Data.SqlClient.SqlException);
while (ex != null)
{
if (ex.GetType() == sqlExType) return ex as System.Data.SqlClient.SqlException;
ex = ex.InnerException;
}
return null;
}
[Serializable()]
protected class DeleteCriteria
{
private int _ItemID;
public int ItemID
{ get { return _ItemID; } }
private string _UserID;
public string UserID
{
get { return _UserID; }
set { _UserID = value; }
}
public DeleteCriteria(int itemID,String userID)
{
_ItemID = itemID;
_UserID = userID;
}
}
[Transactional(TransactionalTypes.TransactionScope)]
private void DataPortal_Delete(DeleteCriteria criteria)
{
if (_MyLog.IsDebugEnabled) _MyLog.DebugFormat("[{0}] Item.DataPortal_Delete", GetHashCode());
try
{
using (SqlConnection cn = Database.VEPROMS_SqlConnection)
{
using (SqlCommand cm = cn.CreateCommand())
{
cm.CommandType = CommandType.StoredProcedure;
cm.CommandTimeout = Database.SQLTimeout;
cm.CommandText = "DeleteItemAndChildren";
cm.Parameters.AddWithValue("@ItemID", criteria.ItemID);
cm.Parameters.AddWithValue("@UserID", criteria.UserID);
cm.ExecuteNonQuery();
}
}
}
catch (Exception ex)
{
if (_MyLog.IsErrorEnabled && !ex.Message.Contains("###Cannot Delete Item###"))
_MyLog.Error("Item.DataPortal_Delete", ex);
_ErrorMessage = ex.Message;
throw new DbCslaException("Item.DataPortal_Delete", ex);
}
}
#endregion
#region PasteReplace
// B2024-045, 049 and 050: remove the treenode that was passed in - adjust tree from user interface code, not in item extension
// code (the 2 PasteReplace methods here had a treenode passed in)
public static ItemInfo PasteReplace(ItemInfo itemInfo, int copyStartID, string chgid)
{
bool tmp = false;
return PasteReplace(itemInfo, copyStartID, chgid, ref tmp);
}
// B2017-179 return a bool (firstTrans) if we could not replace the step but the user wants to position to the first transition that needs resolved
public static ItemInfo PasteReplace(ItemInfo itemInfo, int copyStartID, string chgid, ref bool firstTrans)
{
firstTrans = false;
if (!CanDeleteObject())
throw new System.Security.SecurityException("User not authorized to remove a Item");
// B2016-009 check source and desintation types and display message box if needed
// C2022-017 moved the CheckSourceDestinationType call to btnPasteReplace_Click in StepTabRibbon
// B2023-101 Handle Paste Replace when procedure to be replaced has Incoming Transitions, i.e. do a separate try/catch for this case
ItemInfo newItemInfo = null;
try
{
newItemInfo = ItemInfo.CopyPasteReplaceItemInfoFetch(copyStartID, itemInfo); //itemInfo.ItemID, itemInfo.MyContent.Type, itemInfo.MyContent.Type);
if (newItemInfo == null) return null;
}
catch (Exception ex1)
{
if (ex1.Message.Contains("has External Transitions and has no next step")
|| ex1.Message.Contains("has External Transitions to Procedure")
|| ex1.Message.Contains("has External Transitions to it's children"))
{
FlexibleMessageBox.Show("This procedure has external transition references to it that must be resolved before doing the Paste/Replace.\r\nRight Click on the procedure and select the Incoming Transitions menu option to find these references and resolve them.", "Paste Replace Failed", System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Error);
return null;
}
}
try
{
// Delete business objects, including remove from tree
ItemInfo.DeleteItemInfoAndChildren(itemInfo.ItemID); // Dispose ItemInfo and Children
using (Item item = Get(newItemInfo.ItemID)) ItemInfo.Refresh(item);
ItemInfo.PasteSetChangeId(newItemInfo, chgid);
ItemInfo.PasteClearEnhanced(newItemInfo);
if (newItemInfo.NextItem != null) using (Item item = newItemInfo.NextItem.Get()) ItemInfo.Refresh(item);
newItemInfo.RefreshNextItems();
// if inserting after a caution or note, refreshes tabs. This will adjust bullets
// of any previous cautions or notes.
if (newItemInfo.IsCaution || newItemInfo.IsNote) newItemInfo.ResetOrdinal();
newItemInfo.UpdateTransitionText();
newItemInfo.UpdateROText();
newItemInfo.UpdatePastedStepTransitionText();
// Add to tree
if (newItemInfo.NextItem != null)
{
using (ItemInfo itm = ItemInfo.GetNonCached(newItemInfo.NextItem.ItemID))
{
itm.OnNewSiblingBefore(new ItemInfoInsertEventArgs(newItemInfo, ItemInfo.EAddpingPart.Before));
}
}
else if (newItemInfo.PreviousID != null)
{
using (ItemInfo itm2 = ItemInfo.GetNonCached((int)newItemInfo.PreviousID))
{
itm2.OnNewSiblingAfter(new ItemInfoInsertEventArgs(newItemInfo, ItemInfo.EAddpingPart.After));
}
}
else
{
// B2024-045, 049 and 050: if not a single procedure replace, update user interface by using the 'OnNewChild'. Single
// procedure's MyParent is null because its parent is a working draft (docversion) since MyParent's type is iteminfo.
// For the single procedure case, the user interface code in vlntreeview will update the tree.
if (newItemInfo.MyParent != null)
newItemInfo.MyParent.OnNewChild(new ItemInfoInsertEventArgs(newItemInfo, ItemInfo.EAddpingPart.Child));
}
return newItemInfo;
}
catch (Exception ex)
{
ItemInfo iii = itemInfo.HandleSqlExceptionOnDelete(ex);
if (iii == itemInfo) return null;// If self returned then return null
if (iii != null)
{
firstTrans = true; // B2017-179 set the firstTrans to true and return the itminfo of the first transition location that needs resolved
return iii;
}
if (!HandleSqlExceptionOnCopy(ex))
{
if (ex.Message.Contains("has External Transitions and has no next step")
|| ex.Message.Contains("has External Transitions to Procedure")
|| ex.Message.Contains("has External Transitions to it's children")
|| ex.Message.Contains("This step has been deleted")
)
throw ex;
FlexibleMessageBox.Show("Details were written to the Error Log.", "Paste Replace Failed", System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Error);
return itemInfo;
}
else
return itemInfo;
}
}
#endregion
private static bool HandleSqlExceptionOnCopy(Exception ex)
{
if (ex.Message.Contains("This step has been deleted"))
{
FlexibleMessageBox.Show("The step being pasted has been deleted!", "Cannot Paste Deleted Step"
, System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Hand);
return true;
}
if (ex.Message.Contains("This current step has been deleted in another session"))
{
FlexibleMessageBox.Show("The highlighted step has been deleted by another user!", "Cannot Paste Step"
, System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Hand);
return true;
}
return false;
}
}
}