using System; using System.Text.RegularExpressions; using HeuristicLab.Common; using HeuristicLab.Core; using HeuristicLab.Persistence.Default.CompositeSerializers.Storable; namespace HeuristicLab.Parameters { [Item("ScopePathLookupParameter", "Start parameter lookup after freely navigating the scope tree using a path string.")] [StorableClass] public class ScopePathLookupParameter : LookupParameter, ILookupParameter where T : class, IItem { #region Properties public static Regex ValidPathRegex = new Regex("|(..|[a-zA-Z0-9_ ]+|\\{[0-9]+\\})(/(..|[a-zA-Z0-9_ ]+|\\{[0-9]+\\}))?"); [Storable] private string path; public string Path { get { return path; } set { if (!ValidPathRegex.IsMatch(value)) throw new ArgumentException("Invalid Path"); if (value != null) { path = value; OnPathChanged(); OnToStringChanged(); } } } #endregion #region Constructors & Cloning [StorableConstructor] protected ScopePathLookupParameter(bool deserializing) : base(deserializing) { } protected ScopePathLookupParameter(ScopePathLookupParameter original, Cloner cloner) : base(original, cloner) { path = original.path; } public ScopePathLookupParameter() : base() { path = ""; } public ScopePathLookupParameter(string name) : base(name) { path = ""; } public ScopePathLookupParameter(string name, string description) : base(name, description) { path = ""; } public ScopePathLookupParameter(string name, string description, string actualName) : base(name, description, actualName) { path = ""; } public override IDeepCloneable Clone(Cloner cloner) { return new ScopePathLookupParameter(this, cloner); } #endregion public static IScope NavigateScope(IScope scope, string path) { foreach (var dir in path.Split(new[] { '/' }, StringSplitOptions.RemoveEmptyEntries)) { if (dir == "..") scope = scope.Parent; else if (dir.StartsWith("{")) { scope = scope.SubScopes[int.Parse(dir.Substring(1, dir.Length-2))]; } else { scope = scope.SubScopes.Find(s => s.Name == dir); } } return scope; } protected override IItem GetActualValue() { var originalContext = ExecutionContext as ExecutionContext; ExecutionContext = new ExecutionContext(originalContext.Parent, originalContext.Operator, NavigateScope(originalContext.Scope, Path)); IItem result = base.GetActualValue(); ExecutionContext = originalContext; return result; } protected override void SetActualValue(IItem value) { var originalContext = ExecutionContext as ExecutionContext; ExecutionContext = new ExecutionContext(originalContext.Parent, originalContext.Operator, NavigateScope(originalContext.Scope, Path)); base.SetActualValue(value); ExecutionContext = originalContext; } public event EventHandler PathChanged; protected virtual void OnPathChanged() { EventHandler handler = PathChanged; if (handler != null) handler(this, EventArgs.Empty); } public override string ToString() { return string.Format("{0} [{1}]", base.ToString(), Path); } } }