source: trunk/sources/HeuristicLab.Core/3.3/OperatorGraph.cs @ 3729

Last change on this file since 3729 was 3729, checked in by swagner, 12 years ago

Fixed exception thrown in OperatorGraph views when removing one of the operator parameters of a MultiOperator (#1004)

File size: 10.3 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2010 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 System.Linq;
27using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
28using HeuristicLab.Common;
29using HeuristicLab.Collections;
30
31namespace HeuristicLab.Core {
32  /// <summary>
33  /// Represents a graph of operators.
34  /// </summary>
35  [Item("Operator Graph", "Represents a graph of operators.")]
36  [Creatable("Algorithm Design")]
37  [StorableClass]
38  public class OperatorGraph : Item {
39    [Storable]
40    private OperatorSet operators;
41    /// <summary>
42    /// Gets all operators of the current instance.
43    /// </summary>
44    public OperatorSet Operators {
45      get { return operators; }
46    }
47
48    [Storable]
49    private IOperator initialOperator;
50    /// <summary>
51    /// Gets or sets the initial operator (the starting one).
52    /// </summary>
53    /// <remarks>Calls <see cref="OnInitialOperatorChanged"/> in the setter.</remarks>
54    public IOperator InitialOperator {
55      get { return initialOperator; }
56      set {
57        if (initialOperator != value) {
58          if (value != null) Operators.Add(value);
59          initialOperator = value;
60          OnInitialOperatorChanged();
61        }
62      }
63    }
64
65    [Storable]
66    private IDeepCloneable visualizationInfo;
67    /// <summary>
68    /// Gets or sets the visualizationInfo.
69    /// </summary>
70    /// /// <remarks>The VisualizationInfo can only be set once and fires afterwards and InvalidOperationException</remarks>
71    public IDeepCloneable VisualizationInfo {
72      get { return visualizationInfo; }
73      set {
74        if (visualizationInfo != null)
75          throw new InvalidOperationException("The value of the property VisualizationInfo is already set and cannot be set again.");
76        visualizationInfo = value;
77      }
78    }
79
80    /// <summary>
81    /// Initializes a new instance of <see cref="OperatorGraph"/>.
82    /// </summary>
83    public OperatorGraph() {
84      operators = new OperatorSet();
85      initialOperator = null;
86      visualizationInfo = null;
87      Initialize();
88    }
89    [StorableConstructor]
90    protected OperatorGraph(bool deserializing) : base(deserializing) { }
91
92    //mkommend: IMPORTANT DO NOT REMOVE THIS PRIVATE EVENT
93    //needed to register OperatorGraph events in GraphVisualizationInfo
94    public event EventHandler DeserializationFinished;
95    private void OnOperatorGraphDeserializationFinished() {
96      EventHandler handler = DeserializationFinished;
97      if(handler != null)
98        handler(this,EventArgs.Empty);
99    }
100    [StorableHook(HookType.AfterDeserialization)]
101    private void Initialize() {
102      RegisterOperatorsEvents();
103      OnOperatorGraphDeserializationFinished();
104    }
105
106    /// <summary>
107    /// Clones the current instance (deep clone).
108    /// </summary>
109    /// <remarks>Deep clone through <see cref="cloner.Clone"/> method of helper class
110    /// <see cref="Auxiliary"/>.</remarks>
111    /// <param name="clonedObjects">Dictionary of all already cloned objects. (Needed to avoid cycles.)</param>
112    /// <returns>The cloned object as <see cref="OperatorGraph"/>.</returns>
113    public override IDeepCloneable Clone(Cloner cloner) {
114      OperatorGraph clone = (OperatorGraph)base.Clone(cloner);
115      clone.operators = (OperatorSet)cloner.Clone(operators);
116      clone.initialOperator = (IOperator)cloner.Clone(initialOperator);
117      clone.visualizationInfo = cloner.Clone(visualizationInfo);
118      clone.Initialize();
119      return clone;
120    }
121
122    /// <inheritdoc/>
123    public event EventHandler InitialOperatorChanged;
124    /// <summary>
125    /// Fires a new <c>InitialOperatorChanged</c> event.
126    /// </summary>
127    protected virtual void OnInitialOperatorChanged() {
128      if (InitialOperatorChanged != null)
129        InitialOperatorChanged(this, EventArgs.Empty);
130    }
131
132    #region Operators Events
133    private void AddOperator(IOperator op) {
134      RegisterOperatorEvents(op);
135      foreach (IParameter param in op.Parameters)
136        AddParameter(param);
137    }
138    private void RemoveOperator(IOperator op) {
139      foreach (IParameter param in op.Parameters)
140        RemoveParameter(param);
141      DeregisterOperatorEvents(op);
142
143      // remove edges to removed operator
144      IValueParameter[] opParams = (from o in Operators
145                                    from p in o.Parameters
146                                    where p is IValueParameter
147                                    where typeof(IOperator).IsAssignableFrom(((IValueParameter)p).DataType)
148                                    where (((IValueParameter)p).Value != null) && (((IValueParameter)p).Value == op)
149                                    select (IValueParameter)p).ToArray();
150      foreach (IValueParameter opParam in opParams)
151        opParam.Value = null;
152    }
153    private void AddParameter(IParameter param) {
154      IValueParameter valueParam = param as IValueParameter;
155      if ((valueParam != null) && (typeof(IOperator).IsAssignableFrom(valueParam.DataType))) {
156        RegisterOperatorParameterEvents(valueParam);
157        if (valueParam.Value != null) Operators.Add((IOperator)valueParam.Value);
158      }
159    }
160    private void RemoveParameter(IParameter param) {
161      IValueParameter valueParam = param as IValueParameter;
162      if ((valueParam != null) && (typeof(IOperator).IsAssignableFrom(valueParam.DataType))) {
163        DeregisterOperatorParameterEvents(valueParam);
164      }
165    }
166
167    private void RegisterOperatorsEvents() {
168      if (operators != null) {
169        operators.ItemsAdded += new CollectionItemsChangedEventHandler<IOperator>(Operators_ItemsAdded);
170        operators.ItemsRemoved += new CollectionItemsChangedEventHandler<IOperator>(Operators_ItemsRemoved);
171        operators.CollectionReset += new CollectionItemsChangedEventHandler<IOperator>(Operators_CollectionReset);
172        foreach (IOperator op in operators) {
173          RegisterOperatorEvents(op);
174          var opParams = from p in op.Parameters
175                         where p is IValueParameter
176                         where typeof(IOperator).IsAssignableFrom(((IValueParameter)p).DataType)
177                         select (IValueParameter)p;
178          foreach (IValueParameter opParam in opParams)
179            RegisterOperatorParameterEvents(opParam);
180        }
181      }
182    }
183    private void RegisterOperatorEvents(IOperator op) {
184      op.Parameters.ItemsAdded += new CollectionItemsChangedEventHandler<IParameter>(Parameters_ItemsAdded);
185      op.Parameters.ItemsRemoved += new CollectionItemsChangedEventHandler<IParameter>(Parameters_ItemsRemoved);
186      op.Parameters.ItemsReplaced += new CollectionItemsChangedEventHandler<IParameter>(Parameters_ItemsReplaced);
187      op.Parameters.CollectionReset += new CollectionItemsChangedEventHandler<IParameter>(Parameters_CollectionReset);
188    }
189    private void DeregisterOperatorEvents(IOperator op) {
190      op.Parameters.ItemsAdded -= new CollectionItemsChangedEventHandler<IParameter>(Parameters_ItemsAdded);
191      op.Parameters.ItemsRemoved -= new CollectionItemsChangedEventHandler<IParameter>(Parameters_ItemsRemoved);
192      op.Parameters.ItemsReplaced -= new CollectionItemsChangedEventHandler<IParameter>(Parameters_ItemsReplaced);
193      op.Parameters.CollectionReset -= new CollectionItemsChangedEventHandler<IParameter>(Parameters_CollectionReset);
194    }
195    private void RegisterOperatorParameterEvents(IValueParameter opParam) {
196      opParam.ValueChanged += new EventHandler(opParam_ValueChanged);
197    }
198    private void DeregisterOperatorParameterEvents(IValueParameter opParam) {
199      opParam.ValueChanged -= new EventHandler(opParam_ValueChanged);
200    }
201
202    private void Operators_ItemsAdded(object sender, CollectionItemsChangedEventArgs<IOperator> e) {
203      foreach (IOperator op in e.Items)
204        AddOperator(op);
205    }
206    private void Operators_ItemsRemoved(object sender, CollectionItemsChangedEventArgs<IOperator> e) {
207      foreach (IOperator op in e.Items)
208        RemoveOperator(op);
209      if (!Operators.Contains(InitialOperator)) InitialOperator = null;
210    }
211    private void Operators_CollectionReset(object sender, CollectionItemsChangedEventArgs<IOperator> e) {
212      foreach (IOperator op in e.OldItems)
213        RemoveOperator(op);
214      foreach (IOperator op in e.Items)
215        AddOperator(op);
216      if (!Operators.Contains(InitialOperator)) InitialOperator = null;
217    }
218    private void Parameters_ItemsAdded(object sender, CollectionItemsChangedEventArgs<IParameter> e) {
219      foreach (IParameter param in e.Items)
220        AddParameter(param);
221    }
222    private void Parameters_ItemsRemoved(object sender, CollectionItemsChangedEventArgs<IParameter> e) {
223      foreach (IParameter param in e.Items)
224        RemoveParameter(param);
225    }
226    private void Parameters_ItemsReplaced(object sender, CollectionItemsChangedEventArgs<IParameter> e) {
227      foreach (IParameter param in e.OldItems)
228        RemoveParameter(param);
229      foreach (IParameter param in e.Items)
230        AddParameter(param);
231    }
232    private void Parameters_CollectionReset(object sender, CollectionItemsChangedEventArgs<IParameter> e) {
233      foreach (IParameter param in e.OldItems)
234        RemoveParameter(param);
235      foreach (IParameter param in e.Items)
236        AddParameter(param);
237    }
238    private void opParam_ValueChanged(object sender, EventArgs e) {
239      IValueParameter opParam = (IValueParameter)sender;
240      if (opParam.Value != null) Operators.Add((IOperator)opParam.Value);
241    }
242    #endregion
243  }
244}
Note: See TracBrowser for help on using the repository browser.