#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 } }