Free cookie consent management tool by TermsFeed Policy Generator

source: branches/Operator Architecture Refactoring/HeuristicLab.Core/3.2/Scope.cs @ 2027

Last change on this file since 2027 was 2027, checked in by swagner, 15 years ago

Refactoring of the operator architecture (#95)

File size: 13.9 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2008 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 System.Collections.Generic;
24using System.Text;
25using System.Xml;
26
27namespace HeuristicLab.Core {
28  /// <summary>
29  /// Hierarchical container of variables (and of subscopes).
30  /// </summary>
31  public class Scope : ItemBase, IScope {
32    private IScope parent;
33
34    private string myName;
35    /// <summary>
36    /// Gets the name of the current scope.
37    /// </summary>
38    public string Name {
39      get { return myName; }
40    }
41
42    private IDictionary<string, IVariable> myVariables;
43    /// <inheritdoc/>
44    public ICollection<IVariable> Variables {
45      get { return myVariables.Values; }
46    }
47    private List<IScope> mySubScopes;
48    /// <summary>
49    /// Gets all subscopes of the current instance.
50    /// <note type="caution"> The subscopes are returned as read-only.</note>
51    /// </summary>
52    public IList<IScope> SubScopes {
53      get { return mySubScopes.AsReadOnly(); }
54    }
55
56    /// <summary>
57    /// Initializes a new instance of <see cref="Scope"/> having "Anonymous" as default name.
58    /// </summary>
59    public Scope() {
60      myName = "Anonymous";
61      myVariables = new Dictionary<string, IVariable>();
62      mySubScopes = new List<IScope>();
63    }
64    /// <summary>
65    /// Initializes a new instance of <see cref="Scope"/> with the given <paramref name="name"/>.
66    /// </summary>
67    /// <param name="name">The name of the scope.</param>
68    public Scope(string name)
69      : this() {
70      if (name != null) myName = name;
71    }
72
73    /// <inheritdoc/>
74    public void SetParent(IScope scope) {
75      parent = scope;
76    }
77
78    /// <summary>
79    /// Creates a new instance of <see cref="ScopeView"/> to represent the current instance visually.
80    /// </summary>
81    /// <returns>The created view as <see cref="ScopeView"/>.</returns>
82    public override IView CreateView() {
83      return new ScopeView(this);
84    }
85
86    /// <inheritdoc/>
87    public IVariable GetVariable(string name) {
88      IVariable variable;
89      if (myVariables.TryGetValue(name, out variable))
90        return variable;
91      else
92        return null;
93    }
94    /// <inheritdoc/>
95    public void AddVariable(IVariable variable) {
96      myVariables.Add(variable.Name, variable);
97      variable.NameChanging += new EventHandler<NameChangingEventArgs>(Variable_NameChanging);
98      variable.NameChanged += new EventHandler(Variable_NameChanged);
99      OnVariableAdded(variable);
100    }
101
102    /// <inheritdoc/>
103    public void RemoveVariable(string name) {
104      IVariable variable;
105      if (myVariables.TryGetValue(name, out variable)) {
106        variable.NameChanging -= new EventHandler<NameChangingEventArgs>(Variable_NameChanging);
107        variable.NameChanged -= new EventHandler(Variable_NameChanged);
108        myVariables.Remove(name);
109        OnVariableRemoved(variable);
110      }
111    }
112    private void Variable_NameChanging(object sender, NameChangingEventArgs e) {
113      e.Cancel = myVariables.ContainsKey(e.Name);
114    }
115    private void Variable_NameChanged(object sender, EventArgs e) {
116      IVariable variable = (IVariable)sender;
117      string oldName = null;
118      foreach (KeyValuePair<string, IVariable> element in myVariables) {
119        if (element.Value == variable)
120          oldName = element.Key;
121      }
122      myVariables.Remove(oldName);
123      myVariables.Add(variable.Name, variable);
124    }
125    /// <inheritdoc cref="IScope.GetVariableValue&lt;T&gt;(string, bool)"/>
126    public T GetVariableValue<T>(string name, bool recursiveLookup) where T : class, IItem {
127      return GetVariableValue<T>(name, recursiveLookup, true);
128    }
129    /// <inheritdoc cref="IScope.GetVariableValue&lt;T&gt;(string, bool, bool)"/>
130    public T GetVariableValue<T>(string name, bool recursiveLookup, bool throwOnError) where T : class, IItem {
131      return (T)GetVariableValue(name, recursiveLookup, throwOnError);
132    }
133    /// <inheritdoc cref="IScope.GetVariableValue(string, bool)"/>
134    public IItem GetVariableValue(string name, bool recursiveLookup) {
135      return GetVariableValue(name, recursiveLookup, true);
136    }
137    /// <inheritdoc cref="IScope.GetVariableValue(string, bool, bool)"/>
138    public IItem GetVariableValue(string name, bool recursiveLookup, bool throwOnError) {
139      IVariable variable;
140      if (myVariables.TryGetValue(name, out variable)) {
141        return variable.Value;
142      } else {
143        if (recursiveLookup && (parent != null))
144          return parent.GetVariableValue(name, recursiveLookup, throwOnError);
145        else {
146          if (throwOnError)
147            throw new ArgumentException("Variable " + name + " not found");
148          else
149            return null;
150        }
151      }
152    }
153
154    /// <inheritdoc/>
155    public void AddSubScope(IScope scope) {
156      scope.SetParent(this);
157      mySubScopes.Add(scope);
158      OnSubScopeAdded(scope, mySubScopes.Count - 1);
159    }
160    /// <inheritdoc/>
161    public void RemoveSubScope(IScope scope) {
162      int index = mySubScopes.IndexOf(scope);
163      if (mySubScopes.Remove(scope)) {
164        scope.SetParent(null);
165        OnSubScopeRemoved(scope, index);
166      }
167    }
168    /// <inheritdoc/>
169    public void ReorderSubScopes(int[] sequence) {
170      IScope[] scopes = mySubScopes.ToArray();
171      mySubScopes.Clear();
172      for (int i = 0; i < scopes.Length; i++)
173        mySubScopes.Add(scopes[sequence[i]]);
174      OnSubScopesReordered();
175    }
176    /// <inheritdoc/>
177    public IScope GetScope(Guid guid) {
178      if (Guid == guid) return this;
179      else {
180        for (int i = 0; i < mySubScopes.Count; i++) {
181          IScope s = mySubScopes[i].GetScope(guid);
182          if (s != null) return s;
183        }
184      }
185      return null;
186    }
187    /// <inheritdoc/>
188    public IScope GetScope(string name) {
189      if (Name == name) return this;
190      else {
191        for (int i = 0; i < mySubScopes.Count; i++) {
192          IScope s = mySubScopes[i].GetScope(name);
193          if (s != null) return s;
194        }
195      }
196      return null;
197    }
198
199    /// <inheritdoc/>
200    public void Clear() {
201      string[] variableNames = new string[Variables.Count];
202      int i = 0;
203      foreach (IVariable variable in Variables) {
204        variableNames[i] = variable.Name;
205        i++;
206      }
207      for (int j = 0; j < variableNames.Length; j++)
208        RemoveVariable(variableNames[j]);
209
210      while (SubScopes.Count > 0)
211        RemoveSubScope(SubScopes[0]);
212    }
213
214    /// <inheritdoc/>
215    public override object Clone(IDictionary<Guid, object> clonedObjects) {
216      Scope clone = (Scope)base.Clone(clonedObjects);
217      clone.myName = Name;
218
219      foreach (IVariable variable in myVariables.Values)
220        clone.AddVariable((IVariable)Auxiliary.Clone(variable, clonedObjects));
221      for (int i = 0; i < SubScopes.Count; i++)
222        clone.AddSubScope((IScope)Auxiliary.Clone(SubScopes[i], clonedObjects));
223
224      return clone;
225    }
226
227    /// <inheritdoc />
228    public event EventHandler<VariableEventArgs> VariableAdded;
229    /// <summary>
230    /// Fires a new <c>VariableAdded</c> event.
231    /// </summary>
232    /// <param name="variable">The variable that has been added.</param>
233    protected virtual void OnVariableAdded(IVariable variable) {
234      if (VariableAdded != null)
235        VariableAdded(this, new VariableEventArgs(variable));
236    }
237    /// <inheritdoc />
238    public event EventHandler<VariableEventArgs> VariableRemoved;
239    /// <summary>
240    /// Fires a new <c>VariableRemoved</c>.
241    /// </summary>
242    /// <param name="variable">The variable that has been deleted.</param>
243    protected virtual void OnVariableRemoved(IVariable variable) {
244      if (VariableRemoved != null)
245        VariableRemoved(this, new VariableEventArgs(variable));
246    }
247    /// <inheritdoc/>
248    public event EventHandler<ScopeIndexEventArgs> SubScopeAdded;
249    /// <summary>
250    /// Fires a new <c>SubScopeAdded</c> event.
251    /// </summary>
252    /// <param name="scope">The sub scope that has been added.</param>
253    /// <param name="index">The index where the scope has been added.</param>
254    protected virtual void OnSubScopeAdded(IScope scope, int index) {
255      if (SubScopeAdded != null)
256        SubScopeAdded(this, new ScopeIndexEventArgs(scope, index));
257    }
258    /// <inheritdoc/>
259    public event EventHandler<ScopeIndexEventArgs> SubScopeRemoved;
260    /// <summary>
261    /// Fires a new <c>SubScopeRemoved</c> event.
262    /// </summary>
263    /// <param name="scope">The sub scope that has been deleted.</param>
264    /// <param name="index">The position of the sub scope.</param>
265    protected virtual void OnSubScopeRemoved(IScope scope, int index) {
266      if (SubScopeRemoved != null)
267        SubScopeRemoved(this, new ScopeIndexEventArgs(scope, index));
268    }
269    /// <inheritdoc />
270    public event EventHandler SubScopesReordered;
271    /// <summary>
272    /// Fires a new <c>SubScopesReordered</c> event
273    /// </summary>
274    protected virtual void OnSubScopesReordered() {
275      if (SubScopesReordered != null)
276        SubScopesReordered(this, new EventArgs());
277    }
278
279    #region Persistence Methods
280    /// <summary>
281    /// Saves the current instance as <see cref="XmlNode"/> in the given <paramref name="document"/>.
282    /// </summary>
283    /// <remarks>
284    /// Calls <see cref="StorableBase.GetXmlNode"/> of base class <see cref="ItemBase"/>.<br/>
285    /// A quick overview how the single elements of the current instance are saved:
286    /// <list type="bullet">
287    /// <item>
288    /// <term>Name: </term>
289    /// <description>Saved as an <see cref="XmlAttribute"/> having the tag name <c>Name</c>.</description>
290    /// </item>
291    /// <item>
292    /// <term>Variables: </term>
293    /// <description>A child node is created with the tag name <c>Variables</c>. Beyond this child node,
294    /// all variables are saved as child nodes.</description>
295    /// </item>
296    /// <item>
297    /// <term>Aliases: </term>
298    /// <description>A child node is created with the tag name <c>Aliases</c>. Beyond this child node,
299    /// all aliases are saved as child nodes with the tag name <c>Alias</c>. Each alias has an
300    /// <see cref="XmlAttribute"/> with the tag name "Alias", holding the alias, and an attribute
301    /// with the tag name <c>Name</c>, holding the name of the alias.</description>
302    /// </item>
303    /// <item>
304    /// <term>Sub scopes: </term>
305    /// <description>A child node is created with the tag name <c>SubScopes</c>. Beyond this child node,
306    /// all sub scopes are saved as child nodes.</description>
307    /// </item>
308    /// </list>
309    /// </remarks>
310    /// <param name="name">The (tag)name of the <see cref="XmlNode"/>.</param>
311    /// <param name="document">The <see cref="XmlDocument"/> where to save the data.</param>
312    /// <param name="persistedObjects">The dictionary of all already persisted objects. (Needed to avoid cycles.)</param>
313    /// <returns>The saved <see cref="XmlNode"/>.</returns>
314    public override XmlNode GetXmlNode(string name, XmlDocument document, IDictionary<Guid,IStorable> persistedObjects) {
315      XmlNode node = base.GetXmlNode(name, document, persistedObjects);
316      XmlAttribute nameAttribute = document.CreateAttribute("Name");
317      nameAttribute.Value = Name.ToString();
318      node.Attributes.Append(nameAttribute);
319
320      XmlNode variables = document.CreateNode(XmlNodeType.Element, "Variables", null);
321      foreach (IVariable variable in Variables)
322        variables.AppendChild(PersistenceManager.Persist(variable, document, persistedObjects));
323      node.AppendChild(variables);
324
325      XmlNode subScopes = document.CreateNode(XmlNodeType.Element, "SubScopes", null);
326      for (int i = 0; i < SubScopes.Count; i++)
327        subScopes.AppendChild(PersistenceManager.Persist(SubScopes[i], document, persistedObjects));
328      node.AppendChild(subScopes);
329
330      return node;
331    }
332    /// <summary>
333    /// Loads the persisted scope from the specified <paramref name="node"/>.
334    /// </summary>
335    /// <remarks>See <see cref="GetXmlNode"/> to get further information on how the current instance must
336    /// be saved. <br/>
337    /// Calls <see cref="StorableBase.Populate"/> of base class <see cref="ItemBase"/>.</remarks>
338    /// <param name="node">The <see cref="XmlNode"/> where the boolean value is saved.</param>
339    /// <param name="restoredObjects">The dictionary of all already restored objects.
340    /// (Needed to avoid cycles.)</param>
341    public override void Populate(XmlNode node, IDictionary<Guid,IStorable> restoredObjects) {
342      base.Populate(node, restoredObjects);
343      myName = node.Attributes["Name"].Value;
344
345      XmlNode variables = node.SelectSingleNode("Variables");
346      foreach (XmlNode variableNode in variables.ChildNodes) {
347        IVariable variable = (IVariable)PersistenceManager.Restore(variableNode, restoredObjects);
348        AddVariable(variable);
349      }
350
351      XmlNode subScopes = node.SelectSingleNode("SubScopes");
352      for (int i = 0; i < subScopes.ChildNodes.Count; i++) {
353        IScope scope = (IScope)PersistenceManager.Restore(subScopes.ChildNodes[i], restoredObjects);
354        AddSubScope(scope);
355      }
356    }
357    #endregion
358  }
359}
Note: See TracBrowser for help on using the repository browser.