using System; using System.Linq; using Artemis.Storage.Entities.Profile.Abstract; using Artemis.Storage.Entities.Profile.Conditions; namespace Artemis.Core { /// /// A group containing zero to many s which it evaluates using a boolean specific /// operator /// public class DisplayConditionGroup : DisplayConditionPart { private bool _disposed; /// /// Creates a new instance of the class /// /// public DisplayConditionGroup(DisplayConditionPart parent) { Parent = parent; Entity = new DisplayConditionGroupEntity(); } /// /// Creates a new instance of the class /// /// /// public DisplayConditionGroup(DisplayConditionPart parent, DisplayConditionGroupEntity entity) { Parent = parent; Entity = entity; BooleanOperator = (BooleanOperator) Entity.BooleanOperator; foreach (var childEntity in Entity.Children) { if (childEntity is DisplayConditionGroupEntity groupEntity) AddChild(new DisplayConditionGroup(this, groupEntity)); else if (childEntity is DisplayConditionListEntity listEntity) AddChild(new DisplayConditionList(this, listEntity)); else if (childEntity is DisplayConditionPredicateEntity predicateEntity) AddChild(new DisplayConditionPredicate(this, predicateEntity)); else if (childEntity is DisplayConditionListPredicateEntity listPredicateEntity) AddChild(new DisplayConditionListPredicate(this, listPredicateEntity)); } } /// /// Gets or sets the boolean operator of this group /// public BooleanOperator BooleanOperator { get; set; } internal DisplayConditionGroupEntity Entity { get; set; } /// public override bool Evaluate() { if (_disposed) throw new ObjectDisposedException("DisplayConditionGroup"); // Empty groups are always true if (Children.Count == 0) return true; // Groups with only one child ignore the boolean operator if (Children.Count == 1) return Children[0].Evaluate(); switch (BooleanOperator) { case BooleanOperator.And: return Children.All(c => c.Evaluate()); case BooleanOperator.Or: return Children.Any(c => c.Evaluate()); case BooleanOperator.AndNot: return Children.All(c => !c.Evaluate()); case BooleanOperator.OrNot: return Children.Any(c => !c.Evaluate()); default: throw new ArgumentOutOfRangeException(); } } /// public override bool EvaluateObject(object target) { if (_disposed) throw new ObjectDisposedException("DisplayConditionGroup"); // Empty groups are always true if (Children.Count == 0) return true; // Groups with only one child ignore the boolean operator if (Children.Count == 1) return Children[0].EvaluateObject(target); return BooleanOperator switch { BooleanOperator.And => Children.All(c => c.EvaluateObject(target)), BooleanOperator.Or => Children.Any(c => c.EvaluateObject(target)), BooleanOperator.AndNot => Children.All(c => !c.EvaluateObject(target)), BooleanOperator.OrNot => Children.Any(c => !c.EvaluateObject(target)), _ => throw new ArgumentOutOfRangeException() }; } internal override void Save() { Entity.BooleanOperator = (int) BooleanOperator; Entity.Children.Clear(); Entity.Children.AddRange(Children.Select(c => c.GetEntity())); foreach (var child in Children) child.Save(); } internal override DisplayConditionPartEntity GetEntity() { return Entity; } #region IDisposable protected override void Dispose(bool disposing) { _disposed = true; foreach (var child in Children) child.Dispose(); base.Dispose(disposing); } #endregion } public enum BooleanOperator { And, Or, AndNot, OrNot } }