using System; using System.Collections.Generic; using System.Linq; namespace HeuristicLab.Problems.ProgramSynthesis.Push.Configuration { using HeuristicLab.Common; using HeuristicLab.Core; using HeuristicLab.Persistence.Default.CompositeSerializers.Storable; using HeuristicLab.Problems.ProgramSynthesis.Push.Expressions; using HeuristicLab.Problems.ProgramSynthesis.Push.Stack; [StorableClass] public abstract class PushConfigurationBase : NamedItem, IEnabledExpressionsConfiguration { protected PushConfigurationBase() { Name = "Push Configuration"; enabledExpressions = ExpressionTable.ExpressionNames.ToList(); enabledStacks = new Dictionary(); InitEnabledStacks(); } [StorableConstructor] protected PushConfigurationBase(bool deserializing) : base(deserializing) { } protected PushConfigurationBase(PushConfigurationBase origin, Cloner cloner) : base(origin, cloner) { enabledExpressions = origin.EnabledExpressions.ToList(); enabledStacks = origin.EnabledStacks.ToDictionary(x => x.Key, x => x.Value); } [Storable] private readonly Dictionary enabledStacks; public IReadOnlyDictionary EnabledStacks { get { return enabledStacks; } } public event EventHandler EnabledExpressionsChanged; [Storable] protected readonly List enabledExpressions; public IList EnabledExpressions { get { return enabledExpressions; } set { var removedExpressions = enabledExpressions.ToArray(); enabledExpressions.Clear(); enabledExpressions.AddRange(value); if (EnabledExpressionsChanged != null) { EnabledExpressionsChanged(this, new EnabledExpressionsChangedEventArgs(value, removedExpressions)); } } } private void InitEnabledStacks(bool state = true) { foreach (StackTypes type in Enum.GetValues(typeof(StackTypes))) { if (!enabledStacks.ContainsKey(type) && type != StackTypes.None) enabledStacks.Add(type, state); } } public void SetEnabledStacks(StackTypes types) { // Disable all EnabledExpressions.Clear(); foreach (StackTypes type in Enum.GetValues(types.GetType())) { if (type == StackTypes.None) continue; enabledStacks[type] = false; } foreach (var pair in ExpressionTable.StackDependencyToNamesTable) { if (types.HasFlag(pair.Key)) { foreach (var name in pair.Value) { EnableExpression(name, true); } } } } public void EnableExpressionOfStack(StackTypes types) { EnableExpressions(ExpressionTable.StackTypeToNamesTable[types]); } public void EnableExpressionDependentOnStack(StackTypes types) { var names = ExpressionTable.StackDependencyToNamesTable[types].Where( name => { var type = ExpressionTable.NameToTypeTable[name]; var attribute = ExpressionTable.TypeToAttributeTable[type]; return (attribute.StackType | attribute.AdditionalStackDependencies) .ToEnumerable() .All(st => enabledStacks.ContainsKey(st) && enabledStacks[st]); }); EnableExpressions(names); } private void EnableExpressions(IEnumerable names) { foreach (var name in names.Except(EnabledExpressions)) EnabledExpressions.Add(name); if (EnabledExpressionsChanged != null) { EnabledExpressionsChanged(this, new EnabledExpressionsChangedEventArgs(names, new string[0])); } } public void DisableExpressionsOfStack(StackTypes types) { DisableExpressions(ExpressionTable.StackTypeToNamesTable[types]); } public void DisableExpressionsDependentOnStack(StackTypes types) { var names = ExpressionTable.StackDependencyToNamesTable .Where(pair => pair.Key.HasFlag(types)) .SelectMany(pair => pair.Value); DisableExpressions(names); } private void DisableExpressions(IEnumerable names) { foreach (var name in names.Intersect(EnabledExpressions)) EnabledExpressions.Remove(name); if (EnabledExpressionsChanged != null) { EnabledExpressionsChanged(this, new EnabledExpressionsChangedEventArgs(new string[0], names)); } } public void EnableExpression(string name, bool enableStackIfDisabled = false) { if (EnabledExpressions.Contains(name)) return; EnabledExpressions.Add(name); if (enableStackIfDisabled) { var type = ExpressionTable.TypeToNameTable.Single(x => x.Value == name).Key; var attribute = ExpressionTable.TypeToAttributeTable[type]; enabledStacks[attribute.StackType] = true; } if (EnabledExpressionsChanged != null) { EnabledExpressionsChanged(this, new EnabledExpressionsChangedEventArgs( new[] { name }, new string[0])); } } public void DisableExpression(string name, bool disableStackIfEnabled = false) { if (!EnabledExpressions.Contains(name)) return; EnabledExpressions.Remove(name); if (disableStackIfEnabled) { var type = ExpressionTable.TypeToNameTable.Single(x => x.Value == name).Key; var attribute = ExpressionTable.TypeToAttributeTable[type]; enabledStacks[attribute.StackType] = false; } if (EnabledExpressionsChanged != null) { EnabledExpressionsChanged(this, new EnabledExpressionsChangedEventArgs( new string[0], new[] { name })); } } public void EnableExpression(bool enableStackIfDisabled = false) where T : Expression { var attribute = ExpressionTable.TypeToAttributeTable[typeof(T)]; EnableExpression(attribute.ExpressionName, enableStackIfDisabled); } public void DisableExpression(bool disableStackIfEnabled = false) where T : Expression { var attribute = ExpressionTable.TypeToAttributeTable[typeof(T)]; DisableExpression(attribute.ExpressionName, disableStackIfEnabled); } public void SetExpression(string name, bool state, bool cascadeForStack = false) { if (state) EnableExpression(name, cascadeForStack); else DisableExpression(name, cascadeForStack); } public void SetExpression(bool state, bool cascadeForStack = false) where T : Expression { if (state) EnableExpression(cascadeForStack); else DisableExpression(cascadeForStack); } public void EnableStack(StackTypes type, bool enableExpressions = true, bool enableDependencies = true) { enabledStacks[type] = true; if (enableExpressions) EnableExpressionOfStack(type); if (enableDependencies) EnableExpressionDependentOnStack(type); } public void DisableStack(StackTypes type, bool disableExpressions = true, bool disableDependencies = true) { enabledStacks[type] = false; if (disableExpressions) DisableExpressionsOfStack(type); if (disableDependencies) DisableExpressionsDependentOnStack(type); } public void SetStack(StackTypes type, bool state, bool setExpressions = true, bool setDependencies = true) { if (state) EnableStack(type, setExpressions, setDependencies); else DisableStack(type, setExpressions, setDependencies); } } }