Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/HeuristicLab.Core/3.2/OperatorBase.cs @ 2867

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

Implemented generic EventArgs (#796)

File size: 29.0 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  /// The base class for all operators.
31  /// </summary>
32  public abstract class OperatorBase : ConstrainedItemBase, IOperator {
33    private string myName;
34    /// <summary>
35    /// Gets or sets the name of the operator.
36    /// </summary>
37    /// <remarks>Calls <see cref="OnNameChanged"/> in the setter.</remarks>
38    public string Name {
39      get { return myName; }
40      set {
41        if (myName != value) {
42          myName = value;
43          OnNameChanged();
44        }
45      }
46    }
47    /// <summary>
48    /// Gets the description of the current operator.
49    /// </summary>
50    /// <remarks>Returns "No operator description available" if the method is not overriden.</remarks>
51    public virtual string Description {
52      get { return "No operator description available."; }
53    }
54    /// <summary>
55    /// Flag whether the current instance has been canceled.
56    /// </summary>
57    protected bool myCanceled;
58    /// <inheritdoc/>
59    public bool Canceled {
60      get { return myCanceled; }
61    }
62    private bool myBreakpoint;
63    /// <inheritdoc/>
64    /// <remarks>Calls <see cref="OnBreakpointChanged"/> in the setter.</remarks>
65    public bool Breakpoint {
66      get { return myBreakpoint; }
67      set {
68        if (value != myBreakpoint) {
69          myBreakpoint = value;
70          OnBreakpointChanged();
71        }
72      }
73    }
74
75    private List<IOperator> mySubOperators;
76    /// <summary>
77    /// Gets a list of all suboperators.
78    /// <note type="caution"> Returns the suboperators read-only!</note>
79    /// </summary>
80    public virtual IList<IOperator> SubOperators {
81      get { return mySubOperators.AsReadOnly(); }
82    }
83    private Dictionary<string, IVariableInfo> myVariableInfos;
84    /// <inheritdoc/>
85    public virtual ICollection<IVariableInfo> VariableInfos {
86      get { return myVariableInfos.Values; }
87    }
88    private Dictionary<string, IVariable> myVariables;
89    /// <inheritdoc/>
90    public virtual ICollection<IVariable> Variables {
91      get { return myVariables.Values; }
92    }
93
94    /// <summary>
95    /// Initializes a new instance of <see cref="OperatorBase"/> setting the breakpoint flag and
96    /// the canceled flag to <c>false</c> and the name of the operator to the type name.
97    /// </summary>
98    protected OperatorBase() {
99      myName = this.GetType().Name;
100      myCanceled = false;
101      myBreakpoint = false;
102      mySubOperators = new List<IOperator>();
103      myVariableInfos = new Dictionary<string, IVariableInfo>();
104      myVariables = new Dictionary<string, IVariable>();
105    }
106
107    /// <summary>
108    /// Clones the current instance (deep clone).
109    /// </summary>
110    /// <remarks>Clones also sub operators, variables and variable infos.</remarks>
111    /// <param name="clonedObjects">Dictionary of all already cloned objects. (Needed to avoid cycles.)</param>
112    /// <returns>The cloned object as <see cref="OperatorBase"/>.</returns>
113    public override object Clone(IDictionary<Guid, object> clonedObjects) {
114      OperatorBase clone = (OperatorBase)base.Clone(clonedObjects);
115      clone.myName = Name;
116      clone.mySubOperators.Clear();
117      for (int i = 0; i < SubOperators.Count; i++)
118        clone.AddSubOperator((IOperator)Auxiliary.Clone(SubOperators[i], clonedObjects));
119      clone.myVariableInfos.Clear();
120      foreach (IVariableInfo variableInfo in myVariableInfos.Values)
121        clone.AddVariableInfo((IVariableInfo)Auxiliary.Clone(variableInfo, clonedObjects));
122      clone.myVariables.Clear();
123      foreach (IVariable variable in myVariables.Values)
124        clone.AddVariable((IVariable)Auxiliary.Clone(variable, clonedObjects));
125      return clone;
126    }
127
128    /// <summary>
129    /// Creates a new instance of <see cref="OperatorBaseView"/> to represent the current operator
130    /// visually.
131    /// </summary>
132    /// <returns>The created view as <see cref="OperatorBaseView"/>.</returns>
133    public override IView CreateView() {
134      return new OperatorBaseView(this);
135    }
136
137    #region SubOperator Methods
138    /// <inheritdoc cref="HeuristicLab.Core.IOperator.AddSubOperator(HeuristicLab.Core.IOperator)"/>
139    /// <param name="subOperator">The sub operator to add.</param>
140    /// <remarks>Calls <see cref="OnSubOperatorAdded"/>.</remarks>
141    public virtual void AddSubOperator(IOperator subOperator) {
142      mySubOperators.Add(subOperator);
143      OnSubOperatorAdded(subOperator, mySubOperators.Count - 1);
144    }
145    /// <inheritdoc cref="IOperator.TryAddSubOperator(HeuristicLab.Core.IOperator)"/>
146    /// <param name="subOperator">The sub operator to add.</param>
147    /// <remarks>Calls <see cref="OnSubOperatorAdded"/>.</remarks>
148    public virtual bool TryAddSubOperator(IOperator subOperator) {
149      mySubOperators.Add(subOperator);
150      if (IsValid()) {
151        OnSubOperatorAdded(subOperator, mySubOperators.Count - 1);
152        return true;
153      } else {
154        mySubOperators.RemoveAt(mySubOperators.Count - 1);
155        return false;
156      }
157    }
158    /// <inheritdoc cref="HeuristicLab.Core.IOperator.TryAddSubOperator(HeuristicLab.Core.IOperator,
159    /// out System.Collections.Generic.ICollection&lt;HeuristicLab.Core.IConstraint&gt;)"/>
160    /// <param name="subOperator">The sub operator to add.</param>
161    /// <remarks>Calls <see cref="OnSubOperatorAdded"/>.</remarks>
162    public virtual bool TryAddSubOperator(IOperator subOperator, out ICollection<IConstraint> violatedConstraints) {
163      mySubOperators.Add(subOperator);
164      if (IsValid(out violatedConstraints)) {
165        OnSubOperatorAdded(subOperator, mySubOperators.Count - 1);
166        return true;
167      } else {
168        mySubOperators.RemoveAt(mySubOperators.Count - 1);
169        return false;
170      }
171    }
172    /// <inheritdoc cref="HeuristicLab.Core.IOperator.AddSubOperator(HeuristicLab.Core.IOperator, int)"/>
173    /// <param name="subOperator">The sub operator to add.</param>
174    /// <remarks>Calls <see cref="OnSubOperatorAdded"/>.</remarks>
175    public virtual void AddSubOperator(IOperator subOperator, int index) {
176      mySubOperators.Insert(index, subOperator);
177      OnSubOperatorAdded(subOperator, index);
178    }
179    /// <inheritdoc cref="IOperator.TryAddSubOperator(HeuristicLab.Core.IOperator, int)"/>
180    /// <param name="subOperator">The sub operator to add.</param>
181    /// <remarks>Calls <see cref="OnSubOperatorAdded"/>.</remarks>
182    public virtual bool TryAddSubOperator(IOperator subOperator, int index) {
183      mySubOperators.Insert(index, subOperator);
184      if (IsValid()) {
185        OnSubOperatorAdded(subOperator, index);
186        return true;
187      } else {
188        mySubOperators.RemoveAt(index);
189        return false;
190      }
191    }
192    /// <inheritdoc cref="IOperator.TryAddSubOperator(HeuristicLab.Core.IOperator, int, out
193    /// System.Collections.Generic.ICollection&lt;HeuristicLab.Core.IConstraint&gt;)"/>
194    /// <param name="subOperator">The sub operator to add.</param>
195    /// <remarks>Calls <see cref="OnSubOperatorAdded"/>.</remarks>
196    public virtual bool TryAddSubOperator(IOperator subOperator, int index, out ICollection<IConstraint> violatedConstraints) {
197      mySubOperators.Insert(index, subOperator);
198      if (IsValid(out violatedConstraints)) {
199        OnSubOperatorAdded(subOperator, index);
200        return true;
201      } else {
202        mySubOperators.RemoveAt(index);
203        return false;
204      }
205    }
206    /// <inheritdoc/>
207    /// <remarks>Calls <see cref="OnSubOperatorRemoved"/>.</remarks>
208    public virtual void RemoveSubOperator(int index) {
209      IOperator op = mySubOperators[index];
210      mySubOperators.RemoveAt(index);
211      OnSubOperatorRemoved(op, index);
212    }
213    /// <inheritdoc/>
214    /// <remarks>Calls <see cref="OnSubOperatorRemoved"/>.</remarks>
215    public virtual bool TryRemoveSubOperator(int index) {
216      IOperator op = mySubOperators[index];
217      mySubOperators.RemoveAt(index);
218      if (IsValid()) {
219        OnSubOperatorRemoved(op, index);
220        return true;
221      } else {
222        mySubOperators.Insert(index, op);
223        return false;
224      }
225    }
226    /// <inheritdoc/>
227    /// <remarks>Calls <see cref="OnSubOperatorRemoved"/>.</remarks>
228    public virtual bool TryRemoveSubOperator(int index, out ICollection<IConstraint> violatedConstraints) {
229      IOperator op = mySubOperators[index];
230      mySubOperators.RemoveAt(index);
231      if (IsValid(out violatedConstraints)) {
232        OnSubOperatorRemoved(op, index);
233        return true;
234      } else {
235        mySubOperators.Insert(index, op);
236        return false;
237      }
238    }
239    #endregion
240
241    #region VariableInfo Methods
242    /// <inheritdoc/>
243    public virtual IVariableInfo GetVariableInfo(string formalName) {
244      IVariableInfo info;
245      if (myVariableInfos.TryGetValue(formalName, out info))
246        return info;
247      else
248        return null;
249    }
250    /// <inheritdoc/>
251    /// <remarks>Calls <see cref="OnVariableInfoAdded"/>.</remarks>
252    public virtual void AddVariableInfo(IVariableInfo variableInfo) {
253      myVariableInfos.Add(variableInfo.FormalName, variableInfo);
254      OnVariableInfoAdded(variableInfo);
255    }
256    /// <inheritdoc/>
257    /// <remarks>Calls <see cref="OnVariableInfoAdded"/>.</remarks>
258    public virtual bool TryAddVariableInfo(IVariableInfo variableInfo) {
259      myVariableInfos.Add(variableInfo.FormalName, variableInfo);
260      if (IsValid()) {
261        OnVariableInfoAdded(variableInfo);
262        return true;
263      } else {
264        myVariableInfos.Remove(variableInfo.FormalName);
265        return false;
266      }
267    }
268    /// <inheritdoc/>
269    /// <remarks>Calls <see cref="OnVariableInfoAdded"/>.</remarks>
270    public virtual bool TryAddVariableInfo(IVariableInfo variableInfo, out ICollection<IConstraint> violatedConstraints) {
271      myVariableInfos.Add(variableInfo.FormalName, variableInfo);
272      if (IsValid(out violatedConstraints)) {
273        OnVariableInfoAdded(variableInfo);
274        return true;
275      } else {
276        myVariableInfos.Remove(variableInfo.FormalName);
277        return false;
278      }
279    }
280    /// <inheritdoc/>
281    /// <remarks>Calls <see cref="OnVariableInfoRemoved"/>.</remarks>
282    public virtual void RemoveVariableInfo(string formalName) {
283      IVariableInfo variableInfo;
284      if (myVariableInfos.TryGetValue(formalName, out variableInfo)) {
285        myVariableInfos.Remove(formalName);
286        OnVariableInfoRemoved(variableInfo);
287      }
288    }
289    /// <inheritdoc/>
290    /// <remarks>Calls <see cref="OnVariableInfoRemoved"/>.</remarks>
291    public virtual bool TryRemoveVariableInfo(string formalName) {
292      IVariableInfo variableInfo;
293      if (myVariableInfos.TryGetValue(formalName, out variableInfo)) {
294        myVariableInfos.Remove(formalName);
295        if (IsValid()) {
296          OnVariableInfoRemoved(variableInfo);
297          return true;
298        } else {
299          myVariableInfos.Add(formalName, variableInfo);
300          return false;
301        }
302      }
303      return true;
304    }
305    /// <inheritdoc/>
306    /// <remarks>Calls <see cref="OnVariableInfoRemoved"/>.</remarks>
307    public virtual bool TryRemoveVariableInfo(string formalName, out ICollection<IConstraint> violatedConstraints) {
308      IVariableInfo variableInfo;
309      if (myVariableInfos.TryGetValue(formalName, out variableInfo)) {
310        myVariableInfos.Remove(formalName);
311        if (IsValid(out violatedConstraints)) {
312          OnVariableInfoRemoved(variableInfo);
313          return true;
314        } else {
315          myVariableInfos.Add(formalName, variableInfo);
316          return false;
317        }
318      }
319      violatedConstraints = new List<IConstraint>();
320      return true;
321    }
322    #endregion
323
324    #region Variable Methods
325    /// <inheritdoc/>
326    public virtual IVariable GetVariable(string name) {
327      IVariable variable;
328      if (myVariables.TryGetValue(name, out variable))
329        return variable;
330      else
331        return null;
332    }
333    /// <inheritdoc/>
334    /// <remarks>Calls <see cref="OnVariableAdded"/> and adds <c>NameChanging</c> and <c>NameChanged</c>
335    /// event handlers.</remarks>
336    public virtual void AddVariable(IVariable variable) {
337      myVariables.Add(variable.Name, variable);
338      variable.NameChanging += new EventHandler<CancelEventArgs<string>>(Variable_NameChanging);
339      variable.NameChanged += new EventHandler(Variable_NameChanged);
340      OnVariableAdded(variable);
341    }
342    /// <inheritdoc/>
343    /// <remarks>Calls <see cref="OnVariableAdded"/> and adds <c>NameChanging</c> and <c>NameChanged</c>
344    /// event handlers.</remarks>
345    public virtual bool TryAddVariable(IVariable variable) {
346      myVariables.Add(variable.Name, variable);
347      if (IsValid()) {
348        variable.NameChanging += new EventHandler<CancelEventArgs<string>>(Variable_NameChanging);
349        variable.NameChanged += new EventHandler(Variable_NameChanged);
350        OnVariableAdded(variable);
351        return true;
352      } else {
353        myVariableInfos.Remove(variable.Name);
354        return false;
355      }
356    }
357    /// <inheritdoc/>
358    /// <remarks>Calls <see cref="OnVariableAdded"/> and adds <c>NameChanging</c> and <c>NameChanged</c>
359    /// event handlers.</remarks>
360    public virtual bool TryAddVariable(IVariable variable, out ICollection<IConstraint> violatedConstraints) {
361      myVariables.Add(variable.Name, variable);
362      if (IsValid(out violatedConstraints)) {
363        variable.NameChanging += new EventHandler<CancelEventArgs<string>>(Variable_NameChanging);
364        variable.NameChanged += new EventHandler(Variable_NameChanged);
365        OnVariableAdded(variable);
366        return true;
367      } else {
368        myVariableInfos.Remove(variable.Name);
369        return false;
370      }
371    }
372    /// <inheritdoc/>
373    /// <remarks>Calls <see cref="OnVariableRemoved"/> and removes <c>NameChanging</c> and <c>NameChanged</c>
374    /// event handlers.</remarks>
375    public virtual void RemoveVariable(string name) {
376      IVariable variable;
377      if (myVariables.TryGetValue(name, out variable)) {
378        variable.NameChanging -= new EventHandler<CancelEventArgs<string>>(Variable_NameChanging);
379        variable.NameChanged -= new EventHandler(Variable_NameChanged);
380        myVariables.Remove(name);
381        OnVariableRemoved(variable);
382      }
383    }
384    /// <inheritdoc/>
385    /// <remarks>Calls <see cref="OnVariableRemoved"/> and removes <c>NameChanging</c> and <c>NameChanged</c>
386    /// event handlers.</remarks>
387    public virtual bool TryRemoveVariable(string name) {
388      IVariable variable;
389      if (myVariables.TryGetValue(name, out variable)) {
390        myVariables.Remove(name);
391        if (IsValid()) {
392          variable.NameChanging -= new EventHandler<CancelEventArgs<string>>(Variable_NameChanging);
393          variable.NameChanged -= new EventHandler(Variable_NameChanged);
394          OnVariableRemoved(variable);
395          return true;
396        } else {
397          myVariables.Add(name, variable);
398          return false;
399        }
400      }
401      return true;
402    }
403    /// <inheritdoc/>
404    /// <remarks>Calls <see cref="OnVariableRemoved"/> and removes <c>NameChanging</c> and <c>NameChanged</c>
405    /// event handlers.</remarks>
406    public virtual bool TryRemoveVariable(string name, out ICollection<IConstraint> violatedConstraints) {
407      IVariable variable;
408      if (myVariables.TryGetValue(name, out variable)) {
409        myVariables.Remove(name);
410        if (IsValid(out violatedConstraints)) {
411          variable.NameChanging -= new EventHandler<CancelEventArgs<string>>(Variable_NameChanging);
412          variable.NameChanged -= new EventHandler(Variable_NameChanged);
413          OnVariableRemoved(variable);
414          return true;
415        } else {
416          myVariables.Add(name, variable);
417          return false;
418        }
419      }
420      violatedConstraints = new List<IConstraint>();
421      return true;
422    }
423    private void Variable_NameChanging(object sender, CancelEventArgs<string> e) {
424      e.Cancel = myVariables.ContainsKey(e.Value);
425    }
426    private void Variable_NameChanged(object sender, EventArgs e) {
427      IVariable variable = (IVariable)sender;
428      string oldName = null;
429      foreach (KeyValuePair<string, IVariable> element in myVariables) {
430        if (element.Value == variable)
431          oldName = element.Key;
432      }
433      myVariables.Remove(oldName);
434      myVariables.Add(variable.Name, variable);
435    }
436    /// <inheritdoc cref="IOperator.GetVariableValue&lt;T&gt;(string, HeuristicLab.Core.IScope, bool)"/>
437    ///  <remarks>Calls <see cref="GetVariableValue&lt;T&gt;(string, HeuristicLab.Core.IScope, bool, bool)"/>
438    /// with <c>throwOnError</c> set to <c>false</c>.</remarks>
439    public T GetVariableValue<T>(string formalName, IScope scope, bool recursiveLookup) where T : class, IItem {
440      return GetVariableValue<T>(formalName, scope, recursiveLookup, true);
441    }
442    /// <inheritdoc cref="IOperator.GetVariableValue&lt;T&gt;(string, HeuristicLab.Core.IScope, bool, bool)"/>
443    /// <remarks>Calls
444    /// <see cref="GetVariableValue(string, HeuristicLab.Core.IScope, bool, bool)"/>.</remarks>
445    public T GetVariableValue<T>(string formalName, IScope scope, bool recursiveLookup, bool throwOnError) where T : class, IItem {
446      return (T)GetVariableValue(formalName, scope, recursiveLookup, throwOnError);
447    }
448    /// <inheritdoc cref="IOperator.GetVariableValue(string, HeuristicLab.Core.IScope, bool)"/>
449    /// <remarks>Calls <see cref="GetVariableValue(string, HeuristicLab.Core.IScope, bool, bool)"/>
450    /// with <c>throwOnError</c> set to <c>false</c>.</remarks>
451    public IItem GetVariableValue(string formalName, IScope scope, bool recursiveLookup) {
452      return GetVariableValue(formalName, scope, recursiveLookup, true);
453    }
454    /// <inheritdoc cref="IOperator.GetVariableValue(string, HeuristicLab.Core.IScope, bool, bool)"/>
455    public virtual IItem GetVariableValue(string formalName, IScope scope, bool recursiveLookup, bool throwOnError) {
456      IVariableInfo info = GetVariableInfo(formalName);
457      if (info.Local) {
458        IVariable variable;
459        if (myVariables.TryGetValue(info.ActualName, out variable))
460          return variable.Value;
461        else {
462          if (throwOnError)
463            throw new ArgumentException("Variable " + info.ActualName + " not found");
464          else
465            return null;
466        }
467      } else {
468        return scope.GetVariableValue(formalName, recursiveLookup, throwOnError);
469      }
470    }
471    #endregion
472    /// <inheritdoc/>
473    public virtual IOperation Execute(IScope scope) {
474      myCanceled = false;
475
476      foreach (IVariableInfo variableInfo in VariableInfos)
477        scope.AddAlias(variableInfo.FormalName, variableInfo.ActualName);
478
479      IOperation next = Apply(scope);
480
481      foreach (IVariableInfo variableInfo in VariableInfos)
482        scope.RemoveAlias(variableInfo.FormalName);
483
484      OnExecuted();
485      return next;
486    }
487    /// <inheritdoc/>
488    /// <remarks>Sets property <see cref="Canceled"/> to <c>true</c>.</remarks>
489    public virtual void Abort() {
490      myCanceled = true;
491    }
492    /// <summary>
493    /// Performs the current operator on the specified <paramref name="scope"/>.
494    /// </summary>
495    /// <param name="scope">The scope where to execute the operator</param>
496    /// <returns><c>null</c>.</returns>
497    public virtual IOperation Apply(IScope scope) {
498      return null;
499    }
500    /// <inheritdoc/>
501    public event EventHandler NameChanged;
502    /// <summary>
503    /// Fires a new <c>NameChanged</c> event.
504    /// </summary>
505    protected virtual void OnNameChanged() {
506      if (NameChanged != null) {
507        NameChanged(this, new EventArgs());
508      }
509    }
510    /// <inheritdoc/>
511    public event EventHandler BreakpointChanged;
512    /// <summary>
513    /// Fires a new <c>BreakpointChanged</c> event.
514    /// </summary>
515    protected virtual void OnBreakpointChanged() {
516      if (BreakpointChanged != null) {
517        BreakpointChanged(this, new EventArgs());
518      }
519    }
520    /// <inheritdoc/>
521    public event EventHandler<EventArgs<IOperator, int>> SubOperatorAdded;
522    /// <summary>
523    /// Fires a new <c>SubOperatorAdded</c> event.
524    /// </summary>
525    /// <param name="subOperator">The sub operator that has been added.</param>
526    /// <param name="index">The position where the operator has been added.</param>
527    protected virtual void OnSubOperatorAdded(IOperator subOperator, int index) {
528      if (SubOperatorAdded != null)
529        SubOperatorAdded(this, new EventArgs<IOperator, int>(subOperator, index));
530    }
531    /// <inheritdoc/>
532    public event EventHandler<EventArgs<IOperator, int>> SubOperatorRemoved;
533    /// <summary>
534    /// Fires a new <c>SubOperatorRemoved</c> event.
535    /// </summary>
536    /// <param name="subOperator">The sub operator that has been removed.</param>
537    /// <param name="index">The position where the operator has been removed.</param>
538    protected virtual void OnSubOperatorRemoved(IOperator subOperator, int index) {
539      if (SubOperatorRemoved != null)
540        SubOperatorRemoved(this, new EventArgs<IOperator, int>(subOperator, index));
541    }
542    /// <inheritdoc/>
543    public event EventHandler<EventArgs<IVariableInfo>> VariableInfoAdded;
544    /// <summary>
545    /// Fires a new <c>VariableInfoAdded</c> event.
546    /// </summary>
547    /// <param name="variableInfo">The variable info that has been added.</param>
548    protected virtual void OnVariableInfoAdded(IVariableInfo variableInfo) {
549      if (VariableInfoAdded != null)
550        VariableInfoAdded(this, new EventArgs<IVariableInfo>(variableInfo));
551    }
552    /// <inheritdoc/>
553    public event EventHandler<EventArgs<IVariableInfo>> VariableInfoRemoved;
554    /// <summary>
555    /// Fires a new <c>VariableInfoRemoved</c> event.
556    /// </summary>
557    /// <param name="variableInfo">The variable info that has been removed.</param>
558    protected virtual void OnVariableInfoRemoved(IVariableInfo variableInfo) {
559      if (VariableInfoRemoved != null)
560        VariableInfoRemoved(this, new EventArgs<IVariableInfo>(variableInfo));
561    }
562    /// <inheritdoc/>
563    public event EventHandler<EventArgs<IVariable>> VariableAdded;
564    /// <summary>
565    /// Fires a new <c>VariableAdded</c> event.
566    /// </summary>
567    /// <param name="variable">The variable that has been added.</param>
568    protected virtual void OnVariableAdded(IVariable variable) {
569      if (VariableAdded != null)
570        VariableAdded(this, new EventArgs<IVariable>(variable));
571    }
572    /// <inheritdoc/>
573    public event EventHandler<EventArgs<IVariable>> VariableRemoved;
574    /// <summary>
575    /// Fires a new <c>VariableRemoved</c> event.
576    /// </summary>
577    /// <param name="variable">The variable that has been removed</param>
578    protected virtual void OnVariableRemoved(IVariable variable) {
579      if (VariableRemoved != null)
580        VariableRemoved(this, new EventArgs<IVariable>(variable));
581    }
582    /// <inheritdoc/>
583    public event EventHandler Executed;
584    /// <summary>
585    /// Fires a new <c>Executed</c> event.
586    /// </summary>
587    protected virtual void OnExecuted() {
588      if (Executed != null) {
589        Executed(this, new EventArgs());
590      }
591    }
592
593    #region Persistence Methods
594    /// <summary>
595    /// Saves the current instance as <see cref="XmlNode"/> in the specified <paramref name="document"/>.
596    /// </summary>
597    /// <remarks>
598    /// Calls <see cref="ConstrainedItemBase.GetXmlNode"/> of base class <see cref="ConstrainedItemBase"/>.
599    /// <br/>A quick overview how the single elements of the current instance are saved:
600    /// <list type="bullet">
601    /// <item>
602    /// <term>Name: </term>
603    /// <description>Saved as an <see cref="XmlAttribute"/> with the name <c>Name</c>.</description>
604    /// </item>
605    /// <item>
606    /// <term>Breakpoint: </term>
607    /// <description>Is only saved if it set to <c>true</c>.
608    /// Saved as an <see cref="XmlAttribute"/> with the name <c>Breakpoint</c>.</description>
609    /// </item>
610    /// <item>
611    /// <term>Sub operators: </term>
612    /// <description>Saved as child node with tag name <c>SubOperators</c>. All sub operators are themselves
613    /// saved as child nodes.</description>
614    /// </item>
615    /// <item>
616    /// <term>Variable infos: </term>
617    /// <description>Saved as child node with tag name <c>VariableInfos</c>. All variable infos are themselves
618    /// saved as child nodes.</description>
619    /// </item>
620    /// <item>
621    /// <term>Variables: </term>
622    /// <description>Saved as child node with tag name <c>Variables</c>. All variables are themselves
623    /// saved as child nodes.</description>
624    /// </item>
625    /// </list>
626    /// </remarks>
627    /// <param name="name">The (tag)name of the <see cref="XmlNode"/>.</param>
628    /// <param name="document">The <see cref="XmlDocument"/> where to save the data.</param>
629    /// <param name="persistedObjects">The dictionary of all already persisted objects. (Needed to avoid cycles.)</param>
630    /// <returns>The saved <see cref="XmlNode"/>.</returns>
631    public override XmlNode GetXmlNode(string name, XmlDocument document, IDictionary<Guid,IStorable> persistedObjects) {
632      XmlNode node = base.GetXmlNode(name, document, persistedObjects);
633      XmlAttribute nameAttribute = document.CreateAttribute("Name");
634      nameAttribute.Value = Name;
635      node.Attributes.Append(nameAttribute);
636      if (Breakpoint) {
637        XmlAttribute breakpointAttribute = document.CreateAttribute("Breakpoint");
638        breakpointAttribute.Value = Breakpoint.ToString();
639        node.Attributes.Append(breakpointAttribute);
640      }
641      XmlNode subOperatorsNode = document.CreateNode(XmlNodeType.Element, "SubOperators", null);
642      for (int i = 0; i < SubOperators.Count; i++)
643        subOperatorsNode.AppendChild(PersistenceManager.Persist(SubOperators[i], document, persistedObjects));
644      node.AppendChild(subOperatorsNode);
645      XmlNode infosNode = document.CreateNode(XmlNodeType.Element, "VariableInfos", null);
646      foreach (IVariableInfo info in myVariableInfos.Values)
647        infosNode.AppendChild(PersistenceManager.Persist(info, document, persistedObjects));
648      node.AppendChild(infosNode);
649      XmlNode variablesNode = document.CreateNode(XmlNodeType.Element, "Variables", null);
650      foreach (IVariable variable in myVariables.Values)
651        variablesNode.AppendChild(PersistenceManager.Persist(variable, document, persistedObjects));
652      node.AppendChild(variablesNode);
653      return node;
654    }
655    /// <summary>
656    /// Loads the persisted operation from the specified <paramref name="node"/>.
657    /// </summary>
658    /// <remarks>Calls <see cref="ConstrainedItemBase.Populate"/> of base class
659    /// <see cref="ConstrainedItemBase"/>.
660    /// For informations how the different elements must be saved please see <see cref="GetXmlNode"/>.</remarks>
661    /// <param name="node">The <see cref="XmlNode"/> where the operation is saved.</param>
662    /// <param name="restoredObjects">A dictionary of all already restored objects. (Needed to avoid cycles.)</param>
663    public override void Populate(XmlNode node, IDictionary<Guid,IStorable> restoredObjects) {
664      base.Populate(node, restoredObjects);
665      myName = node.Attributes["Name"].Value;
666      if (node.Attributes["Breakpoint"] != null)
667        myBreakpoint = bool.Parse(node.Attributes["Breakpoint"].Value);
668      XmlNode subOperatorsNode = node.SelectSingleNode("SubOperators");
669      for (int i = 0; i < subOperatorsNode.ChildNodes.Count; i++)
670        AddSubOperator((IOperator)PersistenceManager.Restore(subOperatorsNode.ChildNodes[i], restoredObjects));
671      XmlNode infosNode = node.SelectSingleNode("VariableInfos");
672      myVariableInfos.Clear();
673      foreach (XmlNode infoNode in infosNode.ChildNodes)
674        AddVariableInfo((IVariableInfo)PersistenceManager.Restore(infoNode, restoredObjects));
675      XmlNode variablesNode = node.SelectSingleNode("Variables");
676      myVariables.Clear();
677      foreach (XmlNode variableNode in variablesNode.ChildNodes)
678        AddVariable((IVariable)PersistenceManager.Restore(variableNode, restoredObjects));
679    }
680    #endregion
681  }
682}
Note: See TracBrowser for help on using the repository browser.