Index: branches/OaaS/HeuristicLab.Services.Optimization.Controller/Azure/DAL.cs
===================================================================
--- branches/OaaS/HeuristicLab.Services.Optimization.Controller/Azure/DAL.cs	(revision 9166)
+++ branches/OaaS/HeuristicLab.Services.Optimization.Controller/Azure/DAL.cs	(revision 9215)
@@ -8,4 +8,5 @@
 using Microsoft.WindowsAzure.ServiceRuntime;
 using System.Diagnostics;
+using HeuristicLab.Services.Optimization.ControllerService.Model;
 
 namespace HeuristicLab.Services.Optimization.ControllerService.Azure {
@@ -13,4 +14,5 @@
     public static readonly string SCENARIO_TABLE = "Scenario";
     public static readonly string SCENARIO_BLOB_CONTAINER = "scenario";
+    public static readonly string EXPERIMENT_TABLE = "Experiment";
     public static readonly string CLOUD_SETTINGS_KEY = "Cloudia.WindowsAzure.Storage";
   }
@@ -91,7 +93,96 @@
   }
 
+  internal sealed class ExperimentEntity : TableServiceEntity {
+    public ExperimentEntity() {
+    }
+
+    public ExperimentEntity(string user, Experiment experiment) {
+      PartitionKey = "ScenarioPartition";
+      RowKey = user + "_" + experiment.Name;
+      var scenarios = "";
+      foreach (var scen in experiment.Scenarios) {
+        scenarios += scen.Id + ",";
+      }
+      Scenarios = scenarios.Remove(scenarios.Length - 1);
+      User = user;
+    }
+
+    public string User { get; set; }
+
+    public string Scenarios { get; set; }
+
+  }
+
+  public class ExperimentDao : IExperimentDao {
+    public CloudBlobClient BlobClient { get; set; }
+    public CloudTableClient TableClient { get; set; }
+
+    public bool Add(string username, Model.Experiment experiment) {
+      if (FindByName(username, experiment.Name) != null)
+        return false;
+
+      TableServiceContext serviceContext = TableClient.GetDataServiceContext();
+      TableClient.CreateTableIfNotExist(AzureConstants.EXPERIMENT_TABLE);
+      var entity = new ExperimentEntity(username, experiment);
+      serviceContext.AddObject(AzureConstants.EXPERIMENT_TABLE, entity);
+      serviceContext.SaveChangesWithRetries();
+      return true;
+    }
+
+    public bool DeleteByName(string username, string experiment) {
+      TableServiceContext serviceContext = TableClient.GetDataServiceContext();
+      TableClient.CreateTableIfNotExist(AzureConstants.EXPERIMENT_TABLE);
+      var entity = (from e in serviceContext.CreateQuery<ExperimentEntity>(AzureConstants.EXPERIMENT_TABLE)
+                    where e.RowKey == (username + "_" + experiment)
+                    select e).FirstOrDefault();
+      
+      if (entity == null)
+        return false;
+
+      serviceContext.DeleteObject(entity);
+      serviceContext.SaveChangesWithRetries();
+      return true;
+    }
+
+    public Model.Experiment FindByName(string username, string experiment) {
+      TableServiceContext serviceContext = TableClient.GetDataServiceContext();
+      TableClient.CreateTableIfNotExist(AzureConstants.EXPERIMENT_TABLE);
+      var entity = (from e in serviceContext.CreateQuery<ExperimentEntity>(AzureConstants.EXPERIMENT_TABLE)
+                    where e.RowKey == (username + "_" + experiment)
+                    select e).FirstOrDefault();
+      
+      if (entity == null) {
+        return null;
+      }
+
+      var exp = Convert(entity);
+      return exp;
+    }
+
+    private Experiment Convert(ExperimentEntity entity) {
+      var exp = new Experiment() { Name = entity.RowKey.Split('_')[1] };
+      foreach (var scenarioName in entity.Scenarios.Split(','))
+        exp.Scenarios.Add(new OptimizationScenario() { Id = scenarioName });
+      return exp;
+    }
+
+    public IEnumerable<Model.Experiment> GetExperiments(string user) {
+      TableServiceContext serviceContext = TableClient.GetDataServiceContext();
+      TableClient.CreateTableIfNotExist(AzureConstants.EXPERIMENT_TABLE);
+      var entites = (from e in serviceContext.CreateQuery<ExperimentEntity>(AzureConstants.EXPERIMENT_TABLE)
+                    where e.User == user
+                    select e).ToList();
+      var experiments = new List<Experiment>();
+      foreach (var entity in entites) {
+        experiments.Add(Convert(entity));
+      }
+      return experiments;
+    }
+  }
+
   public class AzureDataAccessLayer : IDataAccessLayer {
     private IScenarioDao scenarioDao;
     private IBlobDao blobDao;
+    private IExperimentDao expDao;
 
     private CloudStorageAccount storageAccount;
@@ -115,5 +206,5 @@
       get {
         if (scenarioDao == null) {
-          scenarioDao = new ScenarioDao();
+          scenarioDao = new ScenarioDao() { TableClient = StorageAccount.CreateCloudTableClient() };
         }
         return scenarioDao;
@@ -124,5 +215,5 @@
       get {
         if (blobDao == null) {
-          blobDao = new BlobDao();
+          blobDao = new BlobDao() { BlobClient = StorageAccount.CreateCloudBlobClient() };
         }
         return blobDao;
@@ -130,10 +221,11 @@
     }
 
-    public IScenarioDao CreateScenarioDao() {
-      return new ScenarioDao() { TableClient = StorageAccount.CreateCloudTableClient() };
-    }
-
-    public IBlobDao CreateBlobDao() {
-      return new BlobDao() { BlobClient = StorageAccount.CreateCloudBlobClient() };
+    public IExperimentDao ExperimentDao {
+      get {
+        if (expDao == null) {
+          expDao = new ExperimentDao() { TableClient = StorageAccount.CreateCloudTableClient() };
+        }
+        return expDao;
+      }
     }
   }
Index: branches/OaaS/HeuristicLab.Services.Optimization.Controller/HL/HiveScenarioManager.cs
===================================================================
--- branches/OaaS/HeuristicLab.Services.Optimization.Controller/HL/HiveScenarioManager.cs	(revision 9166)
+++ branches/OaaS/HeuristicLab.Services.Optimization.Controller/HL/HiveScenarioManager.cs	(revision 9215)
@@ -52,5 +52,5 @@
     }
 
-    public void DispatchScenario(Model.User user, Model.OptimizationScenario scenario, JobExecutionDetails details) {
+    public string DispatchScenario(Model.User user, Model.OptimizationScenario scenario, JobExecutionDetails details) {
       // Experiment experiment = new Experiment();
       // var problem = new TravelingSalesmanProblem();
@@ -66,8 +66,8 @@
         br.Optimizer = algo;        
         br.Repetitions = details.Repititions;
-        SendExperimentToHive(user, br, details);
+        return SendExperimentToHive(user, br, details);
       }
       else {       
-        SendExperimentToHive(user, algo, details);
+        return SendExperimentToHive(user, algo, details);
       }
     }
@@ -141,5 +141,5 @@
     }
 
-    private void SendExperimentToHive(Model.User user, IOptimizer exp, JobExecutionDetails details) {      
+    private string SendExperimentToHive(Model.User user, IOptimizer exp, JobExecutionDetails details) {      
       var job = new RefreshableJob();
       job.IsAllowedPrivileged = true;      
@@ -156,6 +156,7 @@
         Console.WriteLine(ex.StackTrace); 
       }, job, new CancellationToken());
-
+      
       job.StopResultPolling();
+      return job.Id != null ? job.Id.ToString() : null;
     }
 
@@ -168,5 +169,5 @@
       foreach (var job in jobsLoaded) {
         jobs.Add(ConvertJob(user, job));
-      }
+      }      
       return jobs;
     }
@@ -182,4 +183,5 @@
       else
         state = JobState.Waiting;
+
       return new Model.Job() { Id = job.Id.ToString(), Name = job.Name, Resource = job.ResourceNames, State = state.Value, DateCreated = job.DateCreated };
     }
@@ -193,8 +195,9 @@
 
 
-    public void DeleteJob(User user, string id) {
+    public bool DeleteJob(User user, string id) {
       ConfigureHive(user);
-      var guid = Guid.Parse(id);
-      HiveServiceLocator.Instance.CallHiveService(s => s.DeleteJob(guid));      
+      var guid = Guid.Parse(id);      
+      HiveServiceLocator.Instance.CallHiveService(s => s.DeleteJob(guid));
+      return true;
     }
 
@@ -344,6 +347,6 @@
       
       // insert into table & blob store
-      var scenDao = dal.CreateScenarioDao();
-      var blobDao = dal.CreateBlobDao();
+      var scenDao = dal.ScenarioDao;
+      var blobDao = dal.BlobDao;
       
       Guid scenarioXmlGuid = Guid.NewGuid();
@@ -369,6 +372,6 @@
 
     private string GetMapperFromBlobStore(string scenarioName) {
-      var scenarioDao = dal.CreateScenarioDao();
-      var blobDao = dal.CreateBlobDao();
+      var scenarioDao = dal.ScenarioDao;
+      var blobDao = dal.BlobDao;
       var entity = scenarioDao.FindByName(scenarioName);
       if (entity == null)
@@ -383,6 +386,6 @@
     public bool DeleteScenario(User user, string scenarioName) {
       // delete from table & blob store
-      var scenarioDao = dal.CreateScenarioDao();
-      var blobDao = dal.CreateBlobDao();
+      var scenarioDao = dal.ScenarioDao;
+      var blobDao = dal.BlobDao;
 
       var entity = scenarioDao.FindByName(scenarioName);
@@ -395,4 +398,89 @@
       return true;
     }
+
+    public bool SaveExperiment(User user, Model.Experiment experiment) {
+      return dal.ExperimentDao.Add(user.Username, experiment);
+    }
+
+    public IEnumerable<string> GetExperiments(User user) {
+      return (from exp in dal.ExperimentDao.GetExperiments(user.Username)
+              select exp.Name);
+    }
+
+
+    public bool DeleteExperiment(User user, string experiment) {
+      return dal.ExperimentDao.DeleteByName(user.Username, experiment);
+    }
+
+
+    public Model.Task GetTaskData(User u, string jobId, string taskId) {
+      ConfigureHive(u);
+      TaskDownloader downloader = new TaskDownloader(new List<Guid>(){Guid.Parse(taskId)});
+      downloader.StartAsync();
+      while (!downloader.IsFinished) {
+        Thread.Sleep(250);
+        if (downloader.IsFaulted) {
+          throw downloader.Exception;
+        }
+      }
+      
+      IDictionary<Guid, HiveTask> hiveTasks = downloader.Results;
+      var task = hiveTasks[Guid.Parse(taskId)];
+      if (task == null) 
+        return null;
+      
+      return new Model.Task() {
+        State = new Model.TaskState() {
+          DateCreated = task.Task.DateCreated.ToString(),
+          DateFinished = task.Task.DateFinished.ToString(),
+          ExecutionTime = task.Task.ExecutionTime.ToString(),
+          State = task.Task.State.ToString()
+        },
+        General = new Model.General() {
+          Id = task.Task.Id.ToString(),
+          LastChanged = task.Task.Modified.ToString(),
+          Name = task.ItemTask.Name
+        }
+      };
+    }
+
+    public Model.Job GetTasks(User u, string jobId) {
+      ConfigureHive(u);
+      var jobTasks = HiveServiceLocator.Instance.CallHiveService<IEnumerable<HeuristicLab.Clients.Hive.LightweightTask>>(s => s.GetLightweightJobTasks(Guid.Parse(jobId)));
+      
+      var job = new Model.Job();
+      job.Id = jobId;
+      var tasks = new Dictionary<Guid, Model.Task>();
+      // push all elements to dictionary
+      foreach (var task in jobTasks) {
+        // TODO: Crawl children + parent and create hierarchy!
+        var children = HiveServiceLocator.Instance.CallHiveService<IEnumerable<HeuristicLab.Clients.Hive.LightweightTask>>(s => s.GetLightweightChildTasks(Guid.Parse(jobId), true, true));
+        foreach (var child in children) {
+          tasks[child.Id] = new Model.Task() {
+            State = new Model.TaskState() {
+              DateCreated = child.DateCreated.ToString(),
+              DateFinished = child.DateFinished.ToString(),
+              ExecutionTime = child.ExecutionTime.ToString(),
+              State = child.State.ToString()
+            },
+            General = new Model.General() {
+              Id = child.Id.ToString(),
+              LastChanged = child.Modified.ToString(),
+              Name = child.ItemName
+            }
+          };
+        }
+      }
+
+      // traverse all tasks again and create tree of tasks
+      foreach (var task in jobTasks) {
+        if (task.ParentTaskId.HasValue)
+          tasks[task.Id].Children.Add(tasks[task.ParentTaskId.Value]);
+        else // its a root task
+          job.Tasks.Add(tasks[task.Id]);
+      }
+
+      return job;
+    }
   }
 }
Index: branches/OaaS/HeuristicLab.Services.Optimization.Controller/HL/ScenarioParser.cs
===================================================================
--- branches/OaaS/HeuristicLab.Services.Optimization.Controller/HL/ScenarioParser.cs	(revision 9166)
+++ 	(revision )
@@ -1,316 +1,0 @@
-﻿using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.IO;
-using System.Xml;
-using System.Globalization;
-using System.Xml.Linq;
-using HeuristicLab.Services.Optimization.ControllerService.Azure;
-using HeuristicLab.Services.Optimization.ControllerService.Interfaces;
-using System.Diagnostics;
-
-namespace HeuristicLab.Services.Optimization.ControllerService {
-  public class ScenarioParser {
-    private static IList<Model.OptimizationScenario> scenarios;
-    private static object lockable = new object();
-
-    private IDataAccessLayer dal = DataAccessLayerProvider.GetLayer();
-
-    public IList<Model.OptimizationScenario> Scenarios {
-      get {
-        if (scenarios == null) {
-          lock (lockable) {
-            if (scenarios == null) {
-              ParseScenarios();
-            }
-          }
-        }
-        return scenarios;
-      }
-    }
-    
-    public Model.OptimizationScenario GetByName(string name) {
-      foreach (var scen in Scenarios) {
-        if (scen.Id == name) {
-          return scen;
-        }
-      }
-      return null;
-    }
-
-    /*// http://www.sascha-dittmann.de/post/Webseitenpfade-einer-Windows-Azure-Web-Rolle-bestimmen.aspx
-    private static IEnumerable<string> WebSiteDirectories {
-      get {
-        var roleRootDir = Environment.GetEnvironmentVariable("RdRoleRoot");
-        if (roleRootDir == null)
-          return Enumerable.Empty<string>();
-        XNamespace roleModelNs =
-          "http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceDefinition";
-        var roleModelDoc = XDocument.Load(Path.Combine(roleRootDir, "RoleModel.xml"));
-        if (roleModelDoc.Root == null)
-          return Enumerable.Empty<string>();
-
-        var sites = roleModelDoc.Root.Element(roleModelNs + "Sites");
-        if (sites == null)
-          return Enumerable.Empty<string>();
-
-        var siteElements = sites.Elements(roleModelNs + "Site");
-
-        return
-          from siteElement in siteElements
-          where siteElement.Attribute("name") != null
-                && siteElement.Attribute("name").Value == "Web"
-                && siteElement.Attribute("physicalDirectory") != null
-          select Path.Combine(roleRootDir,
-                 siteElement.Attribute("physicalDirectory").Value);
-      }
-    }
-     */
-
-    private void ParseScenarios() {
-      var scens = new List<Model.OptimizationScenario>();
-      /*string path;
-      if (WebSiteDirectories.Count() != 0) {
-        path = WebSiteDirectories.FirstOrDefault() + @"\Mappings";
-      } else {
-        path = AppDomain.CurrentDomain.BaseDirectory + @"\Mappings";
-      }
-        
-      foreach (var file in Directory.EnumerateFiles(path, "*.xml")) {
-        var scenario = ParseScenarioFromFile(file);
-        if (scenario != null)
-          scens.Add(scenario);
-      }*/
-
-      var scenarioDao = dal.CreateScenarioDao();
-      var blobDao = dal.CreateBlobDao();
-      foreach (var entity in scenarioDao.GetAllEntities()) {
-        var scenarioXml = blobDao.FindByKey(entity.Scenario).Text;
-        var scenario = ParseScenarioFromXml(scenarioXml);
-        if (scenario != null)
-          scens.Add(scenario);
-      }
-
-      scenarios = scens;
-    }
-
-    private XmlReaderSettings GetSettings() {
-      // Set the validation settings.
-      XmlReaderSettings settings = new XmlReaderSettings();
-      settings.ValidationType = ValidationType.Schema;
-      settings.Schemas.Add("urn:scenario-schema", AppDomain.CurrentDomain.BaseDirectory + @"\Mappings\scenario.xsd");      
-      return settings;
-    }
-
-    public Model.OptimizationScenario ParseScenarioFromXml(string xml) {
-      //using (var reader = XmlReader.Create(new StringReader(xml), GetSettings())) {
-        return ParseScenario(new StringReader(xml));
-      //}            
-    }
-
-   /* private Model.OptimizationScenario ParseScenarioFromFile(string filename) {
-      using (var reader = XmlReader.Create(new FileStream(filename, FileMode.Open), GetSettings())) {
-        return ParseScenario(reader);
-      }      
-    } */
-
-    private Model.Problem ParseProblem(XmlReader reader) {
-      var problem = new Model.Problem();
-      while (reader.Read()) {
-        if (reader.NodeType == XmlNodeType.EndElement)
-          break;
-        if (reader.Name == "parameters")
-          problem.Parameters.Items = ParseParameters(reader);
-      }
-      return problem;
-    }
-
-    private void ParseAlgorithms(out IList<Model.Algorithm> algos, XmlReader reader) {
-      algos = new List<Model.Algorithm>();
-      var depth = reader.Depth;
-      do {
-        if (reader.Name == "algorithm" && reader.Depth == depth) {
-          var innerAlg = new Model.Algorithm();
-          algos.Add(innerAlg);
-          
-          innerAlg.Mapper = reader.GetAttribute("mapper");
-          reader.Read();
-          for (;;) {
-            if (reader.Name == "algorithm" && reader.NodeType == XmlNodeType.EndElement)
-              break;
-
-            if (reader.Name == "parameters" && reader.NodeType == XmlNodeType.Element) {
-              innerAlg.Parameters.Items = ParseParameters(reader);
-              continue;
-            }
-            else if (reader.Name == "problem" && reader.NodeType == XmlNodeType.Element) {
-              innerAlg.Problem = ParseProblem(reader);
-              continue;
-            }
-            else if (reader.Name == "algorithm" && reader.NodeType == XmlNodeType.Element) {
-              IList<Model.Algorithm> childAlgos;
-              ParseAlgorithms(out childAlgos, reader);
-              innerAlg.ChildAlgorithms = childAlgos;
-              //TODO: Test with child algorithms
-              continue;
-            }
-            reader.Read();
-          }
-        }
-      } while (reader.Read() && reader.Depth >= depth);
-    }
-
-    private Model.OptimizationScenario ParseScenarioElement(XmlReader reader) {
-      var scenario = new Model.OptimizationScenario();
-      var depth = reader.Depth;
-      while (reader.Depth >= depth) {
-        if (reader.Name == "scenario" && reader.NodeType == XmlNodeType.EndElement)
-          break;
-
-        if (reader.Name == "name") {
-          scenario.Id = reader.ReadElementContentAsString();
-          continue;
-        }
-        else if (reader.Name == "algorithm") {
-          IList<Model.Algorithm> algos;
-          ParseAlgorithms(out algos, reader);
-          scenario.Algorithm = algos;
-          continue;
-        }
-        reader.Read();
-      }
-      return scenario;
-    }
-
-    private Model.OptimizationScenario ParseScenario(StringReader str) {
-      // Set the validation settings.      
-      bool isErrorPresent = false;
-      var settings = GetSettings();
-      settings.ValidationEventHandler += (sender, args) => {
-        Trace.WriteLine(args.Message);
-        isErrorPresent = true;
-      };
-      Model.OptimizationScenario scenario = null;      
-      using (var reader = XmlReader.Create(str, settings)) {        
-        while (!reader.EOF) {
-          if (reader.Name == "scenario" && reader.NodeType == XmlNodeType.Element) {
-            scenario = ParseScenarioElement(reader);            
-          }
-          reader.Read();
-        }
-      }
-      
-      if (isErrorPresent)
-        return null;
-      return scenario;
-    }
-
-    struct ValueEntry {
-      public double v1;
-      public double v2;
-    };
-
-    private void ParseDecimalMatrix(Model.DecimalMatrix matrix, XmlReader reader) {      
-      IList<ValueEntry> ventries = new List<ValueEntry>();
-      while (reader.Read()) {        
-        if (reader.Name == "param")
-          break;
-        if (reader.Name == "value") {
-          var val1 = Convert.ToDouble(reader.GetAttribute("v1"), CultureInfo.InvariantCulture.NumberFormat);
-          var val2 = Convert.ToDouble(reader.GetAttribute("v2"), CultureInfo.InvariantCulture.NumberFormat);
-          ventries.Add(new ValueEntry() { v1 = val1, v2 = val2 });          
-        }
-      }
-      double[][] mat = new double[ventries.Count][];
-      int i=0;
-      foreach (var entry in ventries) {
-        mat[i] = new double[2];
-        mat[i][0] = entry.v1;
-        mat[i][1] = entry.v2;
-        i++;
-      }
-      matrix.Value = mat;
-    }
-
-    private IList<Model.Parameter> ParseParameters(XmlReader reader) {
-      IList<Model.Parameter> parameters = new List<Model.Parameter>();
-      while (reader.Read()) {
-        if (reader.Name == "parameters" && reader.NodeType == XmlNodeType.EndElement)
-          break;
-        // parse parameter
-        if (reader.Name == "param" && reader.NodeType == XmlNodeType.Element) {
-          var param = new Model.Parameter();
-          var typeAtt = reader.GetAttribute("type");
-          param.Type = (Model.ParameterType)Enum.Parse(typeof(Model.ParameterType), typeAtt);
-          switch (param.Type) {
-            case Model.ParameterType.Boolean:
-              param.Value = new Model.BoolValue() { Name = reader.GetAttribute("name"), Value = Convert.ToBoolean(reader.GetAttribute("value")) };
-              break;
-            case Model.ParameterType.Integer:
-            case Model.ParameterType.Percent:
-            case Model.ParameterType.Decimal:
-              //TODO: Check which comma char is being used; enhance to use any
-              param.Value = new Model.DecimalValue() { Name = reader.GetAttribute("name"), Value = Convert.ToDouble(reader.GetAttribute("value"), CultureInfo.InvariantCulture.NumberFormat) };
-              break;            
-            case Model.ParameterType.DecimalMatrix:
-              var decMatrix = new Model.DecimalMatrix() { Name = reader.GetAttribute("name") };
-              ParseDecimalMatrix(decMatrix, reader);
-              param.Value = decMatrix;
-              break;
-            case Model.ParameterType.DecimalVector:
-              var decVec = new Model.DecimalVector() { Name = reader.GetAttribute("name") };
-              ParseDecimalVector(decVec, reader);
-              param.Value = decVec;
-              break;
-            case Model.ParameterType.Type:
-              var type = new Model.TypeValue() { Name = reader.GetAttribute("name") };
-              ParseType(type, reader);
-              param.Value = type;
-              break;
-            case Model.ParameterType.String:
-              param.Value = new Model.StringValue() { Name = reader.GetAttribute("name"), Value = reader.GetAttribute("value") };
-              break;
-            default:
-              Console.WriteLine("Unhandled model type: " + param.Type);
-              break;
-          }
-          parameters.Add(param);
-        }
-      }
-      return parameters;
-    }
-
-    private void ParseType(Model.TypeValue type, XmlReader reader) {
-      var choices = new List<string>();
-      string selected = null;
-      while (reader.Read()) {
-        if (reader.Name == "param")
-          break;
-        if (reader.Name == "choice") {
-          var choice = reader.GetAttribute("name");
-          if (reader.HasAttributes && Convert.ToBoolean(reader.GetAttribute("selected"))) {            
-            selected = choice;
-          }
-          choices.Add(choice);
-        }
-      }
-      type.Options = choices.ToArray();
-      type.Value = selected;
-    }
-
-    private void ParseDecimalVector(Model.DecimalVector decVec, XmlReader reader) {
-      var entries = new List<double>();
-      //IList<ValueEntry> ventries = new List<ValueEntry>();
-      while (reader.Read()) {
-        if (reader.Name == "param")
-          break;
-        if (reader.Name == "value") {
-          var val1 = Convert.ToDouble(reader.GetAttribute("v1"), CultureInfo.InvariantCulture.NumberFormat);
-          entries.Add(val1);
-        }
-      }
-      decVec.Value = entries.ToArray();      
-    }
-  }
-}
Index: branches/OaaS/HeuristicLab.Services.Optimization.Controller/HeuristicLab.Services.Optimization.ControllerService.csproj
===================================================================
--- branches/OaaS/HeuristicLab.Services.Optimization.Controller/HeuristicLab.Services.Optimization.ControllerService.csproj	(revision 9166)
+++ branches/OaaS/HeuristicLab.Services.Optimization.Controller/HeuristicLab.Services.Optimization.ControllerService.csproj	(revision 9215)
@@ -151,4 +151,7 @@
     <Reference Include="Microsoft.WindowsAzure.ServiceRuntime, Version=1.7.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL" />
     <Reference Include="Microsoft.WindowsAzure.StorageClient, Version=1.7.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL" />
+    <Reference Include="Newtonsoft.Json">
+      <HintPath>..\packages\Newtonsoft.Json.4.5.11\lib\net40\Newtonsoft.Json.dll</HintPath>
+    </Reference>
     <Reference Include="System" />
     <Reference Include="System.configuration" />
@@ -175,7 +178,8 @@
     <Compile Include="Mockup\MockupDAL.cs" />
     <Compile Include="Mockup\MockupScenarioManager.cs" />
+    <Compile Include="Parsers\AlgorithmConverter.cs" />
     <Compile Include="PlaceholderControllerService.cs" />
     <Compile Include="Properties\AssemblyInfo.cs" />
-    <Compile Include="HL\ScenarioParser.cs" />
+    <Compile Include="Parsers\ScenarioParser.cs" />
     <Compile Include="Utility.cs" />
   </ItemGroup>
@@ -186,5 +190,4 @@
     <None Include="packages.config" />
   </ItemGroup>
-  <ItemGroup />
   <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
   <PropertyGroup>
Index: branches/OaaS/HeuristicLab.Services.Optimization.Controller/Interfaces/DAL.cs
===================================================================
--- branches/OaaS/HeuristicLab.Services.Optimization.Controller/Interfaces/DAL.cs	(revision 9166)
+++ branches/OaaS/HeuristicLab.Services.Optimization.Controller/Interfaces/DAL.cs	(revision 9215)
@@ -3,4 +3,5 @@
 using System.Linq;
 using System.Text;
+using HeuristicLab.Services.Optimization.ControllerService.Model;
 
 namespace HeuristicLab.Services.Optimization.ControllerService.Interfaces {
@@ -17,4 +18,11 @@
   }
 
+  public interface IExperimentDao {
+    bool Add(string username, Experiment experiment);
+    bool DeleteByName(string username, string experiment);
+    Experiment FindByName(string username, string experiment);
+    IEnumerable<Experiment> GetExperiments(string user);
+  }
+
   public interface IBlobDao {
     bool Add(StringEntry entry);
@@ -24,6 +32,7 @@
 
   public interface IDataAccessLayer {
-    IScenarioDao CreateScenarioDao();
-    IBlobDao CreateBlobDao();
+    IScenarioDao ScenarioDao { get; }
+    IBlobDao BlobDao { get; }
+    IExperimentDao ExperimentDao { get; }    
   }
 
Index: branches/OaaS/HeuristicLab.Services.Optimization.Controller/Interfaces/IControllerService.cs
===================================================================
--- branches/OaaS/HeuristicLab.Services.Optimization.Controller/Interfaces/IControllerService.cs	(revision 9166)
+++ branches/OaaS/HeuristicLab.Services.Optimization.Controller/Interfaces/IControllerService.cs	(revision 9215)
@@ -20,5 +20,5 @@
 
     [OperationContract]
-    void ScheduleOptimizationScenario(User user, OptimizationScenario scenario, JobExecutionDetails details);
+    bool ScheduleOptimizationScenario(User user, OptimizationScenario scenario, JobExecutionDetails details);
 
     [OperationContract]
@@ -29,5 +29,5 @@
 
     [OperationContract]
-    void DeleteJob(User user, string id);
+    bool DeleteJob(User user, string id);
 
     [OperationContract]
@@ -39,4 +39,19 @@
     [OperationContract]
     bool DeleteHiveScenario(User user, string scenarioName);
+
+    [OperationContract]
+    bool SaveExperiment(User user, Experiment experiment);
+
+    [OperationContract]
+    IEnumerable<string> GetExperiments(User user);
+
+    [OperationContract]
+    bool DeleteExperiment(User user, string experiment);
+
+    [OperationContract]
+    Job GetTasks(User u, string jobId);
+
+    [OperationContract]
+    Task GetTaskData(User u, string jobId, string taskId);
   }
 }
Index: branches/OaaS/HeuristicLab.Services.Optimization.Controller/Interfaces/IScenarioManager.cs
===================================================================
--- branches/OaaS/HeuristicLab.Services.Optimization.Controller/Interfaces/IScenarioManager.cs	(revision 9166)
+++ branches/OaaS/HeuristicLab.Services.Optimization.Controller/Interfaces/IScenarioManager.cs	(revision 9215)
@@ -7,11 +7,18 @@
 namespace HeuristicLab.Services.Optimization.ControllerService.Interfaces {
   public interface IScenarioManager {
-    void DispatchScenario(User user, OptimizationScenario scenario, JobExecutionDetails details);
+    string DispatchScenario(User user, OptimizationScenario scenario, JobExecutionDetails details);
     IList<Job> GetJobs(User user);
     Job GetJob(User user, string id);
-    void DeleteJob(User user, string id);
+    bool DeleteJob(User user, string id);
     IList<Model.Run> GetJobResults(User user, string id);
     bool AddScenario(User user, string scenarioName, string scenarioXml, string scenarioMapper);
     bool DeleteScenario(User user, string scenarioName);
+
+    bool SaveExperiment(User user, Experiment experiment);
+    IEnumerable<string> GetExperiments(User user);
+    bool DeleteExperiment(User user, string experiment);
+
+    Task GetTaskData(User u, string jobId, string taskId);
+    Job GetTasks(User u, string jobId);
   }
 }
Index: branches/OaaS/HeuristicLab.Services.Optimization.Controller/Interfaces/Model/ControllerModel.cs
===================================================================
--- branches/OaaS/HeuristicLab.Services.Optimization.Controller/Interfaces/Model/ControllerModel.cs	(revision 9166)
+++ branches/OaaS/HeuristicLab.Services.Optimization.Controller/Interfaces/Model/ControllerModel.cs	(revision 9215)
@@ -306,4 +306,7 @@
   public class Experiment {
     [DataMember]
+    public string Name { get; set; }
+
+    [DataMember]
     public IList<OptimizationScenario> Scenarios { get; set; }
 
@@ -340,4 +343,88 @@
 
   [DataContract]
+  public class Property {
+    [DataMember]
+    public string Key { get; set; }
+    [DataMember]
+    public string Value { get; set; }
+  }
+  
+  [DataContract]
+  public class General {
+    [DataMember]
+    public string Name { get { return GetValue("Name"); } set { SetValue("Name", value); } }
+    [DataMember]
+    public string Id { get { return GetValue("Id"); } set { SetValue("Id", value); } }
+    [DataMember]
+    public string Priority { get { return GetValue("Priority"); } set { SetValue("Priority", value); } }
+    [DataMember]
+    public string LastChanged { get { return GetValue("LastChanged"); } set { SetValue("LastChanged", value); } }
+
+    
+    private IList<Property> properties = new List<Property>();
+    [DataMember]
+	  public IList<Property> Properties
+	  {
+		  get { 
+        if (properties == null) 
+          properties = new List<Property>();
+        return properties;
+      }
+		  set { properties = value;}
+	  }
+
+    private string GetValue(string key) {      
+      return (from p in Properties where p.Key == key select p.Value).FirstOrDefault();
+    }
+
+    private void SetValue(string key, string value) {
+      var prop = (from p in Properties where p.Key == key select p).FirstOrDefault();
+      if (prop == null) {
+        prop = new Property();
+        Properties.Add(prop);
+      }
+      prop.Key = key;
+      prop.Value = value;
+    }
+  }
+
+  [DataContract]
+  public class TaskState {
+    [DataMember]
+    public string State { get; set; }
+    [DataMember]
+    public string ExecutionTime { get; set; }
+    [DataMember]
+    public string DateCreated { get; set; }
+    [DataMember]
+    public string DateFinished { get; set; }
+  }
+
+  [DataContract]
+  public class Task {
+    private General general = new General();
+    [DataMember]
+    public General General {
+      get { return general; }
+      set { general = value; }
+    }
+
+    private IList<Task> tasks = new List<Task>();
+    [DataMember]
+    public IList<Task> Children {
+      get { return tasks; }
+      set { tasks = value; }
+    }
+    
+    private TaskState state = new TaskState();
+
+    [DataMember]
+    public TaskState State {
+      get { return state; }
+      set { state = value; }
+    }
+  }
+
+  [DataContract]
   public class Job {
     [DataMember]
@@ -355,4 +442,13 @@
     [DataMember]
     public DateTime DateCreated { get; set; }
+
+    private IList<Task> tasks = new List<Task>();
+
+    [DataMember]
+    public IList<Task> Tasks {
+      get { return tasks; }
+      set { tasks = value; }
+    }
+
   }
 
Index: branches/OaaS/HeuristicLab.Services.Optimization.Controller/Mockup/MockupDAL.cs
===================================================================
--- branches/OaaS/HeuristicLab.Services.Optimization.Controller/Mockup/MockupDAL.cs	(revision 9166)
+++ branches/OaaS/HeuristicLab.Services.Optimization.Controller/Mockup/MockupDAL.cs	(revision 9215)
@@ -246,11 +246,12 @@
     }
 
-    public IScenarioDao CreateScenarioDao() {
-      return new ScenarioDao();
-    }
-
-    public IBlobDao CreateBlobDao() {
-      return new BlobDao();
-    }
+    private IExperimentDao experimentDao;
+
+    public IExperimentDao ExperimentDao {
+      get {         
+        return null; 
+      }      
+    }
+
   }
 }
Index: branches/OaaS/HeuristicLab.Services.Optimization.Controller/Mockup/MockupScenarioManager.cs
===================================================================
--- branches/OaaS/HeuristicLab.Services.Optimization.Controller/Mockup/MockupScenarioManager.cs	(revision 9166)
+++ branches/OaaS/HeuristicLab.Services.Optimization.Controller/Mockup/MockupScenarioManager.cs	(revision 9215)
@@ -131,6 +131,7 @@
     }
 
-    public void DispatchScenario(Model.User user, Model.OptimizationScenario scenario, JobExecutionDetails details) {
-      // does nothign
+    public string DispatchScenario(Model.User user, Model.OptimizationScenario scenario, JobExecutionDetails details) {
+      // does nothing
+      return "guid";
     }
 
@@ -144,6 +145,7 @@
 
 
-    public void DeleteJob(User user, string id) {
+    public bool DeleteJob(User user, string id) {
       jobs.RemoveAll(j => j.Id == id);
+      return true;
     }
 
@@ -199,6 +201,6 @@
       
       // insert into table & blob store
-      var scenDao = dal.CreateScenarioDao();
-      var blobDao = dal.CreateBlobDao();
+      var scenDao = dal.ScenarioDao;
+      var blobDao = dal.BlobDao;
       
       Guid scenarioXmlGuid = Guid.NewGuid();
@@ -225,6 +227,6 @@
     public bool DeleteScenario(User user, string scenarioName) {
       // delete from table & blob store
-      var scenarioDao = dal.CreateScenarioDao();
-      var blobDao = dal.CreateBlobDao();
+      var scenarioDao = dal.ScenarioDao;
+      var blobDao = dal.BlobDao;
 
       var entity = scenarioDao.FindByName(scenarioName);
@@ -237,4 +239,28 @@
       return true;
     }
+
+
+    public bool SaveExperiment(User user, Model.Experiment experiment) {
+      throw new NotImplementedException();
+    }
+
+
+    public IEnumerable<string> GetExperiments(User user) {
+      throw new NotImplementedException();
+    }
+
+
+    public bool DeleteExperiment(User user, string experiment) {
+      throw new NotImplementedException();
+    }
+
+
+    public Model.Task GetTaskData(User u, string jobId, string taskId) {
+      throw new NotImplementedException();
+    }
+
+    public Model.Job GetTasks(User u, string jobId) {
+      throw new NotImplementedException();
+    }
   }
 }
Index: branches/OaaS/HeuristicLab.Services.Optimization.Controller/Parsers/AlgorithmConverter.cs
===================================================================
--- branches/OaaS/HeuristicLab.Services.Optimization.Controller/Parsers/AlgorithmConverter.cs	(revision 9215)
+++ branches/OaaS/HeuristicLab.Services.Optimization.Controller/Parsers/AlgorithmConverter.cs	(revision 9215)
@@ -0,0 +1,76 @@
+﻿using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using HeuristicLab.Services.Optimization.ControllerService.Model;
+using Newtonsoft.Json.Linq;
+
+namespace HeuristicLab.Services.Optimization.ControllerService.Parsers {
+  public static class AlgorithmConverter {
+
+    public static Algorithm Convert(string json) {
+      var algorithm = new Algorithm();
+      var o = JObject.Parse(json);
+      foreach (JProperty param in o["Algorithm Parameters"]) {
+        Parameter parameter = CreateParameter(param);
+        algorithm.Parameters.Items.Add(parameter);
+      }
+
+      var problemParams = o["Problem Parameters"];
+      // TODO: Store problem parameters
+      if (problemParams != null) {
+        algorithm.Problem = new Problem();
+        foreach (JProperty param in problemParams) {
+          Parameter parameter = CreateParameter(param);
+          algorithm.Problem.Parameters.Items.Add(parameter);
+        }
+      }
+      return algorithm;
+    }
+
+    public static Algorithm ConvertAppend(string json, Algorithm algorithm) {
+      var o = JObject.Parse(json);
+      foreach (JProperty param in o["Algorithm Parameters"]) {
+        Parameter parameter = CreateParameter(param);
+        var oldParameter = (from p in algorithm.Parameters.Items where p.Value.Name == parameter.Value.Name select p).FirstOrDefault();
+        if (oldParameter != null) {
+          oldParameter.Value = parameter.Value;
+        }
+        else {
+          algorithm.Parameters.Items.Add(parameter);
+        }
+      }
+
+      var problemParams = o["Problem Parameters"];
+      if (problemParams != null) {
+        algorithm.Problem = new Problem();
+        foreach (JProperty param in problemParams) {
+          Parameter parameter = CreateParameter(param);          
+          var oldParameter = (from p in algorithm.Problem.Parameters.Items where p.Value.Name == parameter.Value.Name select p).FirstOrDefault();
+          if (oldParameter != null) {
+            oldParameter.Value = parameter.Value;
+          }
+          else {
+            algorithm.Problem.Parameters.Items.Add(parameter);
+          }
+        }
+      }
+      return algorithm;
+    }
+
+    private static Parameter CreateParameter(JProperty property) {
+      JToken token = property.Value;
+      switch (token.Type) {
+        case JTokenType.Integer:
+        case JTokenType.Float:
+          return new Parameter() { Type = ParameterType.Decimal, Value = new DecimalValue() { Name = property.Name, Value = (double)property.Value } };
+        case JTokenType.Boolean:
+          return new Parameter() { Type = ParameterType.Boolean, Value = new BoolValue() { Name = property.Name, Value = (bool)property.Value } };
+        case JTokenType.String:
+          return new Parameter() { Type = ParameterType.Type, Value = new TypeValue() { Name = property.Name, Value = (string)property.Value } };                  
+        default:
+          throw new Exception("Unhandled datatype: " + property.Type);
+      }
+    }
+  }
+}
Index: branches/OaaS/HeuristicLab.Services.Optimization.Controller/Parsers/ScenarioParser.cs
===================================================================
--- branches/OaaS/HeuristicLab.Services.Optimization.Controller/Parsers/ScenarioParser.cs	(revision 9215)
+++ branches/OaaS/HeuristicLab.Services.Optimization.Controller/Parsers/ScenarioParser.cs	(revision 9215)
@@ -0,0 +1,316 @@
+﻿using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.IO;
+using System.Xml;
+using System.Globalization;
+using System.Xml.Linq;
+using HeuristicLab.Services.Optimization.ControllerService.Azure;
+using HeuristicLab.Services.Optimization.ControllerService.Interfaces;
+using System.Diagnostics;
+
+namespace HeuristicLab.Services.Optimization.ControllerService {
+  public class ScenarioParser {
+    private static IList<Model.OptimizationScenario> scenarios;
+    private static object lockable = new object();
+
+    private IDataAccessLayer dal = DataAccessLayerProvider.GetLayer();
+
+    public IList<Model.OptimizationScenario> Scenarios {
+      get {
+        if (scenarios == null) {
+          lock (lockable) {
+            if (scenarios == null) {
+              ParseScenarios();
+            }
+          }
+        }
+        return scenarios;
+      }
+    }
+    
+    public Model.OptimizationScenario GetByName(string name) {
+      foreach (var scen in Scenarios) {
+        if (scen.Id == name) {
+          return scen;
+        }
+      }
+      return null;
+    }
+
+    /*// http://www.sascha-dittmann.de/post/Webseitenpfade-einer-Windows-Azure-Web-Rolle-bestimmen.aspx
+    private static IEnumerable<string> WebSiteDirectories {
+      get {
+        var roleRootDir = Environment.GetEnvironmentVariable("RdRoleRoot");
+        if (roleRootDir == null)
+          return Enumerable.Empty<string>();
+        XNamespace roleModelNs =
+          "http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceDefinition";
+        var roleModelDoc = XDocument.Load(Path.Combine(roleRootDir, "RoleModel.xml"));
+        if (roleModelDoc.Root == null)
+          return Enumerable.Empty<string>();
+
+        var sites = roleModelDoc.Root.Element(roleModelNs + "Sites");
+        if (sites == null)
+          return Enumerable.Empty<string>();
+
+        var siteElements = sites.Elements(roleModelNs + "Site");
+
+        return
+          from siteElement in siteElements
+          where siteElement.Attribute("name") != null
+                && siteElement.Attribute("name").Value == "Web"
+                && siteElement.Attribute("physicalDirectory") != null
+          select Path.Combine(roleRootDir,
+                 siteElement.Attribute("physicalDirectory").Value);
+      }
+    }
+     */
+
+    private void ParseScenarios() {
+      var scens = new List<Model.OptimizationScenario>();
+      /*string path;
+      if (WebSiteDirectories.Count() != 0) {
+        path = WebSiteDirectories.FirstOrDefault() + @"\Mappings";
+      } else {
+        path = AppDomain.CurrentDomain.BaseDirectory + @"\Mappings";
+      }
+        
+      foreach (var file in Directory.EnumerateFiles(path, "*.xml")) {
+        var scenario = ParseScenarioFromFile(file);
+        if (scenario != null)
+          scens.Add(scenario);
+      }*/
+
+      var scenarioDao = dal.ScenarioDao;
+      var blobDao = dal.BlobDao;
+      foreach (var entity in scenarioDao.GetAllEntities()) {
+        var scenarioXml = blobDao.FindByKey(entity.Scenario).Text;
+        var scenario = ParseScenarioFromXml(scenarioXml);
+        if (scenario != null)
+          scens.Add(scenario);
+      }
+
+      scenarios = scens;
+    }
+
+    private XmlReaderSettings GetSettings() {
+      // Set the validation settings.
+      XmlReaderSettings settings = new XmlReaderSettings();
+      settings.ValidationType = ValidationType.Schema;
+      settings.Schemas.Add("urn:scenario-schema", AppDomain.CurrentDomain.BaseDirectory + @"\Mappings\scenario.xsd");      
+      return settings;
+    }
+
+    public Model.OptimizationScenario ParseScenarioFromXml(string xml) {
+      //using (var reader = XmlReader.Create(new StringReader(xml), GetSettings())) {
+        return ParseScenario(new StringReader(xml));
+      //}            
+    }
+
+   /* private Model.OptimizationScenario ParseScenarioFromFile(string filename) {
+      using (var reader = XmlReader.Create(new FileStream(filename, FileMode.Open), GetSettings())) {
+        return ParseScenario(reader);
+      }      
+    } */
+
+    private Model.Problem ParseProblem(XmlReader reader) {
+      var problem = new Model.Problem();
+      while (reader.Read()) {
+        if (reader.NodeType == XmlNodeType.EndElement)
+          break;
+        if (reader.Name == "parameters")
+          problem.Parameters.Items = ParseParameters(reader);
+      }
+      return problem;
+    }
+
+    private void ParseAlgorithms(out IList<Model.Algorithm> algos, XmlReader reader) {
+      algos = new List<Model.Algorithm>();
+      var depth = reader.Depth;
+      do {
+        if (reader.Name == "algorithm" && reader.Depth == depth) {
+          var innerAlg = new Model.Algorithm();
+          algos.Add(innerAlg);
+          
+          innerAlg.Mapper = reader.GetAttribute("mapper");
+          reader.Read();
+          for (;;) {
+            if (reader.Name == "algorithm" && reader.NodeType == XmlNodeType.EndElement)
+              break;
+
+            if (reader.Name == "parameters" && reader.NodeType == XmlNodeType.Element) {
+              innerAlg.Parameters.Items = ParseParameters(reader);
+              continue;
+            }
+            else if (reader.Name == "problem" && reader.NodeType == XmlNodeType.Element) {
+              innerAlg.Problem = ParseProblem(reader);
+              continue;
+            }
+            else if (reader.Name == "algorithm" && reader.NodeType == XmlNodeType.Element) {
+              IList<Model.Algorithm> childAlgos;
+              ParseAlgorithms(out childAlgos, reader);
+              innerAlg.ChildAlgorithms = childAlgos;
+              //TODO: Test with child algorithms
+              continue;
+            }
+            reader.Read();
+          }
+        }
+      } while (reader.Read() && reader.Depth >= depth);
+    }
+
+    private Model.OptimizationScenario ParseScenarioElement(XmlReader reader) {
+      var scenario = new Model.OptimizationScenario();
+      var depth = reader.Depth;
+      while (reader.Depth >= depth) {
+        if (reader.Name == "scenario" && reader.NodeType == XmlNodeType.EndElement)
+          break;
+
+        if (reader.Name == "name") {
+          scenario.Id = reader.ReadElementContentAsString();
+          continue;
+        }
+        else if (reader.Name == "algorithm") {
+          IList<Model.Algorithm> algos;
+          ParseAlgorithms(out algos, reader);
+          scenario.Algorithm = algos;
+          continue;
+        }
+        reader.Read();
+      }
+      return scenario;
+    }
+
+    private Model.OptimizationScenario ParseScenario(StringReader str) {
+      // Set the validation settings.      
+      bool isErrorPresent = false;
+      var settings = GetSettings();
+      settings.ValidationEventHandler += (sender, args) => {
+        Trace.WriteLine(args.Message);
+        isErrorPresent = true;
+      };
+      Model.OptimizationScenario scenario = null;      
+      using (var reader = XmlReader.Create(str, settings)) {        
+        while (!reader.EOF) {
+          if (reader.Name == "scenario" && reader.NodeType == XmlNodeType.Element) {
+            scenario = ParseScenarioElement(reader);            
+          }
+          reader.Read();
+        }
+      }
+      
+      if (isErrorPresent)
+        return null;
+      return scenario;
+    }
+
+    struct ValueEntry {
+      public double v1;
+      public double v2;
+    };
+
+    private void ParseDecimalMatrix(Model.DecimalMatrix matrix, XmlReader reader) {      
+      IList<ValueEntry> ventries = new List<ValueEntry>();
+      while (reader.Read()) {        
+        if (reader.Name == "param")
+          break;
+        if (reader.Name == "value") {
+          var val1 = Convert.ToDouble(reader.GetAttribute("v1"), CultureInfo.InvariantCulture.NumberFormat);
+          var val2 = Convert.ToDouble(reader.GetAttribute("v2"), CultureInfo.InvariantCulture.NumberFormat);
+          ventries.Add(new ValueEntry() { v1 = val1, v2 = val2 });          
+        }
+      }
+      double[][] mat = new double[ventries.Count][];
+      int i=0;
+      foreach (var entry in ventries) {
+        mat[i] = new double[2];
+        mat[i][0] = entry.v1;
+        mat[i][1] = entry.v2;
+        i++;
+      }
+      matrix.Value = mat;
+    }
+
+    private IList<Model.Parameter> ParseParameters(XmlReader reader) {
+      IList<Model.Parameter> parameters = new List<Model.Parameter>();
+      while (reader.Read()) {
+        if (reader.Name == "parameters" && reader.NodeType == XmlNodeType.EndElement)
+          break;
+        // parse parameter
+        if (reader.Name == "param" && reader.NodeType == XmlNodeType.Element) {
+          var param = new Model.Parameter();
+          var typeAtt = reader.GetAttribute("type");
+          param.Type = (Model.ParameterType)Enum.Parse(typeof(Model.ParameterType), typeAtt);
+          switch (param.Type) {
+            case Model.ParameterType.Boolean:
+              param.Value = new Model.BoolValue() { Name = reader.GetAttribute("name"), Value = Convert.ToBoolean(reader.GetAttribute("value")) };
+              break;
+            case Model.ParameterType.Integer:
+            case Model.ParameterType.Percent:
+            case Model.ParameterType.Decimal:
+              //TODO: Check which comma char is being used; enhance to use any
+              param.Value = new Model.DecimalValue() { Name = reader.GetAttribute("name"), Value = Convert.ToDouble(reader.GetAttribute("value"), CultureInfo.InvariantCulture.NumberFormat) };
+              break;            
+            case Model.ParameterType.DecimalMatrix:
+              var decMatrix = new Model.DecimalMatrix() { Name = reader.GetAttribute("name") };
+              ParseDecimalMatrix(decMatrix, reader);
+              param.Value = decMatrix;
+              break;
+            case Model.ParameterType.DecimalVector:
+              var decVec = new Model.DecimalVector() { Name = reader.GetAttribute("name") };
+              ParseDecimalVector(decVec, reader);
+              param.Value = decVec;
+              break;
+            case Model.ParameterType.Type:
+              var type = new Model.TypeValue() { Name = reader.GetAttribute("name") };
+              ParseType(type, reader);
+              param.Value = type;
+              break;
+            case Model.ParameterType.String:
+              param.Value = new Model.StringValue() { Name = reader.GetAttribute("name"), Value = reader.GetAttribute("value") };
+              break;
+            default:
+              Console.WriteLine("Unhandled model type: " + param.Type);
+              break;
+          }
+          parameters.Add(param);
+        }
+      }
+      return parameters;
+    }
+
+    private void ParseType(Model.TypeValue type, XmlReader reader) {
+      var choices = new List<string>();
+      string selected = null;
+      while (reader.Read()) {
+        if (reader.Name == "param")
+          break;
+        if (reader.Name == "choice") {
+          var choice = reader.GetAttribute("name");
+          if (reader.HasAttributes && Convert.ToBoolean(reader.GetAttribute("selected"))) {            
+            selected = choice;
+          }
+          choices.Add(choice);
+        }
+      }
+      type.Options = choices.ToArray();
+      type.Value = selected;
+    }
+
+    private void ParseDecimalVector(Model.DecimalVector decVec, XmlReader reader) {
+      var entries = new List<double>();
+      //IList<ValueEntry> ventries = new List<ValueEntry>();
+      while (reader.Read()) {
+        if (reader.Name == "param")
+          break;
+        if (reader.Name == "value") {
+          var val1 = Convert.ToDouble(reader.GetAttribute("v1"), CultureInfo.InvariantCulture.NumberFormat);
+          entries.Add(val1);
+        }
+      }
+      decVec.Value = entries.ToArray();      
+    }
+  }
+}
Index: branches/OaaS/HeuristicLab.Services.Optimization.Controller/PlaceholderControllerService.cs
===================================================================
--- branches/OaaS/HeuristicLab.Services.Optimization.Controller/PlaceholderControllerService.cs	(revision 9166)
+++ branches/OaaS/HeuristicLab.Services.Optimization.Controller/PlaceholderControllerService.cs	(revision 9215)
@@ -69,6 +69,7 @@
     }
 
-    public void ScheduleOptimizationScenario(Model.User user, Model.OptimizationScenario scenario, JobExecutionDetails details) {
+    public bool ScheduleOptimizationScenario(Model.User user, Model.OptimizationScenario scenario, JobExecutionDetails details) {
       hiveManager.DispatchScenario(user, scenario, details);
+      return true;
     }
 
@@ -83,6 +84,6 @@
 
 
-    public void DeleteJob(Model.User user, string id) {
-      hiveManager.DeleteJob(user, id);
+    public bool DeleteJob(Model.User user, string id) {
+      return hiveManager.DeleteJob(user, id);
     }
 
@@ -117,4 +118,28 @@
               select e.Id).AsEnumerable();      
     }
+
+
+    public bool SaveExperiment(User user, Experiment experiment) {
+      return hiveManager.SaveExperiment(user, experiment);
+    }
+
+
+    public IEnumerable<string> GetExperiments(User user) {
+      return hiveManager.GetExperiments(user);
+    }
+
+
+    public bool DeleteExperiment(User user, string experiment) {
+      return hiveManager.DeleteExperiment(user, experiment);
+    }
+
+
+    public Job GetTasks(User u, string jobId) {
+      return hiveManager.GetTasks(u, jobId);
+    }
+
+    public Task GetTaskData(User u, string jobId, string taskId) {
+      return hiveManager.GetTaskData(u, jobId, taskId);
+    }
   }
 }
