Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/HeuristicLab.Core/3.3/OperatorBase.cs @ 2620

Last change on this file since 2620 was 2526, checked in by swagner, 15 years ago

Refactored cloning (#806)

File size: 15.7 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.Persistence.Default.CompositeSerializers.Storable;
27using HeuristicLab.Common;
28
29namespace HeuristicLab.Core {
30  /// <summary>
31  /// The base class for all operators.
32  /// </summary>
33  public abstract class OperatorBase : ItemBase, IOperator {
34
35    [Storable]
36    private string myName;
37    /// <summary>
38    /// Gets or sets the name of the operator.
39    /// </summary>
40    /// <remarks>Calls <see cref="OnNameChanged"/> in the setter.</remarks>
41    public string Name {
42      get { return myName; }
43      set {
44        if (myName != value) {
45          myName = value;
46          OnNameChanged();
47        }
48      }
49    }
50    /// <summary>
51    /// Gets the description of the current operator.
52    /// </summary>
53    /// <remarks>Returns "No operator description available" if the method is not overriden.</remarks>
54    public virtual string Description {
55      get { return "No operator description available."; }
56    }
57    /// <summary>
58    /// Flag whether the current instance has been canceled.
59    /// </summary>
60    protected bool myCanceled;
61    /// <inheritdoc/>
62    public bool Canceled {
63      get { return myCanceled; }
64    }
65
66    [Storable]
67    private bool myBreakpoint;
68    /// <inheritdoc/>
69    /// <remarks>Calls <see cref="OnBreakpointChanged"/> in the setter.</remarks>
70    public bool Breakpoint {
71      get { return myBreakpoint; }
72      set {
73        if (value != myBreakpoint) {
74          myBreakpoint = value;
75          OnBreakpointChanged();
76        }
77      }
78    }
79
80    [Storable]
81    private List<IOperator> mySubOperators;
82    /// <summary>
83    /// Gets a list of all suboperators.
84    /// <note type="caution"> Returns the suboperators read-only!</note>
85    /// </summary>
86    public virtual IList<IOperator> SubOperators {
87      get { return mySubOperators.AsReadOnly(); }
88    }
89
90    [Storable]
91    private Dictionary<string, IVariableInfo> myVariableInfos;
92    /// <inheritdoc/>
93    public virtual ICollection<IVariableInfo> VariableInfos {
94      get { return myVariableInfos.Values; }
95    }
96   
97    private Dictionary<string, IVariable> myVariables;
98    /// <inheritdoc/>   
99    public virtual ICollection<IVariable> Variables {
100      get { return myVariables.Values; }
101    }
102
103    [Storable(Name="Variables")]
104    private List<IVariable> VariablePersistence {
105      get { return new List<IVariable>(myVariables.Values); }
106      set {
107        myVariables.Clear();
108        foreach (IVariable var in value) {
109          AddVariable(var);
110        }
111      }
112    }
113
114    /// <summary>
115    /// Initializes a new instance of <see cref="OperatorBase"/> setting the breakpoint flag and
116    /// the canceled flag to <c>false</c> and the name of the operator to the type name.
117    /// </summary>
118    protected OperatorBase() {
119      myName = this.GetType().Name;
120      myCanceled = false;
121      myBreakpoint = false;
122      mySubOperators = new List<IOperator>();
123      myVariableInfos = new Dictionary<string, IVariableInfo>();
124      myVariables = new Dictionary<string, IVariable>();
125    }
126
127    /// <summary>
128    /// Clones the current instance (deep clone).
129    /// </summary>
130    /// <remarks>Clones also sub operators, variables and variable infos.</remarks>
131    /// <param name="clonedObjects">Dictionary of all already cloned objects. (Needed to avoid cycles.)</param>
132    /// <returns>The cloned object as <see cref="OperatorBase"/>.</returns>
133    public override IItem Clone(ICloner cloner) {
134      OperatorBase clone = (OperatorBase)base.Clone(cloner);
135      clone.myName = Name;
136      clone.mySubOperators.Clear();
137      for (int i = 0; i < SubOperators.Count; i++)
138        clone.AddSubOperator((IOperator)cloner.Clone(SubOperators[i]));
139      clone.myVariableInfos.Clear();
140      foreach (IVariableInfo variableInfo in myVariableInfos.Values)
141        clone.AddVariableInfo((IVariableInfo)cloner.Clone(variableInfo));
142      clone.myVariables.Clear();
143      foreach (IVariable variable in myVariables.Values)
144        clone.AddVariable((IVariable)cloner.Clone(variable));
145      return clone;
146    }
147
148    #region SubOperator Methods
149    /// <inheritdoc cref="HeuristicLab.Core.IOperator.AddSubOperator(HeuristicLab.Core.IOperator)"/>
150    /// <param name="subOperator">The sub operator to add.</param>
151    /// <remarks>Calls <see cref="OnSubOperatorAdded"/>.</remarks>
152    public virtual void AddSubOperator(IOperator subOperator) {
153      mySubOperators.Add(subOperator);
154      OnSubOperatorAdded(subOperator, mySubOperators.Count - 1);
155    }
156    /// <inheritdoc cref="HeuristicLab.Core.IOperator.AddSubOperator(HeuristicLab.Core.IOperator, int)"/>
157    /// <param name="subOperator">The sub operator to add.</param>
158    /// <remarks>Calls <see cref="OnSubOperatorAdded"/>.</remarks>
159    public virtual void AddSubOperator(IOperator subOperator, int index) {
160      mySubOperators.Insert(index, subOperator);
161      OnSubOperatorAdded(subOperator, index);
162    }
163    /// <inheritdoc/>
164    /// <remarks>Calls <see cref="OnSubOperatorRemoved"/>.</remarks>
165    public virtual void RemoveSubOperator(int index) {
166      IOperator op = mySubOperators[index];
167      mySubOperators.RemoveAt(index);
168      OnSubOperatorRemoved(op, index);
169    }
170    #endregion
171
172    #region VariableInfo Methods
173    /// <inheritdoc/>
174    public virtual IVariableInfo GetVariableInfo(string formalName) {
175      IVariableInfo info;
176      if (myVariableInfos.TryGetValue(formalName, out info))
177        return info;
178      else
179        return null;
180    }
181    /// <inheritdoc/>
182    /// <remarks>Calls <see cref="OnVariableInfoAdded"/>.</remarks>
183    public virtual void AddVariableInfo(IVariableInfo variableInfo) {
184      myVariableInfos.Add(variableInfo.FormalName, variableInfo);
185      OnVariableInfoAdded(variableInfo);
186    }
187    /// <inheritdoc/>
188    /// <remarks>Calls <see cref="OnVariableInfoRemoved"/>.</remarks>
189    public virtual void RemoveVariableInfo(string formalName) {
190      IVariableInfo variableInfo;
191      if (myVariableInfos.TryGetValue(formalName, out variableInfo)) {
192        myVariableInfos.Remove(formalName);
193        OnVariableInfoRemoved(variableInfo);
194      }
195    }
196    #endregion
197
198    #region Variable Methods
199    /// <inheritdoc/>
200    public virtual IVariable GetVariable(string name) {
201      IVariable variable;
202      if (myVariables.TryGetValue(name, out variable))
203        return variable;
204      else
205        return null;
206    }
207    /// <inheritdoc/>
208    /// <remarks>Calls <see cref="OnVariableAdded"/> and adds <c>NameChanging</c> and <c>NameChanged</c>
209    /// event handlers.</remarks>
210    public virtual void AddVariable(IVariable variable) {
211      myVariables.Add(variable.Name, variable);
212      variable.NameChanging += new EventHandler<CancelEventArgs<string>>(Variable_NameChanging);
213      variable.NameChanged += new EventHandler(Variable_NameChanged);
214      OnVariableAdded(variable);
215    }
216    /// <inheritdoc/>
217    /// <remarks>Calls <see cref="OnVariableRemoved"/> and removes <c>NameChanging</c> and <c>NameChanged</c>
218    /// event handlers.</remarks>
219    public virtual void RemoveVariable(string name) {
220      IVariable variable;
221      if (myVariables.TryGetValue(name, out variable)) {
222        variable.NameChanging -= new EventHandler<CancelEventArgs<string>>(Variable_NameChanging);
223        variable.NameChanged -= new EventHandler(Variable_NameChanged);
224        myVariables.Remove(name);
225        OnVariableRemoved(variable);
226      }
227    }
228    private void Variable_NameChanging(object sender, CancelEventArgs<string> e) {
229      e.Cancel = myVariables.ContainsKey(e.Value);
230    }
231    private void Variable_NameChanged(object sender, EventArgs e) {
232      IVariable variable = (IVariable)sender;
233      string oldName = null;
234      foreach (KeyValuePair<string, IVariable> element in myVariables) {
235        if (element.Value == variable)
236          oldName = element.Key;
237      }
238      myVariables.Remove(oldName);
239      myVariables.Add(variable.Name, variable);
240    }
241    /// <inheritdoc cref="IOperator.GetVariableValue&lt;T&gt;(string, HeuristicLab.Core.IScope, bool)"/>
242    ///  <remarks>Calls <see cref="GetVariableValue&lt;T&gt;(string, HeuristicLab.Core.IScope, bool, bool)"/>
243    /// with <c>throwOnError</c> set to <c>false</c>.</remarks>
244    public T GetVariableValue<T>(string formalName, IScope scope, bool recursiveLookup) where T : class, IItem {
245      return GetVariableValue<T>(formalName, scope, recursiveLookup, true);
246    }
247    /// <inheritdoc cref="IOperator.GetVariableValue&lt;T&gt;(string, HeuristicLab.Core.IScope, bool, bool)"/>
248    /// <remarks>Calls
249    /// <see cref="GetVariableValue(string, HeuristicLab.Core.IScope, bool, bool)"/>.</remarks>
250    public T GetVariableValue<T>(string formalName, IScope scope, bool recursiveLookup, bool throwOnError) where T : class, IItem {
251      return (T)GetVariableValue(formalName, scope, recursiveLookup, throwOnError);
252    }
253    /// <inheritdoc cref="IOperator.GetVariableValue(string, HeuristicLab.Core.IScope, bool)"/>
254    /// <remarks>Calls <see cref="GetVariableValue(string, HeuristicLab.Core.IScope, bool, bool)"/>
255    /// with <c>throwOnError</c> set to <c>false</c>.</remarks>
256    public IItem GetVariableValue(string formalName, IScope scope, bool recursiveLookup) {
257      return GetVariableValue(formalName, scope, recursiveLookup, true);
258    }
259    /// <inheritdoc cref="IOperator.GetVariableValue(string, HeuristicLab.Core.IScope, bool, bool)"/>
260    public virtual IItem GetVariableValue(string formalName, IScope scope, bool recursiveLookup, bool throwOnError) {
261      IVariableInfo info = GetVariableInfo(formalName);
262      if (info.Local) {
263        IVariable variable;
264        if (myVariables.TryGetValue(info.ActualName, out variable))
265          return variable.Value;
266        else {
267          if (throwOnError)
268            throw new ArgumentException("Variable " + info.ActualName + " not found");
269          else
270            return null;
271        }
272      } else {
273        return scope.GetVariableValue(formalName, recursiveLookup, throwOnError);
274      }
275    }
276    #endregion
277    /// <inheritdoc/>
278    public virtual IOperation Execute(IScope scope) {
279      myCanceled = false;
280
281      foreach (IVariableInfo variableInfo in VariableInfos)
282        scope.AddAlias(variableInfo.FormalName, variableInfo.ActualName);
283
284      IOperation next = Apply(scope);
285
286      foreach (IVariableInfo variableInfo in VariableInfos)
287        scope.RemoveAlias(variableInfo.FormalName);
288
289      OnExecuted();
290      return next;
291    }
292    /// <inheritdoc/>
293    /// <remarks>Sets property <see cref="Canceled"/> to <c>true</c>.</remarks>
294    public virtual void Abort() {
295      myCanceled = true;
296    }
297    /// <summary>
298    /// Performs the current operator on the specified <paramref name="scope"/>.
299    /// </summary>
300    /// <param name="scope">The scope where to execute the operator</param>
301    /// <returns><c>null</c>.</returns>
302    public virtual IOperation Apply(IScope scope) {
303      return null;
304    }
305    /// <inheritdoc/>
306    public event EventHandler NameChanged;
307    /// <summary>
308    /// Fires a new <c>NameChanged</c> event.
309    /// </summary>
310    protected virtual void OnNameChanged() {
311      if (NameChanged != null) {
312        NameChanged(this, new EventArgs());
313      }
314    }
315    /// <inheritdoc/>
316    public event EventHandler BreakpointChanged;
317    /// <summary>
318    /// Fires a new <c>BreakpointChanged</c> event.
319    /// </summary>
320    protected virtual void OnBreakpointChanged() {
321      if (BreakpointChanged != null) {
322        BreakpointChanged(this, new EventArgs());
323      }
324    }
325    /// <inheritdoc/>
326    public event EventHandler<EventArgs<IOperator, int>> SubOperatorAdded;
327    /// <summary>
328    /// Fires a new <c>SubOperatorAdded</c> event.
329    /// </summary>
330    /// <param name="subOperator">The sub operator that has been added.</param>
331    /// <param name="index">The position where the operator has been added.</param>
332    protected virtual void OnSubOperatorAdded(IOperator subOperator, int index) {
333      if (SubOperatorAdded != null)
334        SubOperatorAdded(this, new EventArgs<IOperator, int>(subOperator, index));
335    }
336    /// <inheritdoc/>
337    public event EventHandler<EventArgs<IOperator, int>> SubOperatorRemoved;
338    /// <summary>
339    /// Fires a new <c>SubOperatorRemoved</c> event.
340    /// </summary>
341    /// <param name="subOperator">The sub operator that has been removed.</param>
342    /// <param name="index">The position where the operator has been removed.</param>
343    protected virtual void OnSubOperatorRemoved(IOperator subOperator, int index) {
344      if (SubOperatorRemoved != null)
345        SubOperatorRemoved(this, new EventArgs<IOperator, int>(subOperator, index));
346    }
347    /// <inheritdoc/>
348    public event EventHandler<EventArgs<IVariableInfo>> VariableInfoAdded;
349    /// <summary>
350    /// Fires a new <c>VariableInfoAdded</c> event.
351    /// </summary>
352    /// <param name="variableInfo">The variable info that has been added.</param>
353    protected virtual void OnVariableInfoAdded(IVariableInfo variableInfo) {
354      if (VariableInfoAdded != null)
355        VariableInfoAdded(this, new EventArgs<IVariableInfo>(variableInfo));
356    }
357    /// <inheritdoc/>
358    public event EventHandler<EventArgs<IVariableInfo>> VariableInfoRemoved;
359    /// <summary>
360    /// Fires a new <c>VariableInfoRemoved</c> event.
361    /// </summary>
362    /// <param name="variableInfo">The variable info that has been removed.</param>
363    protected virtual void OnVariableInfoRemoved(IVariableInfo variableInfo) {
364      if (VariableInfoRemoved != null)
365        VariableInfoRemoved(this, new EventArgs<IVariableInfo>(variableInfo));
366    }
367    /// <inheritdoc/>
368    public event EventHandler<EventArgs<IVariable>> VariableAdded;
369    /// <summary>
370    /// Fires a new <c>VariableAdded</c> event.
371    /// </summary>
372    /// <param name="variable">The variable that has been added.</param>
373    protected virtual void OnVariableAdded(IVariable variable) {
374      if (VariableAdded != null)
375        VariableAdded(this, new EventArgs<IVariable>(variable));
376    }
377    /// <inheritdoc/>
378    public event EventHandler<EventArgs<IVariable>> VariableRemoved;
379    /// <summary>
380    /// Fires a new <c>VariableRemoved</c> event.
381    /// </summary>
382    /// <param name="variable">The variable that has been removed</param>
383    protected virtual void OnVariableRemoved(IVariable variable) {
384      if (VariableRemoved != null)
385        VariableRemoved(this, new EventArgs<IVariable>(variable));
386    }
387    /// <inheritdoc/>
388    public event EventHandler Executed;
389    /// <summary>
390    /// Fires a new <c>Executed</c> event.
391    /// </summary>
392    protected virtual void OnExecuted() {
393      if (Executed != null) {
394        Executed(this, new EventArgs());
395      }
396    }
397  }
398}
Note: See TracBrowser for help on using the repository browser.