mirror of
https://github.com/Artemis-RGB/Artemis
synced 2025-12-13 05:48:35 +00:00
Display conditions - Moved pridacte update logic from VM to model
This commit is contained in:
parent
f39e4d719c
commit
4dfc61ab7d
@ -10,12 +10,13 @@ namespace Artemis.Core.Models.Profile.Conditions
|
|||||||
{
|
{
|
||||||
Parent = parent;
|
Parent = parent;
|
||||||
EntityId = Guid.NewGuid();
|
EntityId = Guid.NewGuid();
|
||||||
|
DisplayConditionGroupEntity = new DisplayConditionGroupEntity();
|
||||||
}
|
}
|
||||||
|
|
||||||
public DisplayConditionGroup(DisplayConditionPart parent, DisplayConditionGroupEntity entity)
|
public DisplayConditionGroup(DisplayConditionPart parent, DisplayConditionGroupEntity entity)
|
||||||
{
|
{
|
||||||
DisplayConditionGroupEntity = entity;
|
|
||||||
Parent = parent;
|
Parent = parent;
|
||||||
|
DisplayConditionGroupEntity = entity;
|
||||||
EntityId = DisplayConditionGroupEntity.Id;
|
EntityId = DisplayConditionGroupEntity.Id;
|
||||||
BooleanOperator = (BooleanOperator) DisplayConditionGroupEntity.BooleanOperator;
|
BooleanOperator = (BooleanOperator) DisplayConditionGroupEntity.BooleanOperator;
|
||||||
|
|
||||||
|
|||||||
@ -1,9 +1,10 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Linq.Expressions;
|
using System.Linq.Expressions;
|
||||||
|
using Artemis.Core.Exceptions;
|
||||||
|
using Artemis.Core.Extensions;
|
||||||
using Artemis.Core.Models.Profile.Conditions.Abstract;
|
using Artemis.Core.Models.Profile.Conditions.Abstract;
|
||||||
using Artemis.Core.Plugins.Abstract.DataModels;
|
using Artemis.Core.Plugins.Abstract.DataModels;
|
||||||
using Artemis.Core.Services.Interfaces;
|
|
||||||
using Artemis.Storage.Entities.Profile;
|
using Artemis.Storage.Entities.Profile;
|
||||||
|
|
||||||
namespace Artemis.Core.Models.Profile.Conditions
|
namespace Artemis.Core.Models.Profile.Conditions
|
||||||
@ -13,12 +14,17 @@ namespace Artemis.Core.Models.Profile.Conditions
|
|||||||
public DisplayConditionPredicate(DisplayConditionPart parent)
|
public DisplayConditionPredicate(DisplayConditionPart parent)
|
||||||
{
|
{
|
||||||
Parent = parent;
|
Parent = parent;
|
||||||
|
DisplayConditionPredicateEntity = new DisplayConditionPredicateEntity();
|
||||||
}
|
}
|
||||||
|
|
||||||
public DisplayConditionPredicate(DisplayConditionPart parent, DisplayConditionPredicateEntity entity)
|
public DisplayConditionPredicate(DisplayConditionPart parent, DisplayConditionPredicateEntity entity)
|
||||||
{
|
{
|
||||||
Parent = parent;
|
Parent = parent;
|
||||||
DisplayConditionPredicateEntity = entity;
|
DisplayConditionPredicateEntity = entity;
|
||||||
|
|
||||||
|
// TODO: This has to be done from somewhere
|
||||||
|
// LeftDataModel = dataModelService.GetPluginDataModelByGuid(DisplayConditionPredicateEntity.LeftDataModelGuid);
|
||||||
|
// RightDataModel = dataModelService.GetPluginDataModelByGuid(DisplayConditionPredicateEntity.RightDataModelGuid);
|
||||||
}
|
}
|
||||||
|
|
||||||
public DisplayConditionPredicateEntity DisplayConditionPredicateEntity { get; set; }
|
public DisplayConditionPredicateEntity DisplayConditionPredicateEntity { get; set; }
|
||||||
@ -26,51 +32,122 @@ namespace Artemis.Core.Models.Profile.Conditions
|
|||||||
public PredicateType PredicateType { get; set; }
|
public PredicateType PredicateType { get; set; }
|
||||||
public DisplayConditionOperator Operator { get; set; }
|
public DisplayConditionOperator Operator { get; set; }
|
||||||
|
|
||||||
public Guid LeftDataModelGuid { get; set; }
|
public DataModel LeftDataModel { get; private set; }
|
||||||
public string LeftPropertyPath { get; set; }
|
public string LeftPropertyPath { get; private set; }
|
||||||
|
public DataModel RightDataModel { get; private set; }
|
||||||
public Guid RightDataModelGuid { get; set; }
|
public string RightPropertyPath { get; private set; }
|
||||||
public string RightPropertyPath { get; set; }
|
public object RightStaticValue { get; private set; }
|
||||||
|
|
||||||
// TODO: Implement type-checking or perhaps convert it here
|
|
||||||
public object RightStaticValue { get; set; }
|
|
||||||
|
|
||||||
public Expression<Func<DataModel, DataModel, bool>> DynamicConditionLambda { get; private set; }
|
public Expression<Func<DataModel, DataModel, bool>> DynamicConditionLambda { get; private set; }
|
||||||
public Func<DataModel, DataModel, bool> CompiledDynamicConditionLambda { get; private set; }
|
public Func<DataModel, DataModel, bool> CompiledDynamicConditionLambda { get; private set; }
|
||||||
public Expression<Func<DataModel, bool>> StaticConditionLambda { get; private set; }
|
public Expression<Func<DataModel, bool>> StaticConditionLambda { get; private set; }
|
||||||
public Func<DataModel, bool> CompiledStaticConditionLambda { get; private set; }
|
public Func<DataModel, bool> CompiledStaticConditionLambda { get; private set; }
|
||||||
|
|
||||||
public void CreateExpression(IDataModelService dataModelService)
|
public void UpdateLeftSide(DataModel dataModel, string path)
|
||||||
{
|
{
|
||||||
if (PredicateType == PredicateType.Dynamic)
|
if (!dataModel.ContainsPath(path))
|
||||||
CreateDynamicExpression(dataModelService);
|
throw new ArtemisCoreException($"Data model of type {dataModel.GetType().Name} does not contain a property at path '{path}'");
|
||||||
else
|
|
||||||
CreateStaticExpression(dataModelService);
|
LeftDataModel = dataModel;
|
||||||
|
LeftPropertyPath = path;
|
||||||
|
|
||||||
|
ValidateRightSide();
|
||||||
|
CreateExpression();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void CreateDynamicExpression(IDataModelService dataModelService)
|
public void UpdateRightSide(DataModel dataModel, string path)
|
||||||
{
|
{
|
||||||
if (LeftDataModelGuid == Guid.Empty || string.IsNullOrWhiteSpace(LeftPropertyPath))
|
if (!dataModel.ContainsPath(path))
|
||||||
return;
|
throw new ArtemisCoreException($"Data model of type {dataModel.GetType().Name} does not contain a property at path '{path}'");
|
||||||
if (RightDataModelGuid == Guid.Empty || string.IsNullOrWhiteSpace(RightPropertyPath))
|
|
||||||
return;
|
|
||||||
|
|
||||||
var leftDataModel = dataModelService.GetPluginDataModelByGuid(LeftDataModelGuid);
|
PredicateType = PredicateType.Dynamic;
|
||||||
if (leftDataModel == null)
|
RightDataModel = dataModel;
|
||||||
return;
|
RightPropertyPath = path;
|
||||||
|
|
||||||
var rightDataModel = dataModelService.GetPluginDataModelByGuid(RightDataModelGuid);
|
CreateExpression();
|
||||||
if (rightDataModel == null)
|
}
|
||||||
|
|
||||||
|
public void UpdateRightSide(object staticValue)
|
||||||
|
{
|
||||||
|
PredicateType = PredicateType.Static;
|
||||||
|
RightDataModel = null;
|
||||||
|
RightPropertyPath = null;
|
||||||
|
|
||||||
|
SetStaticValue(staticValue);
|
||||||
|
CreateExpression();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void CreateExpression()
|
||||||
|
{
|
||||||
|
if (PredicateType == PredicateType.Dynamic)
|
||||||
|
CreateDynamicExpression();
|
||||||
|
else
|
||||||
|
CreateStaticExpression();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void ApplyToEntity()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Validates the right side, ensuring it is still compatible with the current left side
|
||||||
|
/// </summary>
|
||||||
|
private void ValidateRightSide()
|
||||||
|
{
|
||||||
|
var leftSideType = LeftDataModel.GetTypeAtPath(LeftPropertyPath);
|
||||||
|
if (PredicateType == PredicateType.Dynamic)
|
||||||
|
{
|
||||||
|
var rightSideType = RightDataModel.GetTypeAtPath(RightPropertyPath);
|
||||||
|
if (!leftSideType.IsCastableFrom(rightSideType))
|
||||||
|
UpdateRightSide(null, null);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Just update the value with itself, it'll validate :)
|
||||||
|
UpdateRightSide(RightStaticValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Updates the current static value, ensuring it is a valid type. This assumes the types are compatible if they
|
||||||
|
/// differ.
|
||||||
|
/// </summary>
|
||||||
|
private void SetStaticValue(object staticValue)
|
||||||
|
{
|
||||||
|
// If the left side is empty simply apply the value, any validation will wait
|
||||||
|
if (LeftDataModel == null)
|
||||||
|
{
|
||||||
|
RightStaticValue = staticValue;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var leftSideType = LeftDataModel.GetTypeAtPath(LeftPropertyPath);
|
||||||
|
|
||||||
|
// If not null ensure the types match and if not, convert it
|
||||||
|
if (staticValue != null && staticValue.GetType() == leftSideType)
|
||||||
|
RightStaticValue = staticValue;
|
||||||
|
else if (staticValue != null)
|
||||||
|
RightStaticValue = Convert.ChangeType(staticValue, leftSideType);
|
||||||
|
// If null create a default instance for value types or simply make it null for reference types
|
||||||
|
else if (leftSideType.IsValueType)
|
||||||
|
RightStaticValue = Activator.CreateInstance(leftSideType);
|
||||||
|
else
|
||||||
|
RightStaticValue = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CreateDynamicExpression()
|
||||||
|
{
|
||||||
|
if (LeftDataModel == null || RightDataModel == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var leftSideParameter = Expression.Parameter(typeof(DataModel), "leftDataModel");
|
var leftSideParameter = Expression.Parameter(typeof(DataModel), "leftDataModel");
|
||||||
var leftSideAccessor = LeftPropertyPath.Split('.').Aggregate<string, Expression>(
|
var leftSideAccessor = LeftPropertyPath.Split('.').Aggregate<string, Expression>(
|
||||||
Expression.Convert(leftSideParameter, leftDataModel.GetType()), // Cast to the appropriate type
|
Expression.Convert(leftSideParameter, LeftDataModel.GetType()), // Cast to the appropriate type
|
||||||
Expression.Property
|
Expression.Property
|
||||||
);
|
);
|
||||||
var rightSideParameter = Expression.Parameter(typeof(DataModel), "rightDataModel");
|
var rightSideParameter = Expression.Parameter(typeof(DataModel), "rightDataModel");
|
||||||
var rightSideAccessor = RightPropertyPath.Split('.').Aggregate<string, Expression>(
|
var rightSideAccessor = RightPropertyPath.Split('.').Aggregate<string, Expression>(
|
||||||
Expression.Convert(rightSideParameter, rightDataModel.GetType()), // Cast to the appropriate type
|
Expression.Convert(rightSideParameter, LeftDataModel.GetType()), // Cast to the appropriate type
|
||||||
Expression.Property
|
Expression.Property
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -85,18 +162,14 @@ namespace Artemis.Core.Models.Profile.Conditions
|
|||||||
CompiledDynamicConditionLambda = DynamicConditionLambda.Compile();
|
CompiledDynamicConditionLambda = DynamicConditionLambda.Compile();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void CreateStaticExpression(IDataModelService dataModelService)
|
private void CreateStaticExpression()
|
||||||
{
|
{
|
||||||
if (LeftDataModelGuid == Guid.Empty || string.IsNullOrWhiteSpace(LeftPropertyPath))
|
if (LeftDataModel == null)
|
||||||
return;
|
|
||||||
|
|
||||||
var leftDataModel = dataModelService.GetPluginDataModelByGuid(LeftDataModelGuid);
|
|
||||||
if (leftDataModel == null)
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var leftSideParameter = Expression.Parameter(typeof(DataModel), "leftDataModel");
|
var leftSideParameter = Expression.Parameter(typeof(DataModel), "leftDataModel");
|
||||||
var leftSideAccessor = LeftPropertyPath.Split('.').Aggregate<string, Expression>(
|
var leftSideAccessor = LeftPropertyPath.Split('.').Aggregate<string, Expression>(
|
||||||
Expression.Convert(leftSideParameter, leftDataModel.GetType()), // Cast to the appropriate type
|
Expression.Convert(leftSideParameter, LeftDataModel.GetType()), // Cast to the appropriate type
|
||||||
Expression.Property
|
Expression.Property
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -110,11 +183,6 @@ namespace Artemis.Core.Models.Profile.Conditions
|
|||||||
StaticConditionLambda = Expression.Lambda<Func<DataModel, bool>>(conditionExpression, leftSideParameter);
|
StaticConditionLambda = Expression.Lambda<Func<DataModel, bool>>(conditionExpression, leftSideParameter);
|
||||||
CompiledStaticConditionLambda = StaticConditionLambda.Compile();
|
CompiledStaticConditionLambda = StaticConditionLambda.Compile();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void ApplyToEntity()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum PredicateType
|
public enum PredicateType
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
using Artemis.Core.Plugins.Abstract.DataModels.Attributes;
|
using System;
|
||||||
|
using Artemis.Core.Plugins.Abstract.DataModels.Attributes;
|
||||||
using Artemis.Core.Plugins.Models;
|
using Artemis.Core.Plugins.Models;
|
||||||
|
|
||||||
namespace Artemis.Core.Plugins.Abstract.DataModels
|
namespace Artemis.Core.Plugins.Abstract.DataModels
|
||||||
@ -16,5 +17,39 @@ namespace Artemis.Core.Plugins.Abstract.DataModels
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
[DataModelIgnore]
|
[DataModelIgnore]
|
||||||
public DataModelPropertyAttribute DataModelDescription { get; internal set; }
|
public DataModelPropertyAttribute DataModelDescription { get; internal set; }
|
||||||
|
|
||||||
|
public bool ContainsPath(string path)
|
||||||
|
{
|
||||||
|
var parts = path.Split('.');
|
||||||
|
var current = GetType();
|
||||||
|
foreach (var part in parts)
|
||||||
|
{
|
||||||
|
var property = current?.GetProperty(part);
|
||||||
|
current = property?.PropertyType;
|
||||||
|
if (property == null)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Type GetTypeAtPath(string path)
|
||||||
|
{
|
||||||
|
if (!ContainsPath(path))
|
||||||
|
return null;
|
||||||
|
|
||||||
|
var parts = path.Split('.');
|
||||||
|
var current = GetType();
|
||||||
|
|
||||||
|
Type result = null;
|
||||||
|
foreach (var part in parts)
|
||||||
|
{
|
||||||
|
var property = current.GetProperty(part);
|
||||||
|
current = property.PropertyType;
|
||||||
|
result = property.PropertyType;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -4,6 +4,7 @@ using System.Collections.Generic;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using Artemis.Core.Extensions;
|
using Artemis.Core.Extensions;
|
||||||
|
using Artemis.Core.Models.Profile.Conditions;
|
||||||
using Artemis.Core.Plugins.Abstract.DataModels;
|
using Artemis.Core.Plugins.Abstract.DataModels;
|
||||||
using Artemis.Core.Plugins.Abstract.DataModels.Attributes;
|
using Artemis.Core.Plugins.Abstract.DataModels.Attributes;
|
||||||
using Artemis.UI.Shared.Exceptions;
|
using Artemis.UI.Shared.Exceptions;
|
||||||
@ -113,6 +114,11 @@ namespace Artemis.UI.Shared.DataModelVisualization.Shared
|
|||||||
IsMatchingFilteredTypes = filteredTypes.Any(t => t == PropertyInfo.PropertyType);
|
IsMatchingFilteredTypes = filteredTypes.Any(t => t == PropertyInfo.PropertyType);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public DataModelVisualizationViewModel GetChildForCondition(DisplayConditionPredicate predicate)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
public DataModelVisualizationViewModel GetChildByPath(Guid dataModelGuid, string propertyPath)
|
public DataModelVisualizationViewModel GetChildByPath(Guid dataModelGuid, string propertyPath)
|
||||||
{
|
{
|
||||||
var path = propertyPath.Split(".");
|
var path = propertyPath.Split(".");
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user