source: branches/2839_HiveProjectManagement/HeuristicLab.Clients.Hive/3.3/HiveAdminClient.cs @ 15966

Last change on this file since 15966 was 15966, checked in by jzenisek, 15 months ago

#2839: Fixed several bugs and added project duration handling

  • fixed project duration handling (client- & service-side)
  • fixed tagging in HiveJobAdmin
  • added ProjectJobs view (under construction)
  • added necessary service methods
File size: 15.8 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2016 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
4 *
5 * This file is part of HeuristicLab.
6 *
7 * HeuristicLab is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * HeuristicLab is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
19 */
20#endregion
21
22using System;
23using System.Threading;
24using HeuristicLab.Common;
25using HeuristicLab.Core;
26using System.Collections.Generic;
27using System.Linq;
28
29namespace HeuristicLab.Clients.Hive {
30  [Item("Hive Administrator", "Hive Administrator")]
31  public sealed class HiveAdminClient : IContent {
32    private static HiveAdminClient instance;
33    public static HiveAdminClient Instance {
34      get {
35        if (instance == null) instance = new HiveAdminClient();
36        return instance;
37      }
38    }
39
40    #region Properties
41    private IItemList<Resource> resources;
42    public IItemList<Resource> Resources {
43      get { return resources; }
44    }
45
46    private IItemList<Downtime> downtimes;
47    public IItemList<Downtime> Downtimes {
48      get { return downtimes; }
49    }
50
51    private Guid downtimeForResourceId;
52    public Guid DowntimeForResourceId {
53      get { return downtimeForResourceId; }
54      set {
55        downtimeForResourceId = value;
56        if (downtimes != null) {
57          downtimes.Clear();
58        }
59      }
60    }
61
62    private IItemList<Project> projects;
63    public IItemList<Project> Projects {
64      get { return projects; }
65    }
66
67    private IItemList<AssignedProjectResource> projectResourceAssignments;
68    public IItemList<AssignedProjectResource> ProjectResourceAssignments {
69      get { return projectResourceAssignments; }
70    }
71
72    private Dictionary<Guid, HiveItemCollection<Job>> jobs;
73    public Dictionary<Guid, HiveItemCollection<Job>> Jobs {
74      get { return jobs; }
75      set {
76        if (value != jobs)
77          jobs = value;
78        }
79    }
80
81
82    //private Dictionary<Guid, HashSet<Project>> projectAncestors;
83    //public Dictionary<Guid, HashSet<Project>> ProjectAncestors {
84    //  get { return projectAncestors; }
85    //}
86
87    //private Dictionary<Guid, HashSet<Project>> projectDescendants;
88    //public Dictionary<Guid, HashSet<Project>> ProjectDescendants {
89    //  get { return projectDescendants; }
90    //}
91
92    //private Dictionary<Guid, HashSet<Resource>> resourceAncestors;
93    //public Dictionary<Guid, HashSet<Resource>> ResourceAncestors {
94    //  get { return resourceAncestors; }
95    //}
96
97    //private Dictionary<Guid, HashSet<Resource>> resourceDescendants;
98    //public Dictionary<Guid, HashSet<Resource>> ResourceDescendants {
99    //  get { return resourceDescendants; }
100    //}
101
102    private Dictionary<Guid, HashSet<Guid>> projectAncestors;
103    public Dictionary<Guid, HashSet<Guid>> ProjectAncestors {
104      get { return projectAncestors; }
105    }
106
107    private Dictionary<Guid, HashSet<Guid>> projectDescendants;
108    public Dictionary<Guid, HashSet<Guid>> ProjectDescendants {
109      get { return projectDescendants; }
110    }
111
112    private Dictionary<Guid, HashSet<Guid>> resourceAncestors;
113    public Dictionary<Guid, HashSet<Guid>> ResourceAncestors {
114      get { return resourceAncestors; }
115    }
116
117    private Dictionary<Guid, HashSet<Guid>> resourceDescendants;
118    public Dictionary<Guid, HashSet<Guid>> ResourceDescendants {
119      get { return resourceDescendants; }
120    }
121    #endregion
122
123    #region Events
124    public event EventHandler Refreshing;
125    private void OnRefreshing() {
126      EventHandler handler = Refreshing;
127      if (handler != null) handler(this, EventArgs.Empty);
128    }
129    public event EventHandler Refreshed;
130    private void OnRefreshed() {
131      var handler = Refreshed;
132      if (handler != null) handler(this, EventArgs.Empty);
133    }
134    #endregion
135
136    private HiveAdminClient() { }
137
138    #region Refresh
139    public void Refresh() {
140      OnRefreshing();
141
142      try {
143        resources = new ItemList<Resource>();
144        projects = new ItemList<Project>();
145        projectResourceAssignments = new ItemList<AssignedProjectResource>();
146        jobs = new Dictionary<Guid, HiveItemCollection<Job>>();
147
148        projectAncestors = new Dictionary<Guid, HashSet<Guid>>();
149        projectDescendants = new Dictionary<Guid, HashSet<Guid>>();
150        resourceAncestors = new Dictionary<Guid, HashSet<Guid>>();
151        resourceDescendants = new Dictionary<Guid, HashSet<Guid>>();
152
153        HiveServiceLocator.Instance.CallHiveService(service => {
154          service.GetSlaveGroupsForAdministration().ForEach(g => resources.Add(g));
155          service.GetSlavesForAdministration().ForEach(s => resources.Add(s));
156          service.GetProjectsForAdministration().ForEach(p => projects.Add(p));
157          var projectIds = projects.Select(p => p.Id).ToList();
158          if (projectIds.Any()) {
159            service.GetAssignedResourcesForProjectsAdministration(projectIds)
160              .ForEach(a => projectResourceAssignments.Add(a));
161            projectIds.ForEach(p => jobs.Add(p, new HiveItemCollection<Job>()));
162            service.GetJobsByProjectIds(projectIds)
163              .ForEach(j => jobs[j.ProjectId].Add(j));
164          }
165        });
166
167        UpdateResourceGenealogy();
168        UpdateProjectGenealogy();
169      }
170      catch {
171        throw;
172      }
173      finally {
174        OnRefreshed();
175      }
176    }
177
178    //public void UpdateResourceGenealogy(IItemList<Resource> resources) {
179    //  resourceAncestors.Clear();
180    //  resourceDescendants.Clear();
181
182    //  foreach (var r in resources) {
183    //    resourceAncestors.Add(r.Id, new HashSet<Resource>());
184    //    resourceDescendants.Add(r.Id, new HashSet<Resource>());
185    //  }
186
187    //  foreach (var r in resources) {
188    //    var parentResourceId = r.ParentResourceId;
189    //    while (parentResourceId != null) {
190    //      var parent = resources.SingleOrDefault(x => x.Id == parentResourceId);
191    //      if (parent != null) {
192    //        resourceAncestors[r.Id].Add(parent);
193    //        resourceDescendants[parent.Id].Add(r);
194    //        parentResourceId = parent.ParentResourceId;
195    //      } else {
196    //        parentResourceId = null;
197    //      }
198    //    }
199    //  }
200    //}
201
202    //public void UpdateProjectGenealogy(IItemList<Project> projects) {
203    //  projectAncestors.Clear();
204    //  projectDescendants.Clear();
205
206    //  foreach (var p in projects) {
207    //    projectAncestors.Add(p.Id, new HashSet<Project>());
208    //    projectDescendants.Add(p.Id, new HashSet<Project>());
209    //  }
210
211    //  foreach (var p in projects) {
212    //    var parentProjectId = p.ParentProjectId;
213    //    while (parentProjectId != null) {
214    //      var parent = projects.SingleOrDefault(x => x.Id == parentProjectId);
215    //      if (parent != null) {
216    //        projectAncestors[p.Id].Add(parent);
217    //        projectDescendants[parent.Id].Add(p);
218    //        parentProjectId = parent.ParentProjectId;
219    //      } else {
220    //        parentProjectId = null;
221    //      }
222    //    }
223    //  }
224    //}
225
226    private void UpdateResourceGenealogy() {
227      resourceAncestors.Clear();
228      resourceDescendants.Clear();
229
230      // fetch resource ancestor set
231      HiveServiceLocator.Instance.CallHiveService(service => {
232        var ra = service.GetResourceGenealogy();
233        ra.Keys.ToList().ForEach(k => resourceAncestors.Add(k, new HashSet<Guid>()));
234        resourceAncestors.Keys.ToList().ForEach(k => resourceAncestors[k].UnionWith(ra[k]));
235      });
236
237      // build resource descendant set
238      resourceAncestors.Keys.ToList().ForEach(k => resourceDescendants.Add(k, new HashSet<Guid>()));
239      foreach (var ra in resourceAncestors) {
240        foreach (var ancestor in ra.Value) {
241          resourceDescendants[ancestor].Add(ra.Key);
242        }
243      }
244    }
245
246    private void UpdateProjectGenealogy() {
247      projectAncestors.Clear();
248      projectDescendants.Clear();
249
250      // fetch project ancestor list
251      HiveServiceLocator.Instance.CallHiveService(service => {
252        var pa = service.GetProjectGenealogy();
253        pa.Keys.ToList().ForEach(k => projectAncestors.Add(k, new HashSet<Guid>()));
254        projectAncestors.Keys.ToList().ForEach(k => projectAncestors[k].UnionWith(pa[k]));
255      });
256
257      // build project descendant list
258      projectAncestors.Keys.ToList().ForEach(k => projectDescendants.Add(k, new HashSet<Guid>()));
259      foreach (var pa in projectAncestors) {
260        foreach (var ancestor in pa.Value) {
261          projectDescendants[ancestor].Add(pa.Key);
262        }
263      }
264    }
265
266    #endregion
267
268    #region Refresh downtime calendar
269    public void RefreshCalendar() {
270      if (downtimeForResourceId != null && downtimeForResourceId != Guid.Empty) {
271        OnRefreshing();
272
273        try {
274          downtimes = new ItemList<Downtime>();
275
276          HiveServiceLocator.Instance.CallHiveService(service => {
277            service.GetDowntimesForResource(downtimeForResourceId).ForEach(d => downtimes.Add(d));
278          });
279        }
280        catch {
281          throw;
282        }
283        finally {
284          OnRefreshed();
285        }
286      }
287    }
288    #endregion
289
290    #region Store
291    public static void Store(IHiveItem item, CancellationToken cancellationToken) {
292      if (item.Id == Guid.Empty) {
293        if (item is SlaveGroup) {
294          item.Id = HiveServiceLocator.Instance.CallHiveService((s) => s.AddSlaveGroup((SlaveGroup)item));
295        }
296        if (item is Slave) {
297          item.Id = HiveServiceLocator.Instance.CallHiveService((s) => s.AddSlave((Slave)item));
298        }
299        if (item is Downtime) {
300          item.Id = HiveServiceLocator.Instance.CallHiveService((s) => s.AddDowntime((Downtime)item));
301        }
302        if (item is Project) {
303          item.Id = HiveServiceLocator.Instance.CallHiveService(s => s.AddProject((Project)item));
304        }
305      } else {
306        if (item is SlaveGroup) {
307          HiveServiceLocator.Instance.CallHiveService((s) => s.UpdateSlaveGroup((SlaveGroup)item));
308        }
309        if (item is Slave) {
310          HiveServiceLocator.Instance.CallHiveService((s) => s.UpdateSlave((Slave)item));
311        }
312        if (item is Downtime) {
313          HiveServiceLocator.Instance.CallHiveService((s) => s.UpdateDowntime((Downtime)item));
314        }
315        if (item is Project) {
316          HiveServiceLocator.Instance.CallHiveService((s) => s.UpdateProject((Project)item));
317        }
318      }
319    }
320    #endregion
321
322    #region Delete
323    public static void Delete(IHiveItem item) {
324      if (item is SlaveGroup) {
325        HiveServiceLocator.Instance.CallHiveService((s) => s.DeleteSlaveGroup(item.Id));
326      } else if (item is Slave) {
327        HiveServiceLocator.Instance.CallHiveService((s) => s.DeleteSlave(item.Id));
328      } else if (item is Downtime) {
329        HiveServiceLocator.Instance.CallHiveService((s) => s.DeleteDowntime(item.Id));
330      } else if (item is Project) {
331        HiveServiceLocator.Instance.CallHiveService((s) => s.DeleteProject(item.Id));
332      }
333    }
334    #endregion
335
336    public void ResetDowntime() {
337      downtimeForResourceId = Guid.Empty;
338      if (downtimes != null) {
339        downtimes.Clear();
340      }
341    }
342
343    #region Helper
344    public IEnumerable<Project> GetAvailableProjectAncestors(Guid id) {
345      if (projectAncestors.ContainsKey(id)) return projects.Where(x => projectAncestors[id].Contains(x.Id));
346      else return Enumerable.Empty<Project>();
347    }
348
349    public IEnumerable<Project> GetAvailableProjectDescendants(Guid id) {
350      if(projectDescendants.ContainsKey(id)) return projects.Where(x => projectDescendants[id].Contains(x.Id));
351      else return Enumerable.Empty<Project>();
352    }
353
354    public IEnumerable<Resource> GetAvailableResourceAncestors(Guid id) {
355      if (resourceAncestors.ContainsKey(id)) return resources.Where(x => resourceAncestors[id].Contains(x.Id));
356      else return Enumerable.Empty<Resource>();
357    }
358
359    public IEnumerable<Resource> GetAvailableResourceDescendants(Guid id) {
360      if (resourceDescendants.ContainsKey(id)) return resources.Where(x => resourceDescendants[id].Contains(x.Id));
361      else return Enumerable.Empty<Resource>();
362    }
363
364    public bool CheckAccessToAdminAreaGranted() {
365      if(projects != null) {
366        return projects.Count > 0;
367      } else {
368        bool accessGranted = false;
369        HiveServiceLocator.Instance.CallHiveService(s => {
370          accessGranted = s.CheckAccessToAdminAreaGranted();
371        });
372        return accessGranted;
373      }
374    }
375
376    public bool CheckOwnershipOfResource(Resource res, Guid userId) {
377      if (res == null || userId == Guid.Empty) return false;
378
379      if (res.OwnerUserId == userId) {
380        return true;
381      } else if(resourceAncestors.ContainsKey(res.Id)) {
382        return GetAvailableResourceAncestors(res.Id).Where(x => x.OwnerUserId == userId).Any();
383      }
384
385      return false;
386    }
387
388    public bool CheckOwnershipOfProject(Project pro, Guid userId) {
389      if (pro == null || userId == Guid.Empty) return false;
390
391      if (pro.OwnerUserId == userId) {
392        return true;
393      } else if (projectAncestors.ContainsKey(pro.Id)) {
394        return GetAvailableProjectAncestors(pro.Id).Where(x => x.OwnerUserId == userId).Any();
395      }
396
397      return false;
398    }
399
400    public bool CheckOwnershipOfParentProject(Project pro, Guid userId) {
401      if (pro == null || userId == Guid.Empty) return false;
402
403      if(projectAncestors.ContainsKey(pro.Id)) {
404        return GetAvailableProjectAncestors(pro.Id).Where(x => x.OwnerUserId == userId).Any();
405      }
406
407      return false;
408    }
409
410    public bool CheckParentChange(Project child, Project parent) {
411      bool changePossible = true;
412
413      // change is not possible...
414      // ... if the moved project is null
415      // ... or the new parent is not stored yet
416      // ... or there is not parental change
417      if (child == null 
418        || (parent != null && parent.Id == Guid.Empty)
419        || (parent != null && parent.Id == child.ParentProjectId)) {
420        changePossible = false;
421      } else if(parent != null && projectDescendants.ContainsKey(child.Id)) {
422        // ... if the new parent is among the moved project's descendants
423        changePossible = !GetAvailableProjectDescendants(child.Id).Where(x => x.Id == parent.Id).Any();
424      }
425
426      return changePossible;
427    }
428
429    public bool CheckParentChange(Resource child, Resource parent) {
430      bool changePossible = true;
431
432      // change is not possisble...
433      // ... if the child resource is null
434      // ... or the child resource equals the parent
435      // ... or the new parent is not stored yet
436      // ... or the new parent is a slave
437      // ... or there is not parental change
438      if (child == null 
439        || child == parent
440        || (parent != null && parent.Id == Guid.Empty)
441        || (parent != null && parent is Slave)
442        || (parent != null && parent.Id == child.ParentResourceId)) {
443        changePossible = false;
444      } else if (parent != null && resourceDescendants.ContainsKey(child.Id)) {
445        // ... or if the new parent is among the moved resource's descendants
446        changePossible = !GetAvailableResourceDescendants(child.Id).Where(x => x.Id == parent.Id).Any();
447      }
448
449      return changePossible;
450    }
451    #endregion
452  }
453}
Note: See TracBrowser for help on using the repository browser.