Index: branches/HeuristicLab.DatastreamAnalysis/HeuristicLab.DatastreamAnalysis/3.4/AnalysisBase.cs
===================================================================
--- branches/HeuristicLab.DatastreamAnalysis/HeuristicLab.DatastreamAnalysis/3.4/AnalysisBase.cs	(revision 14536)
+++ branches/HeuristicLab.DatastreamAnalysis/HeuristicLab.DatastreamAnalysis/3.4/AnalysisBase.cs	(revision 14536)
@@ -0,0 +1,19 @@
+﻿using System;
+using System.Collections.Generic;
+using System.Drawing;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.DataAnalysis;
+
+namespace HeuristicLab.DatastreamAnalysis {
+  [StorableClass]
+  [Item("Analysis Base", "Represents trained models, grouped in ensembles and additional parameters for subsequent analysis purposes")]
+  [Creatable(CreatableAttribute.Categories.DataAnalysisEnsembles, Priority = 100)]
+  public class AnalysisBase {
+
+  }
+}
Index: branches/HeuristicLab.DatastreamAnalysis/HeuristicLab.DatastreamAnalysis/3.4/Datastream.cs
===================================================================
--- branches/HeuristicLab.DatastreamAnalysis/HeuristicLab.DatastreamAnalysis/3.4/Datastream.cs	(revision 14536)
+++ branches/HeuristicLab.DatastreamAnalysis/HeuristicLab.DatastreamAnalysis/3.4/Datastream.cs	(revision 14536)
@@ -0,0 +1,191 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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 System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using HeuristicLab.Collections;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.DataAnalysis;
+
+namespace HeuristicLab.DatastreamAnalysis {
+  [StorableClass]
+  [Item("Datastream", "Represents an item containing a data source and reading options for a certain data stream.")]
+  [Creatable(CreatableAttribute.Categories.Problems)]
+  public class Datastream : ParameterizedNamedItem, IDatastream {
+
+    protected const string ProblemDataParameterName = "ProblemData";
+    protected const string InitialSlidingWindowParameterName = "InitialSlidingWindowParameter";
+    protected const string SlidingWindowSizeParameterName = "SlidingWindowSize";
+    protected const string SlidingWindowStepWidthParameterName = "SlidingWindowStepWidth";
+    protected const string SlidingWindowMovementIntervalParameterName = "SlidingWindowMovementInterval";
+
+    #region parameter properites
+
+    public IValueParameter<RegressionProblemData> ProblemDataParameter {
+      get { return (IValueParameter<RegressionProblemData>) Parameters[ProblemDataParameterName]; }  
+    }
+
+    public IFixedValueParameter<IntRange> InitialSlidingWindowParameter {
+      get { return (IFixedValueParameter<IntRange>) Parameters[InitialSlidingWindowParameterName]; }
+    }
+
+    public IFixedValueParameter<IntValue> SlidingWindowSizeParameter {
+      get { return (IFixedValueParameter<IntValue>)Parameters[InitialSlidingWindowParameterName]; }
+    }
+
+    public IFixedValueParameter<IntValue> SlidingWindowStepWidthParameter {
+      get { return (IFixedValueParameter<IntValue>)Parameters[SlidingWindowStepWidthParameterName]; }
+    }
+
+    public IFixedValueParameter<IntValue> SlidingWindowMovementIntervalParameter {
+      get { return (IFixedValueParameter<IntValue>)Parameters[SlidingWindowMovementIntervalParameterName]; }
+    }
+
+
+    #endregion
+
+    #region properties
+
+    public RegressionProblemData ProblemData {
+      get { return ProblemDataParameter.Value; }
+      set {
+        if(value == null) throw new ArgumentNullException("problemData", "The provided value for the problemData is null.");
+        if (value == ProblemData) return;
+        ProblemDataParameter.Value = value;
+      }
+    }
+
+    public IntRange InitialSlidingWindow {
+      get { return InitialSlidingWindowParameter.Value; }
+    }
+
+    public IntValue SlidingWindowSize {
+      get { return SlidingWindowSizeParameter.Value; }
+    }
+
+    public IntValue SlidingWindowStepWidth {
+      get { return SlidingWindowStepWidthParameter.Value; }
+    }
+
+    public IntValue SlidingWindowMovementInterval {
+      get { return SlidingWindowMovementIntervalParameter.Value; }
+    }
+
+    #endregion
+
+    #region internal properties
+
+    public IntRange FitnessPartition { get; set; }
+
+    public bool SlidingWindowMovementPossible {
+      get {
+        return ProblemData != null && ProblemData.Dataset != null &&
+               FitnessPartition.End + SlidingWindowStepWidth.Value <= ProblemData.Dataset.Rows;
+        // TODO: add external datastream, hub, etc to condition
+      }
+    }
+
+    public bool SlidingWindowEvaluationPossible {
+      get {
+        return ProblemData != null && ProblemData.Dataset != null &&
+               FitnessPartition.Size > 0;
+      }
+    }
+
+    public bool MoveSlidingWindow() {
+      if (ProblemData?.Dataset == null || ProblemData.Dataset.Rows == 0) return false;
+      if (FitnessPartition.End + SlidingWindowStepWidth.Value > ProblemData.Dataset.Rows) return false;
+      
+      if (FitnessPartition.Size > SlidingWindowSize.Value) {
+        FitnessPartition.Start += SlidingWindowStepWidth.Value;
+      } else if (FitnessPartition.Size == SlidingWindowSize.Value) {
+        FitnessPartition.Start += SlidingWindowStepWidth.Value;
+        FitnessPartition.End += SlidingWindowStepWidth.Value;
+      } else {
+        FitnessPartition.End += SlidingWindowStepWidth.Value;
+      }   
+      return true;
+    }
+
+    #endregion
+
+    #region constructors
+    [StorableConstructor]
+    protected Datastream(bool deserializing) : base(deserializing) { }
+
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() {
+      RegisterParameterEvents();
+    }
+
+    protected Datastream(Datastream original, Cloner cloner) : base(original, cloner) {
+      RegisterParameterEvents();
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new Datastream(this, cloner);
+    }
+
+    public Datastream() {
+      Parameters.Add(new ValueParameter<RegressionProblemData>(ProblemDataParameterName, "ProblemData for analysis with selected ensembles.", null));
+      Parameters.Add(new FixedValueParameter<IntRange>(InitialSlidingWindowParameterName, "Initial sliding window boundaries", new IntRange(0, 1)));
+      Parameters.Add(new FixedValueParameter<IntValue>(SlidingWindowSizeParameterName, "Sliding window size", new IntValue(1)));
+      Parameters.Add(new FixedValueParameter<IntValue>(SlidingWindowStepWidthParameterName, "Sliding window step width", new IntValue(1)));
+      Parameters.Add(new FixedValueParameter<IntValue>(SlidingWindowMovementIntervalParameterName, "Sliding window movement interval (milliseconds)", new IntValue(1000)));
+      InitializeState();
+    }
+    #endregion
+
+
+    public void InitializeState() {
+      if (ProblemData == null || ProblemData.Dataset == null || ProblemData.Dataset.Rows == 0) {
+        FitnessPartition = new IntRange(0, 0);
+      } else {
+        FitnessPartition = (IntRange)InitialSlidingWindow.Clone();
+        if (FitnessPartition.End > ProblemData.Dataset.Rows) {
+          FitnessPartition.End = ProblemData.Dataset.Rows;
+        }
+      }
+    }
+
+    public event EventHandler ProblemDataChanged;
+
+
+    private void RegisterParameterEvents() {
+      ProblemDataParameter.ValueChanged += new EventHandler(ProblemData_ValueChanged);
+    }
+
+    private void ProblemData_ValueChanged(object sender, EventArgs e) {
+      if (e == null) return;
+
+      DatastreamAnalysisUtil.RaiseEvent(this, ProblemDataChanged);
+    }
+
+    
+
+  }
+}
Index: branches/HeuristicLab.DatastreamAnalysis/HeuristicLab.DatastreamAnalysis/3.4/DatastreamAnalysisOptimizer.cs
===================================================================
--- branches/HeuristicLab.DatastreamAnalysis/HeuristicLab.DatastreamAnalysis/3.4/DatastreamAnalysisOptimizer.cs	(revision 14491)
+++ branches/HeuristicLab.DatastreamAnalysis/HeuristicLab.DatastreamAnalysis/3.4/DatastreamAnalysisOptimizer.cs	(revision 14536)
@@ -1,3 +1,4 @@
 ﻿#region License Information
+
 /* HeuristicLab
  * Copyright (C) 2002-2016 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
@@ -18,12 +19,19 @@
  * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
  */
+
 #endregion
 
 using System;
 using System.Collections.Generic;
+using System.Diagnostics;
 using System.Drawing;
 using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+using HeuristicLab.Analysis;
+using HeuristicLab.Collections;
 using HeuristicLab.Common;
 using HeuristicLab.Core;
+using HeuristicLab.Data;
 using HeuristicLab.Optimization;
 using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
@@ -31,37 +39,121 @@
 
 namespace HeuristicLab.DatastreamAnalysis {
-  internal enum DatastreamAnalysisOptimizerAction { None, Prepare, Start, Stop, Pause }
+  internal enum DatastreamAnalysisOptimizerAction {
+    None,
+    Prepare,
+    Start,
+    Stop,
+    Pause
+  }
 
   [StorableClass]
-  [Item("DatastreamAnalysis Optimizer", "The main loop for evaluating ensemble models against a incoming datastream of time series fashion.")]
-  [Creatable("Algorithms")]
-  public class DatastreamAnalysisOptimizer : NamedItem, IOptimizer, IStorableContent {
-
-    // TODO: introduce members -> ensembles, datastream
-
-
-    // VAR 1: datastream = problem data
-    [Storable]
-    private IRegressionProblemData problemData;
-
-    public IRegressionProblemData ProblemData {
-      get { return problemData; }
+  [Item("DatastreamAnalysis Optimizer",
+     "The main loop for evaluating ensemble models against a incoming datastream of time series fashion.")]
+  [Creatable(CreatableAttribute.Categories.Algorithms)]
+  public class DatastreamAnalysisOptimizer : Executable, IOptimizer, IStorableContent {
+    #region properties
+    public string Filename { get; set; }
+
+    private DatastreamAnalysisOptimizerAction daoAction;
+
+    public IEnumerable<IOptimizer> NestedOptimizers { get; }
+
+
+    [Storable]
+    protected ILog log;
+    public ILog Log {
+      get { return log; }
+    }
+
+    [Storable]
+    private ResultCollection results;
+
+    public ResultCollection Results {
+      get { return results; }
+    }
+
+    private CancellationTokenSource cancellationTokenSource;
+    private bool stopPending;
+    private DateTime lastUpdateTime;
+
+    [Storable]
+    protected int runsCounter;
+
+    [Storable]
+    private RunCollection runs;
+
+    public RunCollection Runs
+    {
+      get { return runs; }
+      protected set
+      {
+        if (value == null) throw new ArgumentNullException();
+        if (runs != value) {
+          if (runs != null) DeregisterRunsEvents();
+          runs = value;
+          if (runs != null) RegisterRunsEvents();
+        }
+      }
+    }
+
+
+    [Storable]
+    private IItemList<RegressionEnsembleModel> ensembles;
+
+    public IItemList<RegressionEnsembleModel> Ensembles {
+      get { return ensembles; }
       set {
-        if (value == null || value == problemData)
+        if (value == null || value == ensembles)
           return;
 
-        problemData = value;
-      }
-    }
-
-    // VAR 2: datastream = external source (webservice, AMQP-Queue, etc.)
-    // TODO
+        ensembles = value;
+      }
+    }
+
+
+    // VAR 1: datastream ~= problem data, VAR 2 (TODO): datastream = external source e.g. webservice, AMQP-Queue, etc.
+    [Storable]
+    private Datastream datastream;
+
+    public Datastream Datastream {
+      get { return datastream; }
+      set {
+        if (value == null || value == datastream)
+          return;
+
+        datastream = value;
+      }
+    }
+
+    #endregion properties
+
+    #region ResultsProperties
+    private double ResultsBestQuality
+    {
+      get { return ((DoubleValue)Results["Best Quality"].Value).Value; }
+      set { ((DoubleValue)Results["Best Quality"].Value).Value = value; }
+    }
+    private DataTable ResultsQualities
+    {
+      get { return ((DataTable)Results["Qualities"].Value); }
+    }
+    #endregion
+
+    #region constructors, cloner,...
 
     public DatastreamAnalysisOptimizer() {
-      Name = "Datastream Analysis";
+      name = "Datastream Analysis";
+      log = new Log();
+      results = new ResultCollection();
+      ensembles = new ItemList<RegressionEnsembleModel>();
+      datastream = new Datastream();
+      runsCounter = 0;
+      runs = new RunCollection();
+      Initialize();
     }
 
     [StorableConstructor]
-    protected DatastreamAnalysisOptimizer(bool deserializing) : base(deserializing) { }
+    protected DatastreamAnalysisOptimizer(bool deserializing) : base(deserializing) {
+    }
 
     [StorableHook(HookType.AfterDeserialization)]
@@ -71,147 +163,321 @@
 
     protected DatastreamAnalysisOptimizer(DatastreamAnalysisOptimizer original, Cloner cloner) : base(original, cloner) {
-      // TODO: clone members (ensembles, datastream)
-      this.ProblemData = (IRegressionProblemData)original.ProblemData.Clone(cloner);
+      name = original.name;
+      log = cloner.Clone(original.log);
+      results = cloner.Clone(original.results);
+      ensembles = (ItemList<RegressionEnsembleModel>) original.Ensembles.Clone(cloner);
+      datastream = (Datastream) original.Datastream.Clone(cloner);
+      runsCounter = original.runsCounter;
+      runs = cloner.Clone(original.runs);
+      Initialize();
     }
 
     public override IDeepCloneable Clone(Cloner cloner) {
-      return  new DatastreamAnalysisOptimizer(this, cloner);
-    }
-
-
-    // TODO: introduce EventHandler for EnsemblesChanged, DatastreamChanged
-
-    public EventHandler ProblemDataChanged;
-    private void OnProblemDataChanged() {
-      var changed = ProblemDataChanged;
+      return new DatastreamAnalysisOptimizer(this, cloner);
+    }
+
+    private void Initialize() {
+      if (runs != null) RegisterRunsEvents();
+    }
+    #endregion
+
+    #region control actions
+
+    public override void Prepare() {
+      if (ensembles == null || datastream == null) return;
+      Prepare(true);
+    }
+
+    public void Prepare(bool clearRuns) {
+      if (ensembles == null || datastream == null) return;
+      base.Prepare();
+      if (clearRuns) results.Clear();
+      OnPrepared();
+    }
+
+    public override void Start() {
+      if (ensembles == null || datastream == null) return;
+      base.Start();
+      cancellationTokenSource = new CancellationTokenSource();
+      stopPending = false;
+
+      Task task = Task.Factory.StartNew(Run, cancellationTokenSource.Token, cancellationTokenSource.Token);
+      task.ContinueWith(t => {
+        try {
+          t.Wait();
+        }
+        catch (AggregateException ex) {
+          try {
+            ex.Flatten().Handle(x => x is OperationCanceledException);
+          } catch (AggregateException remaining) {
+            if(remaining.InnerExceptions.Count == 1) OnExceptionOccurred(remaining.InnerExceptions[0]);
+            else OnExceptionOccurred(remaining);
+          }
+        }
+        cancellationTokenSource.Dispose();
+        cancellationTokenSource = null;
+
+        // handle stop/pause
+        if(stopPending) { }
+        if(!Datastream.SlidingWindowMovementPossible) OnStopped();
+        else OnPaused();
+      });
+
+    }
+
+    public override void Pause() {
+      if (ensembles == null || datastream == null) return;
+      base.Pause();
+      cancellationTokenSource.Cancel();
+    }
+
+    public override void Stop() {
+      if (ensembles == null || datastream == null) return;
+      base.Stop();
+      if (ExecutionState == ExecutionState.Paused) {
+        OnStopped();
+      } else {
+        stopPending = true;
+        cancellationTokenSource.Cancel();
+      }
+    }
+
+    protected override void OnPrepared() {
+      Log.LogMessage("Datastream analysis prepared");
+      base.OnPrepared();
+    }
+
+    protected override void OnStarted() {
+      Log.LogMessage("Datastream analysis started");
+      base.OnStarted();
+    }
+
+    protected override void OnPaused() {
+      Log.LogMessage("Datastream analysis paused");
+      base.OnPaused();
+    }
+
+    protected override void OnStopped() {
+      Log.LogMessage("Datastream analysis stopped");
+      base.OnStopped();
+    }
+
+    #endregion
+
+
+    private void Run(object state) {
+      CancellationToken cancellationToken = (CancellationToken) state;
+      OnStarted();
+      lastUpdateTime = DateTime.UtcNow;
+      System.Timers.Timer timer = new System.Timers.Timer(250);
+      timer.AutoReset = true;
+      timer.Elapsed += new System.Timers.ElapsedEventHandler(timer_Elapsed);
+      timer.Start();
+
+      try {
+        Run(cancellationToken);
+      }
+      finally {
+        timer.Elapsed -= new System.Timers.ElapsedEventHandler(timer_Elapsed);
+        timer.Stop();
+        ExecutionTime += DateTime.UtcNow - lastUpdateTime;
+      }
+
+      cancellationToken.ThrowIfCancellationRequested();
+    }
+
+    protected void Run(CancellationToken cancellationToken) {
+
+      // setup results
+      var slidingWindowMovements = new IntValue(0);
+      Results.Add(new Result("Sliding Window Movements", slidingWindowMovements));
+
+      var qtable = new DataTable("Qualities");
+      qtable.Rows.Add(new DataRow("R²"));
+      qtable.Rows.Add(new DataRow("Pearson"));
+      Results.Add(new Result("Qualities", qtable));
+
+      var curLoss = new DoubleValue();
+      Results.Add(new Result("R²", curLoss));
+      Results.Add(new Result("Best Quality", curLoss));
+
+
+      // init algorithm
+      var problemData = Datastream.ProblemData;
+      var targetVarName = problemData.TargetVariable;
+      var activeVariables = problemData.AllowedInputVariables;
+      Random rnd = new Random();
+
+      try {
+        while (Datastream.SlidingWindowMovementPossible) {
+          cancellationToken.ThrowIfCancellationRequested();
+
+          Task.Delay(Datastream.SlidingWindowMovementInterval.Value);
+
+          Datastream.MoveSlidingWindow();
+
+          // TODO do the window evaluation
+
+          // TODO: collect results and display them
+
+          curLoss.Value = rnd.Next(100);
+          qtable.Rows["R²"].Values.Add(curLoss.Value);
+          qtable.Rows["Pearson"].Values.Add(curLoss.Value % 10);
+
+          slidingWindowMovements.Value++;
+        }
+
+        // TODO: collect runs (c.f. goal seeking)
+      }
+      catch (Exception ex) {
+        if (ex is ArgumentOutOfRangeException) throw ex;
+        if (ex is OperationCanceledException) throw ex;
+      }
+      finally {
+        // reset everything
+        //Prepare(true);
+      }
+    }
+
+    private void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e) {
+      System.Timers.Timer timer = (System.Timers.Timer)sender;
+      timer.Enabled = false;
+      DateTime now = DateTime.UtcNow;
+      ExecutionTime += now - lastUpdateTime;
+      lastUpdateTime = now;
+      timer.Enabled = true;
+    }
+
+    public void CollectResultValues(IDictionary<string, IItem> values) {
+      values.Add("Execution Time", new TimeSpanValue(ExecutionTime));
+      Results.CollectResultValues(values);
+    }
+
+    #region events
+
+    public EventHandler EnsemblesChanged;
+    public EventHandler DatastreamChanged;
+
+    protected virtual void DeregisterRunsEvents() {
+      runs.CollectionReset -= new CollectionItemsChangedEventHandler<IRun>(Runs_CollectionReset);
+    }
+
+    protected virtual void RegisterRunsEvents() {
+      runs.CollectionReset += new CollectionItemsChangedEventHandler<IRun>(Runs_CollectionReset);
+    }
+
+    protected virtual void Runs_CollectionReset(object sender, CollectionItemsChangedEventArgs<IRun> e) {
+      runsCounter = runs.Count;
+    }
+
+    #region event handling
+
+    private void OnEnsemblesChanged() {
+      var changed = EnsemblesChanged;
       if (changed != null)
         changed(this, EventArgs.Empty);
     }
 
-
-    public void Prepare() {
-      Prepare(false);
-    }
-
-    public void Start() {
-      if ((ExecutionState != ExecutionState.Prepared) && (ExecutionState != ExecutionState.Paused))
-        throw new InvalidOperationException(string.Format("Start not allowed in execution state \"{0}\".", ExecutionState));
-    }
-
-    public void Pause() {
-      if (ExecutionState != ExecutionState.Started)
-        throw new InvalidOperationException(string.Format("Pause not allowed in execution state \"{0}\".", ExecutionState));
-    }
-
-    public void Stop() {
-      if ((ExecutionState != ExecutionState.Started) && (ExecutionState != ExecutionState.Paused))
-        throw new InvalidOperationException(string.Format("Stop not allowed in execution state \"{0}\".", ExecutionState));
-    }
-
-    public void Prepare(bool clearRuns) {
-      if ((ExecutionState != ExecutionState.Prepared) && (ExecutionState != ExecutionState.Paused) && (ExecutionState != ExecutionState.Stopped))
-        throw new InvalidOperationException(string.Format("Prepare not allowed in execution state \"{0}\".", ExecutionState));
-    }
-
-
-    [Storable]
-    private TimeSpan executionTime;
-    public TimeSpan ExecutionTime {
-      get { return executionTime; }
-      private set {
-        executionTime = value;
-        OnExecutionTimeChanged();
-      }
-    }
-
-    public RunCollection Runs {
-      get {
-        return new RunCollection();
-      }
-    }
-
-    public IEnumerable<IOptimizer> NestedOptimizers { get; }
-    public string Filename { get; set; }
-
-    public new static Image StaticItemImage
-    {
-      get { return HeuristicLab.Common.Resources.VSImageLibrary.Event; }
-    }
-
-    public override Image ItemImage {
-      get {
-        if (ExecutionState == ExecutionState.Prepared)
-          return HeuristicLab.Common.Resources.VSImageLibrary.BatchRunPrepared;
-        else if (ExecutionState == ExecutionState.Started)
-          return HeuristicLab.Common.Resources.VSImageLibrary.BatchRunStarted;
-        else if (ExecutionState == ExecutionState.Paused) return HeuristicLab.Common.Resources.VSImageLibrary.BatchRunPaused;
-        else if (ExecutionState == ExecutionState.Stopped)
-          return HeuristicLab.Common.Resources.VSImageLibrary.BatchRunStopped;
-        else return base.ItemImage;
-      }
-    }
-
-    #region Events
-
-    public ExecutionState ExecutionState { get; private set; }
-    public event EventHandler ExecutionStateChanged;
-    public event EventHandler ExecutionTimeChanged;
-    public event EventHandler Prepared;
-    public event EventHandler Started;
-    public event EventHandler Paused;
-    public event EventHandler Stopped;
-    public event EventHandler<EventArgs<Exception>> ExceptionOccurred;
-
-
-    #region event firing
-
-    protected override void OnNameChanged() {
-      base.OnNameChanged();
-    }
-
-    private void OnExecutionStateChanged() {
-      EventHandler handler = ExecutionStateChanged;
+    private void OnDatastreamChanged() {
+      var changed = DatastreamChanged;
+      if (changed != null)
+        changed(this, EventArgs.Empty);
+    }
+
+    #endregion
+
+    #endregion
+
+    #region nameditem
+
+    [Storable] protected string name;
+
+    /// <inheritdoc/>
+    /// <remarks>Calls <see cref="OnNameChanging"/> and also <see cref="OnNameChanged"/> 
+    /// eventually in the setter.</remarks>
+    public string Name {
+      get { return name; }
+      set {
+        if (!CanChangeName) throw new NotSupportedException("Name cannot be changed.");
+        if (!(name.Equals(value) || (value == null) && (name == string.Empty))) {
+          CancelEventArgs<string> e = value == null
+            ? new CancelEventArgs<string>(string.Empty)
+            : new CancelEventArgs<string>(value);
+          OnNameChanging(e);
+          if (!e.Cancel) {
+            name = value == null ? string.Empty : value;
+            OnNameChanged();
+          }
+        }
+      }
+    }
+
+    public virtual bool CanChangeName {
+      get { return true; }
+    }
+
+    [Storable] protected string description;
+
+    public string Description {
+      get { return description; }
+      set {
+        if (!CanChangeDescription) throw new NotSupportedException("Description cannot be changed.");
+        if (!(description.Equals(value) || (value == null) && (description == string.Empty))) {
+          description = value == null ? string.Empty : value;
+          OnDescriptionChanged();
+        }
+      }
+    }
+
+    public virtual bool CanChangeDescription {
+      get { return true; }
+    }
+
+    /// <summary>
+    /// Gets the string representation of the current instance in the format: <c>Name: [null|Value]</c>.
+    /// </summary>
+    /// <returns>The current instance as a string.</returns>
+    public override string ToString() {
+      return Name;
+    }
+
+    /// <inheritdoc/>
+    public event EventHandler<CancelEventArgs<string>> NameChanging;
+
+    /// <summary>
+    /// Fires a new <c>NameChanging</c> event.
+    /// </summary>
+    /// <param name="e">The event arguments of the changing.</param>
+    protected virtual void OnNameChanging(CancelEventArgs<string> e) {
+      var handler = NameChanging;
+      if (handler != null) handler(this, e);
+    }
+
+    /// <inheritdoc/>
+    public event EventHandler NameChanged;
+
+    /// <summary>
+    /// Fires a new <c>NameChanged</c> event.
+    /// </summary>
+    /// <remarks>Calls <see cref="ItemBase.OnChanged"/>.</remarks>
+    protected virtual void OnNameChanged() {
+      var handler = NameChanged;
       if (handler != null) handler(this, EventArgs.Empty);
-    }
-
-    private void OnExecutionTimeChanged() {
-      EventHandler handler = ExecutionTimeChanged;
+      OnToStringChanged();
+    }
+
+    /// <inheritdoc/>
+    public event EventHandler DescriptionChanged;
+
+    /// <summary>
+    /// Fires a new <c>DescriptionChanged</c> event.
+    /// </summary>
+    /// <remarks>Calls <see cref="ItemBase.OnChanged"/>.</remarks>
+    protected virtual void OnDescriptionChanged() {
+      var handler = DescriptionChanged;
       if (handler != null) handler(this, EventArgs.Empty);
     }
 
-    private void OnPrepared() {
-      ExecutionState = ExecutionState.Prepared;
-      EventHandler handler = Prepared;
-      if (handler != null) handler(this, EventArgs.Empty);
-    }
-
-    private void OnStarted() {
-      ExecutionState = ExecutionState.Started;
-      EventHandler handler = Started;
-      if (handler != null) handler(this, EventArgs.Empty);
-    }
-
-    private void OnPaused() {
-      ExecutionState = ExecutionState.Paused;
-      EventHandler handler = Paused;
-      if (handler != null) handler(this, EventArgs.Empty);
-    }
-
-    private void OnStopped() {
-      ExecutionState = ExecutionState.Stopped;
-      EventHandler handler = Stopped;
-      if (handler != null) handler(this, EventArgs.Empty);
-    }
-
-    private void OnExceptionOccurred(Exception exception) {
-      EventHandler<EventArgs<Exception>> handler = ExceptionOccurred;
-      if (handler != null) handler(this, new EventArgs<Exception>(exception));
-    }
-
-    #endregion
-
-
-    #endregion
-
+    #endregion nameditem
   }
 }
Index: branches/HeuristicLab.DatastreamAnalysis/HeuristicLab.DatastreamAnalysis/3.4/DatastreamAnalysisUtil.cs
===================================================================
--- branches/HeuristicLab.DatastreamAnalysis/HeuristicLab.DatastreamAnalysis/3.4/DatastreamAnalysisUtil.cs	(revision 14536)
+++ branches/HeuristicLab.DatastreamAnalysis/HeuristicLab.DatastreamAnalysis/3.4/DatastreamAnalysisUtil.cs	(revision 14536)
@@ -0,0 +1,35 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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 System;
+using HeuristicLab.Collections;
+using HeuristicLab.Core;
+
+namespace HeuristicLab.DatastreamAnalysis {
+  internal static class DatastreamAnalysisUtil {
+
+    internal static void RaiseEvent(object sender, EventHandler handler) {
+      if (handler == null) return;
+      handler(sender, EventArgs.Empty);
+    }
+
+  }
+}
Index: branches/HeuristicLab.DatastreamAnalysis/HeuristicLab.DatastreamAnalysis/3.4/HeuristicLab.DatastreamAnalysis.csproj
===================================================================
--- branches/HeuristicLab.DatastreamAnalysis/HeuristicLab.DatastreamAnalysis/3.4/HeuristicLab.DatastreamAnalysis.csproj	(revision 14491)
+++ branches/HeuristicLab.DatastreamAnalysis/HeuristicLab.DatastreamAnalysis/3.4/HeuristicLab.DatastreamAnalysis.csproj	(revision 14536)
@@ -102,5 +102,10 @@
   </ItemGroup>
   <ItemGroup>
+    <Compile Include="AnalysisBase.cs" />
+    <Compile Include="Datastream.cs" />
     <Compile Include="DatastreamAnalysisOptimizer.cs" />
+    <Compile Include="DatastreamAnalysisUtil.cs" />
+    <Compile Include="IAnalysisBase.cs" />
+    <Compile Include="IDatastream.cs" />
     <Compile Include="Plugin.cs" />
     <Compile Include="Properties\AssemblyInfo.cs" />
Index: branches/HeuristicLab.DatastreamAnalysis/HeuristicLab.DatastreamAnalysis/3.4/HeuristicLab.DatastreamAnalysis.csproj.user
===================================================================
--- branches/HeuristicLab.DatastreamAnalysis/HeuristicLab.DatastreamAnalysis/3.4/HeuristicLab.DatastreamAnalysis.csproj.user	(revision 14491)
+++ branches/HeuristicLab.DatastreamAnalysis/HeuristicLab.DatastreamAnalysis/3.4/HeuristicLab.DatastreamAnalysis.csproj.user	(revision 14536)
@@ -4,8 +4,10 @@
     <StartAction>Program</StartAction>
     <StartProgram>C:\dev\workspaces\hl-core\trunk\sources\bin\HeuristicLab 3.3.exe</StartProgram>
+    <StartArguments>/hidestarter /start:Optimizer</StartArguments>
   </PropertyGroup>
   <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|AnyCPU'">
     <StartAction>Program</StartAction>
     <StartProgram>C:\dev\workspaces\hl-core\trunk\sources\bin\HeuristicLab 3.3.exe</StartProgram>
+    <StartArguments>/hidestarter /start:Optimizer</StartArguments>
   </PropertyGroup>
 </Project>
Index: branches/HeuristicLab.DatastreamAnalysis/HeuristicLab.DatastreamAnalysis/3.4/IAnalysisBase.cs
===================================================================
--- branches/HeuristicLab.DatastreamAnalysis/HeuristicLab.DatastreamAnalysis/3.4/IAnalysisBase.cs	(revision 14536)
+++ branches/HeuristicLab.DatastreamAnalysis/HeuristicLab.DatastreamAnalysis/3.4/IAnalysisBase.cs	(revision 14536)
@@ -0,0 +1,20 @@
+﻿using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Problems.DataAnalysis;
+
+namespace HeuristicLab.DatastreamAnalysis {
+  public interface IAnalysisBase : IParameterizedNamedItem, INamedItem, IItem, IContent, IDeepCloneable, ICloneable, IParameterizedItem {
+
+    // Ensembles
+    void AddEnsemble(IRegressionEnsembleModel ensemble);
+    void RemoveEnsemble(IRegressionEnsembleModel ensemble);
+
+    // Events
+    event EventHandler ModelsChanged;
+  }
+}
Index: branches/HeuristicLab.DatastreamAnalysis/HeuristicLab.DatastreamAnalysis/3.4/IDatastream.cs
===================================================================
--- branches/HeuristicLab.DatastreamAnalysis/HeuristicLab.DatastreamAnalysis/3.4/IDatastream.cs	(revision 14536)
+++ branches/HeuristicLab.DatastreamAnalysis/HeuristicLab.DatastreamAnalysis/3.4/IDatastream.cs	(revision 14536)
@@ -0,0 +1,29 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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 System;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+
+namespace HeuristicLab.DatastreamAnalysis {
+  public interface IDatastream : IParameterizedNamedItem, INamedItem, IItem, IContent, IDeepCloneable, ICloneable, IParameterizedItem {
+  }
+}
Index: branches/HeuristicLab.DatastreamAnalysis/HeuristicLab.DatastreamAnalysis/3.4/Plugin.cs
===================================================================
--- branches/HeuristicLab.DatastreamAnalysis/HeuristicLab.DatastreamAnalysis/3.4/Plugin.cs	(revision 14491)
+++ branches/HeuristicLab.DatastreamAnalysis/HeuristicLab.DatastreamAnalysis/3.4/Plugin.cs	(revision 14536)
@@ -23,5 +23,5 @@
 
 namespace HeuristicLab.DatastreamAnalysis {
-  [Plugin("HeuristicLab.DatastreamAnalysis", "3.4.14.14488")]
+  [Plugin("HeuristicLab.DatastreamAnalysis", "3.4.14.14491")]
   [PluginFile("HeuristicLab.DatastreamAnalysis-3.4.dll", PluginFileType.Assembly)]
   [PluginDependency("HeuristicLab.Collections", "3.3")]
Index: branches/HeuristicLab.DatastreamAnalysis/HeuristicLab.DatastreamAnalysis/3.4/Properties/AssemblyInfo.cs
===================================================================
--- branches/HeuristicLab.DatastreamAnalysis/HeuristicLab.DatastreamAnalysis/3.4/Properties/AssemblyInfo.cs	(revision 14491)
+++ branches/HeuristicLab.DatastreamAnalysis/HeuristicLab.DatastreamAnalysis/3.4/Properties/AssemblyInfo.cs	(revision 14536)
@@ -54,3 +54,3 @@
 // [assembly: AssemblyVersion("1.0.*")]
 [assembly: AssemblyVersion("3.4.0.0")]
-[assembly: AssemblyFileVersion("3.4.14.14488")]
+[assembly: AssemblyFileVersion("3.4.14.14491")]
