Free cookie consent management tool by TermsFeed Policy Generator

source: branches/OptimizationNetworks/HeuristicLab.Networks/3.3/Programmable/ProgrammableNetworkItem.cs @ 13135

Last change on this file since 13135 was 13135, checked in by jkarder, 8 years ago

#2205: worked on optimization networks

  • refactored network visualization
File size: 14.7 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2014 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.CodeDom.Compiler;
24using System.Collections.Generic;
25using System.Drawing;
26using System.IO;
27using System.Linq;
28using System.Reflection;
29using System.Text;
30using HeuristicLab.Common;
31using HeuristicLab.Core;
32using HeuristicLab.Core.Networks;
33using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
34using HeuristicLab.Scripting;
35using Microsoft.CSharp;
36
37namespace HeuristicLab.Networks.Programmable {
38  [Item("ProgrammableNetworkItem", "Abstract base class for programmable items of a network.")]
39  [StorableClass]
40  public abstract class ProgrammableNetworkItem : Item, IProgrammableNetworkItem {
41    public static new Image StaticItemImage {
42      get { return HeuristicLab.Common.Resources.VSImageLibrary.Class; }
43    }
44
45    #region Item Members
46    public override string ItemName {
47      get { return CompiledNetworkItem.ItemName; }
48    }
49    public override string ItemDescription {
50      get { return CompiledNetworkItem.ItemDescription; }
51    }
52    public override Image ItemImage {
53      get { return CompiledNetworkItem.ItemImage; }
54    }
55    #endregion
56
57    #region NamedItem Members
58    [Storable]
59    private string name;
60    public string Name {
61      get { return CompiledNetworkItem.Name; }
62      set { CompiledNetworkItem.Name = value; }
63    }
64    public bool CanChangeName {
65      get { return CompiledNetworkItem.CanChangeName; }
66    }
67    [Storable]
68    private string description;
69    public string Description {
70      get { return CompiledNetworkItem.Description; }
71      set { CompiledNetworkItem.Description = value; }
72    }
73    public virtual bool CanChangeDescription {
74      get { return CompiledNetworkItem.CanChangeDescription; }
75    }
76    public event EventHandler<CancelEventArgs<string>> NameChanging;
77    private void OnNameChanging(CancelEventArgs<string> e) {
78      var handler = NameChanging;
79      if (handler != null) handler(this, e);
80    }
81    public event EventHandler NameChanged;
82    private void OnNameChanged() {
83      var handler = NameChanged;
84      if (handler != null) handler(this, EventArgs.Empty);
85    }
86    public event EventHandler DescriptionChanged;
87    private void OnDescriptionChanged() {
88      var handler = DescriptionChanged;
89      if (handler != null) handler(this, EventArgs.Empty);
90    }
91    #endregion
92
93    #region NetworkItem Members
94    public INetworkItem Parent {
95      get { return CompiledNetworkItem.Parent; }
96    }
97    public IEnumerable<INetworkItem> Children {
98      get { return CompiledNetworkItem.Children; }
99    }
100
101    [Storable]
102    public IVisualProperties VisualProperties { get; set; }
103    #endregion
104
105    protected virtual string CodeTemplate {
106      get { return CodeResources.ProgrammableNetworkItemCode; }
107    }
108    [Storable]
109    private string code;
110    public string Code {
111      get { return code; }
112      set {
113        if (!CanChangeCode) throw new NotSupportedException("Code cannot be changed.");
114        if (value != code) {
115          code = value;
116          OnCodeChanged();
117        }
118      }
119    }
120    private CompilerErrorCollection compileErrors;
121    public CompilerErrorCollection CompileErrors {
122      get { return compileErrors; }
123      protected set {
124        compileErrors = value;
125        OnCompileErrorsChanged();
126      }
127    }
128    public virtual bool CanChangeCode {
129      get { return false; }
130    }
131    [Storable]
132    private VariableStore variableStore;
133    public VariableStore VariableStore {
134      get { return variableStore; }
135    }
136
137    private Type compiledNetworkItemType;
138    private CompiledProgrammableNetworkItem compiledNetworkItem;
139    protected CompiledProgrammableNetworkItem CompiledNetworkItem {
140      get {
141        if (compiledNetworkItem == null)
142          CompiledNetworkItem = (CompiledProgrammableNetworkItem)Activator.CreateInstance(compiledNetworkItemType, this);
143        return compiledNetworkItem;
144      }
145      private set {
146        if (compiledNetworkItem != value) {
147          if (compiledNetworkItem != null) {
148            DeregisterCompiledNetworkItemEvents();
149            compiledNetworkItem.DeregisterEvents();
150          }
151          compiledNetworkItem = value;
152          if (compiledNetworkItem != null) {
153            RegisterCompiledNetworkItemEvents();
154            compiledNetworkItem.RegisterEvents();
155          }
156          OnToStringChanged();
157          OnItemImageChanged();
158          OnNameChanged();
159          OnDescriptionChanged();
160        }
161      }
162    }
163
164    [StorableConstructor]
165    protected ProgrammableNetworkItem(bool deserializing) : base(deserializing) { }
166    protected ProgrammableNetworkItem(ProgrammableNetworkItem original, Cloner cloner)
167      : base(original, cloner) {
168      // name and description are cloned in CompiledProgrammableNetworkItem
169      code = original.code;
170      if (original.compileErrors != null)
171        compileErrors = new CompilerErrorCollection(original.compileErrors);
172      variableStore = cloner.Clone(original.variableStore);
173      CompiledNetworkItem = cloner.Clone(original.compiledNetworkItem);
174      VisualProperties = cloner.Clone(original.VisualProperties);
175    }
176    protected ProgrammableNetworkItem()
177      : base() {
178      name = "ProgrammableNetworkItem";
179      description = string.Empty;
180      code = CodeTemplate;
181      variableStore = new VariableStore();
182      Compile();
183    }
184    protected ProgrammableNetworkItem(string name)
185      : base() {
186      this.name = string.IsNullOrEmpty(name) ? string.Empty : name;
187      description = string.Empty;
188      code = CodeTemplate;
189      variableStore = new VariableStore();
190      Compile();
191    }
192    protected ProgrammableNetworkItem(string name, string description)
193      : base() {
194      this.name = string.IsNullOrEmpty(name) ? string.Empty : name;
195      this.description = string.IsNullOrEmpty(description) ? string.Empty : description;
196      code = CodeTemplate;
197      variableStore = new VariableStore();
198      Compile();
199    }
200
201    [StorableHook(HookType.AfterDeserialization)]
202    private void AfterDeserialization() {
203      Compile();
204    }
205
206    public override string ToString() {
207      return CompiledNetworkItem.ToString();
208    }
209
210    #region Compilation
211    public virtual void Compile() {
212      var codeProvider = new CSharpCodeProvider(
213        new Dictionary<string, string> {
214          {"CompilerVersion", "v4.0"}, // support C# 4.0 syntax
215        }
216      );
217      var compilerParams = new CompilerParameters {
218        GenerateExecutable = false,
219        GenerateInMemory = true,
220        IncludeDebugInformation = true,
221        WarningLevel = 4
222      };
223      compilerParams.ReferencedAssemblies.AddRange(
224        GetAssemblies().Select(a => a.Location).ToArray()
225      );
226      var results = codeProvider.CompileAssemblyFromSource(compilerParams, code);
227      CompileErrors = results.Errors;
228      if (results.Errors.HasErrors) {
229        var sb = new StringBuilder();
230        foreach (CompilerError error in results.Errors) {
231          sb.Append(error.Line).Append(':')
232            .Append(error.Column).Append(": ")
233            .AppendLine(error.ErrorText);
234        }
235        throw new InvalidOperationException(string.Format("Compilation of \"{0}\" failed:{1}{2}",
236          Name, Environment.NewLine, sb.ToString()));
237      }
238      compiledNetworkItemType = results.CompiledAssembly.GetTypes()
239          .Single(x => typeof(CompiledProgrammableNetworkItem).IsAssignableFrom(x));
240      CompiledNetworkItem = null;
241    }
242    public virtual IEnumerable<Assembly> GetAssemblies() {
243      var assemblies = AppDomain.CurrentDomain.GetAssemblies()
244        .Where(a => !a.IsDynamic && File.Exists(a.Location))
245        .ToList();
246      assemblies.Add(typeof(Microsoft.CSharp.RuntimeBinder.Binder).Assembly);  // for dlr functionality
247      return assemblies;
248    }
249    #endregion
250
251    public event EventHandler CodeChanged;
252    protected virtual void OnCodeChanged() {
253      var handler = CodeChanged;
254      if (handler != null) handler(this, EventArgs.Empty);
255    }
256    public event EventHandler CompileErrorsChanged;
257    protected virtual void OnCompileErrorsChanged() {
258      var handler = CompileErrorsChanged;
259      if (handler != null) handler(this, EventArgs.Empty);
260    }
261
262    #region CompiledNetworkItem Events
263    protected virtual void RegisterCompiledNetworkItemEvents() {
264      CompiledNetworkItem.ToStringChanged += CompiledNetworkItem_ToStringChanged;
265      CompiledNetworkItem.ItemImageChanged += CompiledNetworkItem_ItemImageChanged;
266      CompiledNetworkItem.NameChanging += CompiledNetworkItem_NameChanging;
267      CompiledNetworkItem.NameChanged += CompiledNetworkItem_NameChanged;
268      CompiledNetworkItem.DescriptionChanged += CompiledNetworkItem_DescriptionChanged;
269    }
270    protected virtual void DeregisterCompiledNetworkItemEvents() {
271      CompiledNetworkItem.ToStringChanged -= CompiledNetworkItem_ToStringChanged;
272      CompiledNetworkItem.ItemImageChanged -= CompiledNetworkItem_ItemImageChanged;
273      CompiledNetworkItem.NameChanging -= CompiledNetworkItem_NameChanging;
274      CompiledNetworkItem.NameChanged -= CompiledNetworkItem_NameChanged;
275      CompiledNetworkItem.DescriptionChanged -= CompiledNetworkItem_DescriptionChanged;
276    }
277    private void CompiledNetworkItem_ToStringChanged(object sender, EventArgs e) {
278      OnToStringChanged();
279    }
280    private void CompiledNetworkItem_ItemImageChanged(object sender, EventArgs e) {
281      OnItemImageChanged();
282    }
283    private void CompiledNetworkItem_NameChanging(object sender, CancelEventArgs<string> e) {
284      OnNameChanging(e);
285    }
286    private void CompiledNetworkItem_NameChanged(object sender, EventArgs e) {
287      OnNameChanged();
288    }
289    private void CompiledNetworkItem_DescriptionChanged(object sender, EventArgs e) {
290      OnDescriptionChanged();
291    }
292    #endregion
293
294    #region CompiledProgrammableNetworkItem
295    [Item("CompiledProgrammableNetworkItem", "Abstract base class for compiled programmable items of a network.")]
296    public abstract class CompiledProgrammableNetworkItem : Item, INetworkItem {
297      public static new Image StaticItemImage {
298        get { return HeuristicLab.Common.Resources.VSImageLibrary.Class; }
299      }
300
301      #region NamedItem Members
302      public string Name {
303        get { return Context.name; }
304        set {
305          if (!CanChangeName) throw new NotSupportedException("Name cannot be changed.");
306          if (!(Context.name.Equals(value) || (value == null) && (Context.name == string.Empty))) {
307            CancelEventArgs<string> e = value == null ? new CancelEventArgs<string>(string.Empty) : new CancelEventArgs<string>(value);
308            OnNameChanging(e);
309            if (!e.Cancel) {
310              Context.name = value == null ? string.Empty : value;
311              OnNameChanged();
312            }
313          }
314        }
315      }
316      public virtual bool CanChangeName {
317        get { return true; }
318      }
319      public string Description {
320        get { return Context.description; }
321        set {
322          if (!CanChangeDescription) throw new NotSupportedException("Description cannot be changed.");
323          if (!(Context.description.Equals(value) || (value == null) && (Context.description == string.Empty))) {
324            Context.description = value == null ? string.Empty : value;
325            OnDescriptionChanged();
326          }
327        }
328      }
329      public virtual bool CanChangeDescription {
330        get { return true; }
331      }
332
333      public event EventHandler<CancelEventArgs<string>> NameChanging;
334      protected virtual void OnNameChanging(CancelEventArgs<string> e) {
335        var handler = NameChanging;
336        if (handler != null) handler(this, e);
337      }
338      public event EventHandler NameChanged;
339      protected virtual void OnNameChanged() {
340        var handler = NameChanged;
341        if (handler != null) handler(this, EventArgs.Empty);
342        OnToStringChanged();
343      }
344      public event EventHandler DescriptionChanged;
345      protected virtual void OnDescriptionChanged() {
346        var handler = DescriptionChanged;
347        if (handler != null) handler(this, EventArgs.Empty);
348      }
349      #endregion
350
351      #region NetworkItem Members
352      private INetworkItem parent;
353      public INetworkItem Parent {
354        get { return parent; }
355        protected set {
356          if (value != parent) {
357            parent = value;
358          }
359        }
360      }
361      public virtual IEnumerable<INetworkItem> Children {
362        get { return Enumerable.Empty<INetworkItem>(); }
363      }
364
365      // TODO: no visual properties needed here
366      public IVisualProperties VisualProperties {
367        get { return Context.VisualProperties; }
368        set { Context.VisualProperties = value; }
369      }
370      #endregion
371
372      protected ProgrammableNetworkItem Context { get; private set; }
373      private Variables variables;
374      protected Variables Variables {
375        get {
376          if (variables == null) variables = new Variables(Context.variableStore);
377          return variables;
378        }
379      }
380      protected dynamic Vars {
381        get { return Variables; }
382      }
383
384      protected CompiledProgrammableNetworkItem(CompiledProgrammableNetworkItem original, Cloner cloner)
385        : base(original, cloner) {
386        Context = cloner.Clone(original.Context);
387        Context.name = original.Context.name;
388        Context.description = original.Context.description;
389      }
390      protected CompiledProgrammableNetworkItem(ProgrammableNetworkItem context)
391        : base() {
392        Context = context;
393      }
394
395      public virtual void Initialize() {
396        Variables.Clear();
397      }
398
399      public override string ToString() {
400        return Name;
401      }
402
403      #region Events
404      public virtual void RegisterEvents() { }
405      public virtual void DeregisterEvents() { }
406      #endregion
407    }
408    #endregion
409  }
410}
Note: See TracBrowser for help on using the repository browser.