Index: branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Clients.Hive/3.3/HeuristicLab.Clients.Hive-3.3.csproj
===================================================================
--- branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Clients.Hive/3.3/HeuristicLab.Clients.Hive-3.3.csproj	(revision 15962)
+++ branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Clients.Hive/3.3/HeuristicLab.Clients.Hive-3.3.csproj	(revision 16386)
@@ -125,4 +125,7 @@
     <Compile Include="HiveAdminClient.cs" />
     <Compile Include="HiveClient.cs" />
+    <Compile Include="ServiceClients\AssignedJobResource.cs" />
+    <Compile Include="ServiceClients\AssignedProjectResource.cs" />
+    <Compile Include="ServiceClients\Project.cs" />
     <Compile Include="ServiceClients\UserPriority.cs" />
     <Compile Include="ServiceClients\ResourcePermission.cs" />
@@ -194,4 +197,8 @@
   </ItemGroup>
   <ItemGroup>
+    <ProjectReference Include="..\..\HeuristicLab.Clients.Access\3.3\HeuristicLab.Clients.Access-3.3.csproj">
+      <Project>{494F87F4-0F25-4D33-A382-10CDB2174D48}</Project>
+      <Name>HeuristicLab.Clients.Access-3.3</Name>
+    </ProjectReference>
     <ProjectReference Include="..\..\HeuristicLab.Clients.Common\3.3\HeuristicLab.Clients.Common-3.3.csproj">
       <Project>{730A9104-D4D1-4360-966B-E49B7571DDA3}</Project>
Index: branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Clients.Hive/3.3/HiveAdminClient.cs
===================================================================
--- branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Clients.Hive/3.3/HiveAdminClient.cs	(revision 15962)
+++ branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Clients.Hive/3.3/HiveAdminClient.cs	(revision 16386)
@@ -24,4 +24,7 @@
 using HeuristicLab.Common;
 using HeuristicLab.Core;
+using System.Collections.Generic;
+using System.Linq;
+using HeuristicLab.Clients.Access;
 
 namespace HeuristicLab.Clients.Hive {
@@ -36,4 +39,5 @@
     }
 
+    #region Properties
     private IItemList<Resource> resources;
     public IItemList<Resource> Resources {
@@ -57,4 +61,69 @@
     }
 
+    private IItemList<Project> projects;
+    public IItemList<Project> Projects {
+      get { return projects; }
+    }
+
+    private IItemList<AssignedProjectResource> projectResourceAssignments;
+    public IItemList<AssignedProjectResource> ProjectResourceAssignments {
+      get { return projectResourceAssignments; }
+    }
+
+    private Dictionary<Guid, HiveItemCollection<RefreshableJob>> jobs;
+    public Dictionary<Guid, HiveItemCollection<RefreshableJob>> Jobs {
+      get { return jobs; }
+      set {
+        if (value != jobs)
+          jobs = value;
+        }
+    }
+
+    private Dictionary<Guid, List<LightweightTask>> tasks;
+    public Dictionary<Guid, List<LightweightTask>> Tasks {
+      get { return tasks; }
+    }
+
+    private Dictionary<Guid, HashSet<Guid>> projectAncestors;
+    public Dictionary<Guid, HashSet<Guid>> ProjectAncestors {
+      get { return projectAncestors; }
+    }
+
+    private Dictionary<Guid, HashSet<Guid>> projectDescendants;
+    public Dictionary<Guid, HashSet<Guid>> ProjectDescendants {
+      get { return projectDescendants; }
+    }
+
+    private Dictionary<Guid, HashSet<Guid>> resourceAncestors;
+    public Dictionary<Guid, HashSet<Guid>> ResourceAncestors {
+      get { return resourceAncestors; }
+    }
+
+    private Dictionary<Guid, HashSet<Guid>> resourceDescendants;
+    public Dictionary<Guid, HashSet<Guid>> ResourceDescendants {
+      get { return resourceDescendants; }
+    }
+
+    private Dictionary<Guid, string> projectNames;
+    public Dictionary<Guid, string> ProjectNames {
+      get { return projectNames; }
+    }
+
+    private HashSet<Project> disabledParentProjects;
+    public HashSet<Project> DisabledParentProjects {
+      get { return disabledParentProjects; }
+    }
+
+    private Dictionary<Guid, string> resourceNames;
+    public Dictionary<Guid, string> ResourceNames {
+      get { return resourceNames; }
+    }
+
+    private HashSet<Resource> disabledParentResources;
+    public HashSet<Resource> DisabledParentResources {
+      get { return disabledParentResources; }
+    }
+    #endregion
+
     #region Events
     public event EventHandler Refreshing;
@@ -78,9 +147,44 @@
       try {
         resources = new ItemList<Resource>();
+        projects = new ItemList<Project>();
+        projectResourceAssignments = new ItemList<AssignedProjectResource>();
+        jobs = new Dictionary<Guid, HiveItemCollection<RefreshableJob>>();
+        tasks = new Dictionary<Guid, List<LightweightTask>>();
+        projectNames = new Dictionary<Guid, string>();
+        resourceNames = new Dictionary<Guid, string>();
+
+        projectAncestors = new Dictionary<Guid, HashSet<Guid>>();
+        projectDescendants = new Dictionary<Guid, HashSet<Guid>>();
+        resourceAncestors = new Dictionary<Guid, HashSet<Guid>>();
+        resourceDescendants = new Dictionary<Guid, HashSet<Guid>>();
 
         HiveServiceLocator.Instance.CallHiveService(service => {
-          service.GetSlaveGroups().ForEach(g => resources.Add(g));
-          service.GetSlaves().ForEach(s => resources.Add(s));
+          service.GetSlaveGroupsForAdministration().ForEach(g => resources.Add(g));
+          service.GetSlavesForAdministration().ForEach(s => resources.Add(s));
+          service.GetProjectsForAdministration().ForEach(p => projects.Add(p));
+          var projectIds = projects.Select(p => p.Id).ToList();
+          if (projectIds.Any()) {
+            service.GetAssignedResourcesForProjectsAdministration(projectIds)
+              .ForEach(a => projectResourceAssignments.Add(a));
+            projectIds.ForEach(p => jobs.Add(p, new HiveItemCollection<RefreshableJob>()));
+            var unsortedJobs = service.GetJobsByProjectIds(projectIds)
+              .OrderBy(x => x.DateCreated).ToList();
+
+            unsortedJobs.Where(j => j.State == JobState.DeletionPending).ToList().ForEach(j => jobs[j.ProjectId].Add(new RefreshableJob(j)));
+            unsortedJobs.Where(j => j.State == JobState.StatisticsPending).ToList().ForEach(j => jobs[j.ProjectId].Add(new RefreshableJob(j)));
+            unsortedJobs.Where(j => j.State == JobState.Online).ToList().ForEach(j => jobs[j.ProjectId].Add(new RefreshableJob(j)));
+
+            foreach (var job in jobs.SelectMany(x => x.Value))
+              LoadLightweightJob(job);
+
+            projectNames = service.GetProjectNames();
+            resourceNames = service.GetResourceNames();
+          }
         });
+
+        UpdateResourceGenealogy();
+        UpdateProjectGenealogy();
+        RefreshDisabledParentProjects();
+        RefreshDisabledParentResources();
       }
       catch {
@@ -91,4 +195,199 @@
       }
     }
+
+    //public void UpdateResourceGenealogy(IItemList<Resource> resources) {
+    //  resourceAncestors.Clear();
+    //  resourceDescendants.Clear();
+
+    //  foreach (var r in resources) {
+    //    resourceAncestors.Add(r.Id, new HashSet<Resource>());
+    //    resourceDescendants.Add(r.Id, new HashSet<Resource>());
+    //  }
+
+    //  foreach (var r in resources) {
+    //    var parentResourceId = r.ParentResourceId;
+    //    while (parentResourceId != null) {
+    //      var parent = resources.SingleOrDefault(x => x.Id == parentResourceId);
+    //      if (parent != null) {
+    //        resourceAncestors[r.Id].Add(parent);
+    //        resourceDescendants[parent.Id].Add(r);
+    //        parentResourceId = parent.ParentResourceId;
+    //      } else {
+    //        parentResourceId = null;
+    //      }
+    //    }
+    //  }
+    //}
+
+    //public void UpdateProjectGenealogy(IItemList<Project> projects) {
+    //  projectAncestors.Clear();
+    //  projectDescendants.Clear();
+
+    //  foreach (var p in projects) {
+    //    projectAncestors.Add(p.Id, new HashSet<Project>());
+    //    projectDescendants.Add(p.Id, new HashSet<Project>());
+    //  }
+
+    //  foreach (var p in projects) {
+    //    var parentProjectId = p.ParentProjectId;
+    //    while (parentProjectId != null) {
+    //      var parent = projects.SingleOrDefault(x => x.Id == parentProjectId);
+    //      if (parent != null) {
+    //        projectAncestors[p.Id].Add(parent);
+    //        projectDescendants[parent.Id].Add(p);
+    //        parentProjectId = parent.ParentProjectId;
+    //      } else {
+    //        parentProjectId = null;
+    //      }
+    //    }
+    //  }
+    //}
+
+    private void UpdateResourceGenealogy() {
+      resourceAncestors.Clear();
+      resourceDescendants.Clear();
+
+      // fetch resource ancestor set
+      HiveServiceLocator.Instance.CallHiveService(service => {
+        var ra = service.GetResourceGenealogy();
+        ra.Keys.ToList().ForEach(k => resourceAncestors.Add(k, new HashSet<Guid>()));
+        resourceAncestors.Keys.ToList().ForEach(k => resourceAncestors[k].UnionWith(ra[k]));
+      });
+
+      // build resource descendant set
+      resourceAncestors.Keys.ToList().ForEach(k => resourceDescendants.Add(k, new HashSet<Guid>()));
+      foreach (var ra in resourceAncestors) {
+        foreach (var ancestor in ra.Value) {
+          resourceDescendants[ancestor].Add(ra.Key);
+        }
+      }
+    }
+
+    private void UpdateProjectGenealogy() {
+      projectAncestors.Clear();
+      projectDescendants.Clear();
+
+      // fetch project ancestor list
+      HiveServiceLocator.Instance.CallHiveService(service => {
+        var pa = service.GetProjectGenealogy();
+        pa.Keys.ToList().ForEach(k => projectAncestors.Add(k, new HashSet<Guid>()));
+        projectAncestors.Keys.ToList().ForEach(k => projectAncestors[k].UnionWith(pa[k]));
+      });
+
+      // build project descendant list
+      projectAncestors.Keys.ToList().ForEach(k => projectDescendants.Add(k, new HashSet<Guid>()));
+      foreach (var pa in projectAncestors) {
+        foreach (var ancestor in pa.Value) {
+          projectDescendants[ancestor].Add(pa.Key);
+        }
+      }
+    }
+
+    private void RefreshDisabledParentProjects() {
+      disabledParentProjects = new HashSet<Project>();
+
+      foreach (var pid in projects
+        .Where(x => x.ParentProjectId.HasValue)
+        .SelectMany(x => projectAncestors[x.Id]).Distinct()
+        .Where(x => !projects.Select(y => y.Id).Contains(x))) {
+        var p = new Project();
+        p.Id = pid;
+        p.ParentProjectId = projectAncestors[pid].FirstOrDefault();
+        p.Name = projectNames[pid];
+        disabledParentProjects.Add(p);
+      }
+    }
+
+    private void RefreshDisabledParentResources() {
+      disabledParentResources = new HashSet<Resource>();
+
+      foreach (var rid in resources
+        .Where(x => x.ParentResourceId.HasValue)
+        .SelectMany(x => resourceAncestors[x.Id]).Distinct()
+        .Where(x => !resources.Select(y => y.Id).Contains(x))) {
+        var r = new SlaveGroup();
+        r.Id = rid;
+        r.ParentResourceId = resourceAncestors[rid].FirstOrDefault();
+        r.Name = resourceNames[rid];
+        disabledParentResources.Add(r);
+      }
+    }
+
+    public void RefreshJobs() {
+      var projectIds = new List<Guid>();
+      jobs = new Dictionary<Guid, HiveItemCollection<RefreshableJob>>();
+      tasks = new Dictionary<Guid, List<LightweightTask>>();
+
+      HiveServiceLocator.Instance.CallHiveService(service => {
+        service.GetProjectsForAdministration().ForEach(p => projectIds.Add(p.Id));
+        if(projectIds.Any()) {
+          projectIds.ForEach(p => jobs.Add(p, new HiveItemCollection<RefreshableJob>()));
+          var unsortedJobs = service.GetJobsByProjectIds(projectIds)
+            .OrderBy(x => x.DateCreated).ToList();
+          
+          unsortedJobs.Where(j => j.State == JobState.DeletionPending).ToList().ForEach(j => jobs[j.ProjectId].Add(new RefreshableJob(j)));
+          unsortedJobs.Where(j => j.State == JobState.StatisticsPending).ToList().ForEach(j => jobs[j.ProjectId].Add(new RefreshableJob(j)));
+          unsortedJobs.Where(j => j.State == JobState.Online).ToList().ForEach(j => jobs[j.ProjectId].Add(new RefreshableJob(j)));
+
+          foreach(var job in jobs.SelectMany(x => x.Value))
+            LoadLightweightJob(job);
+        }
+      });
+    }
+
+    public void LoadLightweightJob(RefreshableJob refreshableJob) {
+      var job = refreshableJob.Job;
+      var lightweightTasks = HiveServiceLocator.Instance.CallHiveService(s => s.GetLightweightJobTasksWithoutStateLog(job.Id));
+
+      if (tasks.ContainsKey(job.Id)) {
+        tasks[job.Id].Clear();
+        tasks[job.Id].AddRange(lightweightTasks);
+      } else {
+        tasks.Add(job.Id, new List<LightweightTask>(lightweightTasks));        
+      }
+
+      if (lightweightTasks != null && lightweightTasks.Count > 0 && lightweightTasks.All(x => x.Id != Guid.Empty)) {
+        if (lightweightTasks.All(x =>
+          x.State == TaskState.Finished 
+          || x.State == TaskState.Aborted 
+          || x.State == TaskState.Failed)) {
+          refreshableJob.ExecutionState = ExecutionState.Stopped;
+          refreshableJob.RefreshAutomatically = false;
+        } else if (
+          lightweightTasks
+            .Where(x => x.ParentTaskId != null)
+            .All(x =>
+              x.State != TaskState.Waiting
+              || x.State != TaskState.Transferring
+              || x.State != TaskState.Calculating)
+          && lightweightTasks
+             .Where(x => x.ParentTaskId != null)
+             .Any(x => x.State == TaskState.Paused)) {
+          refreshableJob.ExecutionState = ExecutionState.Paused;
+          refreshableJob.RefreshAutomatically = false;
+        } else if (lightweightTasks.Any(x => x.State == TaskState.Calculating 
+                                  || x.State == TaskState.Transferring 
+                                  || x.State == TaskState.Waiting)) {
+          refreshableJob.ExecutionState = ExecutionState.Started;
+        }
+
+        refreshableJob.ExecutionTime = TimeSpan.FromMilliseconds(lightweightTasks.Sum(x => x.ExecutionTime.TotalMilliseconds));
+      }
+    }
+
+    public void SortJobs() {
+      for(int i = 0; i < jobs.Count; i++) {
+        var projectId = jobs.Keys.ElementAt(i);
+        var unsortedJobs = jobs.Values.ElementAt(i);
+
+        var sortedJobs = new HiveItemCollection<RefreshableJob>();
+        sortedJobs.AddRange(unsortedJobs.Where(j => j.Job.State == JobState.DeletionPending));
+        sortedJobs.AddRange(unsortedJobs.Where(j => j.Job.State == JobState.StatisticsPending));
+        sortedJobs.AddRange(unsortedJobs.Where(j => j.Job.State == JobState.Online));
+
+        jobs[projectId] = sortedJobs;
+      }
+    }
+
     #endregion
 
@@ -127,4 +426,7 @@
           item.Id = HiveServiceLocator.Instance.CallHiveService((s) => s.AddDowntime((Downtime)item));
         }
+        if (item is Project) {
+          item.Id = HiveServiceLocator.Instance.CallHiveService(s => s.AddProject((Project)item));
+        }
       } else {
         if (item is SlaveGroup) {
@@ -136,4 +438,7 @@
         if (item is Downtime) {
           HiveServiceLocator.Instance.CallHiveService((s) => s.UpdateDowntime((Downtime)item));
+        }
+        if (item is Project) {
+          HiveServiceLocator.Instance.CallHiveService((s) => s.UpdateProject((Project)item));
         }
       }
@@ -149,5 +454,54 @@
       } else if (item is Downtime) {
         HiveServiceLocator.Instance.CallHiveService((s) => s.DeleteDowntime(item.Id));
-      }
+      } else if (item is Project) {
+        HiveServiceLocator.Instance.CallHiveService((s) => s.DeleteProject(item.Id));
+      }
+    }
+
+    public static void RemoveJobs(List<Guid> jobIds) {
+      HiveServiceLocator.Instance.CallHiveService((s) => s.UpdateJobStates(jobIds, JobState.StatisticsPending));
+    }
+    #endregion
+
+    #region Job Handling
+
+    public static void ResumeJob(RefreshableJob refreshableJob) {
+      HiveServiceLocator.Instance.CallHiveService(service => {
+        var tasks = service.GetLightweightJobTasksWithoutStateLog(refreshableJob.Id);
+        foreach (var task in tasks) {
+          if (task.State == TaskState.Paused) {
+            service.RestartTask(task.Id);
+          }
+        }
+      });
+      refreshableJob.ExecutionState = ExecutionState.Started;
+    }
+
+    public static void PauseJob(RefreshableJob refreshableJob) {
+      HiveServiceLocator.Instance.CallHiveService(service => {
+        var tasks = service.GetLightweightJobTasksWithoutStateLog(refreshableJob.Id);
+        foreach (var task in tasks) {
+          if (task.State != TaskState.Finished && task.State != TaskState.Aborted && task.State != TaskState.Failed)
+            service.PauseTask(task.Id);
+        }
+      });
+      refreshableJob.ExecutionState = ExecutionState.Paused;
+    }
+
+    public static void StopJob(RefreshableJob refreshableJob) {
+      HiveServiceLocator.Instance.CallHiveService(service => {
+        var tasks = service.GetLightweightJobTasksWithoutStateLog(refreshableJob.Id);
+        foreach (var task in tasks) {
+          if (task.State != TaskState.Finished && task.State != TaskState.Aborted && task.State != TaskState.Failed)
+            service.StopTask(task.Id);
+        }
+      });
+      refreshableJob.ExecutionState = ExecutionState.Stopped;
+    }
+
+    public static void RemoveJob(RefreshableJob refreshableJob) {
+      HiveServiceLocator.Instance.CallHiveService((service) => {
+        service.UpdateJobState(refreshableJob.Id, JobState.StatisticsPending);
+      });
     }
     #endregion
@@ -159,4 +513,144 @@
       }
     }
+
+    #region Helper
+    public IEnumerable<Project> GetAvailableProjectAncestors(Guid id) {
+      if (projectAncestors.ContainsKey(id)) return projects.Where(x => projectAncestors[id].Contains(x.Id));
+      else return Enumerable.Empty<Project>();
+    }
+
+    public IEnumerable<Project> GetAvailableProjectDescendants(Guid id) {
+      if(projectDescendants.ContainsKey(id)) return projects.Where(x => projectDescendants[id].Contains(x.Id));
+      else return Enumerable.Empty<Project>();
+    }
+
+    public IEnumerable<Resource> GetAvailableResourceAncestors(Guid id) {
+      if (resourceAncestors.ContainsKey(id)) return resources.Where(x => resourceAncestors[id].Contains(x.Id));
+      else return Enumerable.Empty<Resource>();
+    }
+
+    public IEnumerable<Resource> GetAvailableResourceDescendants(Guid id) {
+      if (resourceDescendants.ContainsKey(id)) return resources.Where(x => resourceDescendants[id].Contains(x.Id));
+      else return Enumerable.Empty<Resource>();
+    }
+
+    public IEnumerable<Resource> GetDisabledResourceAncestors(IEnumerable<Resource> availableResources) {
+      var missingParentIds = availableResources
+        .Where(x => x.ParentResourceId.HasValue)
+        .SelectMany(x => resourceAncestors[x.Id]).Distinct()
+        .Where(x => !availableResources.Select(y => y.Id).Contains(x));
+
+      return resources.OfType<SlaveGroup>().Union(disabledParentResources).Where(x => missingParentIds.Contains(x.Id));
+    }
+
+    public bool CheckAccessToAdminAreaGranted() {
+      if(projects != null) {
+        return projects.Count > 0;
+      } else {
+        bool accessGranted = false;
+        HiveServiceLocator.Instance.CallHiveService(s => {
+          accessGranted = s.CheckAccessToAdminAreaGranted();
+        });
+        return accessGranted;
+      }
+    }
+
+    public bool CheckOwnershipOfResource(Resource res, Guid userId) {
+      if (res == null || userId == Guid.Empty) return false;
+
+      if (res.OwnerUserId == userId) {
+        return true;
+      } else if(resourceAncestors.ContainsKey(res.Id)) {
+        return GetAvailableResourceAncestors(res.Id).Where(x => x.OwnerUserId == userId).Any();
+      }
+
+      return false;
+    }
+
+    public bool CheckOwnershipOfProject(Project pro, Guid userId) {
+      if (pro == null || userId == Guid.Empty) return false;
+
+      if (pro.OwnerUserId == userId) {
+        return true;
+      } else if (projectAncestors.ContainsKey(pro.Id)) {
+        return GetAvailableProjectAncestors(pro.Id).Where(x => x.OwnerUserId == userId).Any();
+      }
+
+      return false;
+    }
+
+    public bool CheckOwnershipOfParentProject(Project pro, Guid userId) {
+      if (pro == null || userId == Guid.Empty) return false;
+
+      if(projectAncestors.ContainsKey(pro.Id)) {
+        return GetAvailableProjectAncestors(pro.Id).Any(x => x.OwnerUserId == userId);
+      }
+
+      if (pro.ParentProjectId != null && pro.ParentProjectId != Guid.Empty) {
+        var parent = projects.FirstOrDefault(x => x.Id == pro.ParentProjectId.Value);
+        if (parent != null)
+          return parent.OwnerUserId == userId || GetAvailableProjectAncestors(parent.Id).Any(x => x.OwnerUserId == userId);
+      }
+
+      return false;
+    }
+
+    public bool CheckParentChange(Project child, Project parent) {
+      bool changePossible = true;
+
+      // change is not possible...
+      // ... if the moved project is null
+      // ... or the new parent is not stored yet
+      // ... or there is not parental change
+      if (child == null
+          || (parent != null && parent.Id == Guid.Empty)
+          || (parent != null && parent.Id == child.ParentProjectId)) {
+        changePossible = false;
+      } else if (parent == null && !IsAdmin()) {
+        // ... if parent is null, but user is no admin (only admins are allowed to create root projects)
+        changePossible = false;
+      } else if (parent != null && (!IsAdmin() && parent.OwnerUserId != UserInformation.Instance.User.Id && !CheckOwnershipOfParentProject(parent, UserInformation.Instance.User.Id))) {
+        // ... if the user is no admin nor owner of the new parent or grand..grandparents
+        changePossible = false;
+      } else if(parent != null && projectDescendants.ContainsKey(child.Id)) {
+        // ... if the new parent is among the moved project's descendants
+        changePossible = !GetAvailableProjectDescendants(child.Id).Where(x => x.Id == parent.Id).Any();
+      }
+
+      return changePossible;
+    }
+
+    public bool CheckParentChange(Resource child, Resource parent) {
+      bool changePossible = true;
+
+      // change is not possisble...
+      // ... if the child resource is null
+      // ... or the child resource equals the parent
+      // ... or the new parent is not stored yet
+      // ... or the new parent is a slave
+      // ... or there is not parental change
+      if (child == null 
+        || child == parent
+        || (parent != null && parent.Id == Guid.Empty)
+        || (parent != null && parent is Slave)
+        || (parent != null && parent.Id == child.ParentResourceId)) {
+        changePossible = false;
+      } else if (parent != null && resourceDescendants.ContainsKey(child.Id)) {
+        // ... or if the new parent is among the moved resource's descendants
+        changePossible = !GetAvailableResourceDescendants(child.Id).Where(x => x.Id == parent.Id).Any();
+      }
+
+      return changePossible;
+    }
+
+    public IEnumerable<Resource> GetAssignedResourcesForJob(Guid jobId) {
+      var assignedJobResource =  HiveServiceLocator.Instance.CallHiveService(service => service.GetAssignedResourcesForJob(jobId));
+      return Resources.Where(x => assignedJobResource.Select(y => y.ResourceId).Contains(x.Id));
+    }
+
+    private bool IsAdmin() {
+      return HiveRoles.CheckAdminUserPermissions();
+    }
+    #endregion
   }
 }
Index: branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Clients.Hive/3.3/HiveClient.cs
===================================================================
--- branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Clients.Hive/3.3/HiveClient.cs	(revision 15962)
+++ branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Clients.Hive/3.3/HiveClient.cs	(revision 16386)
@@ -1,5 +1,5 @@
 ﻿#region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) 2002-2016 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
@@ -57,4 +57,54 @@
     }
 
+    private IItemList<Project> projects;
+    public IItemList<Project> Projects {
+      get { return projects; }
+    }
+
+    private IItemList<Resource> resources;
+    public IItemList<Resource> Resources {
+      get { return resources; }
+    }
+
+    private Dictionary<Guid, HashSet<Guid>> projectAncestors;
+    public Dictionary<Guid, HashSet<Guid>> ProjectAncestors {
+      get { return projectAncestors; }
+    }
+
+    private Dictionary<Guid, HashSet<Guid>> projectDescendants;
+    public Dictionary<Guid, HashSet<Guid>> ProjectDescendants {
+      get { return projectDescendants; }
+    }
+
+    private Dictionary<Guid, HashSet<Guid>> resourceAncestors;
+    public Dictionary<Guid, HashSet<Guid>> ResourceAncestors {
+      get { return resourceAncestors; }
+    }
+
+    private Dictionary<Guid, HashSet<Guid>> resourceDescendants;
+    public Dictionary<Guid, HashSet<Guid>> ResourceDescendants {
+      get { return resourceDescendants; }
+    }
+
+    private Dictionary<Guid, string> projectNames;
+    public Dictionary<Guid, string> ProjectNames {
+      get { return projectNames; }
+    }
+
+    private HashSet<Project> disabledParentProjects;
+    public HashSet<Project> DisabledParentProjects {
+      get { return disabledParentProjects; }
+    }
+
+    private Dictionary<Guid, string> resourceNames;
+    public Dictionary<Guid, string> ResourceNames {
+      get { return resourceNames; }
+    }
+
+    private HashSet<Resource> disabledParentResources;
+    public HashSet<Resource> DisabledParentResources {
+      get { return disabledParentResources; }
+    }
+
     private List<Plugin> onlinePlugins;
     public List<Plugin> OnlinePlugins {
@@ -93,20 +143,193 @@
 
       try {
+        projects = new ItemList<Project>();
+        resources = new ItemList<Resource>();
         jobs = new HiveItemCollection<RefreshableJob>();
-        var jobsLoaded = HiveServiceLocator.Instance.CallHiveService<IEnumerable<Job>>(s => s.GetJobs());
-
-        try {
-          foreach (var j in jobsLoaded) {
-            jobs.Add(new RefreshableJob(j));
-          }
-        } catch (NullReferenceException) {
-          // jobs was set to null during ClearHiveClient
-        }
+        projectNames = new Dictionary<Guid, string>();
+        resourceNames = new Dictionary<Guid, string>();
+
+        projectAncestors = new Dictionary<Guid, HashSet<Guid>>();
+        projectDescendants = new Dictionary<Guid, HashSet<Guid>>();
+        resourceAncestors = new Dictionary<Guid, HashSet<Guid>>();
+        resourceDescendants = new Dictionary<Guid, HashSet<Guid>>();
+
+        HiveServiceLocator.Instance.CallHiveService(service => {
+          service.GetProjects().ForEach(p => projects.Add(p));
+          service.GetSlaveGroups().ForEach(g => resources.Add(g));
+          service.GetSlaves().ForEach(s => resources.Add(s));
+          service.GetJobs().ForEach(p => jobs.Add(new RefreshableJob(p)));
+          projectNames = service.GetProjectNames();
+          resourceNames = service.GetResourceNames();
+        });
+
+        RefreshResourceGenealogy();
+        RefreshProjectGenealogy();
+        RefreshDisabledParentProjects();
+        RefreshDisabledParentResources();
+      }
+      catch {
+        jobs = null;
+        projects = null;
+        resources = null;
+        throw;
+      }
+      finally {
+        OnRefreshed();
+      }
+    }
+
+    public void RefreshProjectsAndResources() {
+      OnRefreshing();
+
+      try {
+        projects = new ItemList<Project>();
+        projectNames = new Dictionary<Guid, string>();
+        resources = new ItemList<Resource>();
+        resourceNames = new Dictionary<Guid, string>();
+
+        projectAncestors = new Dictionary<Guid, HashSet<Guid>>();
+        projectDescendants = new Dictionary<Guid, HashSet<Guid>>();
+        resourceAncestors = new Dictionary<Guid, HashSet<Guid>>();
+        resourceDescendants = new Dictionary<Guid, HashSet<Guid>>();
+
+        HiveServiceLocator.Instance.CallHiveService(service => {
+          service.GetProjects().ForEach(p => projects.Add(p));
+          service.GetSlaveGroups().ForEach(g => resources.Add(g));
+          service.GetSlaves().ForEach(s => resources.Add(s));
+          projectNames = service.GetProjectNames();
+          resourceNames = service.GetResourceNames();
+        });
+
+        RefreshResourceGenealogy();
+        RefreshProjectGenealogy();
+        RefreshDisabledParentProjects();
+        RefreshDisabledParentResources();
       } catch {
-        jobs = null;
+        projects = null;
+        resources = null;
         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);
+    }
+
+    private void RefreshResourceGenealogy() {
+      resourceAncestors.Clear();
+      resourceDescendants.Clear();
+
+      // fetch resource ancestor set
+      HiveServiceLocator.Instance.CallHiveService(service => {
+        var ra = service.GetResourceGenealogy();
+        ra.Keys.ToList().ForEach(k => resourceAncestors.Add(k, new HashSet<Guid>()));
+        resourceAncestors.Keys.ToList().ForEach(k => resourceAncestors[k].UnionWith(ra[k]));
+      });
+
+      // build resource descendant set
+      resourceAncestors.Keys.ToList().ForEach(k => resourceDescendants.Add(k, new HashSet<Guid>()));
+      foreach (var ra in resourceAncestors) {
+        foreach(var ancestor in ra.Value) {
+          resourceDescendants[ancestor].Add(ra.Key);
+        }
+      }
+    }
+
+    private void RefreshProjectGenealogy() {
+      projectAncestors.Clear();
+      projectDescendants.Clear();
+
+      // fetch project ancestor list
+      HiveServiceLocator.Instance.CallHiveService(service => {
+        var pa = service.GetProjectGenealogy();
+        pa.Keys.ToList().ForEach(k => projectAncestors.Add(k, new HashSet<Guid>()));
+        projectAncestors.Keys.ToList().ForEach(k => projectAncestors[k].UnionWith(pa[k]));
+      });
+
+      // build project descendant list
+      projectAncestors.Keys.ToList().ForEach(k => projectDescendants.Add(k, new HashSet<Guid>()));
+      foreach(var pa in projectAncestors) {
+        foreach(var ancestor in pa.Value) {
+          projectDescendants[ancestor].Add(pa.Key);
+        }
+      }
+    }
+
+    private void RefreshDisabledParentProjects() {
+      disabledParentProjects = new HashSet<Project>();
+
+      foreach (var pid in projects
+        .Where(x => x.ParentProjectId.HasValue)
+        .SelectMany(x => projectAncestors[x.Id]).Distinct()
+        .Where(x => !projects.Select(y => y.Id).Contains(x))) {
+        var p = new Project();
+        p.Id = pid;
+        p.ParentProjectId = projectAncestors[pid].FirstOrDefault();
+        p.Name = projectNames[pid];
+        disabledParentProjects.Add(p);
+      }
+    }
+
+    private void RefreshDisabledParentResources() {
+      disabledParentResources = new HashSet<Resource>();
+
+      foreach (var rid in resources
+        .Where(x => x.ParentResourceId.HasValue)
+        .SelectMany(x => resourceAncestors[x.Id]).Distinct()
+        .Where(x => !resources.Select(y => y.Id).Contains(x))) {
+        var r = new SlaveGroup();
+        r.Id = rid;
+        r.ParentResourceId = resourceAncestors[rid].FirstOrDefault();
+        r.Name = resourceNames[rid];
+        disabledParentResources.Add(r);
+      }
+    }
+
+    public IEnumerable<Project> GetAvailableProjectAncestors(Guid id) {
+      if (projectAncestors.ContainsKey(id)) return projects.Where(x => projectAncestors[id].Contains(x.Id));
+      else return Enumerable.Empty<Project>();
+    }
+
+    public IEnumerable<Project> GetAvailableProjectDescendants(Guid id) {
+      if (projectDescendants.ContainsKey(id)) return projects.Where(x => projectDescendants[id].Contains(x.Id));
+      else return Enumerable.Empty<Project>();
+    }
+
+    public IEnumerable<Resource> GetAvailableResourceAncestors(Guid id) {
+      if (resourceAncestors.ContainsKey(id)) return resources.Where(x => resourceAncestors[id].Contains(x.Id));
+      else return Enumerable.Empty<Resource>();
+    }
+
+    public IEnumerable<Resource> GetAvailableResourceDescendants(Guid id) {
+      if (resourceDescendants.ContainsKey(id)) return resources.Where(x => resourceDescendants[id].Contains(x.Id));
+      else return Enumerable.Empty<Resource>();
+    }
+
+    public IEnumerable<Resource> GetAvailableResourcesForProject(Guid id) {
+      var assignedProjectResources = HiveServiceLocator.Instance.CallHiveService(s => s.GetAssignedResourcesForProject(id));
+      return resources.Where(x => assignedProjectResources.Select(y => y.ResourceId).Contains(x.Id));
+    }
+
+    public IEnumerable<Resource> GetDisabledResourceAncestors(IEnumerable<Resource> availableResources) {
+      var missingParentIds = availableResources
+        .Where(x => x.ParentResourceId.HasValue)
+        .SelectMany(x => resourceAncestors[x.Id]).Distinct()
+        .Where(x => !availableResources.Select(y => y.Id).Contains(x));
+
+      return resources.OfType<SlaveGroup>().Union(disabledParentResources).Where(x => missingParentIds.Contains(x.Id));
     }
     #endregion
@@ -116,5 +339,5 @@
       if (item.Id == Guid.Empty) {
         if (item is RefreshableJob) {
-          HiveClient.Instance.UploadJob((RefreshableJob)item, cancellationToken);
+          item.Id = HiveClient.Instance.UploadJob((RefreshableJob)item, cancellationToken);
         }
         if (item is JobPermission) {
@@ -126,19 +349,27 @@
           HiveServiceLocator.Instance.CallHiveService((s) => s.GrantPermission(hep.JobId, hep.GrantedUserId, hep.Permission));
         }
+        if (item is Project) {
+          item.Id = HiveServiceLocator.Instance.CallHiveService(s => s.AddProject((Project)item));
+        }
       } else {
-        if (item is Job)
-          HiveServiceLocator.Instance.CallHiveService(s => s.UpdateJob((Job)item));
+        if (item is Job) {
+          var job = (Job)item;
+          HiveServiceLocator.Instance.CallHiveService(s => s.UpdateJob(job, job.ResourceIds));
+        }
+        if (item is Project)
+          HiveServiceLocator.Instance.CallHiveService(s => s.UpdateProject((Project)item));
       }
     }
     public static void StoreAsync(Action<Exception> exceptionCallback, IHiveItem item, CancellationToken cancellationToken) {
-      var call = new Func<Exception>(delegate () {
+      var call = new Func<Exception>(delegate() {
         try {
           Store(item, cancellationToken);
-        } catch (Exception ex) {
+        }
+        catch (Exception ex) {
           return ex;
         }
         return null;
       });
-      call.BeginInvoke(delegate (IAsyncResult result) {
+      call.BeginInvoke(delegate(IAsyncResult result) {
         Exception ex = call.EndInvoke(result);
         if (ex != null) exceptionCallback(ex);
@@ -153,5 +384,5 @@
 
       if (item is Job)
-        HiveServiceLocator.Instance.CallHiveService(s => s.DeleteJob(item.Id));
+        HiveServiceLocator.Instance.CallHiveService(s => s.UpdateJobState(item.Id, JobState.StatisticsPending));
       if (item is RefreshableJob) {
         RefreshableJob job = (RefreshableJob)item;
@@ -159,5 +390,5 @@
           job.StopResultPolling();
         }
-        HiveServiceLocator.Instance.CallHiveService(s => s.DeleteJob(item.Id));
+        HiveServiceLocator.Instance.CallHiveService(s => s.UpdateJobState(item.Id, JobState.StatisticsPending));
       }
       if (item is JobPermission) {
@@ -227,21 +458,39 @@
     }
 
+    public static void UpdateJob(Action<Exception> exceptionCallback, RefreshableJob refreshableJob, CancellationToken cancellationToken) {
+      refreshableJob.IsProgressing = true;
+      refreshableJob.Progress.Status = "Saving Job...";
+      HiveClient.StoreAsync(
+        new Action<Exception>((Exception ex) => {
+          exceptionCallback(ex);
+        }), refreshableJob.Job, cancellationToken);
+      refreshableJob.IsProgressing = false;
+      refreshableJob.Progress.Finish();
+    }
+
+    public static void UpdateJob(RefreshableJob refreshableJob) {
+      refreshableJob.IsProgressing = true;
+
+      try {
+        refreshableJob.Progress.Start("Saving Job...");
+        HiveClient.StoreAsync(new Action<Exception>((Exception ex) => {
+          throw new Exception("Update failed.", ex);
+        }), refreshableJob.Job, new CancellationToken());
+      } finally {
+        refreshableJob.IsProgressing = false;
+        refreshableJob.Progress.Finish();
+      }
+    }
+
+
+
     #region Upload Job
     private Semaphore taskUploadSemaphore = new Semaphore(Settings.Default.MaxParallelUploads, Settings.Default.MaxParallelUploads);
     private static object jobCountLocker = new object();
     private static object pluginLocker = new object();
-    private void UploadJob(RefreshableJob refreshableJob, CancellationToken cancellationToken) {
+    private Guid UploadJob(RefreshableJob refreshableJob, CancellationToken cancellationToken) {
       try {
         refreshableJob.IsProgressing = true;
         refreshableJob.Progress.Start("Connecting to server...");
-        IEnumerable<string> resourceNames = ToResourceNameList(refreshableJob.Job.ResourceNames);
-        var resourceIds = new List<Guid>();
-        foreach (var resourceName in resourceNames) {
-          Guid resourceId = HiveServiceLocator.Instance.CallHiveService((s) => s.GetResourceId(resourceName));
-          if (resourceId == Guid.Empty) {
-            throw new ResourceNotFoundException(string.Format("Could not find the resource '{0}'", resourceName));
-          }
-          resourceIds.Add(resourceId);
-        }
 
         foreach (OptimizerHiveTask hiveJob in refreshableJob.HiveTasks.OfType<OptimizerHiveTask>()) {
@@ -251,5 +500,5 @@
         // upload Job
         refreshableJob.Progress.Status = "Uploading Job...";
-        refreshableJob.Job.Id = HiveServiceLocator.Instance.CallHiveService((s) => s.AddJob(refreshableJob.Job));
+        refreshableJob.Job.Id = HiveServiceLocator.Instance.CallHiveService((s) => s.AddJob(refreshableJob.Job, refreshableJob.Job.ResourceIds));
         refreshableJob.Job = HiveServiceLocator.Instance.CallHiveService((s) => s.GetJob(refreshableJob.Job.Id)); // update owner and permissions
         cancellationToken.ThrowIfCancellationRequested();
@@ -273,5 +522,5 @@
         foreach (HiveTask hiveTask in refreshableJob.HiveTasks) {
           var task = TS.Task.Factory.StartNew((hj) => {
-            UploadTaskWithChildren(refreshableJob.Progress, (HiveTask)hj, null, resourceIds, jobCount, totalJobCount, configFilePlugin.Id, refreshableJob.Job.Id, refreshableJob.Log, cancellationToken);
+            UploadTaskWithChildren(refreshableJob.Progress, (HiveTask)hj, null, jobCount, totalJobCount, configFilePlugin.Id, refreshableJob.Job.Id, refreshableJob.Log, cancellationToken);
           }, hiveTask);
           task.ContinueWith((x) => refreshableJob.Log.LogException(x.Exception), TaskContinuationOptions.OnlyOnFaulted);
@@ -279,9 +528,11 @@
         }
         TS.Task.WaitAll(tasks.ToArray());
-      } finally {
+      }
+      finally {
         refreshableJob.Job.Modified = false;
         refreshableJob.IsProgressing = false;
         refreshableJob.Progress.Finish();
       }
+      return (refreshableJob.Job != null) ? refreshableJob.Job.Id : Guid.Empty;
     }
 
@@ -317,5 +568,5 @@
     /// </summary>
     /// <param name="parentHiveTask">shall be null if its the root task</param>
-    private void UploadTaskWithChildren(IProgress progress, HiveTask hiveTask, HiveTask parentHiveTask, IEnumerable<Guid> groups, int[] taskCount, int totalJobCount, Guid configPluginId, Guid jobId, ILog log, CancellationToken cancellationToken) {
+    private void UploadTaskWithChildren(IProgress progress, HiveTask hiveTask, HiveTask parentHiveTask, int[] taskCount, int totalJobCount, Guid configPluginId, Guid jobId, ILog log, CancellationToken cancellationToken) {
       taskUploadSemaphore.WaitOne();
       bool semaphoreReleased = false;
@@ -356,5 +607,5 @@
               hiveTask.Task.Id = HiveServiceLocator.Instance.CallHiveService((s) => s.AddChildTask(parentHiveTask.Task.Id, hiveTask.Task, taskData));
             } else {
-              hiveTask.Task.Id = HiveServiceLocator.Instance.CallHiveService((s) => s.AddTask(hiveTask.Task, taskData, groups.ToList()));
+              hiveTask.Task.Id = HiveServiceLocator.Instance.CallHiveService((s) => s.AddTask(hiveTask.Task, taskData));
             }
           }
@@ -371,5 +622,5 @@
           var task = TS.Task.Factory.StartNew((tuple) => {
             var arguments = (Tuple<HiveTask, HiveTask>)tuple;
-            UploadTaskWithChildren(progress, arguments.Item1, arguments.Item2, groups, taskCount, totalJobCount, configPluginId, jobId, log, cancellationToken);
+            UploadTaskWithChildren(progress, arguments.Item1, arguments.Item2, taskCount, totalJobCount, configPluginId, jobId, log, cancellationToken);
           }, new Tuple<HiveTask, HiveTask>(child, hiveTask));
           task.ContinueWith((x) => log.LogException(x.Exception), TaskContinuationOptions.OnlyOnFaulted);
@@ -426,9 +677,10 @@
         } else if (refreshableJob.IsPaused()) {
           refreshableJob.ExecutionState = Core.ExecutionState.Paused;
-        } else {
+        } else { 
           refreshableJob.ExecutionState = Core.ExecutionState.Started;
         }
         refreshableJob.OnLoaded();
-      } finally {
+      }
+      finally {
         refreshableJob.IsProgressing = false;
         refreshableJob.Progress.Finish();
@@ -467,5 +719,6 @@
       try {
         return PersistenceUtil.Deserialize<ItemTask>(taskData.Data);
-      } catch {
+      }
+      catch {
         return null;
       }
@@ -478,5 +731,6 @@
     public static void TryAndRepeat(Action action, int repetitions, string errorMessage, ILog log = null) {
       while (true) {
-        try { action(); return; } catch (Exception e) {
+        try { action(); return; }
+        catch (Exception e) {
           if (repetitions == 0) throw new HiveException(errorMessage, e);
           if (log != null) log.LogMessage(string.Format("{0}: {1} - will try again!", errorMessage, e.ToString()));
@@ -495,4 +749,16 @@
       });
     }
+
+    public string GetProjectAncestry(Guid projectId) {
+      if (projectId == null || projectId == Guid.Empty) return "";
+      var projects = projectAncestors[projectId].Reverse().ToList();
+      projects.Add(projectId);
+      return string.Join(" » ", projects.Select(x => ProjectNames[x]).ToArray());
+    }
+
+    public IEnumerable<Resource> GetAssignedResourcesForJob(Guid jobId) {
+      var assignedJobResource = HiveServiceLocator.Instance.CallHiveService(service => service.GetAssignedResourcesForJob(jobId));
+      return Resources.Where(x => assignedJobResource.Select(y => y.ResourceId).Contains(x.Id));
+    }
   }
 }
Index: branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Clients.Hive/3.3/Plugin.cs.frame
===================================================================
--- branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Clients.Hive/3.3/Plugin.cs.frame	(revision 15962)
+++ branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Clients.Hive/3.3/Plugin.cs.frame	(revision 16386)
@@ -30,4 +30,5 @@
   [PluginFile("HeuristicLab.Clients.Hive-3.3.dll", PluginFileType.Assembly)]
   [PluginDependency("HeuristicLab.Clients.Common", "3.3")]
+  [PluginDependency("HeuristicLab.Clients.Access", "3.3")]  
   [PluginDependency("HeuristicLab.Collections", "3.3")]
   [PluginDependency("HeuristicLab.Common", "3.3")]
Index: branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Clients.Hive/3.3/ServiceClients/AssignedJobResource.cs
===================================================================
--- branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Clients.Hive/3.3/ServiceClients/AssignedJobResource.cs	(revision 16386)
+++ branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Clients.Hive/3.3/ServiceClients/AssignedJobResource.cs	(revision 16386)
@@ -0,0 +1,12 @@
+﻿using HeuristicLab.Common;
+
+namespace HeuristicLab.Clients.Hive {
+  public partial class AssignedJobResource : IDeepCloneable, IContent {
+    public AssignedJobResource() { }
+
+    public AssignedJobResource(AssignedJobResource original, Cloner cloner) : base(original, cloner) {
+      ResourceId = original.ResourceId;
+      JobId = original.JobId;
+    }
+  }
+}
Index: branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Clients.Hive/3.3/ServiceClients/AssignedProjectResource.cs
===================================================================
--- branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Clients.Hive/3.3/ServiceClients/AssignedProjectResource.cs	(revision 16386)
+++ branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Clients.Hive/3.3/ServiceClients/AssignedProjectResource.cs	(revision 16386)
@@ -0,0 +1,12 @@
+﻿using HeuristicLab.Common;
+
+namespace HeuristicLab.Clients.Hive {
+  public partial class AssignedProjectResource : IDeepCloneable, IContent {
+    public AssignedProjectResource() { }
+
+    public AssignedProjectResource(AssignedProjectResource original, Cloner cloner) : base(original, cloner) {
+      ResourceId = original.ResourceId;
+      ProjectId = original.ProjectId;
+    }
+  }
+}
Index: branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Clients.Hive/3.3/ServiceClients/HiveServiceClient.cs
===================================================================
--- branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Clients.Hive/3.3/ServiceClients/HiveServiceClient.cs	(revision 15962)
+++ branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Clients.Hive/3.3/ServiceClients/HiveServiceClient.cs	(revision 16386)
@@ -26,7 +26,10 @@
     [System.Runtime.Serialization.KnownTypeAttribute(typeof(HeuristicLab.Clients.Hive.SlaveGroup))]
     [System.Runtime.Serialization.KnownTypeAttribute(typeof(HeuristicLab.Clients.Hive.Plugin))]
+    [System.Runtime.Serialization.KnownTypeAttribute(typeof(HeuristicLab.Clients.Hive.Project))]
+    [System.Runtime.Serialization.KnownTypeAttribute(typeof(HeuristicLab.Clients.Hive.AssignedJobResource))]
     [System.Runtime.Serialization.KnownTypeAttribute(typeof(HeuristicLab.Clients.Hive.JobPermission))]
     [System.Runtime.Serialization.KnownTypeAttribute(typeof(HeuristicLab.Clients.Hive.PluginData))]
-    [System.Runtime.Serialization.KnownTypeAttribute(typeof(HeuristicLab.Clients.Hive.ResourcePermission))]
+    [System.Runtime.Serialization.KnownTypeAttribute(typeof(HeuristicLab.Clients.Hive.ProjectPermission))]
+    [System.Runtime.Serialization.KnownTypeAttribute(typeof(HeuristicLab.Clients.Hive.AssignedProjectResource))]
     [System.Runtime.Serialization.KnownTypeAttribute(typeof(HeuristicLab.Clients.Hive.Downtime))]
     [System.Runtime.Serialization.KnownTypeAttribute(typeof(HeuristicLab.Clients.Hive.UserPriority))]
@@ -211,4 +214,5 @@
     [System.Runtime.Serialization.KnownTypeAttribute(typeof(HeuristicLab.Clients.Hive.SlaveGroup))]
     [System.Runtime.Serialization.KnownTypeAttribute(typeof(HeuristicLab.Clients.Hive.Plugin))]
+    [System.Runtime.Serialization.KnownTypeAttribute(typeof(HeuristicLab.Clients.Hive.Project))]
     public partial class NamedHiveItem : HeuristicLab.Clients.Hive.HiveItem
     {
@@ -284,5 +288,8 @@
         
         [System.Runtime.Serialization.OptionalFieldAttribute()]
-        private string ResourceNamesField;
+        private System.Guid ProjectIdField;
+        
+        [System.Runtime.Serialization.OptionalFieldAttribute()]
+        private HeuristicLab.Clients.Hive.JobState StateField;
         
         [System.Runtime.Serialization.DataMemberAttribute()]
@@ -406,16 +413,33 @@
         
         [System.Runtime.Serialization.DataMemberAttribute()]
-        public string ResourceNames
-        {
-            get
-            {
-                return this.ResourceNamesField;
-            }
-            set
-            {
-                if ((object.ReferenceEquals(this.ResourceNamesField, value) != true))
-                {
-                    this.ResourceNamesField = value;
-                    this.RaisePropertyChanged("ResourceNames");
+        public System.Guid ProjectId
+        {
+            get
+            {
+                return this.ProjectIdField;
+            }
+            set
+            {
+                if ((this.ProjectIdField.Equals(value) != true))
+                {
+                    this.ProjectIdField = value;
+                    this.RaisePropertyChanged("ProjectId");
+                }
+            }
+        }
+        
+        [System.Runtime.Serialization.DataMemberAttribute()]
+        public HeuristicLab.Clients.Hive.JobState State
+        {
+            get
+            {
+                return this.StateField;
+            }
+            set
+            {
+                if ((this.StateField.Equals(value) != true))
+                {
+                    this.StateField = value;
+                    this.RaisePropertyChanged("State");
                 }
             }
@@ -839,4 +863,160 @@
     [System.Diagnostics.DebuggerStepThroughAttribute()]
     [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Runtime.Serialization", "4.0.0.0")]
+    [System.Runtime.Serialization.DataContractAttribute(Name="Project", Namespace="http://schemas.datacontract.org/2004/07/HeuristicLab.Services.Hive.DataTransfer")]
+    [System.SerializableAttribute()]
+    public partial class Project : HeuristicLab.Clients.Hive.NamedHiveItem
+    {
+        
+        [System.Runtime.Serialization.OptionalFieldAttribute()]
+        private System.DateTime DateCreatedField;
+        
+        [System.Runtime.Serialization.OptionalFieldAttribute()]
+        private System.Nullable<System.DateTime> EndDateField;
+        
+        [System.Runtime.Serialization.OptionalFieldAttribute()]
+        private System.Guid OwnerUserIdField;
+        
+        [System.Runtime.Serialization.OptionalFieldAttribute()]
+        private System.Nullable<System.Guid> ParentProjectIdField;
+        
+        [System.Runtime.Serialization.OptionalFieldAttribute()]
+        private System.DateTime StartDateField;
+        
+        [System.Runtime.Serialization.DataMemberAttribute()]
+        public System.DateTime DateCreated
+        {
+            get
+            {
+                return this.DateCreatedField;
+            }
+            set
+            {
+                if ((this.DateCreatedField.Equals(value) != true))
+                {
+                    this.DateCreatedField = value;
+                    this.RaisePropertyChanged("DateCreated");
+                }
+            }
+        }
+        
+        [System.Runtime.Serialization.DataMemberAttribute()]
+        public System.Nullable<System.DateTime> EndDate
+        {
+            get
+            {
+                return this.EndDateField;
+            }
+            set
+            {
+                if ((this.EndDateField.Equals(value) != true))
+                {
+                    this.EndDateField = value;
+                    this.RaisePropertyChanged("EndDate");
+                }
+            }
+        }
+        
+        [System.Runtime.Serialization.DataMemberAttribute()]
+        public System.Guid OwnerUserId
+        {
+            get
+            {
+                return this.OwnerUserIdField;
+            }
+            set
+            {
+                if ((this.OwnerUserIdField.Equals(value) != true))
+                {
+                    this.OwnerUserIdField = value;
+                    this.RaisePropertyChanged("OwnerUserId");
+                }
+            }
+        }
+        
+        [System.Runtime.Serialization.DataMemberAttribute()]
+        public System.Nullable<System.Guid> ParentProjectId
+        {
+            get
+            {
+                return this.ParentProjectIdField;
+            }
+            set
+            {
+                if ((this.ParentProjectIdField.Equals(value) != true))
+                {
+                    this.ParentProjectIdField = value;
+                    this.RaisePropertyChanged("ParentProjectId");
+                }
+            }
+        }
+        
+        [System.Runtime.Serialization.DataMemberAttribute()]
+        public System.DateTime StartDate
+        {
+            get
+            {
+                return this.StartDateField;
+            }
+            set
+            {
+                if ((this.StartDateField.Equals(value) != true))
+                {
+                    this.StartDateField = value;
+                    this.RaisePropertyChanged("StartDate");
+                }
+            }
+        }
+    }
+    
+    [System.Diagnostics.DebuggerStepThroughAttribute()]
+    [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Runtime.Serialization", "4.0.0.0")]
+    [System.Runtime.Serialization.DataContractAttribute(Name="AssignedJobResource", Namespace="http://schemas.datacontract.org/2004/07/HeuristicLab.Services.Hive.DataTransfer")]
+    [System.SerializableAttribute()]
+    public partial class AssignedJobResource : HeuristicLab.Clients.Hive.HiveItem
+    {
+        
+        [System.Runtime.Serialization.OptionalFieldAttribute()]
+        private System.Guid JobIdField;
+        
+        [System.Runtime.Serialization.OptionalFieldAttribute()]
+        private System.Guid ResourceIdField;
+        
+        [System.Runtime.Serialization.DataMemberAttribute()]
+        public System.Guid JobId
+        {
+            get
+            {
+                return this.JobIdField;
+            }
+            set
+            {
+                if ((this.JobIdField.Equals(value) != true))
+                {
+                    this.JobIdField = value;
+                    this.RaisePropertyChanged("JobId");
+                }
+            }
+        }
+        
+        [System.Runtime.Serialization.DataMemberAttribute()]
+        public System.Guid ResourceId
+        {
+            get
+            {
+                return this.ResourceIdField;
+            }
+            set
+            {
+                if ((this.ResourceIdField.Equals(value) != true))
+                {
+                    this.ResourceIdField = value;
+                    this.RaisePropertyChanged("ResourceId");
+                }
+            }
+        }
+    }
+    
+    [System.Diagnostics.DebuggerStepThroughAttribute()]
+    [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Runtime.Serialization", "4.0.0.0")]
     [System.Runtime.Serialization.DataContractAttribute(Name="JobPermission", Namespace="http://schemas.datacontract.org/2004/07/HeuristicLab.Services.Hive.DataTransfer")]
     [System.SerializableAttribute()]
@@ -995,7 +1175,7 @@
     [System.Diagnostics.DebuggerStepThroughAttribute()]
     [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Runtime.Serialization", "4.0.0.0")]
-    [System.Runtime.Serialization.DataContractAttribute(Name="ResourcePermission", Namespace="http://schemas.datacontract.org/2004/07/HeuristicLab.Services.Hive.DataTransfer")]
+    [System.Runtime.Serialization.DataContractAttribute(Name="ProjectPermission", Namespace="http://schemas.datacontract.org/2004/07/HeuristicLab.Services.Hive.DataTransfer")]
     [System.SerializableAttribute()]
-    public partial class ResourcePermission : HeuristicLab.Clients.Hive.HiveItem
+    public partial class ProjectPermission : HeuristicLab.Clients.Hive.HiveItem
     {
         
@@ -1007,5 +1187,5 @@
         
         [System.Runtime.Serialization.OptionalFieldAttribute()]
-        private System.Guid ResourceIdField;
+        private System.Guid ProjectIdField;
         
         [System.Runtime.Serialization.DataMemberAttribute()]
@@ -1039,4 +1219,52 @@
                     this.GrantedUserIdField = value;
                     this.RaisePropertyChanged("GrantedUserId");
+                }
+            }
+        }
+        
+        [System.Runtime.Serialization.DataMemberAttribute()]
+        public System.Guid ProjectId
+        {
+            get
+            {
+                return this.ProjectIdField;
+            }
+            set
+            {
+                if ((this.ProjectIdField.Equals(value) != true))
+                {
+                    this.ProjectIdField = value;
+                    this.RaisePropertyChanged("ProjectId");
+                }
+            }
+        }
+    }
+    
+    [System.Diagnostics.DebuggerStepThroughAttribute()]
+    [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Runtime.Serialization", "4.0.0.0")]
+    [System.Runtime.Serialization.DataContractAttribute(Name="AssignedProjectResource", Namespace="http://schemas.datacontract.org/2004/07/HeuristicLab.Services.Hive.DataTransfer")]
+    [System.SerializableAttribute()]
+    public partial class AssignedProjectResource : HeuristicLab.Clients.Hive.HiveItem
+    {
+        
+        [System.Runtime.Serialization.OptionalFieldAttribute()]
+        private System.Guid ProjectIdField;
+        
+        [System.Runtime.Serialization.OptionalFieldAttribute()]
+        private System.Guid ResourceIdField;
+        
+        [System.Runtime.Serialization.DataMemberAttribute()]
+        public System.Guid ProjectId
+        {
+            get
+            {
+                return this.ProjectIdField;
+            }
+            set
+            {
+                if ((this.ProjectIdField.Equals(value) != true))
+                {
+                    this.ProjectIdField = value;
+                    this.RaisePropertyChanged("ProjectId");
                 }
             }
@@ -1612,4 +1840,19 @@
         [System.Runtime.Serialization.EnumMemberAttribute()]
         Full = 2,
+    }
+    
+    [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Runtime.Serialization", "4.0.0.0")]
+    [System.Runtime.Serialization.DataContractAttribute(Name="JobState", Namespace="http://schemas.datacontract.org/2004/07/HeuristicLab.Services.Hive.DataTransfer")]
+    public enum JobState : int
+    {
+        
+        [System.Runtime.Serialization.EnumMemberAttribute()]
+        Online = 0,
+        
+        [System.Runtime.Serialization.EnumMemberAttribute()]
+        StatisticsPending = 1,
+        
+        [System.Runtime.Serialization.EnumMemberAttribute()]
+        DeletionPending = 2,
     }
     
@@ -2100,5 +2343,5 @@
         
         [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IHiveService/AddTask", ReplyAction="http://tempuri.org/IHiveService/AddTaskResponse")]
-        System.Guid AddTask(HeuristicLab.Clients.Hive.Task task, HeuristicLab.Clients.Hive.TaskData taskData, System.Collections.Generic.List<System.Guid> resourceIds);
+        System.Guid AddTask(HeuristicLab.Clients.Hive.Task task, HeuristicLab.Clients.Hive.TaskData taskData);
         
         [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IHiveService/AddChildTask", ReplyAction="http://tempuri.org/IHiveService/AddChildTaskResponse")]
@@ -2141,12 +2384,24 @@
         System.Collections.Generic.List<HeuristicLab.Clients.Hive.Job> GetJobs();
         
+        [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IHiveService/GetJobsByProjectId", ReplyAction="http://tempuri.org/IHiveService/GetJobsByProjectIdResponse")]
+        System.Collections.Generic.List<HeuristicLab.Clients.Hive.Job> GetJobsByProjectId(System.Guid projectId);
+        
+        [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IHiveService/GetJobsByProjectIds", ReplyAction="http://tempuri.org/IHiveService/GetJobsByProjectIdsResponse")]
+        System.Collections.Generic.List<HeuristicLab.Clients.Hive.Job> GetJobsByProjectIds(System.Collections.Generic.List<System.Guid> projectIds);
+        
         [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IHiveService/AddJob", ReplyAction="http://tempuri.org/IHiveService/AddJobResponse")]
-        System.Guid AddJob(HeuristicLab.Clients.Hive.Job jobDto);
+        System.Guid AddJob(HeuristicLab.Clients.Hive.Job jobDto, System.Collections.Generic.List<System.Guid> resourceIds);
         
         [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IHiveService/UpdateJob", ReplyAction="http://tempuri.org/IHiveService/UpdateJobResponse")]
-        void UpdateJob(HeuristicLab.Clients.Hive.Job jobDto);
-        
-        [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IHiveService/DeleteJob", ReplyAction="http://tempuri.org/IHiveService/DeleteJobResponse")]
-        void DeleteJob(System.Guid JobId);
+        void UpdateJob(HeuristicLab.Clients.Hive.Job jobDto, System.Collections.Generic.List<System.Guid> resourceIds);
+        
+        [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IHiveService/UpdateJobState", ReplyAction="http://tempuri.org/IHiveService/UpdateJobStateResponse")]
+        void UpdateJobState(System.Guid JobId, HeuristicLab.Clients.Hive.JobState jobState);
+        
+        [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IHiveService/UpdateJobStates", ReplyAction="http://tempuri.org/IHiveService/UpdateJobStatesResponse")]
+        void UpdateJobStates(System.Collections.Generic.List<System.Guid> jobIds, HeuristicLab.Clients.Hive.JobState jobState);
+        
+        [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IHiveService/GetAssignedResourcesForJob", ReplyAction="http://tempuri.org/IHiveService/GetAssignedResourcesForJobResponse")]
+        System.Collections.Generic.List<HeuristicLab.Clients.Hive.AssignedJobResource> GetAssignedResourcesForJob(System.Guid jobId);
         
         [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IHiveService/GrantPermission", ReplyAction="http://tempuri.org/IHiveService/GrantPermissionResponse")]
@@ -2184,12 +2439,47 @@
         System.Collections.Generic.List<HeuristicLab.Clients.Hive.PluginData> GetPluginDatas(System.Collections.Generic.List<System.Guid> pluginIds);
         
-        [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IHiveService/GrantResourcePermissions", ReplyAction="http://tempuri.org/IHiveService/GrantResourcePermissionsResponse")]
-        void GrantResourcePermissions(System.Guid resourceId, System.Collections.Generic.List<System.Guid> grantedUserIds);
-        
-        [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IHiveService/RevokeResourcePermissions", ReplyAction="http://tempuri.org/IHiveService/RevokeResourcePermissionsResponse")]
-        void RevokeResourcePermissions(System.Guid resourceId, System.Collections.Generic.List<System.Guid> grantedUserIds);
-        
-        [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IHiveService/GetResourcePermissions", ReplyAction="http://tempuri.org/IHiveService/GetResourcePermissionsResponse")]
-        System.Collections.Generic.List<HeuristicLab.Clients.Hive.ResourcePermission> GetResourcePermissions(System.Guid resourceId);
+        [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IHiveService/AddProject", ReplyAction="http://tempuri.org/IHiveService/AddProjectResponse")]
+        System.Guid AddProject(HeuristicLab.Clients.Hive.Project projectDto);
+        
+        [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IHiveService/UpdateProject", ReplyAction="http://tempuri.org/IHiveService/UpdateProjectResponse")]
+        void UpdateProject(HeuristicLab.Clients.Hive.Project projectDto);
+        
+        [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IHiveService/DeleteProject", ReplyAction="http://tempuri.org/IHiveService/DeleteProjectResponse")]
+        void DeleteProject(System.Guid projectId);
+        
+        [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IHiveService/GetProject", ReplyAction="http://tempuri.org/IHiveService/GetProjectResponse")]
+        HeuristicLab.Clients.Hive.Project GetProject(System.Guid projectId);
+        
+        [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IHiveService/GetProjects", ReplyAction="http://tempuri.org/IHiveService/GetProjectsResponse")]
+        System.Collections.Generic.List<HeuristicLab.Clients.Hive.Project> GetProjects();
+        
+        [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IHiveService/GetProjectsForAdministration", ReplyAction="http://tempuri.org/IHiveService/GetProjectsForAdministrationResponse")]
+        System.Collections.Generic.List<HeuristicLab.Clients.Hive.Project> GetProjectsForAdministration();
+        
+        [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IHiveService/GetProjectGenealogy", ReplyAction="http://tempuri.org/IHiveService/GetProjectGenealogyResponse")]
+        System.Collections.Generic.Dictionary<System.Guid, System.Collections.Generic.List<System.Guid>> GetProjectGenealogy();
+        
+        [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IHiveService/GetProjectNames", ReplyAction="http://tempuri.org/IHiveService/GetProjectNamesResponse")]
+        System.Collections.Generic.Dictionary<System.Guid, string> GetProjectNames();
+        
+        [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IHiveService/SaveProjectPermissions", ReplyAction="http://tempuri.org/IHiveService/SaveProjectPermissionsResponse")]
+        void SaveProjectPermissions(System.Guid projectId, System.Collections.Generic.List<System.Guid> grantedUserIds, bool reassign, bool cascading, bool reassignCascading);
+        
+        [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IHiveService/GetProjectPermissions", ReplyAction="http://tempuri.org/IHiveService/GetProjectPermissionsResponse")]
+        System.Collections.Generic.List<HeuristicLab.Clients.Hive.ProjectPermission> GetProjectPermissions(System.Guid projectId);
+        
+        [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IHiveService/SaveProjectResourceAssignments", ReplyAction="http://tempuri.org/IHiveService/SaveProjectResourceAssignmentsResponse")]
+        void SaveProjectResourceAssignments(System.Guid projectId, System.Collections.Generic.List<System.Guid> resourceIds, bool reassign, bool cascading, bool reassignCascading);
+        
+        [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IHiveService/GetAssignedResourcesForProject", ReplyAction="http://tempuri.org/IHiveService/GetAssignedResourcesForProjectResponse")]
+        System.Collections.Generic.List<HeuristicLab.Clients.Hive.AssignedProjectResource> GetAssignedResourcesForProject(System.Guid projectId);
+        
+        [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IHiveService/GetAssignedResourcesForProjectAdministration", ReplyAction="http://tempuri.org/IHiveService/GetAssignedResourcesForProjectAdministrationRespo" +
+            "nse")]
+        System.Collections.Generic.List<HeuristicLab.Clients.Hive.AssignedProjectResource> GetAssignedResourcesForProjectAdministration(System.Guid projectId);
+        
+        [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IHiveService/GetAssignedResourcesForProjectsAdministration", ReplyAction="http://tempuri.org/IHiveService/GetAssignedResourcesForProjectsAdministrationResp" +
+            "onse")]
+        System.Collections.Generic.List<HeuristicLab.Clients.Hive.AssignedProjectResource> GetAssignedResourcesForProjectsAdministration(System.Collections.Generic.List<System.Guid> projectIds);
         
         [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IHiveService/AddSlave", ReplyAction="http://tempuri.org/IHiveService/AddSlaveResponse")]
@@ -2208,4 +2498,16 @@
         System.Collections.Generic.List<HeuristicLab.Clients.Hive.SlaveGroup> GetSlaveGroups();
         
+        [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IHiveService/GetSlavesForAdministration", ReplyAction="http://tempuri.org/IHiveService/GetSlavesForAdministrationResponse")]
+        System.Collections.Generic.List<HeuristicLab.Clients.Hive.Slave> GetSlavesForAdministration();
+        
+        [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IHiveService/GetSlaveGroupsForAdministration", ReplyAction="http://tempuri.org/IHiveService/GetSlaveGroupsForAdministrationResponse")]
+        System.Collections.Generic.List<HeuristicLab.Clients.Hive.SlaveGroup> GetSlaveGroupsForAdministration();
+        
+        [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IHiveService/GetResourceGenealogy", ReplyAction="http://tempuri.org/IHiveService/GetResourceGenealogyResponse")]
+        System.Collections.Generic.Dictionary<System.Guid, System.Collections.Generic.List<System.Guid>> GetResourceGenealogy();
+        
+        [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IHiveService/GetResourceNames", ReplyAction="http://tempuri.org/IHiveService/GetResourceNamesResponse")]
+        System.Collections.Generic.Dictionary<System.Guid, string> GetResourceNames();
+        
         [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IHiveService/UpdateSlave", ReplyAction="http://tempuri.org/IHiveService/UpdateSlaveResponse")]
         void UpdateSlave(HeuristicLab.Clients.Hive.Slave slave);
@@ -2252,4 +2554,10 @@
         [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IHiveService/GetUserIdByUsername", ReplyAction="http://tempuri.org/IHiveService/GetUserIdByUsernameResponse")]
         System.Guid GetUserIdByUsername(string username);
+        
+        [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IHiveService/GetUserGroupTree", ReplyAction="http://tempuri.org/IHiveService/GetUserGroupTreeResponse")]
+        System.Collections.Generic.Dictionary<System.Guid, System.Collections.Generic.List<System.Guid>> GetUserGroupTree();
+        
+        [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IHiveService/CheckAccessToAdminAreaGranted", ReplyAction="http://tempuri.org/IHiveService/CheckAccessToAdminAreaGrantedResponse")]
+        bool CheckAccessToAdminAreaGranted();
         
         [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IHiveService/GetUserPriorities", ReplyAction="http://tempuri.org/IHiveService/GetUserPrioritiesResponse")]
@@ -2291,7 +2599,7 @@
         }
         
-        public System.Guid AddTask(HeuristicLab.Clients.Hive.Task task, HeuristicLab.Clients.Hive.TaskData taskData, System.Collections.Generic.List<System.Guid> resourceIds)
-        {
-            return base.Channel.AddTask(task, taskData, resourceIds);
+        public System.Guid AddTask(HeuristicLab.Clients.Hive.Task task, HeuristicLab.Clients.Hive.TaskData taskData)
+        {
+            return base.Channel.AddTask(task, taskData);
         }
         
@@ -2361,17 +2669,37 @@
         }
         
-        public System.Guid AddJob(HeuristicLab.Clients.Hive.Job jobDto)
-        {
-            return base.Channel.AddJob(jobDto);
-        }
-        
-        public void UpdateJob(HeuristicLab.Clients.Hive.Job jobDto)
-        {
-            base.Channel.UpdateJob(jobDto);
-        }
-        
-        public void DeleteJob(System.Guid JobId)
-        {
-            base.Channel.DeleteJob(JobId);
+        public System.Collections.Generic.List<HeuristicLab.Clients.Hive.Job> GetJobsByProjectId(System.Guid projectId)
+        {
+            return base.Channel.GetJobsByProjectId(projectId);
+        }
+        
+        public System.Collections.Generic.List<HeuristicLab.Clients.Hive.Job> GetJobsByProjectIds(System.Collections.Generic.List<System.Guid> projectIds)
+        {
+            return base.Channel.GetJobsByProjectIds(projectIds);
+        }
+        
+        public System.Guid AddJob(HeuristicLab.Clients.Hive.Job jobDto, System.Collections.Generic.List<System.Guid> resourceIds)
+        {
+            return base.Channel.AddJob(jobDto, resourceIds);
+        }
+        
+        public void UpdateJob(HeuristicLab.Clients.Hive.Job jobDto, System.Collections.Generic.List<System.Guid> resourceIds)
+        {
+            base.Channel.UpdateJob(jobDto, resourceIds);
+        }
+        
+        public void UpdateJobState(System.Guid JobId, HeuristicLab.Clients.Hive.JobState jobState)
+        {
+            base.Channel.UpdateJobState(JobId, jobState);
+        }
+        
+        public void UpdateJobStates(System.Collections.Generic.List<System.Guid> jobIds, HeuristicLab.Clients.Hive.JobState jobState)
+        {
+            base.Channel.UpdateJobStates(jobIds, jobState);
+        }
+        
+        public System.Collections.Generic.List<HeuristicLab.Clients.Hive.AssignedJobResource> GetAssignedResourcesForJob(System.Guid jobId)
+        {
+            return base.Channel.GetAssignedResourcesForJob(jobId);
         }
         
@@ -2431,17 +2759,72 @@
         }
         
-        public void GrantResourcePermissions(System.Guid resourceId, System.Collections.Generic.List<System.Guid> grantedUserIds)
-        {
-            base.Channel.GrantResourcePermissions(resourceId, grantedUserIds);
-        }
-        
-        public void RevokeResourcePermissions(System.Guid resourceId, System.Collections.Generic.List<System.Guid> grantedUserIds)
-        {
-            base.Channel.RevokeResourcePermissions(resourceId, grantedUserIds);
-        }
-        
-        public System.Collections.Generic.List<HeuristicLab.Clients.Hive.ResourcePermission> GetResourcePermissions(System.Guid resourceId)
-        {
-            return base.Channel.GetResourcePermissions(resourceId);
+        public System.Guid AddProject(HeuristicLab.Clients.Hive.Project projectDto)
+        {
+            return base.Channel.AddProject(projectDto);
+        }
+        
+        public void UpdateProject(HeuristicLab.Clients.Hive.Project projectDto)
+        {
+            base.Channel.UpdateProject(projectDto);
+        }
+        
+        public void DeleteProject(System.Guid projectId)
+        {
+            base.Channel.DeleteProject(projectId);
+        }
+        
+        public HeuristicLab.Clients.Hive.Project GetProject(System.Guid projectId)
+        {
+            return base.Channel.GetProject(projectId);
+        }
+        
+        public System.Collections.Generic.List<HeuristicLab.Clients.Hive.Project> GetProjects()
+        {
+            return base.Channel.GetProjects();
+        }
+        
+        public System.Collections.Generic.List<HeuristicLab.Clients.Hive.Project> GetProjectsForAdministration()
+        {
+            return base.Channel.GetProjectsForAdministration();
+        }
+        
+        public System.Collections.Generic.Dictionary<System.Guid, System.Collections.Generic.List<System.Guid>> GetProjectGenealogy()
+        {
+            return base.Channel.GetProjectGenealogy();
+        }
+        
+        public System.Collections.Generic.Dictionary<System.Guid, string> GetProjectNames()
+        {
+            return base.Channel.GetProjectNames();
+        }
+        
+        public void SaveProjectPermissions(System.Guid projectId, System.Collections.Generic.List<System.Guid> grantedUserIds, bool reassign, bool cascading, bool reassignCascading)
+        {
+            base.Channel.SaveProjectPermissions(projectId, grantedUserIds, reassign, cascading, reassignCascading);
+        }
+        
+        public System.Collections.Generic.List<HeuristicLab.Clients.Hive.ProjectPermission> GetProjectPermissions(System.Guid projectId)
+        {
+            return base.Channel.GetProjectPermissions(projectId);
+        }
+        
+        public void SaveProjectResourceAssignments(System.Guid projectId, System.Collections.Generic.List<System.Guid> resourceIds, bool reassign, bool cascading, bool reassignCascading)
+        {
+            base.Channel.SaveProjectResourceAssignments(projectId, resourceIds, reassign, cascading, reassignCascading);
+        }
+        
+        public System.Collections.Generic.List<HeuristicLab.Clients.Hive.AssignedProjectResource> GetAssignedResourcesForProject(System.Guid projectId)
+        {
+            return base.Channel.GetAssignedResourcesForProject(projectId);
+        }
+        
+        public System.Collections.Generic.List<HeuristicLab.Clients.Hive.AssignedProjectResource> GetAssignedResourcesForProjectAdministration(System.Guid projectId)
+        {
+            return base.Channel.GetAssignedResourcesForProjectAdministration(projectId);
+        }
+        
+        public System.Collections.Generic.List<HeuristicLab.Clients.Hive.AssignedProjectResource> GetAssignedResourcesForProjectsAdministration(System.Collections.Generic.List<System.Guid> projectIds)
+        {
+            return base.Channel.GetAssignedResourcesForProjectsAdministration(projectIds);
         }
         
@@ -2471,4 +2854,24 @@
         }
         
+        public System.Collections.Generic.List<HeuristicLab.Clients.Hive.Slave> GetSlavesForAdministration()
+        {
+            return base.Channel.GetSlavesForAdministration();
+        }
+        
+        public System.Collections.Generic.List<HeuristicLab.Clients.Hive.SlaveGroup> GetSlaveGroupsForAdministration()
+        {
+            return base.Channel.GetSlaveGroupsForAdministration();
+        }
+        
+        public System.Collections.Generic.Dictionary<System.Guid, System.Collections.Generic.List<System.Guid>> GetResourceGenealogy()
+        {
+            return base.Channel.GetResourceGenealogy();
+        }
+        
+        public System.Collections.Generic.Dictionary<System.Guid, string> GetResourceNames()
+        {
+            return base.Channel.GetResourceNames();
+        }
+        
         public void UpdateSlave(HeuristicLab.Clients.Hive.Slave slave)
         {
@@ -2546,4 +2949,14 @@
         }
         
+        public System.Collections.Generic.Dictionary<System.Guid, System.Collections.Generic.List<System.Guid>> GetUserGroupTree()
+        {
+            return base.Channel.GetUserGroupTree();
+        }
+        
+        public bool CheckAccessToAdminAreaGranted()
+        {
+            return base.Channel.CheckAccessToAdminAreaGranted();
+        }
+        
         public System.Collections.Generic.List<HeuristicLab.Clients.Hive.UserPriority> GetUserPriorities()
         {
Index: branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Clients.Hive/3.3/ServiceClients/Job.cs
===================================================================
--- branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Clients.Hive/3.3/ServiceClients/Job.cs	(revision 15962)
+++ branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Clients.Hive/3.3/ServiceClients/Job.cs	(revision 16386)
@@ -21,4 +21,5 @@
 
 using System;
+using System.Collections.Generic;
 using System.ComponentModel;
 using HeuristicLab.Common;
@@ -26,8 +27,9 @@
 namespace HeuristicLab.Clients.Hive {
   public partial class Job : IDeepCloneable, IContent {
+    public List<Guid> ResourceIds { get; set; }
 
     #region Constructors and Cloning
     public Job() {
-      ResourceNames = "HEAL";
+      ProjectId = Guid.Empty;
       DateCreated = DateTime.Now;
       Permission = Permission.Full;
@@ -38,9 +40,10 @@
       this.OwnerUserId = original.OwnerUserId;
       this.DateCreated = original.DateCreated;
-      this.ResourceNames = original.ResourceNames;
+      this.ProjectId = original.ProjectId;
       this.Name = original.Name;
       this.Description = original.Description;
       this.Id = original.Id;
       this.Permission = original.Permission;
+      this.ResourceIds = original.ResourceIds;
     }
     public override IDeepCloneable Clone(Cloner cloner) {
Index: branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Clients.Hive/3.3/ServiceClients/Project.cs
===================================================================
--- branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Clients.Hive/3.3/ServiceClients/Project.cs	(revision 16386)
+++ branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Clients.Hive/3.3/ServiceClients/Project.cs	(revision 16386)
@@ -0,0 +1,42 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2017 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using HeuristicLab.Common;
+
+namespace HeuristicLab.Clients.Hive {
+  public partial class Project : IDeepCloneable, IContent {
+    public Project() {
+      Description = string.Empty;
+      DateCreated = DateTime.Now;
+      StartDate = DateCreated;
+      EndDate = DateCreated.AddMonths(3);
+    }
+
+    protected Project(Project original, Cloner cloner) : base(original, cloner) {
+      ParentProjectId = original.ParentProjectId;
+      DateCreated = original.DateCreated;
+      OwnerUserId = original.OwnerUserId;
+      StartDate = original.StartDate;
+      EndDate = original.EndDate;
+    }
+  }
+}
Index: branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Clients.Hive/3.3/ServiceClients/ResourcePermission.cs
===================================================================
--- branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Clients.Hive/3.3/ServiceClients/ResourcePermission.cs	(revision 15962)
+++ branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Clients.Hive/3.3/ServiceClients/ResourcePermission.cs	(revision 16386)
@@ -24,5 +24,5 @@
 
 namespace HeuristicLab.Clients.Hive {
-  public partial class ResourcePermission : IDeepCloneable, IContent {
+  public partial class ProjectPermission : IDeepCloneable, IContent {
 
     private string grantedUserName;
@@ -41,5 +41,5 @@
     }
 
-    public ResourcePermission() { }
+    public ProjectPermission() { }
 
     protected override void OnPropertyChanged(PropertyChangedEventArgs e) {
@@ -50,13 +50,13 @@
     }
 
-    protected ResourcePermission(ResourcePermission original, Cloner cloner)
+    protected ProjectPermission(ProjectPermission original, Cloner cloner)
       : base(original, cloner) {
       this.GrantedByUserId = original.GrantedByUserId;
       this.GrantedUserId = original.GrantedUserId;
-      this.ResourceId = original.ResourceId;
+      this.ProjectId = original.ProjectId;
     }
 
     public override IDeepCloneable Clone(Cloner cloner) {
-      return new ResourcePermission(this, cloner);
+      return new ProjectPermission(this, cloner);
     }
 
Index: branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Clients.Hive/3.3/app.config
===================================================================
--- branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Clients.Hive/3.3/app.config	(revision 15962)
+++ branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Clients.Hive/3.3/app.config	(revision 16386)
@@ -71,5 +71,5 @@
     </bindings>
     <client>
-      <endpoint address="http://services.heuristiclab.com/Hive-3.3/HiveService.svc"
+      <endpoint address="http://services.heuristiclab.com/Hive-3.4/HiveService.svc"
         binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_IHiveService"
         contract="HeuristicLab.Clients.Hive.IHiveService" name="WSHttpBinding_IHiveService">
@@ -78,5 +78,5 @@
         </identity>
       </endpoint>
-      <endpoint address="net.tcp://services.heuristiclab.com/Hive-3.3/HiveService.svc"
+      <endpoint address="net.tcp://services.heuristiclab.com/Hive-3.4/HiveService.svc"
         binding="netTcpBinding" bindingConfiguration="NetBinding_IHiveService"
         contract="HeuristicLab.Clients.Hive.IHiveService" name="NetBinding_IHiveService">
