Free cookie consent management tool by TermsFeed Policy Generator

source: branches/CloningRefactorBranch/HeuristicLab.Core/Scope.cs @ 836

Last change on this file since 836 was 836, checked in by gkronber, 15 years ago

worked on #285 (Cloning could be improved by creating objects at the bottom of the cloning chain with 'new' instead of the top with Activator.CreateInstance())

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