Free cookie consent management tool by TermsFeed Policy Generator

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

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

#2205: Worked on optimization networks

File size: 8.5 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          OnItemImageChanged();
64        }
65      }
66    }
67
68    [StorableConstructor]
69    protected GenericPort(bool deserializing) : base(deserializing) { }
70    protected GenericPort(GenericPort original, Cloner cloner) : base(original, cloner) {
71      connectedPort = cloner.Clone(original.connectedPort);
72      portConnectionValid = original.portConnectionValid;
73      RegisterConnectedPortEvents();
74    }
75    public GenericPort() : base("GenericPort") { }
76    public GenericPort(string name) : base(name) { }
77    public GenericPort(string name, string description) : base(name, description) { }
78
79    [StorableHook(HookType.AfterDeserialization)]
80    private void AfterDeserialization() {
81      RegisterConnectedPortEvents();
82    }
83
84    public override IDeepCloneable Clone(Cloner cloner) {
85      return new GenericPort(this, cloner);
86    }
87
88    public bool CanConnectToPort(IPort port) {
89      if (port == null) return true;
90
91      var cp = port as IConnectedPort;
92      if (cp == null) return false;
93
94      // check connected port input parameters
95      foreach (var input in cp.Parameters.Where(p => p.Type.HasFlag(PortParameterType.Input))) {
96        IPortParameter param;
97        Parameters.TryGetValue(input.Name, out param);
98        if ((param == null) && (input.DefaultValue == null)) return false;
99        if (!param.Type.HasFlag(PortParameterType.Output)) return false;
100        if (!input.DataType.IsAssignableFrom(param.DataType)) return false;
101      }
102      // check local port input parameters
103      foreach (var input in Parameters.Where(p => p.Type.HasFlag(PortParameterType.Input))) {
104        IPortParameter param;
105        cp.Parameters.TryGetValue(input.Name, out param);
106        if ((param == null) && (input.DefaultValue == null)) return false;
107        if (!param.Type.HasFlag(PortParameterType.Output)) return false;
108        if (!input.DataType.IsAssignableFrom(param.DataType)) return false;
109      }
110      return true;
111    }
112    public void CloneConnectedPortParameters() {
113      Parameters.Clear();
114      foreach (var p in connectedPort.Parameters) {
115        var param = (IPortParameter)p.Clone();
116        if (!(param.Type.HasFlag(PortParameterType.Input) && param.Type.HasFlag(PortParameterType.Output))) {
117          param.Type = ~param.Type;  // bitwise negation: input -> output, output -> input
118        }
119        Parameters.Add(param);
120      }
121    }
122
123    public IMessage PrepareMessage() {
124      if (!PortConnectionValid) throw new InvalidOperationException("Port connection is not valid");
125      var message = new Message();
126
127      // collect output parameters from local port
128      message.Values.AddRange(
129        Parameters.
130        Where(p => p.Type.HasFlag(PortParameterType.Output)).
131        Select(p => p.CreateMessageValue())
132      );
133
134      // collect remaining input parameters from connected port
135      if (ConnectedPort != null) {
136        message.Values.AddRange(
137          ConnectedPort.Parameters.
138          Where(p => p.Type.HasFlag(PortParameterType.Input) && !message.Values.ContainsKey(p.Name)).
139          Select(p => p.CreateMessageValue())
140        );
141      }
142
143      // collect output parameters from connected port
144      if (ConnectedPort != null) {
145        message.Values.AddRange(
146          ConnectedPort.Parameters.
147          Where(p => p.Type.HasFlag(PortParameterType.Output)).
148          Select(p => p.CreateMessageValue())
149        );
150      }
151
152      // collect remaining input parameters from local port
153      message.Values.AddRange(
154        Parameters.
155        Where(p => p.Type.HasFlag(PortParameterType.Input) && !message.Values.ContainsKey(p.Name)).
156        Select(p => p.CreateMessageValue())
157      );
158
159      return message;
160    }
161    public void SendMessage(IMessage message) {
162      SendMessage(message, CancellationToken.None);
163    }
164    public void SendMessage(IMessage message, CancellationToken token) {
165      if (!PortConnectionValid) throw new InvalidOperationException("Port connection is not valid");
166      if (ConnectedPort != null) ConnectedPort.ReceiveMessage(message, token);
167      OnMessageSent(message, token);
168    }
169    public async Task SendMessageAsync(IMessage message) {
170      await SendMessageAsync(message, CancellationToken.None);
171    }
172    public async Task SendMessageAsync(IMessage message, CancellationToken token) {
173      await Task.Run(() => { SendMessage(message, token); }, token);
174    }
175    public event EventHandler<EventArgs<IMessage, CancellationToken>> MessageSent;
176    protected virtual void OnMessageSent(IMessage message, CancellationToken token) {
177      var handler = MessageSent;
178      if (handler != null) handler(this, new EventArgs<IMessage, CancellationToken>(message, token));
179    }
180
181    public void ReceiveMessage(IMessage message, CancellationToken token) {
182      OnMessageReceived(message, token);
183    }
184    public event EventHandler<EventArgs<IMessage, CancellationToken>> MessageReceived;
185    protected virtual void OnMessageReceived(IMessage message, CancellationToken token) {
186      var handler = MessageReceived;
187      if (handler != null) handler(this, new EventArgs<IMessage, CancellationToken>(message, token));
188    }
189
190    public event EventHandler ConnectedPortChanged;
191    protected virtual void OnConnectedPortChanged() {
192      var handler = ConnectedPortChanged;
193      if (handler != null) handler(this, EventArgs.Empty);
194    }
195
196    protected override void OnInterfaceChanged() {
197      PortConnectionValid = (connectedPort != null) && CanConnectToPort(connectedPort);
198      base.OnInterfaceChanged();
199    }
200
201    #region ConnectedPort Events
202    protected virtual void RegisterConnectedPortEvents() {
203      if (connectedPort != null) {
204        connectedPort.InterfaceChanged += ConnectedPort_InterfaceChanged;
205        connectedPort.MessageSent += ConnectedPort_MessageSent;
206      }
207    }
208    protected virtual void DeregisterConnectedPortEvents() {
209      if (connectedPort != null) {
210        connectedPort.InterfaceChanged -= ConnectedPort_InterfaceChanged;
211        connectedPort.MessageSent -= ConnectedPort_MessageSent;
212      }
213    }
214    protected virtual void ConnectedPort_InterfaceChanged(object sender, EventArgs e) {
215      OnInterfaceChanged();
216    }
217    protected virtual void ConnectedPort_MessageSent(object sender, EventArgs<IMessage, CancellationToken> e) {
218      ReceiveMessage(e.Value, e.Value2);
219    }
220    #endregion
221  }
222}
Note: See TracBrowser for help on using the repository browser.