Conditions - Move to new paths API (more WIP)

This commit is contained in:
Robert committed 2020-10-07 23:15:10 +02:00
1 parent da132fa4e9
commit 9417332a07
7 files changed
+81 -59

No files matched your search

@@ -25,6 +25,7 @@ namespace Artemis.Core
PredicateType = predicateType;
Entity = new DataModelConditionListPredicateEntity();
DataModelConditionList = null!;
ApplyParentList();
Initialize();
}
@@ -35,6 +36,7 @@ namespace Artemis.Core
Entity = entity;
PredicateType = (ListRightSideType) entity.PredicateType;
DataModelConditionList = null!;
ApplyParentList();
Initialize();
}
@@ -49,37 +51,22 @@ namespace Artemis.Core
/// <summary>
/// Gets the operator
/// </summary>
public ConditionOperator Operator { get; private set; }
public ConditionOperator? Operator { get; private set; }
/// <summary>
/// Gets the data model condition list this predicate belongs to
/// </summary>
public DataModelConditionList DataModelConditionList { get; private set; }
/// <summary>
/// Gets the path of the left property in the <see cref="ListType" />
/// </summary>
public string LeftPropertyPath { get; private set; }
public DataModelPath? LeftPath { get; set; }
/// <summary>
/// Gets the currently used instance of the right side data model
/// <para>Note: This is null when using a path inside the list</para>
/// </summary>
public DataModel RightDataModel { get; set; }
/// <summary>
/// Gets the path of the right property in the <see cref="ListType" />
/// </summary>
public string RightPropertyPath { get; private set; }
public DataModelPath? RightPath { get; set; }
/// <summary>
/// Gets the right static value, only used it <see cref="PredicateType" /> is
/// <see cref="ListRightSideType.Static" />
/// </summary>
public object RightStaticValue { get; private set; }
public Func<object, object> LeftSideAccessor { get; set; }
public Func<object, object> RightSideAccessor { get; set; }
public object? RightStaticValue { get; private set; }
/// <summary>
/// Updates the left side of the predicate
@@ -92,7 +79,8 @@ namespace Artemis.Core
if (!ListContainsInnerPath(path))
throw new ArtemisCoreException($"List type {DataModelConditionList.ListType.Name} does not contain path {path}");
LeftPropertyPath = path;
LeftPath?.Dispose();
LeftPath = new DataModelPath(new ListPredicateWrapperDataModel(), path);
ValidateOperator();
ValidateRightSide();
@@ -110,7 +98,8 @@ namespace Artemis.Core
throw new ArtemisCoreException($"List type {DataModelConditionList.ListType.Name} does not contain path {path}");
PredicateType = ListRightSideType.DynamicList;
RightPropertyPath = path;
RightPath?.Dispose();
RightPath = new DataModelPath(new ListPredicateWrapperDataModel(), path);
CreateExpression();
}
@@ -135,8 +124,8 @@ namespace Artemis.Core
}
PredicateType = ListRightSideType.Dynamic;
RightDataModel = dataModel;
RightPropertyPath = path;
RightPath?.Dispose();
RightPath = new DataModelPath(dataModel, path);
CreateExpression();
}
@@ -148,7 +137,8 @@ namespace Artemis.Core
public void UpdateRightSideStatic(object staticValue)
{
PredicateType = ListRightSideType.Static;
RightPropertyPath = null;
RightPath?.Dispose();
RightPath = null;
SetStaticValue(staticValue);
CreateExpression();
@@ -166,13 +156,18 @@ namespace Artemis.Core
return;
}
if (LeftPropertyPath == null)
// No need to clear compiled expressions, without a left data model they are already null
if (LeftPath == null || !LeftPath.IsValid)
{
Operator = conditionOperator;
return;
}
Type leftType = GetTypeAtInnerPath(LeftPropertyPath);
Type leftType = LeftPath.GetPropertyType()!;
if (!conditionOperator.SupportsType(leftType))
throw new ArtemisCoreException($"Cannot apply operator {conditionOperator.GetType().Name} to this predicate because " +
$"it does not support left side type {leftType.Name}");
if (conditionOperator.SupportsType(leftType))
Operator = conditionOperator;
@@ -209,26 +204,30 @@ namespace Artemis.Core
return true;
}
internal override bool EvaluateObject(object target)
{
if (Operator == null || LeftSideAccessor == null || PredicateType != ListRightSideType.Static && RightSideAccessor == null)
if (Operator == null || LeftPath == null || !LeftPath.IsValid)
return false;
// Compare with a static value
if (PredicateType == ListRightSideType.Static)
{
if (!DataModelConditionList.ListType.IsValueType && RightStaticValue == null)
object? leftSideValue = GetListPathValue(LeftPath, target);
if (leftSideValue != null && leftSideValue.GetType().IsValueType && RightStaticValue == null)
return false;
return Operator.Evaluate(LeftSideAccessor(target), RightStaticValue);
return Operator.Evaluate(leftSideValue, RightStaticValue);
}
if (RightPath == null || !RightPath.IsValid)
return false;
// Compare with dynamic values
if (PredicateType == ListRightSideType.Dynamic)
return Operator.Evaluate(LeftSideAccessor(target), RightSideAccessor(RightDataModel));
return Operator.Evaluate(GetListPathValue(LeftPath, target), RightPath.GetValue());
if (PredicateType == ListRightSideType.DynamicList)
return Operator.Evaluate(LeftSideAccessor(target), RightSideAccessor(target));
return Operator.Evaluate(GetListPathValue(LeftPath, target), GetListPathValue(RightPath, target));
return false;
}
@@ -444,6 +443,15 @@ namespace Artemis.Core
RightStaticValue = null;
}
private object? GetListPathValue(DataModelPath path, object target)
{
if (!(path.Target is ListPredicateWrapperDataModel wrapper))
throw new ArtemisCoreException("Data model condition list predicate has a path with an invalid target");
wrapper.Value = target;
return path.GetValue();
}
private void CreateDynamicListAccessors()
{
if (LeftPropertyPath == null || RightPropertyPath == null || Operator == null)
@@ -515,6 +523,9 @@ namespace Artemis.Core
ConditionOperatorStore.ConditionOperatorAdded -= ConditionOperatorStoreOnConditionOperatorAdded;
ConditionOperatorStore.ConditionOperatorRemoved -= ConditionOperatorStoreOnConditionOperatorRemoved;
LeftPath?.Dispose();
RightPath?.Dispose();
base.Dispose(disposing);
}
@@ -0,0 +1,9 @@
using Artemis.Core.DataModelExpansions;
namespace Artemis.Core
{
internal class ListPredicateWrapperDataModel : DataModel
{
public object Value { get; set; }
}
}
@@ -21,13 +21,11 @@ namespace Artemis.Core
/// Creates a new instance of the <see cref="DataModelPath" /> class pointing directly to the target
/// </summary>
/// <param name="target">The target at which this path starts</param>
public DataModelPath(object target)
public DataModelPath(DataModel target)
{
Target = target ?? throw new ArgumentNullException(nameof(target));
Path = "";
Entity = new DataModelPathEntity();
if (Target is DataModel dataModel)
DataModelGuid = dataModel.PluginInfo.Guid;
_segments = new LinkedList<DataModelPathSegment>();
@@ -41,13 +39,11 @@ namespace Artemis.Core
/// </summary>
/// <param name="target">The target at which this path starts</param>
/// <param name="path">A point-separated path</param>
public DataModelPath(object target, string path)
public DataModelPath(DataModel target, string path)
{
Target = target ?? throw new ArgumentNullException(nameof(target));
Path = path ?? throw new ArgumentNullException(nameof(path));
Entity = new DataModelPathEntity();
if (Target is DataModel dataModel)
DataModelGuid = dataModel.PluginInfo.Guid;
_segments = new LinkedList<DataModelPathSegment>();
@@ -56,9 +52,9 @@ namespace Artemis.Core
SubscribeToDataModelStore();
}
internal DataModelPath(object? target, DataModelPathEntity entity)
internal DataModelPath(DataModel? target, DataModelPathEntity entity)
{
Target = target!;
Target = target;
Path = entity.Path;
Entity = entity;
@@ -72,14 +68,14 @@ namespace Artemis.Core
/// <summary>
/// Gets the data model at which this path starts
/// </summary>
public object? Target { get; private set; }
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>
public Guid? DataModelGuid { get; private set; }
public Guid? DataModelGuid => Target?.PluginInfo.Guid;
/// <summary>
/// Gets the point-separated path associated with this <see cref="DataModelPath" />
@@ -221,10 +217,9 @@ namespace Artemis.Core
public void Load()
{
Path = Entity.Path;
DataModelGuid = Entity.DataModelGuid;
if (Target == null && Entity.DataModelGuid != null)
Target = DataModelStore.Get(Entity.DataModelGuid.Value);
if (Target == null && Entity.DataModelGuid != null)
Target = DataModelStore.Get(Entity.DataModelGuid.Value)?.DataModel;
}
/// <inheritdoc />
@@ -253,7 +248,7 @@ namespace Artemis.Core
private void DataModelStoreOnDataModelAdded(object? sender, DataModelStoreEvent e)
{
if (e.Registration.DataModel.PluginInfo.Guid != DataModelGuid)
if (e.Registration.DataModel.PluginInfo.Guid != Entity.DataModelGuid)
return;
Target = e.Registration.DataModel;
@@ -262,7 +257,7 @@ namespace Artemis.Core
private void DataModelStoreOnDataModelRemoved(object? sender, DataModelStoreEvent e)
{
if (e.Registration.DataModel.PluginInfo.Guid != DataModelGuid)
if (e.Registration.DataModel.PluginInfo.Guid != Entity.DataModelGuid)
return;
Target = null;