mirror of
https://github.com/Artemis-RGB/Artemis
synced 2025-12-13 05:48:35 +00:00
163 lines
5.9 KiB
C#
163 lines
5.9 KiB
C#
using System;
|
|
using Artemis.Storage.Entities.Profile;
|
|
using Artemis.Storage.Entities.Profile.Conditions;
|
|
|
|
namespace Artemis.Core
|
|
{
|
|
/// <summary>
|
|
/// A predicate like evaluated inside a <see cref="DataModelConditionEvent" />
|
|
/// </summary>
|
|
public class DataModelConditionEventPredicate : DataModelConditionPredicate
|
|
{
|
|
/// <summary>
|
|
/// Creates a new instance of the <see cref="DataModelConditionEventPredicate" /> class
|
|
/// </summary>
|
|
/// <param name="parent"></param>
|
|
/// <param name="predicateType"></param>
|
|
public DataModelConditionEventPredicate(DataModelConditionPart parent, ProfileRightSideType predicateType)
|
|
: base(parent, predicateType, new DataModelConditionEventPredicateEntity())
|
|
{
|
|
DataModelConditionEvent = null!;
|
|
ApplyParentEvent();
|
|
Initialize();
|
|
}
|
|
|
|
internal DataModelConditionEventPredicate(DataModelConditionPart parent, DataModelConditionEventPredicateEntity entity)
|
|
: base(parent, entity)
|
|
{
|
|
DataModelConditionEvent = null!;
|
|
ApplyParentEvent();
|
|
Initialize();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the data model condition event this predicate belongs to
|
|
/// </summary>
|
|
public DataModelConditionEvent DataModelConditionEvent { get; private set; }
|
|
|
|
private void ApplyParentEvent()
|
|
{
|
|
DataModelConditionPart? current = Parent;
|
|
while (current != null)
|
|
{
|
|
if (current is DataModelConditionEvent parentEvent)
|
|
{
|
|
DataModelConditionEvent = parentEvent;
|
|
return;
|
|
}
|
|
|
|
current = current.Parent;
|
|
}
|
|
|
|
if (DataModelConditionEvent == null)
|
|
throw new ArtemisCoreException("This data model condition event predicate does not belong to a data model condition event");
|
|
}
|
|
|
|
private object? GetEventPathValue(DataModelPath path, object? target)
|
|
{
|
|
lock (path)
|
|
{
|
|
if (!(path.Target is EventPredicateWrapperDataModel wrapper))
|
|
throw new ArtemisCoreException("Data model condition event predicate has a path with an invalid target");
|
|
|
|
wrapper.UntypedArguments = target;
|
|
return path.GetValue();
|
|
}
|
|
}
|
|
|
|
#region Initialization
|
|
|
|
/// <inheritdoc />
|
|
protected override void InitializeLeftPath()
|
|
{
|
|
if (Entity.LeftPath != null)
|
|
LeftPath = DataModelConditionEvent.EventArgumentType != null
|
|
? new DataModelPath(EventPredicateWrapperDataModel.Create(DataModelConditionEvent.EventArgumentType), Entity.LeftPath)
|
|
: null;
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
protected override void InitializeRightPath()
|
|
{
|
|
if (PredicateType == ProfileRightSideType.Dynamic && Entity.RightPath != null)
|
|
{
|
|
// Right side dynamic using event arguments
|
|
if (Entity.RightPath.WrapperType == PathWrapperType.Event)
|
|
{
|
|
RightPath = DataModelConditionEvent.EventArgumentType != null
|
|
? new DataModelPath(EventPredicateWrapperDataModel.Create(DataModelConditionEvent.EventArgumentType), Entity.RightPath)
|
|
: null;
|
|
}
|
|
// Right side dynamic
|
|
else
|
|
RightPath = new DataModelPath(null, Entity.RightPath);
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Modification
|
|
|
|
/// <inheritdoc />
|
|
public override Type? GetPreferredRightSideType()
|
|
{
|
|
Type? preferredType = Operator?.RightSideType;
|
|
Type? leftSideType = LeftPath?.GetPropertyType();
|
|
if (preferredType == null)
|
|
return null;
|
|
|
|
if (leftSideType != null && preferredType.IsAssignableFrom(leftSideType))
|
|
preferredType = leftSideType;
|
|
|
|
return preferredType;
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Evaluation
|
|
|
|
/// <summary>
|
|
/// Not supported for event predicates, always returns <c>false</c>
|
|
/// </summary>
|
|
public override bool Evaluate()
|
|
{
|
|
return false;
|
|
}
|
|
|
|
internal override bool EvaluateObject(object? target)
|
|
{
|
|
if (Operator == null || LeftPath == null || !LeftPath.IsValid)
|
|
return false;
|
|
|
|
// If the operator does not support a right side, immediately evaluate with null
|
|
if (Operator.RightSideType == null)
|
|
return Operator.InternalEvaluate(GetEventPathValue(LeftPath, target), null);
|
|
|
|
// Compare with a static value
|
|
if (PredicateType == ProfileRightSideType.Static)
|
|
{
|
|
object? leftSideValue = GetEventPathValue(LeftPath, target);
|
|
if (leftSideValue != null && leftSideValue.GetType().IsValueType && RightStaticValue == null)
|
|
return false;
|
|
|
|
return Operator.InternalEvaluate(leftSideValue, RightStaticValue);
|
|
}
|
|
|
|
if (RightPath == null || !RightPath.IsValid)
|
|
return false;
|
|
|
|
// Compare with dynamic values
|
|
if (PredicateType == ProfileRightSideType.Dynamic)
|
|
{
|
|
// If the path targets a property inside the event, evaluate on the event path value instead of the right path value
|
|
if (RightPath.Target is EventPredicateWrapperDataModel)
|
|
return Operator.InternalEvaluate(GetEventPathValue(LeftPath, target), GetEventPathValue(RightPath, target));
|
|
return Operator.InternalEvaluate(GetEventPathValue(LeftPath, target), RightPath.GetValue());
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
#endregion
|
|
}
|
|
} |