Free cookie consent management tool by TermsFeed Policy Generator

source: branches/Operator Architecture Refactoring/HeuristicLab.Core/3.2/OperatorBase.cs @ 2045

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

Refactoring of the operator architecture (#95)

File size: 14.4 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 : ItemBase, 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, IParameter> myParameters;
83    /// <inheritdoc/>
84    public virtual ICollection<IParameter> Parameters {
85      get { return myParameters.Values; }
86    }
87
88    /// <summary>
89    /// Initializes a new instance of <see cref="OperatorBase"/> setting the breakpoint flag and
90    /// the canceled flag to <c>false</c> and the name of the operator to the type name.
91    /// </summary>
92    protected OperatorBase() {
93      myName = this.GetType().Name;
94      myCanceled = false;
95      myBreakpoint = false;
96      mySubOperators = new List<IOperator>();
97      myParameters = new Dictionary<string, IParameter>();
98    }
99
100    /// <summary>
101    /// Clones the current instance (deep clone).
102    /// </summary>
103    /// <remarks>Clones also sub operators, variables and variable infos.</remarks>
104    /// <param name="clonedObjects">Dictionary of all already cloned objects. (Needed to avoid cycles.)</param>
105    /// <returns>The cloned object as <see cref="OperatorBase"/>.</returns>
106    public override object Clone(IDictionary<Guid, object> clonedObjects) {
107      OperatorBase clone = (OperatorBase)base.Clone(clonedObjects);
108      clone.myName = Name;
109      clone.mySubOperators.Clear();
110      for (int i = 0; i < SubOperators.Count; i++)
111        clone.AddSubOperator((IOperator)Auxiliary.Clone(SubOperators[i], clonedObjects));
112      clone.myParameters.Clear();
113      foreach (IParameter parameter in myParameters.Values)
114        clone.AddParameter((IParameter)Auxiliary.Clone(parameter, clonedObjects));
115      return clone;
116    }
117
118    /// <summary>
119    /// Creates a new instance of <see cref="OperatorBaseView"/> to represent the current operator
120    /// visually.
121    /// </summary>
122    /// <returns>The created view as <see cref="OperatorBaseView"/>.</returns>
123    public override IView CreateView() {
124      return new OperatorBaseView(this);
125    }
126
127    #region SubOperator Methods
128    /// <inheritdoc cref="HeuristicLab.Core.IOperator.AddSubOperator(HeuristicLab.Core.IOperator)"/>
129    /// <param name="subOperator">The sub operator to add.</param>
130    /// <remarks>Calls <see cref="OnSubOperatorAdded"/>.</remarks>
131    public virtual void AddSubOperator(IOperator subOperator) {
132      mySubOperators.Add(subOperator);
133      OnSubOperatorAdded(subOperator, mySubOperators.Count - 1);
134    }
135    /// <inheritdoc cref="HeuristicLab.Core.IOperator.AddSubOperator(HeuristicLab.Core.IOperator, int)"/>
136    /// <param name="subOperator">The sub operator to add.</param>
137    /// <remarks>Calls <see cref="OnSubOperatorAdded"/>.</remarks>
138    public virtual void AddSubOperator(IOperator subOperator, int index) {
139      mySubOperators.Insert(index, subOperator);
140      OnSubOperatorAdded(subOperator, index);
141    }
142    /// <inheritdoc/>
143    /// <remarks>Calls <see cref="OnSubOperatorRemoved"/>.</remarks>
144    public virtual void RemoveSubOperator(int index) {
145      IOperator op = mySubOperators[index];
146      mySubOperators.RemoveAt(index);
147      OnSubOperatorRemoved(op, index);
148    }
149    #endregion
150
151    #region Parameter Methods
152    /// <inheritdoc/>
153    public virtual IParameter GetParameter(string name) {
154      IParameter info;
155      if (myParameters.TryGetValue(name, out info))
156        return info;
157      else
158        return null;
159    }
160    /// <inheritdoc/>
161    /// <remarks>Calls <see cref="OnVariableInfoAdded"/>.</remarks>
162    public virtual void AddParameter(IParameter parameter) {
163      myParameters.Add(parameter.Name, parameter);
164      OnParameterAdded(parameter);
165    }
166    /// <inheritdoc/>
167    /// <remarks>Calls <see cref="OnVariableInfoRemoved"/>.</remarks>
168    public virtual void RemoveParameter(string name) {
169      IParameter parameter;
170      if (myParameters.TryGetValue(name, out parameter)) {
171        myParameters.Remove(name);
172        OnParameterRemoved(parameter);
173      }
174    }
175    #endregion
176
177    /// <inheritdoc/>
178    public virtual IOperation Execute(IEnvironment env, IScope scope) {
179      myCanceled = false;
180
181      IOperation next = Apply(env, scope);
182
183      OnExecuted();
184      return next;
185    }
186    /// <inheritdoc/>
187    /// <remarks>Sets property <see cref="Canceled"/> to <c>true</c>.</remarks>
188    public virtual void Abort() {
189      myCanceled = true;
190    }
191    /// <summary>
192    /// Performs the current operator on the specified <paramref name="scope"/>.
193    /// </summary>
194    /// <param name="scope">The scope where to execute the operator</param>
195    /// <returns><c>null</c>.</returns>
196    public virtual IOperation Apply(IEnvironment env, IScope scope) {
197      return null;
198    }
199    /// <inheritdoc/>
200    public event EventHandler NameChanged;
201    /// <summary>
202    /// Fires a new <c>NameChanged</c> event.
203    /// </summary>
204    protected virtual void OnNameChanged() {
205      if (NameChanged != null) {
206        NameChanged(this, new EventArgs());
207      }
208    }
209    /// <inheritdoc/>
210    public event EventHandler BreakpointChanged;
211    /// <summary>
212    /// Fires a new <c>BreakpointChanged</c> event.
213    /// </summary>
214    protected virtual void OnBreakpointChanged() {
215      if (BreakpointChanged != null) {
216        BreakpointChanged(this, new EventArgs());
217      }
218    }
219    /// <inheritdoc/>
220    public event EventHandler<OperatorIndexEventArgs> SubOperatorAdded;
221    /// <summary>
222    /// Fires a new <c>SubOperatorAdded</c> event.
223    /// </summary>
224    /// <param name="subOperator">The sub operator that has been added.</param>
225    /// <param name="index">The position where the operator has been added.</param>
226    protected virtual void OnSubOperatorAdded(IOperator subOperator, int index) {
227      if (SubOperatorAdded != null)
228        SubOperatorAdded(this, new OperatorIndexEventArgs(subOperator, index));
229    }
230    /// <inheritdoc/>
231    public event EventHandler<OperatorIndexEventArgs> SubOperatorRemoved;
232    /// <summary>
233    /// Fires a new <c>SubOperatorRemoved</c> event.
234    /// </summary>
235    /// <param name="subOperator">The sub operator that has been removed.</param>
236    /// <param name="index">The position where the operator has been removed.</param>
237    protected virtual void OnSubOperatorRemoved(IOperator subOperator, int index) {
238      if (SubOperatorRemoved != null)
239        SubOperatorRemoved(this, new OperatorIndexEventArgs(subOperator, index));
240    }
241    /// <inheritdoc/>
242    public event EventHandler<ParameterEventArgs> ParameterAdded;
243    /// <summary>
244    /// Fires a new <c>ParameterAdded</c> event.
245    /// </summary>
246    /// <param name="parameter">The parameter that has been added.</param>
247    protected virtual void OnParameterAdded(IParameter parameter) {
248      if (ParameterAdded != null)
249        ParameterAdded(this, new ParameterEventArgs(parameter));
250    }
251    /// <inheritdoc/>
252    public event EventHandler<ParameterEventArgs> ParameterRemoved;
253    /// <summary>
254    /// Fires a new <c>ParameterRemoved</c> event.
255    /// </summary>
256    /// <param name="parameter">The parameter that has been removed.</param>
257    protected virtual void OnParameterRemoved(IParameter parameter) {
258      if (ParameterRemoved != null)
259        ParameterRemoved(this, new ParameterEventArgs(parameter));
260    }
261    /// <inheritdoc/>
262    public event EventHandler Executed;
263    /// <summary>
264    /// Fires a new <c>Executed</c> event.
265    /// </summary>
266    protected virtual void OnExecuted() {
267      if (Executed != null) {
268        Executed(this, new EventArgs());
269      }
270    }
271
272    #region Persistence Methods
273    /// <summary>
274    /// Saves the current instance as <see cref="XmlNode"/> in the specified <paramref name="document"/>.
275    /// </summary>
276    /// <remarks>
277    /// Calls <see cref="ConstrainedItemBase.GetXmlNode"/> of base class <see cref="ConstrainedItemBase"/>.
278    /// <br/>A quick overview how the single elements of the current instance are saved:
279    /// <list type="bullet">
280    /// <item>
281    /// <term>Name: </term>
282    /// <description>Saved as an <see cref="XmlAttribute"/> with the name <c>Name</c>.</description>
283    /// </item>
284    /// <item>
285    /// <term>Breakpoint: </term>
286    /// <description>Is only saved if it set to <c>true</c>.
287    /// Saved as an <see cref="XmlAttribute"/> with the name <c>Breakpoint</c>.</description>
288    /// </item>
289    /// <item>
290    /// <term>Sub operators: </term>
291    /// <description>Saved as child node with tag name <c>SubOperators</c>. All sub operators are themselves
292    /// saved as child nodes.</description>
293    /// </item>
294    /// <item>
295    /// <term>Variable infos: </term>
296    /// <description>Saved as child node with tag name <c>VariableInfos</c>. All variable infos are themselves
297    /// saved as child nodes.</description>
298    /// </item>
299    /// <item>
300    /// <term>Variables: </term>
301    /// <description>Saved as child node with tag name <c>Variables</c>. All variables are themselves
302    /// saved as child nodes.</description>
303    /// </item>
304    /// </list>
305    /// </remarks>
306    /// <param name="name">The (tag)name of the <see cref="XmlNode"/>.</param>
307    /// <param name="document">The <see cref="XmlDocument"/> where to save the data.</param>
308    /// <param name="persistedObjects">The dictionary of all already persisted objects. (Needed to avoid cycles.)</param>
309    /// <returns>The saved <see cref="XmlNode"/>.</returns>
310    public override XmlNode GetXmlNode(string name, XmlDocument document, IDictionary<Guid,IStorable> persistedObjects) {
311      XmlNode node = base.GetXmlNode(name, document, persistedObjects);
312      XmlAttribute nameAttribute = document.CreateAttribute("Name");
313      nameAttribute.Value = Name;
314      node.Attributes.Append(nameAttribute);
315      if (Breakpoint) {
316        XmlAttribute breakpointAttribute = document.CreateAttribute("Breakpoint");
317        breakpointAttribute.Value = Breakpoint.ToString();
318        node.Attributes.Append(breakpointAttribute);
319      }
320      XmlNode subOperatorsNode = document.CreateNode(XmlNodeType.Element, "SubOperators", null);
321      for (int i = 0; i < SubOperators.Count; i++)
322        subOperatorsNode.AppendChild(PersistenceManager.Persist(SubOperators[i], document, persistedObjects));
323      node.AppendChild(subOperatorsNode);
324      XmlNode parametersNode = document.CreateNode(XmlNodeType.Element, "Parameters", null);
325      foreach (IParameter parameter in myParameters.Values)
326        parametersNode.AppendChild(PersistenceManager.Persist(parameter, document, persistedObjects));
327      node.AppendChild(parametersNode);
328      return node;
329    }
330    /// <summary>
331    /// Loads the persisted operation from the specified <paramref name="node"/>.
332    /// </summary>
333    /// <remarks>Calls <see cref="ConstrainedItemBase.Populate"/> of base class
334    /// <see cref="ConstrainedItemBase"/>.
335    /// For informations how the different elements must be saved please see <see cref="GetXmlNode"/>.</remarks>
336    /// <param name="node">The <see cref="XmlNode"/> where the operation is saved.</param>
337    /// <param name="restoredObjects">A dictionary of all already restored objects. (Needed to avoid cycles.)</param>
338    public override void Populate(XmlNode node, IDictionary<Guid,IStorable> restoredObjects) {
339      base.Populate(node, restoredObjects);
340      myName = node.Attributes["Name"].Value;
341      if (node.Attributes["Breakpoint"] != null)
342        myBreakpoint = bool.Parse(node.Attributes["Breakpoint"].Value);
343      XmlNode subOperatorsNode = node.SelectSingleNode("SubOperators");
344      for (int i = 0; i < subOperatorsNode.ChildNodes.Count; i++)
345        AddSubOperator((IOperator)PersistenceManager.Restore(subOperatorsNode.ChildNodes[i], restoredObjects));
346      XmlNode parametersNode = node.SelectSingleNode("Parameters");
347      myParameters.Clear();
348      foreach (XmlNode parameterNode in parametersNode.ChildNodes)
349        AddParameter((IParameter)PersistenceManager.Restore(parameterNode, restoredObjects));
350    }
351    #endregion
352  }
353}
Note: See TracBrowser for help on using the repository browser.