Index: branches/2839_HiveProjectManagement/HeuristicLab.Clients.Hive/3.3/HiveClient.cs
===================================================================
--- branches/2839_HiveProjectManagement/HeuristicLab.Clients.Hive/3.3/HiveClient.cs	(revision 15761)
+++ branches/2839_HiveProjectManagement/HeuristicLab.Clients.Hive/3.3/HiveClient.cs	(revision 15913)
@@ -67,4 +67,24 @@
     }
 
+    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 List<Plugin> onlinePlugins;
@@ -107,4 +127,9 @@
         resources = new ItemList<Resource>();
         jobs = new HiveItemCollection<RefreshableJob>();
+
+        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 => {
@@ -114,4 +139,7 @@
           service.GetJobs().ForEach(p => jobs.Add(new RefreshableJob(p)));
         });
+
+        UpdateResourceGenealogy();
+        UpdateProjectGenealogy();
       }
       catch {
@@ -133,4 +161,9 @@
         resources = new ItemList<Resource>();
 
+        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));
@@ -138,4 +171,7 @@
           service.GetSlaves().ForEach(s => resources.Add(s));
         });
+
+        UpdateResourceGenealogy();
+        UpdateProjectGenealogy();
       } catch {
         projects = null;
@@ -162,5 +198,61 @@
       }, 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);
+        }
+      }
+    }
+
+    public IEnumerable<Project> GetAvailableParentProjects(Guid id) {
+      return projects.Where(x => projectAncestors[id].Contains(x.Id));
+    }
+
+    public IEnumerable<Project> GetAvailableChildProjects(Guid id) {
+      return projects.Where(x => projectDescendants[id].Contains(x.Id));
+    }
+
+    public IEnumerable<Resource> GetAvailableParentResources(Guid id) {
+      return resources.Where(x => resourceAncestors[id].Contains(x.Id));
+    }
+
+    public IEnumerable<Resource> GetAvailableChildResources(Guid id) {
+      return resources.Where(x => resourceDescendants[id].Contains(x.Id));
+    }
+
     #endregion
 
@@ -446,77 +538,4 @@
       }
     }
-
-
-    /// <summary>
-    /// Uploads the given task and all its child-jobs while setting the proper parentJobId values for the childs
-    /// </summary>
-    /// <param name="parentHiveTask">shall be null if its the root task</param>
-    //private void UploadTaskWithChildren_Old(IProgress progress, HiveTask hiveTask, HiveTask parentHiveTask, IEnumerable<Guid> groups, int[] taskCount, int totalJobCount, Guid configPluginId, Guid jobId, ILog log, CancellationToken cancellationToken) {
-    //  taskUploadSemaphore.WaitOne();
-    //  bool semaphoreReleased = false;
-    //  try {
-    //    cancellationToken.ThrowIfCancellationRequested();
-    //    lock (jobCountLocker) {
-    //      taskCount[0]++;
-    //    }
-    //    TaskData taskData;
-    //    List<IPluginDescription> plugins;
-
-    //    if (hiveTask.ItemTask.ComputeInParallel) {
-    //      hiveTask.Task.IsParentTask = true;
-    //      hiveTask.Task.FinishWhenChildJobsFinished = true;
-    //      taskData = hiveTask.GetAsTaskData(true, out plugins);
-    //    } else {
-    //      hiveTask.Task.IsParentTask = false;
-    //      hiveTask.Task.FinishWhenChildJobsFinished = false;
-    //      taskData = hiveTask.GetAsTaskData(false, out plugins);
-    //    }
-    //    cancellationToken.ThrowIfCancellationRequested();
-
-    //    TryAndRepeat(() => {
-    //      if (!cancellationToken.IsCancellationRequested) {
-    //        lock (pluginLocker) {
-    //          HiveServiceLocator.Instance.CallHiveService((s) => hiveTask.Task.PluginsNeededIds = PluginUtil.GetPluginDependencies(s, this.onlinePlugins, this.alreadyUploadedPlugins, plugins));
-    //        }
-    //      }
-    //    }, Settings.Default.MaxRepeatServiceCalls, "Failed to upload plugins");
-    //    cancellationToken.ThrowIfCancellationRequested();
-    //    hiveTask.Task.PluginsNeededIds.Add(configPluginId);
-    //    hiveTask.Task.JobId = jobId;
-
-    //    log.LogMessage(string.Format("Uploading task ({0} kb, {1} objects)", taskData.Data.Count() / 1024, hiveTask.ItemTask.GetObjectGraphObjects().Count()));
-    //    TryAndRepeat(() => {
-    //      if (!cancellationToken.IsCancellationRequested) {
-    //        if (parentHiveTask != null) {
-    //          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()));
-    //        }
-    //      }
-    //    }, Settings.Default.MaxRepeatServiceCalls, "Failed to add task", log);
-    //    cancellationToken.ThrowIfCancellationRequested();
-
-    //    lock (jobCountLocker) {
-    //      progress.ProgressValue = (double)taskCount[0] / totalJobCount;
-    //      progress.Status = string.Format("Uploaded task ({0} of {1})", taskCount[0], totalJobCount);
-    //    }
-
-    //    var tasks = new List<TS.Task>();
-    //    foreach (HiveTask child in hiveTask.ChildHiveTasks) {
-    //      var task = TS.Task.Factory.StartNew((tuple) => {
-    //        var arguments = (Tuple<HiveTask, HiveTask>)tuple;
-    //        UploadTaskWithChildren_Old(progress, arguments.Item1, arguments.Item2, groups, taskCount, totalJobCount, configPluginId, jobId, log, cancellationToken);
-    //      }, new Tuple<HiveTask, HiveTask>(child, hiveTask));
-    //      task.ContinueWith((x) => log.LogException(x.Exception), TaskContinuationOptions.OnlyOnFaulted);
-    //      tasks.Add(task);
-    //    }
-    //    taskUploadSemaphore.Release(); semaphoreReleased = true; // the semaphore has to be release before waitall!
-    //    TS.Task.WaitAll(tasks.ToArray());
-    //  }
-    //  finally {
-    //    if (!semaphoreReleased) taskUploadSemaphore.Release();
-    //  }
-    //}
-    
     #endregion
 
