Free cookie consent management tool by TermsFeed Policy Generator

source: branches/CloningRefactorBranch/HeuristicLab.Core/OperatorBase.cs @ 887

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

Refactored cloning in all plugins except: HL.Communication, HL.Hive, HL.GP, HL.Routing, HL.Scheduling, HL.SimOpt, HL.Visualization

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