Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/HeuristicLab.Parameters/3.3/LookupParameter.cs @ 2996

Last change on this file since 2996 was 2994, checked in by epitzer, 15 years ago

Make StorableClass attribute compulsory for StorableSerializer to work, add named property StorableClassType to choose between Empty and MarkedOnly, later other options will be added. (#548)

File size: 6.6 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2010 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
4 *
5 * This file is part of HeuristicLab.
6 *
7 * HeuristicLab is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * HeuristicLab is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
19 */
20#endregion
21
22using System;
23using HeuristicLab.Common;
24using HeuristicLab.Core;
25using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
26
27namespace HeuristicLab.Parameters {
28  /// <summary>
29  /// A parameter whose value is retrieved from the scope.
30  /// </summary>
31  [Item("LookupParameter<T>", "A parameter whose value is retrieved from or written to a scope.")]
32  [StorableClass(StorableClassType.MarkedOnly)]
33  public class LookupParameter<T> : Parameter, ILookupParameter<T> where T : class, IItem {
34    [Storable]
35    private string actualName;
36    public string ActualName {
37      get { return actualName; }
38      set {
39        if (value == null) throw new ArgumentNullException();
40        if (!actualName.Equals(value)) {
41          actualName = value;
42          OnActualNameChanged();
43        }
44      }
45    }
46    public new T ActualValue {
47      get {
48        if (cachedActualValue == null) cachedActualValue = GetActualValue();
49        return (T)cachedActualValue;
50      }
51      set {
52        cachedActualValue = value;
53        SetActualValue(value);
54      }
55    }
56
57    public LookupParameter()
58      : base("Anonymous", typeof(T)) {
59      actualName = Name;
60    }
61    public LookupParameter(string name)
62      : base(name, typeof(T)) {
63      actualName = Name;
64    }
65    public LookupParameter(string name, string description)
66      : base(name, description, typeof(T)) {
67      actualName = Name;
68    }
69
70    public override IDeepCloneable Clone(Cloner cloner) {
71      LookupParameter<T> clone = (LookupParameter<T>)base.Clone(cloner);
72      clone.actualName = actualName;
73      return clone;
74    }
75
76    public override string ToString() {
77      return string.Format("{0}: {1} ({2})", Name, ActualName, DataType.GetPrettyName());
78    }
79
80    private IValueParameter GetParameter(out string name) {
81      IValueParameter valueParam = this as IValueParameter;
82      ILookupParameter lookupParam = this as ILookupParameter;
83      IExecutionContext current = ExecutionContext;
84
85      name = Name;
86      while ((valueParam != null) || (lookupParam != null)) {
87        if ((valueParam != null) && (valueParam.Value != null)) return valueParam;
88        if (lookupParam != null) name = lookupParam.ActualName;
89
90        current = current.Parent;
91        while ((current != null) && !current.Parameters.ContainsKey(name))
92          current = current.Parent;
93
94        if (current != null) {
95          valueParam = current.Parameters[name] as IValueParameter;
96          lookupParam = current.Parameters[name] as ILookupParameter;
97          if ((valueParam == null) && (lookupParam == null))
98            throw new InvalidOperationException(
99              string.Format("Parameter look-up chain broken. Parameter \"{0}\" is not an \"{1}\" or an \"{2}\".",
100                            name,
101                            typeof(IValueParameter).GetPrettyName(),
102                            typeof(ILookupParameter).GetPrettyName())
103            );
104        } else {
105          valueParam = null;
106          lookupParam = null;
107        }
108      }
109      return null;
110    }
111    private IVariable LookupVariable(string name) {
112      IScope scope = ExecutionContext.Scope;
113      while ((scope != null) && !scope.Variables.ContainsKey(name))
114        scope = scope.Parent;
115      return scope != null ? scope.Variables[actualName] : null;
116    }
117    protected override IItem GetActualValue() {
118      string name;
119      // try to get value from context stack
120      IValueParameter param = GetParameter(out name);
121      if (param != null) return param.Value;
122
123      // try to get variable from scope
124      IVariable var = LookupVariable(name);
125      if (var != null) {
126        if (!(var.Value is T))
127          throw new InvalidOperationException(
128            string.Format("Type mismatch. Variable \"{0}\" does not contain a \"{1}\".",
129                          name,
130                          typeof(T).GetPrettyName())
131          );
132        return var.Value;
133      }
134      return null;
135    }
136    protected override void SetActualValue(IItem value) {
137      if (!(value is T))
138        throw new InvalidOperationException(
139          string.Format("Type mismatch. Value is not a \"{0}\".",
140                        typeof(T).GetPrettyName())
141        );
142      // try to set value in context stack
143      string name;
144      IValueParameter param = GetParameter(out name);
145      if (param != null) {
146        param.Value = value;
147        return;
148      }
149
150      // try to set value in scope
151      IVariable var = LookupVariable(name);
152      if (var != null) {
153        var.Value = value;
154        return;
155      }
156
157      // create new variable
158      ExecutionContext.Scope.Variables.Add(new Variable(name, value));
159    }
160
161    public event EventHandler ActualNameChanged;
162    private void OnActualNameChanged() {
163      if (ActualNameChanged != null)
164        ActualNameChanged(this, EventArgs.Empty);
165      OnToStringChanged();
166    }
167
168    public static string TranslateName(string name, IExecutionContext context) {
169      string currentName = name;
170      IExecutionContext currentContext = context;
171      IParameter param;
172      ILookupParameter lookupParam;
173
174      while (currentContext != null) {
175        currentContext.Parameters.TryGetValue(currentName, out param);
176        if (param != null) {
177          lookupParam = param as ILookupParameter;
178          if (lookupParam == null)
179            throw new InvalidOperationException(
180              string.Format("Parameter look-up chain broken. Parameter \"{0}\" is not an \"{1}\".",
181                            currentName,
182                            typeof(ILookupParameter).GetPrettyName())
183            );
184          currentName = lookupParam.ActualName;
185        }
186        currentContext = currentContext.Parent;
187      }
188      return currentName;
189    }
190  }
191}
Note: See TracBrowser for help on using the repository browser.