Files
Common-VS2019/SacsStandardBase/Base/Bus/SacsHierarchyItem.cs
T
2021-06-25 11:25:36 +01:00

467 lines
14 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using Sarand.Net.Standard.Base.App;
using Sarand.Net.Standard.Base.Core;
using Sarand.Net.Standard.Base.Dbas;
using Sarand.Net.Standard.Base.Utils;
namespace Sarand.Net.Standard.Base.Bus
{
//=======================================================================
public class UpdateStamp
{
private DateTime on = DateTime.Now;
private SysId by = new SysId();
private String host = String.Empty;
public DateTime On
{
get { return on; }
set { on = value; }
}
public SysId By
{
get { return by; }
set { by = SysId.InvalidOnNull(value); }
}
public String Host
{
get { return host; }
set { host = StringUtil.EmptyOnNull(value); }
}
}
//=======================================================================
public class SacsHierarchyItem : SaErrorStateItem
{
//-------------------------------------------------------------------
// Definitions.
public class Data
{
//---------------------------------------------------------------
// Common properties.
private SysId id = new SysId();
private String notes = String.Empty;
/// <summary>Item identifier.</summary>
public SysId Id
{
get { return SysId.InvalidOnNull(id); }
set
{
CheckChanged(id, value);
id = SysId.InvalidOnNull(value);
}
}
/// <summary>Item notes.</summary>
public String Notes
{
get { return StringUtil.EmptyOnNull(notes); }
set
{
CheckChanged(notes, value);
notes = StringUtil.EmptyOnNull(value);
}
}
//---------------------------------------------------------------
// Flags.
private UInt16 flags = 0;
/// <summary>Item flags.<para>Up to 16 flags supported.</para></summary>
public UInt16 Flags
{
get { return flags; }
set
{
CheckChanged(flags, value);
flags = value;
}
}
/// <summary>Get flag value - position 1 - 16</summary>
public bool GetFlag (Byte flagPos)
{
return SacsHierarchyItem.GetFlag(Flags, flagPos);
}
/// <summary>Set flag value - position 1 - 16</summary>
public void SetFlag (Byte flagPos, bool value)
{
CheckChanged(GetFlag(flagPos), value);
Flags = SacsHierarchyItem.SetFlag(Flags, flagPos, value);
}
//---------------------------------------------------------------
// Status.
private SaStatus status = SaStatus.Unknown;
/// <summary>Item status.</summary>
public SaStatus Status
{
get { return status; }
set
{
CheckChangedEnum(status, value);
status = value;
}
}
public String StatusCode
{
get { return SacsSystem.GetStatusCode(Status); }
set { Status = SacsSystem.GetStatusForCode(value); }
}
public String StatusDesc
{
get { return SacsSystem.GetStatusDesc(Status); }
}
public bool IsStatusCurrent { get { return Status == SaStatus.Current; } }
public bool IsStatusActive { get { return Status == SaStatus.Active; } }
public bool IsStatusEnabled { get { return Status == SaStatus.Enabled; } }
public bool IsStatusCompleted { get { return Status == SaStatus.Completed; } }
public bool IsStatusCancelled { get { return Status == SaStatus.Cancelled; } }
public bool IsStatusDeleted { get { return Status == SaStatus.Deleted; } }
//---------------------------------------------------------------
// Update stamps.
public UpdateStamp CreateStamp { get; protected set; } = new UpdateStamp();
public UpdateStamp UpdateStamp { get; protected set; } = new UpdateStamp();
//---------------------------------------------------------------
// Population.
/// <summary>Copy common properties to this object.</summary>
protected void PopulateFrom (Data sourceData)
{
Id = sourceData.Id;
Notes = sourceData.Notes;
Status = sourceData.Status;
Flags = sourceData.Flags;
CreateStamp = sourceData.CreateStamp;
UpdateStamp = sourceData.UpdateStamp;
}
/// <summary>Copy comon properties to the target object.</summary>
internal void PopulateTo (Data targetData)
{
targetData.PopulateFrom(this);
}
//---------------------------------------------------------------
// Property change tracking.
private bool changed = false;
/// <summary>Flag to indicate whether any property has been modified.</summary>
public bool Changed
{
get { return changed; }
set
{
if (changed == value) return;
changed = value;
}
}
/// <summary>Clear 'Changed' flag.</summary>
public void AcceptChanges ()
{
Changed = false;
}
//---------------------------------------------------------------
// Compare old and new property values and set 'Changed' if different.
protected void CheckChanged (SysId oldValue, SysId newValue)
{
if (Changed) return;
// Compare by numeric value so that invalid values are equal.
Changed = SysId.ToInt(oldValue) != SysId.ToInt(newValue);
}
protected void CheckChanged (ItemId oldValue, ItemId newValue)
{
if (Changed) return;
Changed = (oldValue.Type != newValue.Type) || (!oldValue.Id.Equals(newValue.Id));
}
protected void CheckChanged (String oldValue, String newValue)
{
if (Changed) return;
Changed = !StringUtil.EmptyOnNull(oldValue).Equals(StringUtil.EmptyOnNull(newValue));
}
protected void CheckChanged (bool oldValue, bool newValue)
{
if (Changed) return;
Changed = (oldValue != newValue);
}
protected void CheckChangedEnum<T>(T oldValue, T newValue) where T : struct, IConvertible
{
if (!(oldValue is Enum) || !(newValue is Enum))
throw new ArgumentException(GetType().Name+ ".CheckChangedEnum<T> Parameters must be enumerated types. Type supplied: " + oldValue.GetType().Name + ", " + newValue.GetType().Name);
if (Changed) return;
Changed = ((int)(oldValue as IConvertible) != (int)(newValue as IConvertible));
}
protected void CheckChanged (long oldValue, long newValue)
{
if (Changed) return;
Changed = (oldValue != newValue);
}
protected void CheckChanged (double oldValue, double newValue)
{
if (Changed) return;
Changed = (oldValue != newValue);
}
protected void CheckChanged (decimal oldValue, decimal newValue)
{
if (Changed) return;
Changed = (oldValue != newValue);
}
protected void CheckChanged (DateTime oldValue, DateTime newValue)
{
if (Changed) return;
Changed = !oldValue.Equals(newValue);
}
protected void CheckChanged (List<String> oldValues, List<String> newValues)
{
if (Changed) return;
Changed = !oldValues.ContentEquals(newValues);
}
protected void CheckChanged<T> (List<T> oldValues, List<T> newValues)
{
if (Changed) return;
if (oldValues.Count() != newValues.Count()) Changed = true;
else
{
for (int idx = 0; idx < oldValues.Count(); idx++)
{
if (!oldValues[idx].Equals(newValues[idx]))
{
Changed = true;
return;
}
}
}
}
protected void CheckChanged (byte[] oldValue, byte[] newValue)
{
if (Changed) return;
if ((oldValue == null) != (newValue != null)) Changed = true;
else if (oldValue.Length != newValue.Length) Changed = true;
if (oldValue != null && newValue != null)
Changed = !oldValue.SequenceEqual(newValue);
}
//---------------------------------------------------------------
}
//-------------------------------------------------------------------
// Property validation.
public enum ValidValue
{
/// <summary>Property is valid (or has not been validate).</summary>
Valid,
/// <summary>Property is invalid.</summary>
Invalid,
/// <summary>Property is to be ignored during validation.</summary>
Ignore,
}
public class ErrField
{
// Identifies the field that has invalid data.
public ValidValue Id { get; set; } = ValidValue.Valid;
public ValidValue Notes { get; set; } = ValidValue.Valid;
public ValidValue Status { get; set; } = ValidValue.Valid;
public ValidValue Flags { get; set; } = ValidValue.Valid;
}
//-------------------------------------------------------------------
// Data members.
// Data object holds object business properties.
// Starts as internal class, replaced on construction by object specific class.
private Data data = new Data();
//-------------------------------------------------------------------
// Construction.
protected SacsHierarchyItem ()
{
}
protected SacsHierarchyItem (SysId id)
{
data.Id = id;
}
//-------------------------------------------------------------------
// Disposal.
protected override void Dispose (bool disposing)
{
if (disposing)
{
}
}
//-------------------------------------------------------------------
// Properties.
public virtual bool ItemHasId { get; } = true;
public SysId Id
{
get
{
if (!ItemHasId) throw new NotSupportedException(GetType().Name + ".Id Item has no Id property");
return data.Id;
}
set
{
if (!ItemHasId && SysId.IsValid(data.Id)) throw new NotSupportedException(GetType().Name + ".Id Item has no Id property");
if (SysId.IsValid(data.Id) && (!SysId.IsValid(value) || !data.Id.Equals(value)))
throw new NotSupportedException("SacsHierarchyItem.Id.set Id already has a valid value");
data.Id = value;
}
}
public String Notes
{
get { return StringUtil.EmptyOnNull(data.Notes); }
set { data.Notes = value; }
}
//-------------------------------------------------------------------
// Status.
public SaStatus Status
{
get { return data.Status; }
set { data.Status = value; }
}
public String StatusCode
{
get { return data.StatusCode; }
set { data.StatusCode = value; }
}
public String StatusDesc
{
get { return data.StatusDesc; }
}
public bool IsStatusCurrent { get { return data.IsStatusCurrent; } }
public bool IsStatusActive { get { return data.IsStatusActive; } }
public bool IsStatusEnabled { get { return data.IsStatusEnabled; } }
public bool IsStatusCompleted { get { return data.IsStatusCompleted; } }
public bool IsStatusCancelled { get { return data.IsStatusCancelled; } }
public bool IsStatusDeleted { get { return data.IsStatusDeleted; } }
//-------------------------------------------------------------------
// Flags.
public UInt16 Flags
{
get { return data.Flags; }
protected set { data.Flags = value; }
}
/// <summary>Flags are positioned from 1, up to 16 allowed.</summary>
public static bool GetFlag (UInt16 flags, Byte flagPos)
{
bool flag = false;
if (flagPos > 0 && flagPos <= 16)
flag = (((flags >> (flagPos - 1)) & 0x0001) == 1 ? true : false);
return flag;
}
/// <summary>Flags are positioned from 1, up to 16 allowed.</summary>
public bool GetFlag (Byte flagPos)
{
return GetFlag(data.Flags, flagPos);
}
/// <summary>Set flag value - position 1 - 16</summary>
public static UInt16 SetFlag (UInt16 flags, Byte flagPos, bool value)
{
if (flagPos > 0 && flagPos <= 16)
{
UInt16 mask = (UInt16)(1 << (flagPos - 1));
if (value)
flags |= mask;
else
flags &= (UInt16)(~mask);
}
return flags;
}
/// <summary>Set flag value - position 1 - 16</summary>
public void SetFlag (Byte flagPos, bool value)
{
data.Flags = SetFlag(data.Flags, flagPos, value);
}
//-------------------------------------------------------------------
// Update stamps.
public UpdateStamp CreateStamp { get { return data.CreateStamp; } }
public void SetCreateStamp (DateTime on, SysId by, String host)
{
CreateStamp.On = on;
CreateStamp.By = by;
CreateStamp.Host = host;
}
public UpdateStamp UpdateStamp { get { return data.UpdateStamp; } }
public void SetUpdateStamp (DateTime on, SysId by, String host)
{
UpdateStamp.On = on;
UpdateStamp.By = by;
UpdateStamp.Host = host;
}
//-------------------------------------------------------------------
// Populate data item - only once on construction.
protected void SetData (Data data)
{
String fn = GetType().Name + ".SetData";
// Can only be replaced if currently internal class.
if (this.data.GetType() != typeof(Data))
throw new NotSupportedException(fn + " Data object has already been specified");
// If Id has already been specified (on construction) and supplied Id is not valid, set it to the existing value.
if (ItemHasId && SysId.IsValid(Id) && !SysId.IsValid(data.Id)) data.Id = Id;
// Properties that cannot be changed if previously specified.
if (ItemHasId && SysId.IsValid(Id) && SysId.ToInt(Id) != SysId.ToInt(data.Id))
throw new NotSupportedException(fn + " Id cannot be changed");
this.data.PopulateTo(data);
this.data = data;
}
//-------------------------------------------------------------------
// Property change tracking.
/// <summary>Flag to indicate whether any property has been modified.</summary>
public bool Changed
{
get { return data.Changed; }
set
{
if (data.Changed == value) return;
data.Changed = value;
}
}
/// <summary>Clear the 'Changed' flag to indicate that no changes have been made.</summary>
public void AcceptChanges ()
{
Changed = false;
}
//-------------------------------------------------------------------
// Format value for display.
public static String FormatForDisplay (String value, int maxLength = 0)
{
if (StringUtil.IsEmpty(value)) return String.Empty;
// Replace non-display characters.
value = value.Replace("\t", " ").Replace("\r", " ").Replace("\n", " ");
// Remove leading, trailing and multiple internal spaces.
value = value.Trim().Replace(" +", " ");
// Restrict to maximum length.
if (maxLength > 0 && value.Length > maxLength)
{
value = value.Left(maxLength);
if (maxLength > 20) value += "...";
}
return value;
}
//-------------------------------------------------------------------
// Parameters.
public class Params
{
// Construction.
protected Params ()
{
}
/// <summary>Primary table alias to use if different from default.</summary>
public String TableAlias { get; set; }
/// <summary>Flag to indicate whether default filter ('1=1') is included if no other filter.</summary>
public bool IncludeDefaultFilter { get; set; } = true;
/// <summary>Results list paging.</summary>
public DbQuery.Paging ResultsPaging { get; } = new DbQuery.Paging();
/// <summary>Sort columns.</summary>
public List<ColumnDfn> SortColumns { get; } = new List<ColumnDfn>();
}
//-------------------------------------------------------------------
}
//=======================================================================
}