Index: branches/OptimizationNetworks/HeuristicLab.Optimization.Networks/3.3/### obsolete/ClientNode.cs
===================================================================
--- branches/OptimizationNetworks/HeuristicLab.Optimization.Networks/3.3/### obsolete/ClientNode.cs	(revision 11526)
+++ branches/OptimizationNetworks/HeuristicLab.Optimization.Networks/3.3/### obsolete/ClientNode.cs	(revision 11526)
@@ -0,0 +1,99 @@
+#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 <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace HeuristicLab.Optimization.Networks {
+  [Item("ClientNode", "A node of an optimization network which calls service nodes.")]
+  [StorableClass]
+  public class ClientNode : Node, IClientNode {
+    private object locker = new object();
+
+    new public PortCollection Ports {
+      get { return base.Ports; }
+    }
+
+    [Storable]
+    private IItemCollection<ServiceParameterCollection> calls;
+    public IItemCollection<ServiceParameterCollection> Calls {
+      get { return calls; }
+    }
+
+    [StorableConstructor]
+    protected ClientNode(bool deserializing) : base(deserializing) { }
+    protected ClientNode(ClientNode original, Cloner cloner)
+      : base(original, cloner) {
+      calls = cloner.Clone(original.calls);
+    }
+    public ClientNode()
+      : base("ClientNode") {
+      calls = new ItemCollection<ServiceParameterCollection>();
+    }
+    public ClientNode(string name)
+      : base(name) {
+      calls = new ItemCollection<ServiceParameterCollection>();
+    }
+    public ClientNode(string name, string description)
+      : base(name, description) {
+      calls = new ItemCollection<ServiceParameterCollection>();
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new ClientNode(this, cloner);
+    }
+
+    public virtual async Task CallServicesAsync() {
+      await CallServicesAsync(CancellationToken.None);
+    }
+    public virtual async Task CallServicesAsync(CancellationToken token) {
+      foreach (var clientPort in Ports.OfType<IClientPort>()) {
+        var parameters = clientPort.PrepareParameters();
+
+        // retrieve inputs
+        foreach (var inputPort in Ports.OfType<IInputPort>().
+                                        Where(x => parameters.ContainsKey(x.Name) &&
+                                                    parameters[x.Name].Type == ServiceParameterType.Input &&
+                                                    parameters[x.Name].DataType.IsAssignableFrom(x.DataType))) {
+          parameters[inputPort.Name].Value = (IItem)inputPort.Value.Clone();
+        }
+
+        parameters = await clientPort.CallServiceAsync(parameters, token);
+
+        lock (locker) {
+          // set outputs
+          foreach (var outputPort in Ports.OfType<IOutputPort>().
+                                            Where(x => parameters.ContainsKey(x.Name) &&
+                                                      parameters[x.Name].Type == ServiceParameterType.Output &&
+                                                      x.DataType.IsAssignableFrom(parameters[x.Name].DataType))) {
+            outputPort.Value = (IItem)parameters[outputPort.Name].Value.Clone();
+          }
+
+          Calls.Add(parameters);
+        }
+      }
+    }
+  }
+}
Index: branches/OptimizationNetworks/HeuristicLab.Optimization.Networks/3.3/### obsolete/IClientNode.cs
===================================================================
--- branches/OptimizationNetworks/HeuristicLab.Optimization.Networks/3.3/### obsolete/IClientNode.cs	(revision 11526)
+++ branches/OptimizationNetworks/HeuristicLab.Optimization.Networks/3.3/### obsolete/IClientNode.cs	(revision 11526)
@@ -0,0 +1,35 @@
+#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 <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using HeuristicLab.Core;
+using System;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace HeuristicLab.Optimization.Networks {
+  public interface IClientNode : INode {
+    new PortCollection Ports { get; }
+    IItemCollection<ServiceParameterCollection> Calls { get; }
+
+    Task CallServicesAsync();
+    Task CallServicesAsync(CancellationToken token);
+  }
+}
Index: branches/OptimizationNetworks/HeuristicLab.Optimization.Networks/3.3/### obsolete/IVariablesNode.cs
===================================================================
--- branches/OptimizationNetworks/HeuristicLab.Optimization.Networks/3.3/### obsolete/IVariablesNode.cs	(revision 11526)
+++ branches/OptimizationNetworks/HeuristicLab.Optimization.Networks/3.3/### obsolete/IVariablesNode.cs	(revision 11526)
@@ -0,0 +1,31 @@
+#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 <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using HeuristicLab.Core;
+using System;
+
+namespace HeuristicLab.Optimization.Networks {
+  public interface IVariablesNode : INode {
+    new PortCollection Ports { get; }
+
+    VariableCollection Variables { get; }
+  }
+}
Index: branches/OptimizationNetworks/HeuristicLab.Optimization.Networks/3.3/### obsolete/MultiplierNode.cs
===================================================================
--- branches/OptimizationNetworks/HeuristicLab.Optimization.Networks/3.3/### obsolete/MultiplierNode.cs	(revision 11526)
+++ branches/OptimizationNetworks/HeuristicLab.Optimization.Networks/3.3/### obsolete/MultiplierNode.cs	(revision 11526)
@@ -0,0 +1,79 @@
+#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 <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using System;
+
+namespace HeuristicLab.Optimization.Networks {
+  [Item("MultiplierNode", "A node for multiplying integer values.")]
+  [StorableClass]
+  public class MultiplierNode : Node {
+    protected static readonly string MultiplierPortName = "Multiplier";
+    protected static readonly string ValuePortName = "Value";
+
+    public IInputPort<IntValue> MultiplierPort {
+      get { return (IInputPort<IntValue>)Ports[MultiplierPortName]; }
+    }
+    public IInputOutputPort<IntValue, IntValue> ValuePort {
+      get { return (IInputOutputPort<IntValue, IntValue>)Ports[ValuePortName]; }
+    }
+
+    [StorableConstructor]
+    protected MultiplierNode(bool deserializing) : base(deserializing) { }
+    protected MultiplierNode(MultiplierNode original, Cloner cloner) : base(original, cloner) { }
+    public MultiplierNode()
+      : base("MultiplierNode") {
+      Initialize();
+    }
+    public MultiplierNode(string name)
+      : base(name) {
+      Initialize();
+    }
+    public MultiplierNode(string name, string description)
+      : base(name, description) {
+      Initialize();
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new MultiplierNode(this, cloner);
+    }
+
+    protected virtual void Initialize() {
+      Ports.Add(new InputPort<IntValue>(MultiplierPortName));
+      Ports.Add(new InputOutputPort<IntValue, IntValue>(ValuePortName));
+      RegisterPortEvents();
+    }
+
+    protected virtual void RegisterPortEvents() {
+      ValuePort.ValueReceived += ValuePort_ValueReceived;
+    }
+
+    protected virtual void ValuePort_ValueReceived(object sender, OutputInputPortEventArgs<IntValue, IntValue> e) {
+      if (MultiplierPort.Value == null) throw new InvalidOperationException("Multiplier is null");
+      if (e.Value != null) {
+        e.Result = new IntValue(e.Value.Value * MultiplierPort.Value.Value);
+      }
+    }
+  }
+}
Index: branches/OptimizationNetworks/HeuristicLab.Optimization.Networks/3.3/### obsolete/VariablesNode.cs
===================================================================
--- branches/OptimizationNetworks/HeuristicLab.Optimization.Networks/3.3/### obsolete/VariablesNode.cs	(revision 11526)
+++ branches/OptimizationNetworks/HeuristicLab.Optimization.Networks/3.3/### obsolete/VariablesNode.cs	(revision 11526)
@@ -0,0 +1,248 @@
+#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 <http://www.gnu.org/licenses/>.
+ */
+#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<IPort> e) {
+      base.Ports_ItemsAdded(sender, e);
+      foreach (var p in e.Items)
+        RegisterPortEvents(p);
+    }
+    protected override void Ports_ItemsRemoved(object sender, Collections.CollectionItemsChangedEventArgs<IPort> e) {
+      base.Ports_ItemsRemoved(sender, e);
+      foreach (var p in e.Items)
+        DeregisterPortEvents(p);
+    }
+    protected override void Ports_ItemsReplaced(object sender, Collections.CollectionItemsChangedEventArgs<IPort> 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<IPort> 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<IVariable> e) {
+      foreach (var v in e.Items)
+        RegisterVariableEvents(v);
+    }
+    private void Variables_ItemsRemoved(object sender, Collections.CollectionItemsChangedEventArgs<IVariable> e) {
+      foreach (var v in e.Items)
+        DeregisterVariableEvents(v);
+    }
+    private void Variables_ItemsReplaced(object sender, Collections.CollectionItemsChangedEventArgs<IVariable> 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<IVariable> 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
+  }
+}
