mirror of
https://github.com/Artemis-RGB/Artemis
synced 2026-11-11 19:36:28 +00:00
Data model paths - Moved all condition code over to the new pats API
This commit is contained in:
1 parent
94bde1fe38
commit
d46a610e23
25 files changed
+238
-179
No files matched your search
@@ -43,7 +43,7 @@ namespace Artemis.Core
|
||||
/// <summary>
|
||||
/// Gets the path of the list property
|
||||
/// </summary>
|
||||
public DataModelPath? ListPath { get; set; }
|
||||
public DataModelPath? ListPath { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the type of the content of the list this predicate is evaluated on
|
||||
@@ -82,15 +82,15 @@ namespace Artemis.Core
|
||||
throw new ArtemisCoreException("Cannot update list to an invalid path");
|
||||
|
||||
ListPath?.Dispose();
|
||||
ListPath = path;
|
||||
ListPath = path != null ? new DataModelPath(path) : null;
|
||||
|
||||
// Remove the old root group that was tied to the old data model
|
||||
while (Children.Any())
|
||||
RemoveChild(Children[0]);
|
||||
|
||||
if (path != null)
|
||||
if (ListPath != null)
|
||||
{
|
||||
Type listType = path.GetPropertyType()!;
|
||||
Type listType = ListPath.GetPropertyType()!;
|
||||
ListType = listType.GetGenericArguments()[0];
|
||||
IsPrimitiveList = ListType.IsPrimitive || ListType.IsEnum || ListType == typeof(string);
|
||||
|
||||
@@ -99,7 +99,6 @@ namespace Artemis.Core
|
||||
}
|
||||
else
|
||||
{
|
||||
ListPath = null;
|
||||
ListType = null;
|
||||
}
|
||||
}
|
||||
@@ -171,12 +170,21 @@ namespace Artemis.Core
|
||||
// Ensure the list path is valid and points to a list
|
||||
DataModelPath listPath = new DataModelPath(null, Entity.ListPath);
|
||||
Type listType = listPath.GetPropertyType()!;
|
||||
if (!listPath.IsValid || !typeof(IList).IsAssignableFrom(listType))
|
||||
// Can't check this on an invalid list, if it becomes valid later lets hope for the best
|
||||
if (listPath.IsValid && !typeof(IList).IsAssignableFrom(listType))
|
||||
return;
|
||||
|
||||
ListPath = listPath;
|
||||
ListType = listType.GetGenericArguments()[0];
|
||||
IsPrimitiveList = ListType.IsPrimitive || ListType.IsEnum || ListType == typeof(string);
|
||||
if (ListPath.IsValid)
|
||||
{
|
||||
ListType = listType.GetGenericArguments()[0];
|
||||
IsPrimitiveList = ListType.IsPrimitive || ListType.IsEnum || ListType == typeof(string);
|
||||
}
|
||||
else
|
||||
{
|
||||
ListType = null;
|
||||
IsPrimitiveList = false;
|
||||
}
|
||||
|
||||
// There should only be one child and it should be a group
|
||||
if (Entity.Children.SingleOrDefault() is DataModelConditionGroupEntity rootGroup)
|
||||
|
||||
@@ -54,9 +54,15 @@ namespace Artemis.Core
|
||||
/// </summary>
|
||||
public DataModelConditionList DataModelConditionList { get; private set; }
|
||||
|
||||
public DataModelPath? LeftPath { get; set; }
|
||||
/// <summary>
|
||||
/// Gets the path of the left property
|
||||
/// </summary>
|
||||
public DataModelPath? LeftPath { get; private set; }
|
||||
|
||||
public DataModelPath? RightPath { get; set; }
|
||||
/// <summary>
|
||||
/// Gets the path of the right property
|
||||
/// </summary>
|
||||
public DataModelPath? RightPath { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the right static value, only used it <see cref="PredicateType" /> is
|
||||
@@ -70,17 +76,17 @@ namespace Artemis.Core
|
||||
/// Updates the left side of the predicate
|
||||
/// </summary>
|
||||
/// <param name="path">The path pointing to the left side value inside the list</param>
|
||||
public void UpdateLeftSide(string? path)
|
||||
public void UpdateLeftSide(DataModelPath? path)
|
||||
{
|
||||
if (DataModelConditionList.IsPrimitiveList)
|
||||
throw new ArtemisCoreException("Cannot apply a left side to a predicate inside a primitive list");
|
||||
|
||||
if (path != null && !path.IsValid)
|
||||
throw new ArtemisCoreException("Cannot update left side of predicate to an invalid path");
|
||||
|
||||
LeftPath?.Dispose();
|
||||
if (path != null && DataModelConditionList.ListType != null)
|
||||
LeftPath = new DataModelPath(ListPredicateWrapperDataModel.Create(DataModelConditionList.ListType), path);
|
||||
else
|
||||
LeftPath = null;
|
||||
|
||||
LeftPath = path != null ? new DataModelPath(path) : null;
|
||||
|
||||
ValidateOperator();
|
||||
ValidateRightSide();
|
||||
}
|
||||
@@ -92,8 +98,11 @@ namespace Artemis.Core
|
||||
/// <param name="path">The path pointing to the right side value inside the list</param>
|
||||
public void UpdateRightSideDynamicList(DataModelPath? path)
|
||||
{
|
||||
if (path != null && !path.IsValid)
|
||||
throw new ArtemisCoreException("Cannot update right side of predicate to an invalid path");
|
||||
|
||||
RightPath?.Dispose();
|
||||
RightPath = path;
|
||||
RightPath = path != null ? new DataModelPath(path) : null;
|
||||
|
||||
PredicateType = ListRightSideType.DynamicList;
|
||||
}
|
||||
|
||||
@@ -48,12 +48,12 @@ namespace Artemis.Core
|
||||
/// <summary>
|
||||
/// Gets the path of the left property
|
||||
/// </summary>
|
||||
public DataModelPath? LeftPath { get; set; }
|
||||
public DataModelPath? LeftPath { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the path of the right property
|
||||
/// </summary>
|
||||
public DataModelPath? RightPath { get; set; }
|
||||
public DataModelPath? RightPath { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the right static value, only used it <see cref="PredicateType" /> is
|
||||
@@ -66,27 +66,14 @@ namespace Artemis.Core
|
||||
/// <summary>
|
||||
/// Updates the left side of the predicate
|
||||
/// </summary>
|
||||
/// <param name="dataModel">The data model of the left side value</param>
|
||||
/// <param name="path">The path pointing to the left side value inside the data model</param>
|
||||
public void UpdateLeftSide(DataModel? dataModel, string? path)
|
||||
public void UpdateLeftSide(DataModelPath? path)
|
||||
{
|
||||
if (dataModel != null && path == null)
|
||||
throw new ArtemisCoreException("If a data model is provided, a path is also required");
|
||||
if (dataModel == null && path != null)
|
||||
throw new ArtemisCoreException("If path is provided, a data model is also required");
|
||||
if (path != null && !path.IsValid)
|
||||
throw new ArtemisCoreException("Cannot update left side of predicate to an invalid path");
|
||||
|
||||
LeftPath?.Dispose();
|
||||
if (dataModel != null)
|
||||
{
|
||||
DataModelPath newPath = new DataModelPath(dataModel, path);
|
||||
if (!newPath.IsValid)
|
||||
throw new ArtemisCoreException($"New left path '{newPath}' is invalid");
|
||||
LeftPath = newPath;
|
||||
}
|
||||
else
|
||||
{
|
||||
LeftPath = null;
|
||||
}
|
||||
LeftPath = path != null ? new DataModelPath(path) : null;
|
||||
|
||||
ValidateOperator();
|
||||
ValidateRightSide();
|
||||
@@ -95,27 +82,14 @@ namespace Artemis.Core
|
||||
/// <summary>
|
||||
/// Updates the right side of the predicate, makes the predicate dynamic and re-compiles the expression
|
||||
/// </summary>
|
||||
/// <param name="dataModel">The data model of the right side value</param>
|
||||
/// <param name="path">The path pointing to the right side value inside the data model</param>
|
||||
public void UpdateRightSide(DataModel? dataModel, string? path)
|
||||
public void UpdateRightSideDynamic(DataModelPath? path)
|
||||
{
|
||||
if (dataModel != null && path == null)
|
||||
throw new ArtemisCoreException("If a data model is provided, a path is also required");
|
||||
if (dataModel == null && path != null)
|
||||
throw new ArtemisCoreException("If path is provided, a data model is also required");
|
||||
if (path != null && !path.IsValid)
|
||||
throw new ArtemisCoreException("Cannot update right side of predicate to an invalid path");
|
||||
|
||||
RightPath?.Dispose();
|
||||
if (dataModel != null)
|
||||
{
|
||||
DataModelPath newPath = new DataModelPath(dataModel, path);
|
||||
if (!newPath.IsValid)
|
||||
throw new ArtemisCoreException($"New right path '{newPath}' is invalid");
|
||||
RightPath = newPath;
|
||||
}
|
||||
else
|
||||
{
|
||||
RightPath = null;
|
||||
}
|
||||
RightPath = path != null ? new DataModelPath(path) : null;
|
||||
|
||||
PredicateType = ProfileRightSideType.Dynamic;
|
||||
}
|
||||
@@ -124,7 +98,7 @@ namespace Artemis.Core
|
||||
/// Updates the right side of the predicate, makes the predicate static and re-compiles the expression
|
||||
/// </summary>
|
||||
/// <param name="staticValue">The right side value to use</param>
|
||||
public void UpdateRightSide(object? staticValue)
|
||||
public void UpdateRightSideStatic(object? staticValue)
|
||||
{
|
||||
PredicateType = ProfileRightSideType.Static;
|
||||
RightPath?.Dispose();
|
||||
@@ -253,7 +227,7 @@ namespace Artemis.Core
|
||||
ConditionOperatorStore.ConditionOperatorRemoved += ConditionOperatorStoreOnConditionOperatorRemoved;
|
||||
|
||||
// Left side
|
||||
if (Entity.LeftPath != null)
|
||||
if (Entity.LeftPath != null)
|
||||
LeftPath = new DataModelPath(null, Entity.LeftPath);
|
||||
|
||||
// Operator
|
||||
@@ -288,12 +262,12 @@ namespace Artemis.Core
|
||||
rightSideValue = Activator.CreateInstance(leftSideType);
|
||||
}
|
||||
|
||||
UpdateRightSide(rightSideValue);
|
||||
UpdateRightSideStatic(rightSideValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Hope for the best...
|
||||
UpdateRightSide(JsonConvert.DeserializeObject(Entity.RightStaticValue));
|
||||
UpdateRightSideStatic(JsonConvert.DeserializeObject(Entity.RightStaticValue));
|
||||
}
|
||||
}
|
||||
catch (JsonReaderException)
|
||||
@@ -328,14 +302,14 @@ namespace Artemis.Core
|
||||
|
||||
Type rightSideType = RightPath.GetPropertyType()!;
|
||||
if (leftType != null && !leftType.IsCastableFrom(rightSideType))
|
||||
UpdateRightSide(null, null);
|
||||
UpdateRightSideDynamic(null);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (RightStaticValue != null && (leftType == null || leftType.IsCastableFrom(RightStaticValue.GetType())))
|
||||
UpdateRightSide(RightStaticValue);
|
||||
UpdateRightSideStatic(RightStaticValue);
|
||||
else
|
||||
UpdateRightSide(null);
|
||||
UpdateRightSideStatic(null);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@ namespace Artemis.Core
|
||||
/// </summary>
|
||||
public class DataModelPath : IStorageModel, IDisposable
|
||||
{
|
||||
private bool _disposed;
|
||||
private readonly LinkedList<DataModelPathSegment> _segments;
|
||||
private Expression<Func<object, object>>? _accessorLambda;
|
||||
|
||||
@@ -52,6 +53,26 @@ namespace Artemis.Core
|
||||
SubscribeToDataModelStore();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of the <see cref="DataModelPath" /> class based on an existing path
|
||||
/// </summary>
|
||||
/// <param name="dataModelPath">The path to base the new instance on</param>
|
||||
public DataModelPath(DataModelPath dataModelPath)
|
||||
{
|
||||
if (dataModelPath == null)
|
||||
throw new ArgumentNullException(nameof(dataModelPath));
|
||||
|
||||
Target = dataModelPath.Target;
|
||||
Path = dataModelPath.Path;
|
||||
Entity = new DataModelPathEntity();
|
||||
|
||||
_segments = new LinkedList<DataModelPathSegment>();
|
||||
|
||||
Save();
|
||||
Initialize();
|
||||
SubscribeToDataModelStore();
|
||||
}
|
||||
|
||||
internal DataModelPath(DataModel? target, DataModelPathEntity entity)
|
||||
{
|
||||
Target = target;
|
||||
@@ -65,26 +86,11 @@ namespace Artemis.Core
|
||||
SubscribeToDataModelStore();
|
||||
}
|
||||
|
||||
internal DataModelPath(DataModelPath dataModelPath)
|
||||
{
|
||||
Target = dataModelPath.Target;
|
||||
Path = dataModelPath.Path;
|
||||
Entity = new DataModelPathEntity();
|
||||
|
||||
_segments = new LinkedList<DataModelPathSegment>();
|
||||
|
||||
Save();
|
||||
Initialize();
|
||||
SubscribeToDataModelStore();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the data model at which this path starts
|
||||
/// </summary>
|
||||
public DataModel? Target { get; private set; }
|
||||
|
||||
internal DataModelPathEntity Entity { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the data model GUID of the <see cref="Target" /> if it is a <see cref="DataModel" />
|
||||
/// </summary>
|
||||
@@ -108,7 +114,10 @@ namespace Artemis.Core
|
||||
/// <summary>
|
||||
/// Gets a boolean indicating whether this data model path points to a list
|
||||
/// </summary>
|
||||
public bool PointsToList => Segments.LastOrDefault()?.GetPropertyType() != null && typeof(IList).IsAssignableFrom(Segments.LastOrDefault()?.GetPropertyType());
|
||||
public bool PointsToList => Segments.LastOrDefault()?.GetPropertyType() != null &&
|
||||
typeof(IList).IsAssignableFrom(Segments.LastOrDefault()?.GetPropertyType());
|
||||
|
||||
internal DataModelPathEntity Entity { get; }
|
||||
|
||||
internal Func<object, object>? Accessor { get; private set; }
|
||||
|
||||
@@ -117,6 +126,9 @@ namespace Artemis.Core
|
||||
/// </summary>
|
||||
public object? GetValue()
|
||||
{
|
||||
if (_disposed)
|
||||
throw new ObjectDisposedException("DataModelPath");
|
||||
|
||||
if (_accessorLambda == null || Target == null)
|
||||
return null;
|
||||
|
||||
@@ -132,6 +144,9 @@ namespace Artemis.Core
|
||||
/// <returns>If static, the property info. If dynamic, <c>null</c></returns>
|
||||
public PropertyInfo? GetPropertyInfo()
|
||||
{
|
||||
if (_disposed)
|
||||
throw new ObjectDisposedException("DataModelPath");
|
||||
|
||||
return Segments.LastOrDefault()?.GetPropertyInfo();
|
||||
}
|
||||
|
||||
@@ -141,6 +156,9 @@ namespace Artemis.Core
|
||||
/// <returns>If possible, the property type</returns>
|
||||
public Type? GetPropertyType()
|
||||
{
|
||||
if (_disposed)
|
||||
throw new ObjectDisposedException("DataModelPath");
|
||||
|
||||
return Segments.LastOrDefault()?.GetPropertyType();
|
||||
}
|
||||
|
||||
@@ -150,6 +168,9 @@ namespace Artemis.Core
|
||||
/// <returns>If found, the data model property description</returns>
|
||||
public DataModelPropertyAttribute? GetPropertyDescription()
|
||||
{
|
||||
if (_disposed)
|
||||
throw new ObjectDisposedException("DataModelPath");
|
||||
|
||||
return Segments.LastOrDefault()?.GetPropertyDescription();
|
||||
}
|
||||
|
||||
@@ -186,7 +207,9 @@ namespace Artemis.Core
|
||||
for (int index = 0; index < segments.Length; index++)
|
||||
{
|
||||
string identifier = segments[index];
|
||||
LinkedListNode<DataModelPathSegment> node = _segments.AddLast(new DataModelPathSegment(this, identifier, string.Join('.', segments.Take(index + 1))));
|
||||
LinkedListNode<DataModelPathSegment> node = _segments.AddLast(
|
||||
new DataModelPathSegment(this, identifier, string.Join('.', segments.Take(index + 1)))
|
||||
);
|
||||
node.Value.Node = node;
|
||||
}
|
||||
}
|
||||
@@ -224,6 +247,21 @@ namespace Artemis.Core
|
||||
DataModelStore.DataModelRemoved += DataModelStoreOnDataModelRemoved;
|
||||
}
|
||||
|
||||
#region IDisposable
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Dispose()
|
||||
{
|
||||
_disposed = true;
|
||||
|
||||
DataModelStore.DataModelAdded -= DataModelStoreOnDataModelAdded;
|
||||
DataModelStore.DataModelRemoved -= DataModelStoreOnDataModelRemoved;
|
||||
|
||||
Invalidate();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Storage
|
||||
|
||||
/// <inheritdoc />
|
||||
@@ -238,25 +276,16 @@ namespace Artemis.Core
|
||||
/// <inheritdoc />
|
||||
public void Save()
|
||||
{
|
||||
// Do not save an invalid state
|
||||
if (!IsValid)
|
||||
return;
|
||||
|
||||
Entity.Path = Path;
|
||||
Entity.DataModelGuid = DataModelGuid;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IDisposable
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Dispose()
|
||||
{
|
||||
DataModelStore.DataModelAdded -= DataModelStoreOnDataModelAdded;
|
||||
DataModelStore.DataModelRemoved -= DataModelStoreOnDataModelRemoved;
|
||||
|
||||
Invalidate();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Event handlers
|
||||
|
||||
private void DataModelStoreOnDataModelAdded(object? sender, DataModelStoreEvent e)
|
||||
|
||||
Reference in new issue
Block a user