Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/HeuristicLab.Core/3.2/Scope.cs @ 2989

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

Implemented generic EventArgs (#796)

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