#region License Information
/* HeuristicLab
* Copyright (C) 2002-2014 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
*
* This file is part of HeuristicLab.
*
* HeuristicLab is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* HeuristicLab is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with HeuristicLab. If not, see .
*/
#endregion
using HeuristicLab.Common;
using HeuristicLab.Core;
using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
using System;
namespace HeuristicLab.Optimization.Networks {
[Item("VariablesNode", "A node of an optimization network which contains variables.")]
[StorableClass]
public class VariablesNode : Node, IVariablesNode {
new public PortCollection Ports {
get { return base.Ports; }
}
[Storable]
private VariableCollection variables;
public VariableCollection Variables {
get { return variables; }
}
[StorableConstructor]
protected VariablesNode(bool deserializing) : base(deserializing) { }
protected VariablesNode(VariablesNode original, Cloner cloner)
: base(original, cloner) {
variables = cloner.Clone(original.variables);
RegisterVariablesEvents();
}
public VariablesNode()
: base("VariablesNode") {
variables = new VariableCollection();
RegisterVariablesEvents();
}
public VariablesNode(string name)
: base(name) {
variables = new VariableCollection();
RegisterVariablesEvents();
}
public VariablesNode(string name, string description)
: base(name, description) {
variables = new VariableCollection();
RegisterVariablesEvents();
}
[StorableHook(HookType.AfterDeserialization)]
private void AfterDeserialization() {
RegisterVariablesEvents();
}
public override IDeepCloneable Clone(Cloner cloner) {
return new VariablesNode(this, cloner);
}
private void UpdateVariable(IInputPort port) {
if (!variables.ContainsKey(port.Name))
variables.Add(new Variable(port.Name));
variables[port.Name].Value = (IItem)port.Value;
}
private void UpdateOutputPort(IVariable variable) {
IPort port = null;
if (Ports.TryGetValue(variable.Name, out port)) {
IOutputPort o = port as IOutputPort;
if (o != null) {
o.Value = variable.Value;
}
IOutputInputPort oi = port as IOutputInputPort;
if (oi != null) {
var result = (IItem)oi.SendValue(variable.Value);
if (!variables.ContainsKey(oi.Name + "Result"))
variables.Add(new Variable(oi.Name + "Result"));
variables[oi.Name + "Result"].Value = result;
}
}
}
private void UpdateOutputPort(IOutputPort port) {
IVariable var = null;
if (variables.TryGetValue(port.Name, out var)) {
port.Value = var.Value;
} else {
port.Value = null;
}
}
private void UpdateOutputInputPort(IOutputInputPort port) {
IVariable var = null;
IItem result = null;
if (variables.TryGetValue(port.Name, out var)) {
result = (IItem)port.SendValue(var.Value);
} else {
result = (IItem)port.SendValue(null);
}
if (!variables.ContainsKey(port.Name + "Result"))
variables.Add(new Variable(port.Name + "Result"));
variables[port.Name + "Result"].Value = result;
}
#region Ports Events
protected override void RegisterPortsEvents() {
base.RegisterPortsEvents();
foreach (var p in Ports)
RegisterPortEvents(p);
}
protected override void Ports_ItemsAdded(object sender, Collections.CollectionItemsChangedEventArgs e) {
base.Ports_ItemsAdded(sender, e);
foreach (var p in e.Items)
RegisterPortEvents(p);
}
protected override void Ports_ItemsRemoved(object sender, Collections.CollectionItemsChangedEventArgs e) {
base.Ports_ItemsRemoved(sender, e);
foreach (var p in e.Items)
DeregisterPortEvents(p);
}
protected override void Ports_ItemsReplaced(object sender, Collections.CollectionItemsChangedEventArgs e) {
base.Ports_ItemsReplaced(sender, e);
foreach (var p in e.OldItems)
DeregisterPortEvents(p);
foreach (var p in e.Items)
RegisterPortEvents(p);
}
protected override void Ports_CollectionReset(object sender, Collections.CollectionItemsChangedEventArgs e) {
base.Ports_CollectionReset(sender, e);
foreach (var p in e.OldItems)
DeregisterPortEvents(p);
foreach (var p in e.Items)
RegisterPortEvents(p);
}
#endregion
#region Port Events
private void RegisterPortEvents(IPort port) {
IInputPort i = port as IInputPort;
if (i != null) {
i.NameChanged += InputPort_NameChanged;
i.ValueChanged += InputPort_ValueChanged;
UpdateVariable(i);
}
IOutputPort o = port as IOutputPort;
if (o != null) {
o.NameChanged += OutputPort_NameChanged;
UpdateOutputPort(o);
}
IOutputInputPort oi = port as IOutputInputPort;
if (oi != null) {
oi.NameChanged += OutputInputPort_NameChanged;
UpdateOutputInputPort(oi);
}
}
private void DeregisterPortEvents(IPort port) {
IInputPort i = port as IInputPort;
if (i != null) {
i.NameChanged -= InputPort_NameChanged;
i.ValueChanged -= InputPort_ValueChanged;
}
IOutputPort o = port as IOutputPort;
if (o != null) {
o.NameChanged -= OutputPort_NameChanged;
}
IOutputInputPort oi = port as IOutputInputPort;
if (oi != null) {
oi.NameChanged -= OutputInputPort_NameChanged;
}
}
private void InputPort_NameChanged(object sender, EventArgs e) {
UpdateVariable((IInputPort)sender);
}
private void InputPort_ValueChanged(object sender, EventArgs e) {
UpdateVariable((IInputPort)sender);
}
private void OutputPort_NameChanged(object sender, EventArgs e) {
UpdateOutputPort((IOutputPort)sender);
}
private void OutputInputPort_NameChanged(object sender, EventArgs e) {
UpdateOutputInputPort((IOutputInputPort)sender);
}
#endregion
#region Variables Events
private void RegisterVariablesEvents() {
variables.ItemsAdded += Variables_ItemsAdded;
variables.ItemsRemoved += Variables_ItemsRemoved;
variables.ItemsReplaced += Variables_ItemsReplaced;
variables.CollectionReset += Variables_CollectionReset;
foreach (var v in variables)
RegisterVariableEvents(v);
}
private void Variables_ItemsAdded(object sender, Collections.CollectionItemsChangedEventArgs e) {
foreach (var v in e.Items)
RegisterVariableEvents(v);
}
private void Variables_ItemsRemoved(object sender, Collections.CollectionItemsChangedEventArgs e) {
foreach (var v in e.Items)
DeregisterVariableEvents(v);
}
private void Variables_ItemsReplaced(object sender, Collections.CollectionItemsChangedEventArgs e) {
foreach (var v in e.OldItems)
DeregisterVariableEvents(v);
foreach (var v in e.Items)
RegisterVariableEvents(v);
}
private void Variables_CollectionReset(object sender, Collections.CollectionItemsChangedEventArgs e) {
foreach (var v in e.OldItems)
DeregisterVariableEvents(v);
foreach (var v in e.Items)
RegisterVariableEvents(v);
}
#endregion
#region Variable Events
private void RegisterVariableEvents(IVariable variable) {
if (variable != null) {
variable.ValueChanged += Variable_ValueChanged;
variable.ToStringChanged += Variable_ToStringChanged;
UpdateOutputPort(variable);
}
}
private void DeregisterVariableEvents(IVariable variable) {
if (variable != null) {
variable.ValueChanged -= Variable_ValueChanged;
variable.ToStringChanged += Variable_ToStringChanged;
}
}
private void Variable_ValueChanged(object sender, EventArgs e) {
UpdateOutputPort((IVariable)sender);
}
private void Variable_ToStringChanged(object sender, EventArgs e) {
UpdateOutputPort((IVariable)sender);
}
#endregion
}
}