Index: /branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Administrator/3.3/HeuristicLab.Clients.Hive.Administrator-3.3.csproj
===================================================================
--- /branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Administrator/3.3/HeuristicLab.Clients.Hive.Administrator-3.3.csproj	(revision 6755)
+++ /branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Administrator/3.3/HeuristicLab.Clients.Hive.Administrator-3.3.csproj	(revision 6756)
@@ -153,5 +153,4 @@
   </ItemGroup>
   <ItemGroup>
-    <Compile Include="HiveAdministratorClient.cs" />
     <Compile Include="Views\HiveAdministratorView.cs">
       <SubType>UserControl</SubType>
Index: /branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Administrator/3.3/Views/Common/UpdateControl.cs
===================================================================
--- /branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Administrator/3.3/Views/Common/UpdateControl.cs	(revision 6755)
+++ /branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Administrator/3.3/Views/Common/UpdateControl.cs	(revision 6756)
@@ -21,4 +21,5 @@
 
 using System;
+using System.Threading.Tasks;
 using System.Windows.Forms;
 using TS = System.Threading.Tasks;
@@ -58,6 +59,7 @@
 
         Action action = new Action(PrivUpdateAction);
-        TS.Task task = new TS.Task(action);
-        task.Start();
+        TS.Task.Factory.StartNew(action).ContinueWith((t) => {
+          throw t.Exception;
+        }, TaskContinuationOptions.OnlyOnFaulted);
       }
     }
Index: /branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Administrator/3.3/Views/HiveAdministratorView.cs
===================================================================
--- /branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Administrator/3.3/Views/HiveAdministratorView.cs	(revision 6755)
+++ /branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Administrator/3.3/Views/HiveAdministratorView.cs	(revision 6756)
@@ -21,13 +21,13 @@
 
 using System.Windows.Forms;
-using HeuristicLab.Core.Views;
 using HeuristicLab.MainForm;
+using HeuristicLab.MainForm.WindowsForms;
 
 namespace HeuristicLab.Clients.Hive.Administrator.Views {
   [View("Hive Administrator")]
-  [Content(typeof(HiveAdministratorClient), IsDefaultView = true)]
-  public partial class HiveAdministratorView : ItemView {
-    public new HiveAdministratorClient Content {
-      get { return (HiveAdministratorClient)base.Content; }
+  [Content(typeof(HiveAdminClient), IsDefaultView = true)]
+  public partial class HiveAdministratorView : AsynchronousContentView {
+    public new HiveAdminClient Content {
+      get { return (HiveAdminClient)base.Content; }
       set { base.Content = value; }
     }
Index: /branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Administrator/3.3/Views/MenuItems/AdministratorMenuItem.cs
===================================================================
--- /branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Administrator/3.3/Views/MenuItems/AdministratorMenuItem.cs	(revision 6755)
+++ /branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Administrator/3.3/Views/MenuItems/AdministratorMenuItem.cs	(revision 6756)
@@ -21,5 +21,5 @@
 
 using System.Collections.Generic;
-using HeuristicLab.Clients.Hive.Administrator;
+using HeuristicLab.Clients.Hive;
 using HeuristicLab.MainForm;
 
@@ -33,5 +33,5 @@
     }
     public override void Execute() {
-      MainFormManager.MainForm.ShowContent(new HiveAdministratorClient());
+      MainFormManager.MainForm.ShowContent(HiveAdminClient.Instance);
     }
     public override int Position {
Index: /branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Administrator/3.3/Views/ResourcesView.Designer.cs
===================================================================
--- /branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Administrator/3.3/Views/ResourcesView.Designer.cs	(revision 6755)
+++ /branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Administrator/3.3/Views/ResourcesView.Designer.cs	(revision 6756)
@@ -61,4 +61,5 @@
       this.updateScheduleControl = new HeuristicLab.Clients.Hive.Administrator.Views.Common.UpdateControl();
       this.scheduleView = new HeuristicLab.Clients.Hive.Administrator.Views.ScheduleView();
+      this.progressBar = new System.Windows.Forms.ProgressBar();
       ((System.ComponentModel.ISupportInitialize)(this.splitSlaves)).BeginInit();
       this.splitSlaves.Panel1.SuspendLayout();
@@ -86,4 +87,5 @@
       // splitSlaves.Panel1
       // 
+      this.splitSlaves.Panel1.Controls.Add(this.progressBar);
       this.splitSlaves.Panel1.Controls.Add(this.updateSlaveGroup);
       this.splitSlaves.Panel1.Controls.Add(this.btnSave);
@@ -224,7 +226,14 @@
       this.scheduleView.Name = "scheduleView";
       this.scheduleView.ReadOnly = false;
-      this.scheduleView.ResourceId = new System.Guid("00000000-0000-0000-0000-000000000000");
       this.scheduleView.Size = new System.Drawing.Size(568, 473);
       this.scheduleView.TabIndex = 0;
+      // 
+      // progressBar
+      // 
+      this.progressBar.Location = new System.Drawing.Point(176, 3);
+      this.progressBar.Name = "progressBar";
+      this.progressBar.Size = new System.Drawing.Size(70, 23);
+      this.progressBar.Style = System.Windows.Forms.ProgressBarStyle.Continuous;
+      this.progressBar.TabIndex = 7;
       // 
       // ResourcesView
@@ -261,4 +270,5 @@
     private System.Windows.Forms.Button btnSave;
     private UpdateControl updateSlaveGroup;
+    private System.Windows.Forms.ProgressBar progressBar;
   }
 }
Index: /branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Administrator/3.3/Views/ResourcesView.cs
===================================================================
--- /branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Administrator/3.3/Views/ResourcesView.cs	(revision 6755)
+++ /branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Administrator/3.3/Views/ResourcesView.cs	(revision 6756)
@@ -23,4 +23,6 @@
 using System.Drawing;
 using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
 using System.Windows.Forms;
 using HeuristicLab.Clients.Hive.Views;
@@ -28,9 +30,10 @@
 using HeuristicLab.Core.Views;
 using HeuristicLab.MainForm;
+using TS = System.Threading.Tasks;
 
 namespace HeuristicLab.Clients.Hive.Administrator.Views {
-  [View("ResourcesView")]
+  [View("Resources View")]
   [Content(typeof(IItemList<Resource>), IsDefaultView = true)]
-  public partial class ResourcesView : ItemView {
+  public partial class ResourcesView : ItemView, IDisposable {
     public new IItemList<Resource> Content {
       get { return (IItemList<Resource>)base.Content; }
@@ -41,4 +44,6 @@
     private const int slaveImageIndex = 0;
     private const int slaveGroupImageIndex = 1;
+    private TS.Task progressTask;
+    private bool stopProgressTask;
 
 
@@ -47,8 +52,37 @@
       treeSlaveGroup.ImageList.Images.Add(HiveImageLibrary.Slave);
       treeSlaveGroup.ImageList.Images.Add(HiveImageLibrary.SlaveGroup);
+      //TODO: remove updatecontrol and replace with a regular button
       updateScheduleControl.UpdateAction = new Action(UpdateSchedule);
-      updateSlaveGroup.UpdateAction = new Action(UpdateSlaveGroups);
-
-      updateSlaveGroup.Update();
+      updateSlaveGroup.UpdateAction = new Action(UpdateResources);
+
+      HiveAdminClient.Instance.Refreshing += new EventHandler(Instance_Refreshing);
+      HiveAdminClient.Instance.Refreshed += new EventHandler(Instance_Refreshed);
+
+      UpdateResourcesAsync();
+    }
+
+    public new void Dispose() {
+      HiveAdminClient.Instance.Refreshing -= new EventHandler(Instance_Refreshing);
+      HiveAdminClient.Instance.Refreshed -= new EventHandler(Instance_Refreshed);
+    }
+
+    private void UpdateProgress() {
+      while (!stopProgressTask) {
+        int diff = (progressBar.Maximum - progressBar.Minimum) / 10;
+        progressBar.Value = (progressBar.Value + diff) % progressBar.Maximum;
+        //ok, this is not very clever...
+        Thread.Sleep(500);
+      }
+      progressBar.Value = progressBar.Minimum;
+    }
+
+    void Instance_Refreshing(object sender, EventArgs e) {
+      stopProgressTask = false;
+      progressTask = new TS.Task(UpdateProgress);
+      progressTask.Start();
+    }
+
+    void Instance_Refreshed(object sender, EventArgs e) {
+      stopProgressTask = true;
     }
 
@@ -142,5 +176,5 @@
 
       slaveView.Content = (Resource)e.Node.Tag;
-      scheduleView.ResourceId = ((Resource)e.Node.Tag).Id;
+      HiveAdminClient.Instance.DowntimeForResourceId = ((Resource)e.Node.Tag).Id;
 
       if (e.Node.Tag is SlaveGroup) {
@@ -149,5 +183,5 @@
 
       if (tabSlaveGroup.SelectedIndex == 1) {
-        UpdateSchedule();
+        UpdateScheduleAsync();
       }
     }
@@ -175,16 +209,16 @@
         Resource res = (Resource)treeSlaveGroup.SelectedNode.Tag;
 
-        DialogResult diagRes = MessageBox.Show("Do you really want to delete " + res.Name + "?", "HeuristicLab Hive Administration", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
+        DialogResult diagRes = MessageBox.Show("Do you really want to delete " + res.Name + "?", "HeuristicLab Hive Administrator", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
         if (diagRes == DialogResult.Yes) {
           if (res is Slave) {
             Content.Remove(res);
-            ServiceLocator.Instance.CallHiveService(service => service.DeleteSlave(res.Id));
+            HiveAdminClient.Delete(res);
           } else if (res is SlaveGroup) {
             //only delete empty groups
             if (Content.Where(s => s.ParentResourceId == res.Id).Count() < 1) {
               Content.Remove(res);
-              ServiceLocator.Instance.CallHiveService(service => service.DeleteSlaveGroup(res.Id));
+              HiveAdminClient.Delete(res);
             } else {
-              MessageBox.Show("Only empty groups can be deleted.", "HeuristicLab Hive Administration", MessageBoxButtons.OK, MessageBoxIcon.Error);
+              MessageBox.Show("Only empty groups can be deleted.", "HeuristicLab Hive Administrator", MessageBoxButtons.OK, MessageBoxIcon.Error);
             }
           }
@@ -197,12 +231,8 @@
         if (res is SlaveGroup && res.Id == Guid.Empty) {
           SlaveGroup slaveGroup = (SlaveGroup)res;
-          ServiceLocator.Instance.CallHiveService(service => slaveGroup.Id = service.AddSlaveGroup(slaveGroup));
+          slaveGroup.Store();
         }
         if (res.Id != Guid.Empty && res.Modified) {
-          if (res is SlaveGroup) {
-            ServiceLocator.Instance.CallHiveService(service => service.UpdateSlaveGroup((SlaveGroup)res));
-          } else if (res is Slave) {
-            ServiceLocator.Instance.CallHiveService(service => service.UpdateSlave((Slave)res));
-          }
+          res.Store();
         }
       }
@@ -218,5 +248,5 @@
           if (destNode.Text == ungroupedGroupName || (destNode.Parent != null && destNode.Parent.Text == ungroupedGroupName)) {
             MessageBox.Show(String.Format("You can't drag items to the {0} group.{1}This group only contains slaves which haven't yet been assigned to a real group.",
-              ungroupedGroupName, Environment.NewLine), "HeuristicLab Hive Administration", MessageBoxButtons.OK, MessageBoxIcon.Information);
+              ungroupedGroupName, Environment.NewLine), "HeuristicLab Hive Administrator", MessageBoxButtons.OK, MessageBoxIcon.Information);
             return;
           }
@@ -239,5 +269,5 @@
             //save parent group to get an id
             if (sgrp.Id == Guid.Empty) {
-              ServiceLocator.Instance.CallHiveService(service => sgrp.Id = service.AddSlaveGroup(sgrp));
+              sgrp.Store();
             }
 
@@ -300,8 +330,11 @@
       }
       slaveView.Content = null;
-      scheduleView.ResourceId = Guid.Empty;
-    }
-
-    private void UpdateSlaveGroups() {
+      if (scheduleView.Content != null) {
+        scheduleView.Content.Clear();
+      }
+      HiveAdminClient.Instance.ResetDowntime();
+    }
+
+    private void UpdateResources() {
       if (this.InvokeRequired) {
         this.Invoke(new Action(ResetView));
@@ -310,28 +343,32 @@
       }
 
-      IItemList<Resource> resources = new ItemList<Resource>();
-
-      ServiceLocator.Instance.CallHiveService(service => {
-        service.GetSlaveGroups().ForEach(g => resources.Add(g));
-        service.GetSlaves().ForEach(s => resources.Add(s));
-      });
-      Content = resources;
+      HiveAdminClient.Instance.Refresh();
+      Content = HiveAdminClient.Instance.Resources;
+    }
+
+    private void UpdateResourcesAsync() {
+      TS.Task.Factory.StartNew(UpdateResources).ContinueWith((t) => {
+        DisplayError(t.Exception);
+      }, TaskContinuationOptions.OnlyOnFaulted);
     }
 
     private void UpdateSchedule() {
-      Guid resourceId = scheduleView.ResourceId;
-      if (resourceId != null) {
-        ServiceLocator.Instance.CallHiveService(service => {
-          var appointments = service.GetDowntimesForResource(resourceId);
-          ItemList<Downtime> ias = new ItemList<Downtime>();
-          appointments.ForEach(a => ias.Add(a));
-          scheduleView.Invoke(new Action(() => scheduleView.Content = ias));
-        });
-      }
+      HiveAdminClient.Instance.RefreshCalendar();
+      scheduleView.Invoke(new Action(() => scheduleView.Content = HiveAdminClient.Instance.Downtimes));
+    }
+
+    private void UpdateScheduleAsync() {
+      TS.Task.Factory.StartNew(UpdateSchedule).ContinueWith((t) => {
+        DisplayError(t.Exception);
+      }, TaskContinuationOptions.OnlyOnFaulted);
+    }
+
+    private void DisplayError(Exception ex) {
+      MessageBox.Show("An error occured updating the schedule: " + Environment.NewLine + ex.ToString(), "HeuristicLab Hive Administrator");
     }
 
     private void tabSlaveGroup_SelectedIndexChanged(object sender, EventArgs e) {
       if (tabSlaveGroup.SelectedIndex == 1) {
-        UpdateSchedule();
+        UpdateScheduleAsync();
       }
     }
Index: /branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Administrator/3.3/Views/ScheduleView.cs
===================================================================
--- /branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Administrator/3.3/Views/ScheduleView.cs	(revision 6755)
+++ /branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Administrator/3.3/Views/ScheduleView.cs	(revision 6756)
@@ -32,5 +32,5 @@
 
 namespace HeuristicLab.Clients.Hive.Administrator.Views {
-  [View("ScheduleView")]
+  [View("Schedule View")]
   [Content(typeof(IItemList<Downtime>), IsDefaultView = true)]
   public partial class ScheduleView : ItemView {
@@ -47,14 +47,4 @@
     public delegate void OnDialogClosedDelegate(RecurrentEvent e);
 
-    private Guid resourceId;
-    public Guid ResourceId {
-      get {
-        return resourceId;
-      }
-      set {
-        resourceId = value;
-      }
-    }
-
     public ScheduleView() {
       InitializeComponent();
@@ -93,17 +83,8 @@
     private void UpdateCalendarFromContent() {
       offlineTimes.Clear();
-      foreach (Downtime app in Content) {
-        offlineTimes.Add(new HiveAppointment {
-          AllDayEvent = app.AllDayEvent,
-          EndDate = app.EndDate,
-          StartDate = app.StartDate,
-          Recurring = app.Recurring,
-          RecurringId = app.RecurringId,
-          BorderColor = Color.Red,
-          Locked = true,
-          Subject = "Offline",
-          Changed = false,
-          Id = app.Id
-        });
+      if (Content != null) {
+        foreach (Downtime app in Content) {
+          offlineTimes.Add(ToHiveAppointment(app));
+        }
       }
       dvOnline.Invalidate();
@@ -233,10 +214,8 @@
     #region Register Content Events
     protected override void DeregisterContentEvents() {
-      // TODO: Deregister your event handlers on the Content here
       base.DeregisterContentEvents();
     }
     protected override void RegisterContentEvents() {
       base.RegisterContentEvents();
-      // TODO: Register your event handlers on the Content here
     }
     #endregion
@@ -244,14 +223,9 @@
     protected override void OnContentChanged() {
       base.OnContentChanged();
-      if (Content == null) {
-        // TODO: Put code here when content is null
-      } else {
-        UpdateCalendarFromContent();
-      }
+      UpdateCalendarFromContent();
     }
 
     protected override void SetEnabledStateOfControls() {
       base.SetEnabledStateOfControls();
-      // TODO: Put code here to enable or disable controls based on whether the Content is/not null or the view is ReadOnly
     }
 
@@ -333,31 +307,44 @@
       List<Downtime> appointments = new List<Downtime>();
       foreach (HiveAppointment app in offlineTimes) {
-        if (app.Deleted) {
-          ServiceLocator.Instance.CallHiveService(service => {
-            if (app.Id != Guid.Empty) {
-              service.DeleteDowntime(app.Id);
-            }
-          });
-        } else if (app.Changed) {
-          Downtime apdto = new Downtime {
-            AllDayEvent = app.AllDayEvent,
-            EndDate = app.EndDate,
-            Recurring = app.Recurring,
-            RecurringId = app.RecurringId,
-            StartDate = app.StartDate,
-            ResourceId = resourceId
-          };
-          appointments.Add(apdto);
-        }
-      }
-
-      if (appointments.Count > 0) {
-        //TODO: find a sane way to do this
-        ServiceLocator.Instance.CallHiveService(service => {
-          foreach (Downtime app in appointments) {
-            service.AddDowntime(app);
-          }
-        });
-      }
+        if (app.Deleted && app.Id != Guid.Empty) {
+          HiveAdminClient.Delete(ToDowntime(app));
+        } else if (app.Changed || app.Id == null || app.Id == Guid.Empty) {
+          Downtime dt = ToDowntime(app);
+          appointments.Add(dt);
+        }
+      }
+      foreach (Downtime dt in appointments) {
+        dt.Store();
+      }
+    }
+
+    private HiveAppointment ToHiveAppointment(Downtime downtime) {
+      HiveAppointment app = new HiveAppointment {
+        AllDayEvent = downtime.AllDayEvent,
+        EndDate = downtime.EndDate,
+        StartDate = downtime.StartDate,
+        Recurring = downtime.Recurring,
+        RecurringId = downtime.RecurringId,
+        Deleted = false,
+        BorderColor = Color.Red,
+        Locked = true,
+        Subject = "Offline",
+        Changed = downtime.Modified,
+        Id = downtime.Id
+      };
+      return app;
+    }
+
+    private Downtime ToDowntime(HiveAppointment app) {
+      Downtime downtime = new Downtime {
+        AllDayEvent = app.AllDayEvent,
+        EndDate = app.EndDate,
+        StartDate = app.StartDate,
+        Recurring = app.Recurring,
+        RecurringId = app.RecurringId,
+        ResourceId = HiveAdminClient.Instance.DowntimeForResourceId,
+        Id = app.Id
+      };
+      return downtime;
     }
   }
Index: /branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive/3.3/HeuristicLab.Clients.Hive-3.3.csproj
===================================================================
--- /branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive/3.3/HeuristicLab.Clients.Hive-3.3.csproj	(revision 6755)
+++ /branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive/3.3/HeuristicLab.Clients.Hive-3.3.csproj	(revision 6756)
@@ -112,4 +112,5 @@
   </ItemGroup>
   <ItemGroup>
+    <Compile Include="HiveAdminClient.cs" />
     <Compile Include="HiveClient.cs" />
     <Compile Include="Settings.Designer.cs">
@@ -120,5 +121,5 @@
     <Compile Include="Tasks\ItemTask.cs" />
     <Compile Include="RefreshableJob.cs" />
-    <Compile Include="ServiceClients\HiveExperimentPermission.cs" />
+    <Compile Include="ServiceClients\JobPermission.cs" />
     <Compile Include="StateLogList.cs" />
     <Compile Include="StateLogListList.cs" />
@@ -167,5 +168,5 @@
     <Compile Include="ServiceClients\Resource.cs" />
     <Compile Include="ServiceClients\StateLog.cs" />
-    <Compile Include="ServiceClients\HiveExperiment.cs" />
+    <Compile Include="ServiceClients\Job.cs" />
     <Compile Include="ServiceClients\SlaveGroup.cs" />
     <Compile Include="ServiceClients\Slave.cs" />
Index: /branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive/3.3/HiveAdminClient.cs
===================================================================
--- /branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive/3.3/HiveAdminClient.cs	(revision 6756)
+++ /branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive/3.3/HiveAdminClient.cs	(revision 6756)
@@ -0,0 +1,214 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2011 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.Threading;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+
+namespace HeuristicLab.Clients.Hive {
+  [Item("Hive Administrator", "Hive Administrator")]
+  public sealed class HiveAdminClient : IContent {
+    private static HiveAdminClient instance;
+    public static HiveAdminClient Instance {
+      get {
+        if (instance == null) instance = new HiveAdminClient();
+        return instance;
+      }
+    }
+
+    private IItemList<Resource> resources;
+    public IItemList<Resource> Resources {
+      get { return resources; }
+    }
+
+    private IItemList<Downtime> downtimes;
+    public IItemList<Downtime> Downtimes {
+      get { return downtimes; }
+    }
+
+    private Guid downtimeForResourceId;
+    public Guid DowntimeForResourceId {
+      get { return downtimeForResourceId; }
+      set {
+        downtimeForResourceId = value;
+        if (downtimes != null) {
+          downtimes.Clear();
+        }
+        OnDowntimesChanged();
+      }
+    }
+
+    #region Events
+    public event EventHandler Refreshing;
+    private void OnRefreshing() {
+      EventHandler handler = Refreshing;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+    public event EventHandler Refreshed;
+    private void OnRefreshed() {
+      var handler = Refreshed;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+    public event EventHandler DowntimesChanged;
+    private void OnDowntimesChanged() {
+      var handler = DowntimesChanged;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+    #endregion
+
+    private HiveAdminClient() { }
+
+    #region Refresh
+    public void Refresh() {
+      OnRefreshing();
+
+      try {
+        resources = new ItemList<Resource>();
+
+        ServiceLocator.Instance.CallHiveService(service => {
+          service.GetSlaveGroups().ForEach(g => resources.Add(g));
+          service.GetSlaves().ForEach(s => resources.Add(s));
+        });
+      }
+      catch {
+        throw;
+      }
+      finally {
+        OnRefreshed();
+      }
+    }
+    public void RefreshAsync(Action<Exception> exceptionCallback) {
+      var call = new Func<Exception>(delegate() {
+        try {
+          Refresh();
+        }
+        catch (Exception ex) {
+          return ex;
+        }
+        return null;
+      });
+      call.BeginInvoke(delegate(IAsyncResult result) {
+        Exception ex = call.EndInvoke(result);
+        if (ex != null) exceptionCallback(ex);
+      }, null);
+    }
+    #endregion
+
+    #region Refresh downtime calendar
+    public void RefreshCalendar() {
+      if (downtimeForResourceId != null && downtimeForResourceId != Guid.Empty) {
+        OnRefreshing();
+
+        try {
+          downtimes = new ItemList<Downtime>();
+
+          ServiceLocator.Instance.CallHiveService(service => {
+            service.GetDowntimesForResource(downtimeForResourceId).ForEach(d => downtimes.Add(d));
+          });
+        }
+        catch {
+          throw;
+        }
+        finally {
+          OnRefreshed();
+        }
+      }
+    }
+    public void RefreshCalendarAsync(Action<Exception> exceptionCallback) {
+      var call = new Func<Exception>(delegate() {
+        try {
+          RefreshCalendar();
+        }
+        catch (Exception ex) {
+          return ex;
+        }
+        return null;
+      });
+      call.BeginInvoke(delegate(IAsyncResult result) {
+        Exception ex = call.EndInvoke(result);
+        if (ex != null) exceptionCallback(ex);
+      }, null);
+    }
+    #endregion
+
+    #region Store
+    public static void Store(IHiveItem item, CancellationToken cancellationToken) {
+      if (item.Id == Guid.Empty) {
+        if (item is SlaveGroup) {
+          item.Id = ServiceLocator.Instance.CallHiveService((s) => s.AddSlaveGroup((SlaveGroup)item));
+        }
+        if (item is Slave) {
+          item.Id = ServiceLocator.Instance.CallHiveService((s) => s.AddSlave((Slave)item));
+        }
+        if (item is Downtime) {
+          item.Id = ServiceLocator.Instance.CallHiveService((s) => s.AddDowntime((Downtime)item));
+        }
+      } else {
+        if (item is SlaveGroup) {
+          ServiceLocator.Instance.CallHiveService((s) => s.UpdateSlaveGroup((SlaveGroup)item));
+        }
+        if (item is Slave) {
+          ServiceLocator.Instance.CallHiveService((s) => s.UpdateSlave((Slave)item));
+        }
+        if (item is Downtime) {
+          ServiceLocator.Instance.CallHiveService((s) => s.UpdateDowntime((Downtime)item));
+        }
+      }
+    }
+    public static void StoreAsync(Action<Exception> exceptionCallback, IHiveItem item, CancellationToken cancellationToken) {
+      var call = new Func<Exception>(delegate() {
+        try {
+          Store(item, cancellationToken);
+        }
+        catch (Exception ex) {
+          return ex;
+        }
+        return null;
+      });
+      call.BeginInvoke(delegate(IAsyncResult result) {
+        Exception ex = call.EndInvoke(result);
+        if (ex != null) exceptionCallback(ex);
+      }, null);
+    }
+    #endregion
+
+    #region Delete
+    public static void Delete(IHiveItem item) {
+      if (item is SlaveGroup) {
+        ServiceLocator.Instance.CallHiveService((s) => s.DeleteSlaveGroup(item.Id));
+      } else if (item is Slave) {
+        ServiceLocator.Instance.CallHiveService((s) => s.DeleteSlave(item.Id));
+      } else if (item is Downtime) {
+        ServiceLocator.Instance.CallHiveService((s) => s.DeleteDowntime(item.Id));
+      }
+    }
+    #endregion
+
+    public void ResetDowntime() {
+      downtimeForResourceId = Guid.Empty;
+      if (downtimes != null) {
+        downtimes.Clear();
+      }
+      OnDowntimesChanged();
+    }
+  }
+}
Index: /branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive/3.3/HiveClient.cs
===================================================================
--- /branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive/3.3/HiveClient.cs	(revision 6755)
+++ /branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive/3.3/HiveClient.cs	(revision 6756)
@@ -75,5 +75,5 @@
     #endregion
 
-    public HiveClient() { }
+    private HiveClient() { }
 
     #region Refresh
@@ -101,10 +101,10 @@
         }
         // remove those which were not in the list of loaded hiveexperiments
-        foreach (var experiment in oldJobs) {
-          if (experiment.Id == Guid.Empty) {
+        foreach (var job in oldJobs) {
+          if (job.Id == Guid.Empty) {
             // experiment not uploaded... keep
-            jobs.Add(experiment);
+            jobs.Add(job);
           } else {
-            experiment.RefreshAutomatically = false; // stop results polling
+            job.RefreshAutomatically = false; // stop results polling
           }
         }
Index: /branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive/3.3/ServiceClients/Downtime.cs
===================================================================
--- /branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive/3.3/ServiceClients/Downtime.cs	(revision 6755)
+++ /branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive/3.3/ServiceClients/Downtime.cs	(revision 6756)
@@ -27,4 +27,9 @@
     public Downtime() { }
 
+    public override void Store() {
+      HiveAdminClient.Store(this, new System.Threading.CancellationToken());
+      Modified = false;
+    }
+
     protected Downtime(Downtime original, Cloner cloner)
       : base(original, cloner) {
Index: /branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive/3.3/ServiceClients/HiveItem.cs
===================================================================
--- /branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive/3.3/ServiceClients/HiveItem.cs	(revision 6755)
+++ /branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive/3.3/ServiceClients/HiveItem.cs	(revision 6756)
@@ -85,5 +85,5 @@
     #endregion
 
-    public void Store() {
+    public virtual void Store() {
       HiveClient.Store(this, new System.Threading.CancellationToken());
       Modified = false;
Index: /branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive/3.3/ServiceClients/Job.cs
===================================================================
--- /branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive/3.3/ServiceClients/Job.cs	(revision 6756)
+++ /branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive/3.3/ServiceClients/Job.cs	(revision 6756)
@@ -0,0 +1,87 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2011 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.ComponentModel;
+using HeuristicLab.Common;
+
+namespace HeuristicLab.Clients.Hive {
+  public partial class Job : IDeepCloneable, IContent {
+
+    private bool isPrivileged;
+    public bool IsPrivileged {
+      get { return isPrivileged; }
+      set { isPrivileged = value; }
+    }
+
+    #region Constructors and Cloning
+    public Job() {
+      this.ResourceNames = "HEAL";
+      this.DateCreated = DateTime.Now;
+      this.Permission = Permission.Full;
+    }
+
+    protected Job(Job original, Cloner cloner) {
+      cloner.RegisterClonedObject(original, this);
+      this.OwnerUserId = original.OwnerUserId;
+      this.DateCreated = original.DateCreated;
+      this.ResourceNames = original.ResourceNames;
+      this.LastAccessed = original.LastAccessed;
+      this.Name = original.Name;
+      this.Description = original.Description;
+      this.Id = original.Id;
+      this.IsPrivileged = original.IsPrivileged;
+      this.Permission = original.Permission;
+    }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new Job(this, cloner);
+    }
+    #endregion
+
+    #region Events
+    public event EventHandler StateLogListChanged;
+    private void OnStateLogListChanged() {
+      var handler = StateLogListChanged;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+    #endregion
+
+    protected override void OnPropertyChanged(PropertyChangedEventArgs e) {
+      base.OnPropertyChanged(e);
+      if (e.PropertyName == "Name") {
+        OnToStringChanged();
+      }
+    }
+
+    protected override void RaisePropertyChanged(string propertyName) {
+      if (!(propertyName == "ExecutionTime")
+        && !(propertyName == "JobCount")
+        && !(propertyName == "CalculatingCount")
+        && !(propertyName == "FinishedCount")) {
+        base.RaisePropertyChanged(propertyName);
+      }
+    }
+
+    public override string ToString() {
+      return Name;
+    }
+  }
+}
Index: /branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive/3.3/ServiceClients/JobPermission.cs
===================================================================
--- /branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive/3.3/ServiceClients/JobPermission.cs	(revision 6756)
+++ /branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive/3.3/ServiceClients/JobPermission.cs	(revision 6756)
@@ -0,0 +1,65 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2011 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.ComponentModel;
+using HeuristicLab.Common;
+
+namespace HeuristicLab.Clients.Hive {
+  public partial class JobPermission : IDeepCloneable, IContent {
+
+    private string grantedUserName;
+    public string GrantedUserName {
+      get { return grantedUserName; }
+      set {
+        if (value != grantedUserName) {
+          grantedUserName = value;
+          RaisePropertyChanged("GrantedUserName");
+        }
+      }
+    }
+
+    #region Constructors and Cloning
+    public JobPermission() {
+      this.Permission = Permission.Read;
+      this.PropertyChanged += new PropertyChangedEventHandler(HiveExperimentPermission_PropertyChanged);
+    }
+
+    protected JobPermission(JobPermission original, Cloner cloner)
+      : base(original, cloner) {
+      this.GrantedByUserId = original.GrantedByUserId;
+      this.GrantedUserId = original.GrantedUserId;
+      this.JobId = original.JobId;
+      this.Permission = original.Permission;
+    }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new JobPermission(this, cloner);
+    }
+    #endregion
+
+    private void HiveExperimentPermission_PropertyChanged(object sender, PropertyChangedEventArgs e) {
+      OnToStringChanged();
+    }
+
+    public override string ToString() {
+      return string.Format("{0}: {1}", GrantedUserName, Permission.ToString());
+    }
+  }
+}
Index: /branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive/3.3/ServiceClients/Resource.cs
===================================================================
--- /branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive/3.3/ServiceClients/Resource.cs	(revision 6755)
+++ /branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive/3.3/ServiceClients/Resource.cs	(revision 6756)
@@ -28,4 +28,9 @@
     public Resource() { }
 
+    public override void Store() {
+      HiveAdminClient.Store(this, new System.Threading.CancellationToken());
+      Modified = false;
+    }
+
     protected Resource(Resource original, Cloner cloner)
       : base(original, cloner) {
Index: /branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Services.Hive.DataAccess/3.3/Enums/Permission.cs
===================================================================
--- /branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Services.Hive.DataAccess/3.3/Enums/Permission.cs	(revision 6755)
+++ /branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Services.Hive.DataAccess/3.3/Enums/Permission.cs	(revision 6756)
@@ -31,10 +31,10 @@
 
     /// <summary>
-    /// User can only download and view experiments
+    /// User can only download and view jobs
     /// </summary>
     Read,
 
     /// <summary>
-    /// User can pause, stop, restart, delete experiment. can also grant other 
+    /// User can pause, stop, restart, delete jobs. can also grant other 
     /// </summary>
     Full
Index: /branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Services.Hive/3.3/HiveDao.cs
===================================================================
--- /branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Services.Hive/3.3/HiveDao.cs	(revision 6755)
+++ /branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Services.Hive/3.3/HiveDao.cs	(revision 6756)
@@ -233,9 +233,9 @@
     public DT.Job GetJob(Guid id) {
       using (var db = CreateContext()) {
-        return AddStatsToExperiment(db, DT.Convert.ToDto(db.Jobs.SingleOrDefault(x => x.JobId == id)));
-      }
-    }
-
-    private DT.Job AddStatsToExperiment(HiveDataContext db, DT.Job exp) {
+        return AddStatsToJob(db, DT.Convert.ToDto(db.Jobs.SingleOrDefault(x => x.JobId == id)));
+      }
+    }
+
+    private DT.Job AddStatsToJob(HiveDataContext db, DT.Job exp) {
       if (exp == null)
         return null;
@@ -250,5 +250,5 @@
     public IEnumerable<DT.Job> GetJobs(Expression<Func<Job, bool>> predicate) {
       using (var db = CreateContext()) {
-        return db.Jobs.Where(predicate).Select(x => AddStatsToExperiment(db, DT.Convert.ToDto(x))).ToArray();
+        return db.Jobs.Where(predicate).Select(x => AddStatsToJob(db, DT.Convert.ToDto(x))).ToArray();
       }
     }
