Files
Pilz/Pilz.Collections/SimpleHistory/HistoryPoint.cs
2024-10-21 09:12:54 +02:00

615 lines
28 KiB
C#

using System.Data;
using System.Reflection;
namespace Pilz.Collections.SimpleHistory;
/// <summary>
/// Represent some Object States and Actions.
/// </summary>
public class HistoryPoint
{
/// <summary>
/// Represents the Name of this History Point
/// </summary>
/// <returns></returns>
public string Name { get; set; } = string.Empty;
/// <summary>
/// A List of Object States and Actions.
/// </summary>
/// <returns></returns>
public List<ObjectBase> Entries { get; } = [];
/// <summary>
/// Some data can be refered on this HistoryPoint. Don't know, in some situations this can be helpful.
/// </summary>
public readonly object? Tag = null;
public bool HasEntries<T>() where T : ObjectBase
{
return Entries.Where(n => n is T).Any();
}
internal void Undo()
{
foreach (var s in Entries.OrderBy(n => n.UndoPriority))
{
switch (s)
{
case ObjectState state:
state.Patch();
break;
case ObjectAction action:
action.Undo();
break;
}
}
}
internal void Redo()
{
foreach (var s in Entries.OrderBy(n => n.RedoPriority))
{
switch (s)
{
case ObjectState state:
state.Patch();
break;
case ObjectAction action:
action.Redo();
break;
}
}
}
/// <summary>
/// Creates an History Point with Object States automaticly from input.
/// </summary>
/// <param name="obj">The objects that should be included.</param>
/// <param name="whiteList">Specify which members to include.</param>
/// <returns>A History Point with Object States.</returns>
public static HistoryPoint FromObject(object[] obj, MemberWhiteList whiteList)
{
return FromObject([obj], ObjectValueType.None, (object)whiteList, BindingFlags.Default);
}
/// <summary>
/// Creates an History Point with Object States automaticly from input.
/// </summary>
/// <param name="obj">The objects that should be included.</param>
/// <param name="blackList">Specify which members to exclude.</param>
/// <returns>A History Point with Object States.</returns>
public static HistoryPoint FromObject(object[] obj, MemberBlackList blackList)
{
return FromObject([obj], ObjectValueType.None, (object)blackList, BindingFlags.Default);
}
/// <summary>
/// Creates an History Point with Object States automaticly from input.
/// </summary>
/// <param name="obj">The objects that should be included.</param>
/// <param name="memberName">The member names to include.</param>
/// <returns>A History Point with Object States.</returns>
public static HistoryPoint FromObject(object[] obj, params string[] memberName)
{
return FromObject(obj, true, memberName);
}
/// <summary>
/// Creates an History Point with Object States automaticly from input.
/// </summary>
/// <param name="obj">The objects that should be included.</param>
/// <param name="isWhiteList">If true, the memberName-Array has member names that should be included.</param>
/// <param name="memberName">The member names to include/exclude.</param>
/// <returns>A History Point with Object States.</returns>
public static HistoryPoint FromObject(object[] obj, bool isWhiteList, params string[] memberName)
{
if (isWhiteList)
return FromObject([obj], ObjectValueType.None, (object)new MemberWhiteList(memberName), BindingFlags.Default);
else
return FromObject([obj], ObjectValueType.None, (object)new MemberBlackList(memberName), BindingFlags.Default);
}
/// <summary>
/// Creates an History Point with Object States automaticly from input.
/// </summary>
/// <param name="obj">The objects that should be included.</param>
/// <param name="membersToStore">Specify what member types to include.</param>
/// <param name="memberName">The member names to include.</param>
/// <returns>A History Point with Object States.</returns>
public static HistoryPoint FromObject(object[] obj, ObjectValueType membersToStore, params string[] memberName)
{
return FromObject(obj, membersToStore, true, memberName);
}
/// <summary>
/// Creates an History Point with Object States automaticly from input.
/// </summary>
/// <param name="obj">The objects that should be included.</param>
/// <param name="membersToStore">Specify what member types to include.</param>
/// <param name="isWhiteList">If true, the memberName-Array has member names that should be included.</param>
/// <param name="memberName">The member names to include/exclude.</param>
/// <returns>A History Point with Object States.</returns>
public static HistoryPoint FromObject(object[] obj, ObjectValueType membersToStore, bool isWhiteList, params string[] memberName)
{
if (isWhiteList)
return FromObject([obj], membersToStore, (object)new MemberWhiteList(memberName), BindingFlags.Default);
else
return FromObject([obj], membersToStore, (object)new MemberBlackList(memberName), BindingFlags.Default);
}
/// <summary>
/// Creates an History Point with Object States automaticly from input.
/// </summary>
/// <param name="obj">The objects that should be included.</param>
/// <param name="flags">The Binding Flags that the members should have.</param>
/// <param name="memberName">The member names to include.</param>
/// <returns>A History Point with Object States.</returns>
public static HistoryPoint FromObject(object[] obj, BindingFlags flags, params string[] memberName)
{
return FromObject(obj, flags, true, memberName);
}
/// <summary>
/// Creates an History Point with Object States automaticly from input.
/// </summary>
/// <param name="obj">The objects that should be included.</param>
/// <param name="flags">The Binding Flags that the members should have.</param>
/// <param name="isWhiteList">If true, the memberName-Array has member names that should be included.</param>
/// <param name="memberName">The member names to include/exclude.</param>
/// <returns>A History Point with Object States.</returns>
public static HistoryPoint FromObject(object[] obj, BindingFlags flags, bool isWhiteList, params string[] memberName)
{
if (isWhiteList)
return FromObject([obj], ObjectValueType.None, (object)new MemberWhiteList(memberName), flags);
else
return FromObject([obj], ObjectValueType.None, (object)new MemberBlackList(memberName), flags);
}
/// <summary>
/// Creates an History Point with Object States automaticly from input.
/// </summary>
/// <param name="obj">The objects that should be included.</param>
/// <param name="membersToStore">Specify what member types to include.</param>
/// <param name="flags">The Binding Flags that the members should have.</param>
/// <param name="memberName">The member names to include.</param>
/// <returns>A History Point with Object States.</returns>
public static HistoryPoint FromObject(object[] obj, ObjectValueType membersToStore, BindingFlags flags, params string[] memberName)
{
return FromObject(obj, flags, true, memberName);
}
/// <summary>
/// Creates an History Point with Object States automaticly from input.
/// </summary>
/// <param name="obj">The objects that should be included.</param>
/// <param name="membersToStore">Specify what member types to include.</param>
/// <param name="flags">The Binding Flags that the members should have.</param>
/// <param name="isWhiteList">If true, the memberName-Array has member names that should be included.</param>
/// <param name="memberName">The member names to include/exclude.</param>
/// <returns>A History Point with Object States.</returns>
public static HistoryPoint FromObject(object[] obj, ObjectValueType membersToStore, BindingFlags flags, bool isWhiteList, params string[] memberName)
{
if (isWhiteList)
return FromObject([obj], membersToStore, (object)new MemberWhiteList(memberName), flags);
else
return FromObject([obj], membersToStore, (object)new MemberBlackList(memberName), flags);
}
/// <summary>
/// Creates an History Point with Object States automaticly from input.
/// </summary>
/// <param name="obj">The object that should be included.</param>
/// <param name="whiteList">Specify which members to include.</param>
/// <returns>A History Point with Object States.</returns>
public static HistoryPoint FromObject(object obj, MemberWhiteList whiteList)
{
return FromObject([obj], ObjectValueType.None, (object)whiteList, BindingFlags.Default);
}
/// <summary>
/// Creates an History Point with Object States automaticly from input.
/// </summary>
/// <param name="obj">The object that should be included.</param>
/// <param name="blackList">Specify which members to exclude.</param>
/// <returns>A History Point with Object States.</returns>
public static HistoryPoint FromObject(object obj, MemberBlackList blackList)
{
return FromObject([obj], ObjectValueType.None, (object)blackList, BindingFlags.Default);
}
/// <summary>
/// Creates an History Point with Object States automaticly from input.
/// </summary>
/// <param name="obj">The object that should be included.</param>
/// <param name="memberName">The member names to include/exclude.</param>
/// <returns>A History Point with Object States.</returns>
public static HistoryPoint FromObject(object obj, params string[] memberName)
{
return FromObject(obj, true, memberName);
}
/// <summary>
/// Creates an History Point with Object States automaticly from input.
/// </summary>
/// <param name="obj">The object that should be included.</param>
/// <param name="isWhiteList">If true, the memberName-Array has member names that should be included.</param>
/// <param name="memberName">The member names to include/exclude.</param>
/// <returns>A History Point with Object States.</returns>
public static HistoryPoint FromObject(object obj, bool isWhiteList, params string[] memberName)
{
if (isWhiteList)
return FromObject([obj], ObjectValueType.None, (object)new MemberWhiteList(memberName), BindingFlags.Default);
else
return FromObject([obj], ObjectValueType.None, (object)new MemberBlackList(memberName), BindingFlags.Default);
}
/// <summary>
/// Creates an History Point with Object States automaticly from input.
/// </summary>
/// <param name="obj">The object that should be included.</param>
/// <param name="membersToStore">Specify what member types to include.</param>
/// <param name="memberName">The member names to include.</param>
/// <returns>A History Point with Object States.</returns>
public static HistoryPoint FromObject(object obj, ObjectValueType membersToStore, params string[] memberName)
{
return FromObject(obj, membersToStore, true, memberName);
}
/// <summary>
/// Creates an History Point with Object States automaticly from input.
/// </summary>
/// <param name="obj">The object that should be included.</param>
/// <param name="membersToStore">Specify what member types to include.</param>
/// <param name="isWhiteList">If true, the memberName-Array has member names that should be included.</param>
/// <param name="memberName">The member names to include/exclude.</param>
/// <returns>A History Point with Object States.</returns>
public static HistoryPoint FromObject(object obj, ObjectValueType membersToStore, bool isWhiteList, params string[] memberName)
{
if (isWhiteList)
return FromObject([obj], membersToStore, (object)new MemberWhiteList(memberName), BindingFlags.Default);
else
return FromObject([obj], membersToStore, (object)new MemberBlackList(memberName), BindingFlags.Default);
}
/// <summary>
/// Creates an History Point with Object States automaticly from input.
/// </summary>
/// <param name="obj">The object that should be included.</param>
/// <param name="flags">The Binding Flags that the members should have.</param>
/// <param name="memberName">The member names to include.</param>
/// <returns>A History Point with Object States.</returns>
public static HistoryPoint FromObject(object obj, BindingFlags flags, params string[] memberName)
{
return FromObject(obj, flags, true, memberName);
}
/// <summary>
/// Creates an History Point with Object States automaticly from input.
/// </summary>
/// <param name="obj">The object that should be included.</param>
/// <param name="flags">The Binding Flags that the members should have.</param>
/// <param name="isWhiteList">If true, the memberName-Array has member names that should be included.</param>
/// <param name="memberName">The member names to include/exclude.</param>
/// <returns>A History Point with Object States.</returns>
public static HistoryPoint FromObject(object obj, BindingFlags flags, bool isWhiteList, params string[] memberName)
{
if (isWhiteList)
return FromObject([obj], ObjectValueType.None, (object)new MemberWhiteList(memberName), flags);
else
return FromObject([obj], ObjectValueType.None, (object)new MemberBlackList(memberName), flags);
}
/// <summary>
/// Creates an History Point with Object States automaticly from input.
/// </summary>
/// <param name="obj">The object that should be included.</param>
/// <param name="membersToStore">Specify what member types to include.</param>
/// <param name="flags">The Binding Flags that the members should have.</param>
/// <param name="memberName">The member names to include.</param>
/// <returns>A History Point with Object States.</returns>
public static HistoryPoint FromObject(object obj, ObjectValueType membersToStore, BindingFlags flags, params string[] memberName)
{
return FromObject(obj, flags, true, memberName);
}
/// <summary>
/// Creates an History Point with Object States automaticly from input.
/// </summary>
/// <param name="obj">The object that should be included.</param>
/// <param name="membersToStore">Specify what member types to include.</param>
/// <param name="flags">The Binding Flags that the members should have.</param>
/// <param name="isWhiteList">If true, the memberName-Array has member names that should be included.</param>
/// <param name="memberName">The member names to include/exclude.</param>
/// <returns>A History Point with Object States.</returns>
public static HistoryPoint FromObject(object obj, ObjectValueType membersToStore, BindingFlags flags, bool isWhiteList, params string[] memberName)
{
if (isWhiteList)
return FromObject([obj], membersToStore, (object)new MemberWhiteList(memberName), flags);
else
return FromObject([obj], membersToStore, (object)new MemberBlackList(memberName), flags);
}
/// <summary>
/// Creates an History Point with Object States automaticly from input.
/// </summary>
/// <param name="obj">The object that should be included.</param>
/// <returns>A History Point with Object States.</returns>
public static HistoryPoint FromObject(object obj)
{
return FromObject([obj], ObjectValueType.None, default(object), BindingFlags.Default);
}
/// <summary>
/// Creates an History Point with Object States automaticly from input.
/// </summary>
/// <param name="obj">The object that should be included.</param>
/// <param name="membersToStore">Specify what member types to include.</param>
/// <returns>A History Point with Object States.</returns>
public static HistoryPoint FromObject(object obj, ObjectValueType membersToStore)
{
return FromObject([obj], membersToStore, default(object), BindingFlags.Default);
}
/// <summary>
/// Creates an History Point with Object States automaticly from input.
/// </summary>
/// <param name="obj">The object that should be included.</param>
/// <param name="membersToStore">Specify what member types to include.</param>
/// <param name="whiteList">Specify which members to include.</param>
/// <returns>A History Point with Object States.</returns>
public static HistoryPoint FromObject(object obj, ObjectValueType membersToStore, MemberWhiteList whiteList)
{
return FromObject([obj], membersToStore, (object)whiteList, BindingFlags.Default);
}
/// <summary>
/// Creates an History Point with Object States automaticly from input.
/// </summary>
/// <param name="obj">The object that should be included.</param>
/// <param name="membersToStore">Specify what member types to include.</param>
/// <param name="blackList">Specify which members to exclude.</param>
/// <returns>A History Point with Object States.</returns>
public static HistoryPoint FromObject(object obj, ObjectValueType membersToStore, MemberBlackList blackList)
{
return FromObject([obj], membersToStore, (object)blackList, BindingFlags.Default);
}
/// <summary>
/// Creates an History Point with Object States automaticly from input.
/// </summary>
/// <param name="obj">The object that should be included.</param>
/// <param name="flags">The Binding Flags that the members should have.</param>
/// <returns>A History Point with Object States.</returns>
public static HistoryPoint FromObject(object obj, BindingFlags flags)
{
return FromObject([obj], ObjectValueType.None, default(object), flags);
}
/// <summary>
/// Creates an History Point with Object States automaticly from input.
/// </summary>
/// <param name="obj">The object that should be included.</param>
/// <param name="membersToStore">Specify what member types to include.</param>
/// <param name="flags">The Binding Flags that the members should have.</param>
/// <returns>A History Point with Object States.</returns>
public static HistoryPoint FromObject(object obj, ObjectValueType membersToStore, BindingFlags flags)
{
return FromObject([obj], membersToStore, default(object), flags);
}
/// <summary>
/// Creates an History Point with Object States automaticly from input.
/// </summary>
/// <param name="obj">The object that should be included.</param>
/// <param name="membersToStore">Specify what member types to include.</param>
/// <param name="whiteList">Specify which members to include.</param>
/// <param name="flags">The Binding Flags that the members should have.</param>
/// <returns>A History Point with Object States.</returns>
public static HistoryPoint FromObject(object obj, ObjectValueType membersToStore, MemberWhiteList whiteList, BindingFlags flags)
{
return FromObject([obj], membersToStore, (object)whiteList, flags);
}
/// <summary>
/// Creates an History Point with Object States automaticly from input.
/// </summary>
/// <param name="obj">The object that should be included.</param>
/// <param name="membersToStore">Specify what member types to include.</param>
/// <param name="blackList">Specify which members to exclude.</param>
/// <param name="flags">The Binding Flags that the members should have.</param>
/// <returns>A History Point with Object States.</returns>
public static HistoryPoint FromObject(object obj, ObjectValueType membersToStore, MemberBlackList blackList, BindingFlags flags)
{
return FromObject([obj], membersToStore, (object)blackList, flags);
}
/// <summary>
/// Creates an History Point with Object States automaticly from input.
/// </summary>
/// <param name="objs">The objects that should be included.</param>
/// <returns>A History Point with Object States.</returns>
public static HistoryPoint FromObject(object[] objs)
{
return FromObject(objs, ObjectValueType.None, default(object), BindingFlags.Default);
}
/// <summary>
/// Creates an History Point with Object States automaticly from input.
/// </summary>
/// <param name="objs">The objects that should be included.</param>
/// <param name="membersToStore">Specify what member types to include.</param>
/// <returns>A History Point with Object States.</returns>
public static HistoryPoint FromObject(object[] objs, ObjectValueType membersToStore)
{
return FromObject(objs, membersToStore, default(object), BindingFlags.Default);
}
/// <summary>
/// Creates an History Point with Object States automaticly from input.
/// </summary>
/// <param name="objs">The objects that should be included.</param>
/// <param name="membersToStore">Specify what member types to include.</param>
/// <param name="whiteList">Specify which members to include.</param>
/// <returns>A History Point with Object States.</returns>
public static HistoryPoint FromObject(object[] objs, ObjectValueType membersToStore, MemberWhiteList whiteList)
{
return FromObject(objs, membersToStore, (object)whiteList, BindingFlags.Default);
}
/// <summary>
/// Creates an History Point with Object States automaticly from input.
/// </summary>
/// <param name="objs">The objects that should be included.</param>
/// <param name="membersToStore">Specify what member types to include.</param>
/// <param name="blackList">Specify which members to exclude.</param>
/// <returns>A History Point with Object States.</returns>
public static HistoryPoint FromObject(object[] objs, ObjectValueType membersToStore, MemberBlackList blackList)
{
return FromObject(objs, membersToStore, (object)blackList, BindingFlags.Default);
}
/// <summary>
/// Creates an History Point with Object States automaticly from input.
/// </summary>
/// <param name="objs">The objects that should be included.</param>
/// <param name="flags">The Binding Flags that the members should have.</param>
/// <returns>A History Point with Object States.</returns>
public static HistoryPoint FromObject(object[] objs, BindingFlags flags)
{
return FromObject(objs, ObjectValueType.None, default(object), flags);
}
/// <summary>
/// Creates an History Point with Object States automaticly from input.
/// </summary>
/// <param name="objs">The objects that should be included.</param>
/// <param name="membersToStore">Specify what member types to include.</param>
/// <param name="flags">The Binding Flags that the members should have.</param>
/// <returns>A History Point with Object States.</returns>
public static HistoryPoint FromObject(object[] objs, ObjectValueType membersToStore, BindingFlags flags)
{
return FromObject(objs, membersToStore, default(object), flags);
}
/// <summary>
/// Creates an History Point with Object States automaticly from input.
/// </summary>
/// <param name="objs">The objects that should be included.</param>
/// <param name="membersToStore">Specify what member types to include.</param>
/// <param name="whiteList">Specify which members to include.</param>
/// <param name="flags">The Binding Flags that the members should have.</param>
/// <returns>A History Point with Object States.</returns>
public static HistoryPoint FromObject(object[] objs, ObjectValueType membersToStore, MemberWhiteList whiteList, BindingFlags flags)
{
return FromObject(objs, membersToStore, (object)whiteList, flags);
}
/// <summary>
/// Creates an History Point with Object States automaticly from input.
/// </summary>
/// <param name="objs">The objects that should be included.</param>
/// <param name="membersToStore">Specify what member types to include.</param>
/// <param name="blackList">Specify which members to exclude.</param>
/// <param name="flags">The Binding Flags that the members should have.</param>
/// <returns>A History Point with Object States.</returns>
public static HistoryPoint FromObject(object[] objs, ObjectValueType membersToStore, MemberBlackList blackList, BindingFlags flags)
{
return FromObject(objs, membersToStore, (object)blackList, flags);
}
/// <summary>
/// Creates an History Point with Object States automaticly from input.
/// </summary>
/// <param name="objs">The objects that should be included.</param>
/// <param name="membersToStore">Specify what member types to include.</param>
/// <param name="whiteOrBlackList">Specify which members to include.</param>
/// <param name="flags">The Binding Flags that the members should have.</param>
/// <returns>A History Point with Object States.</returns>
private static HistoryPoint FromObject(object[] objs, ObjectValueType membersToStore, object? whiteOrBlackList, BindingFlags flags)
{
var hp = new HistoryPoint();
whiteOrBlackList ??= new MemberBlackList();
var isWhiteList = whiteOrBlackList is MemberWhiteList;
if (flags == BindingFlags.Default)
flags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
if (membersToStore == ObjectValueType.None)
membersToStore = ObjectValueType.Field | ObjectValueType.Property;
foreach (var obj in objs)
{
if ((membersToStore & ObjectValueType.Field) == ObjectValueType.Field)
{
foreach (var fi in obj.GetType().GetFields(flags))
{
var contains = ((List<string>)whiteOrBlackList).Contains(fi.Name);
if (isWhiteList ? contains : !contains)
{
var os = new ObjectState
{
Object = obj,
MemberName = fi.Name,
MemberType = ObjectValueType.Field,
MemberFlags = flags,
ValueToPatch = fi.GetValue(obj)
};
hp.Entries.Add(os);
}
}
}
if ((membersToStore & ObjectValueType.Property) == ObjectValueType.Property)
{
foreach (var pi in obj.GetType().GetProperties(flags))
{
var contains = ((List<string>)whiteOrBlackList).Contains(pi.Name);
if (isWhiteList ? contains : !contains)
{
var os = new ObjectState
{
Object = obj,
MemberName = pi.Name,
MemberType = ObjectValueType.Property,
MemberFlags = flags,
ValueToPatch = pi.GetValue(obj)
};
hp.Entries.Add(os);
}
}
}
}
return hp;
}
/// <summary>
/// Combines some History Points to one.
/// </summary>
/// <param name="hps">An array of History Points to combine.</param>
/// <returns>One History Point that contains all Data of inputted History Points.</returns>
public static HistoryPoint Concat(params HistoryPoint[] hps)
{
return Concat(null, hps);
}
/// <summary>
/// Combines some History Points to one.
/// </summary>
/// <param name="hps">An array of History Points to combine.</param>
/// <param name="newName">The new name for the History Point after concating.</param>
/// <returns>One History Point that contains all Data of inputted History Points.</returns>
public static HistoryPoint Concat(string? newName, params HistoryPoint[] hps)
{
var hp = new HistoryPoint();
foreach (var _hp in hps)
hp.Entries.AddRange(_hp.Entries);
if (newName != null)
hp.Name = newName;
else
hp.Name = hps.FirstOrDefault()?.Name ?? string.Empty;
return hp;
}
}