source: branches/OptimizationNetworks/HeuristicLab.Optimization.Networks/3.3/Ports/GenericPort.cs @ 11520

Last change on this file since 11520 was 11520, checked in by swagner, 8 years ago

#2205: Worked on optimization networks

File size: 10.0 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 HeuristicLab.Common;
23using HeuristicLab.Core;
24using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
25using System;
26using System.Drawing;
27using System.Linq;
28using System.Threading;
29using System.Threading.Tasks;
30
31namespace HeuristicLab.Optimization.Networks {
32  [Item("GenericPort", "A generic port of an optimization network node.")]
33  [StorableClass]
34  public class GenericPort : ParameterizedPort, IGenericPort, IConnectedPort {
35    public override Image ItemImage {
36      get {
37        if (PortConnectionValid) return base.ItemImage;
38        else return HeuristicLab.Common.Resources.VSImageLibrary.Error;
39      }
40    }
41
42    [Storable]
43    protected IConnectedPort connectedPort;
44    public IConnectedPort ConnectedPort {
45      get { return connectedPort; }
46      set {
47        if (connectedPort != value) {
48          DeregisterConnectedPortEvents();
49          connectedPort = value;
50          RegisterConnectedPortEvents();
51          OnConnectedPortChanged();
52          OnInterfaceChanged();
53        }
54      }
55    }
56    [Storable]
57    protected bool portConnectionValid;
58    public bool PortConnectionValid {
59      get { return portConnectionValid; }
60      protected set {
61        if (value != portConnectionValid) {
62          portConnectionValid = value;
63          OnPortConnectionValidChanged();
64          OnItemImageChanged();
65        }
66      }
67    }
68    [Storable]
69    protected bool logMessages;
70    public bool LogMessages {
71      get { return logMessages; }
72      set {
73        if (value != logMessages) {
74          logMessages = value;
75          OnLogMessagesChanged();
76        }
77      }
78    }
79    [Storable]
80    protected MessageCollection messages;
81    public MessageCollection Messages {
82      get { return messages; }
83    }
84
85    [StorableConstructor]
86    protected GenericPort(bool deserializing) : base(deserializing) { }
87    protected GenericPort(GenericPort original, Cloner cloner)
88      : base(original, cloner) {
89      connectedPort = cloner.Clone(original.connectedPort);
90      portConnectionValid = original.portConnectionValid;
91      logMessages = original.logMessages;
92      messages = cloner.Clone(original.messages);
93      RegisterConnectedPortEvents();
94    }
95    public GenericPort()
96      : base("GenericPort") {
97      portConnectionValid = true;
98      logMessages = false;
99      messages = new MessageCollection();
100    }
101    public GenericPort(string name)
102      : base(name) {
103      portConnectionValid = true;
104      logMessages = false;
105      messages = new MessageCollection();
106    }
107    public GenericPort(string name, string description)
108      : base(name, description) {
109      portConnectionValid = true;
110      logMessages = false;
111      messages = new MessageCollection();
112    }
113
114    [StorableHook(HookType.AfterDeserialization)]
115    private void AfterDeserialization() {
116      RegisterConnectedPortEvents();
117    }
118
119    public override IDeepCloneable Clone(Cloner cloner) {
120      return new GenericPort(this, cloner);
121    }
122
123    public bool CanConnectToPort(IPort port) {
124      if (port == null) return true;
125
126      var cp = port as IConnectedPort;
127      if (cp == null) return false;
128
129      // check connected port input parameters
130      foreach (var input in cp.Parameters.Where(p => p.Type.HasFlag(PortParameterType.Input))) {
131        IPortParameter param;
132        Parameters.TryGetValue(input.Name, out param);
133        if ((param == null) && (input.DefaultValue == null)) return false;
134        if (!param.Type.HasFlag(PortParameterType.Output)) return false;
135        if (!input.DataType.IsAssignableFrom(param.DataType)) return false;
136      }
137      // check local port input parameters
138      foreach (var input in Parameters.Where(p => p.Type.HasFlag(PortParameterType.Input))) {
139        IPortParameter param;
140        cp.Parameters.TryGetValue(input.Name, out param);
141        if ((param == null) && (input.DefaultValue == null)) return false;
142        if (!param.Type.HasFlag(PortParameterType.Output)) return false;
143        if (!input.DataType.IsAssignableFrom(param.DataType)) return false;
144      }
145      return true;
146    }
147    public void CloneConnectedPortParameters() {
148      Parameters.Clear();
149      foreach (var p in connectedPort.Parameters) {
150        var param = (IPortParameter)p.Clone();
151        if (!(param.Type.HasFlag(PortParameterType.Input) && param.Type.HasFlag(PortParameterType.Output))) {
152          param.Type = ~param.Type;  // bitwise negation: input -> output, output -> input
153        }
154        Parameters.Add(param);
155      }
156    }
157
158    public IMessage PrepareMessage() {
159      if (!PortConnectionValid) throw new InvalidOperationException("Port connection is not valid");
160      var message = new Message();
161
162      // collect output parameters from local port
163      message.Values.AddRange(
164        Parameters.
165        Where(p => p.Type.HasFlag(PortParameterType.Output)).
166        Select(p => p.CreateMessageValue())
167      );
168
169      // collect remaining input parameters from connected port
170      if (ConnectedPort != null) {
171        message.Values.AddRange(
172          ConnectedPort.Parameters.
173          Where(p => p.Type.HasFlag(PortParameterType.Input) && !message.Values.ContainsKey(p.Name)).
174          Select(p => p.CreateMessageValue())
175        );
176      }
177
178      // collect output parameters from connected port
179      if (ConnectedPort != null) {
180        message.Values.AddRange(
181          ConnectedPort.Parameters.
182          Where(p => p.Type.HasFlag(PortParameterType.Output) && !message.Values.ContainsKey(p.Name)).
183          Select(p => p.CreateMessageValue())
184        );
185      }
186
187      // collect remaining input parameters from local port
188      message.Values.AddRange(
189        Parameters.
190        Where(p => p.Type.HasFlag(PortParameterType.Input) && !message.Values.ContainsKey(p.Name)).
191        Select(p => p.CreateMessageValue())
192      );
193
194      return message;
195    }
196    public void SendMessage(IMessage message) {
197      SendMessage(message, CancellationToken.None);
198    }
199    public void SendMessage(IMessage message, CancellationToken token) {
200      if (!PortConnectionValid) throw new InvalidOperationException("Port connection is not valid");
201      if (LogMessages) Messages.Add(message);
202      if (ConnectedPort != null) ConnectedPort.ReceiveMessage(message, token);
203      OnMessageSent(message, token);
204    }
205    public async Task SendMessageAsync(IMessage message) {
206      await SendMessageAsync(message, CancellationToken.None);
207    }
208    public async Task SendMessageAsync(IMessage message, CancellationToken token) {
209      await Task.Run(() => { SendMessage(message, token); }, token);
210    }
211    public event EventHandler<EventArgs<IMessage, CancellationToken>> MessageSent;
212    protected virtual void OnMessageSent(IMessage message, CancellationToken token) {
213      var handler = MessageSent;
214      if (handler != null) handler(this, new EventArgs<IMessage, CancellationToken>(message, token));
215    }
216
217    public void ReceiveMessage(IMessage message, CancellationToken token) {
218      if (!PortConnectionValid) throw new InvalidOperationException("Port connection is not valid");
219      if (LogMessages) Messages.Add(message);
220      OnMessageReceived(message, token);
221    }
222    public event EventHandler<EventArgs<IMessage, CancellationToken>> MessageReceived;
223    protected virtual void OnMessageReceived(IMessage message, CancellationToken token) {
224      var handler = MessageReceived;
225      if (handler != null) handler(this, new EventArgs<IMessage, CancellationToken>(message, token));
226    }
227
228    public event EventHandler ConnectedPortChanged;
229    protected virtual void OnConnectedPortChanged() {
230      var handler = ConnectedPortChanged;
231      if (handler != null) handler(this, EventArgs.Empty);
232    }
233    public event EventHandler PortConnectionValidChanged;
234    protected virtual void OnPortConnectionValidChanged() {
235      var handler = PortConnectionValidChanged;
236      if (handler != null) handler(this, EventArgs.Empty);
237    }
238    public event EventHandler LogMessagesChanged;
239    protected virtual void OnLogMessagesChanged() {
240      var handler = LogMessagesChanged;
241      if (handler != null) handler(this, EventArgs.Empty);
242    }
243
244    protected override void OnInterfaceChanged() {
245      PortConnectionValid = CanConnectToPort(connectedPort);
246      base.OnInterfaceChanged();
247    }
248
249    #region ConnectedPort Events
250    protected virtual void RegisterConnectedPortEvents() {
251      if (connectedPort != null) {
252        connectedPort.InterfaceChanged += ConnectedPort_InterfaceChanged;
253        connectedPort.MessageSent += ConnectedPort_MessageSent;
254      }
255    }
256    protected virtual void DeregisterConnectedPortEvents() {
257      if (connectedPort != null) {
258        connectedPort.InterfaceChanged -= ConnectedPort_InterfaceChanged;
259        connectedPort.MessageSent -= ConnectedPort_MessageSent;
260      }
261    }
262    protected virtual void ConnectedPort_InterfaceChanged(object sender, EventArgs e) {
263      OnInterfaceChanged();
264    }
265    protected virtual void ConnectedPort_MessageSent(object sender, EventArgs<IMessage, CancellationToken> e) {
266      ReceiveMessage(e.Value, e.Value2);
267    }
268    #endregion
269  }
270}
Note: See TracBrowser for help on using the repository browser.