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; 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 { #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 itmlst = _CacheByPrimaryKey[ItemID.ToString()]; foreach (ItemInfo itm in itmlst) if (itm.BeforeDelete != null) { itm.BeforeDelete(itm); } } } public event ItemInfoEvent Deleted; internal void OnDeleted(object sender) { if (Deleted != null) Deleted(sender); } public event ItemInfoInsertEvent NewSiblingAfter; internal void OnNewSiblingAfter(object sender, ItemInfoInsertEventArgs args) { if (NewSiblingAfter != null) NewSiblingAfter(sender,args); } 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); } 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); } 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) { ItemInfo tmp = NewItemInfoFetch(ItemID, EAddpingPart.Before, number, text, null, null, null, null, DateTime.Now, Environment.UserName); // 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.UpdateTransitionText(); OnNewSiblingBefore(new ItemInfoInsertEventArgs(tmp, EAddpingPart.Before)); ((ItemInfo)ActiveParent).MyContent.RefreshContentParts(); 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 = NewItemInfoFetch(ItemID, EAddpingPart.After, number, text, type, null, null, null, DateTime.Now, Environment.UserName); //tmp = DataPortal.Fetch(new AddingPartCriteria(ItemID, EAddpingPart.After, number, text, type, null, null, null, DateTime.Now, Environment.UserName)); // 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(); // Update all of the content records that have transitions that point to the Siblings or Sibling Children of the new item tmp.UpdateTransitionText(); 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(new AddingPartCriteria(itemID, addType, number, text, type, fromType, formatID, config, dts, userID)); break; case E_FromType.Section: tmp = DataPortal.Fetch(new AddingPartCriteria(itemID, addType, number, text, type, fromType, formatID, config, dts, userID)); break; default: tmp = DataPortal.Fetch(new AddingPartCriteria(itemID, addType, number, text, type, fromType, formatID, config, dts, userID)); break; } } else { if (GetType() == typeof(ProcedureInfo)) tmp = DataPortal.Fetch(new AddingPartCriteria(itemID, addType, number, text, type, fromType, formatID, config, dts, userID)); else if (GetType() == typeof(SectionInfo)) tmp = DataPortal.Fetch(new AddingPartCriteria(itemID, addType, number, text, type, fromType, formatID, config, dts, userID)); else tmp = DataPortal.Fetch(new AddingPartCriteria(itemID, addType, number, text, type, fromType, formatID, config, dts, userID)); } 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)) { foreach (TransitionInfo tran in trans) { using (Content content = tran.MyContent.Get()) { content.FixTransitionText(tran); if (content.IsDirty) content.Save(); } } } } #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 = NewItemInfoFetch(ItemID, EAddpingPart.Child, number, text, type, (int?) fromType, null, null, DateTime.Now, Environment.UserName); // 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(); MyContent.RefreshContentParts(); OnNewChild(new ItemInfoInsertEventArgs(tmp, EAddpingPart.Child)); return tmp; } #endregion #region DataPortal private void DataPortal_Fetch(AddingPartCriteria criteria) { if (_MyLog.IsDebugEnabled) _MyLog.DebugFormat("[{0}] ItemInfo.DataPortal_Fetch", GetHashCode()); try { using (SqlConnection cn = Database.VEPROMS_SqlConnection) { ApplicationContext.LocalContext["cn"] = cn; using (SqlCommand cm = cn.CreateCommand()) { cm.CommandType = CommandType.StoredProcedure; cm.Parameters.AddWithValue("@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; } 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 (ApplicationContext.ExecutionLocation == ApplicationContext.ExecutionLocations.Client) 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 [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 } public ItemInfo NextItem { get { if (NextItemCount > 0 && NextItems.Count > 0) return NextItems[0]; return null; } } 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) { //Console.WriteLine("ResetOrdinal item = {0}, ordinal = {1}", item, item.Ordinal); item._Ordinal = null; item._TagsSetup = false; item.MyContent.ShowChange(); if (key == null && item.NextItem != null) key = item.NextItem.ItemID.ToString(); } } } public void ResetOrdinal() { ResetOrdinal(ItemID); } public static void DeleteItemInfoAndChildren(int itemID) { ConvertListToDictionary(); string key = itemID.ToString(); if(_CacheByPrimaryKey.ContainsKey(key)) { ItemInfo [] items = _CacheByPrimaryKey[key].ToArray(); ItemInfo parent = items[0].ActiveParent as ItemInfo; 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) { item.OnDeleted(item); item.DeleteItemInfoAndChildren(" "); } //Console.WriteLine("\r\n'Item Deleted'"); } } private void DeleteItemInfoAndChildren(string depth) { if (MyContent.LocalContentParts != null) { foreach (PartInfo part in MyContent.LocalContentParts) { if (part._MyItems != null) { int whereami = 1; try { List items = new List(); 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 } } public partial class Item { #region DeleteItemAndChildren public static void DeleteItemAndChildren(ItemInfo item) { if (!CanDeleteObject()) throw new System.Security.SecurityException("User not authorized to remove a Item"); try { ItemInfo nextItem = item.NextItem; ItemInfo prevItem = item.MyPrevious; item.OnBeforeDelete(); DataPortal.Delete(new DeleteCriteria(item.ItemID,Environment.UserName)); if (nextItem != null) // Adjust PreviousID for NextItem { 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 stepitem was not open (i.e. in the step editor window). nextItem.RefreshItemParts(); //nextItem.ResetOrdinal(); - UpdateTransitionText calls ResetOrdinal nextItem.UpdateTransitionText(); } else if (prevItem != null) prevItem.RefreshNextItems(); ItemInfo.DeleteItemInfoAndChildren(item.ItemID); // Dispose ItemInfo and Children } catch (Exception ex) { Console.WriteLine("ItemInsertExt: Stacktrace = {0}", ex.StackTrace); System.Data.SqlClient.SqlException exSQL = SqlException(ex); if (exSQL != null && exSQL.Message.Contains("###Cannot Delete Item###")) //return false; throw exSQL; else throw new DbCslaException("Error on Item.DeleteItemAndChildren", ex); } } 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.CommandText = "DeleteItemAndChildren"; cm.Parameters.AddWithValue("@ItemID", criteria.ItemID); cm.Parameters.AddWithValue("@UserID", criteria.UserID); cm.ExecuteNonQuery(); } } } catch (Exception ex) { if (_MyLog.IsErrorEnabled) _MyLog.Error("Item.DataPortal_Delete", ex); _ErrorMessage = ex.Message; throw new DbCslaException("Item.DataPortal_Delete", ex); } } #endregion } }