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

Last change on this file since 15922 was 15922, checked in by jzenisek, 16 months ago

#2839:

  • replaced use of TreeView with NoDoubleClickTreeView everywhere allegedly reasonable for Hive
  • updated genealogy computation for HiveAdminClient and corresponding views (ResourcesView & ProjectResourcesView)
File size: 15.6 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, HashSet<Project>> projectAncestors;
73    //public Dictionary<Guid, HashSet<Project>> ProjectAncestors {
74    //  get { return projectAncestors; }
75    //}
76
77    //private Dictionary<Guid, HashSet<Project>> projectDescendants;
78    //public Dictionary<Guid, HashSet<Project>> ProjectDescendants {
79    //  get { return projectDescendants; }
80    //}
81
82    //private Dictionary<Guid, HashSet<Resource>> resourceAncestors;
83    //public Dictionary<Guid, HashSet<Resource>> ResourceAncestors {
84    //  get { return resourceAncestors; }
85    //}
86
87    //private Dictionary<Guid, HashSet<Resource>> resourceDescendants;
88    //public Dictionary<Guid, HashSet<Resource>> ResourceDescendants {
89    //  get { return resourceDescendants; }
90    //}
91
92    private Dictionary<Guid, HashSet<Guid>> projectAncestors;
93    public Dictionary<Guid, HashSet<Guid>> ProjectAncestors {
94      get { return projectAncestors; }
95    }
96
97    private Dictionary<Guid, HashSet<Guid>> projectDescendants;
98    public Dictionary<Guid, HashSet<Guid>> ProjectDescendants {
99      get { return projectDescendants; }
100    }
101
102    private Dictionary<Guid, HashSet<Guid>> resourceAncestors;
103    public Dictionary<Guid, HashSet<Guid>> ResourceAncestors {
104      get { return resourceAncestors; }
105    }
106
107    private Dictionary<Guid, HashSet<Guid>> resourceDescendants;
108    public Dictionary<Guid, HashSet<Guid>> ResourceDescendants {
109      get { return resourceDescendants; }
110    }
111    #endregion
112
113    #region Events
114    public event EventHandler Refreshing;
115    private void OnRefreshing() {
116      EventHandler handler = Refreshing;
117      if (handler != null) handler(this, EventArgs.Empty);
118    }
119    public event EventHandler Refreshed;
120    private void OnRefreshed() {
121      var handler = Refreshed;
122      if (handler != null) handler(this, EventArgs.Empty);
123    }
124    #endregion
125
126    private HiveAdminClient() { }
127
128    #region Refresh
129    public void Refresh() {
130      OnRefreshing();
131
132      try {
133        resources = new ItemList<Resource>();
134        projects = new ItemList<Project>();
135        projectResourceAssignments = new ItemList<AssignedProjectResource>();
136
137        //projectAncestors = new Dictionary<Guid, HashSet<Project>>();
138        //projectDescendants = new Dictionary<Guid, HashSet<Project>>();
139        //resourceAncestors = new Dictionary<Guid, HashSet<Resource>>();
140        //resourceDescendants = new Dictionary<Guid, HashSet<Resource>>();
141        projectAncestors = new Dictionary<Guid, HashSet<Guid>>();
142        projectDescendants = new Dictionary<Guid, HashSet<Guid>>();
143        resourceAncestors = new Dictionary<Guid, HashSet<Guid>>();
144        resourceDescendants = new Dictionary<Guid, HashSet<Guid>>();
145
146        HiveServiceLocator.Instance.CallHiveService(service => {
147          service.GetSlaveGroupsForAdministration().ForEach(g => resources.Add(g));
148          service.GetSlavesForAdministration().ForEach(s => resources.Add(s));
149          service.GetProjectsForAdministration().ForEach(p => projects.Add(p));
150          var projectIds = projects.Select(p => p.Id).ToList();
151          if(projectIds.Any())
152            service.GetAssignedResourcesForProjectsAdministration(projectIds)
153            .ForEach(a => projectResourceAssignments.Add(a));
154        });
155
156        UpdateResourceGenealogy();
157        UpdateProjectGenealogy();
158      }
159      catch {
160        throw;
161      }
162      finally {
163        OnRefreshed();
164      }
165    }
166
167    //public void UpdateResourceGenealogy(IItemList<Resource> resources) {
168    //  resourceAncestors.Clear();
169    //  resourceDescendants.Clear();
170
171    //  foreach (var r in resources) {
172    //    resourceAncestors.Add(r.Id, new HashSet<Resource>());
173    //    resourceDescendants.Add(r.Id, new HashSet<Resource>());
174    //  }
175
176    //  foreach (var r in resources) {
177    //    var parentResourceId = r.ParentResourceId;
178    //    while (parentResourceId != null) {
179    //      var parent = resources.SingleOrDefault(x => x.Id == parentResourceId);
180    //      if (parent != null) {
181    //        resourceAncestors[r.Id].Add(parent);
182    //        resourceDescendants[parent.Id].Add(r);
183    //        parentResourceId = parent.ParentResourceId;
184    //      } else {
185    //        parentResourceId = null;
186    //      }
187    //    }
188    //  }
189    //}
190
191    //public void UpdateProjectGenealogy(IItemList<Project> projects) {
192    //  projectAncestors.Clear();
193    //  projectDescendants.Clear();
194
195    //  foreach (var p in projects) {
196    //    projectAncestors.Add(p.Id, new HashSet<Project>());
197    //    projectDescendants.Add(p.Id, new HashSet<Project>());
198    //  }
199
200    //  foreach (var p in projects) {
201    //    var parentProjectId = p.ParentProjectId;
202    //    while (parentProjectId != null) {
203    //      var parent = projects.SingleOrDefault(x => x.Id == parentProjectId);
204    //      if (parent != null) {
205    //        projectAncestors[p.Id].Add(parent);
206    //        projectDescendants[parent.Id].Add(p);
207    //        parentProjectId = parent.ParentProjectId;
208    //      } else {
209    //        parentProjectId = null;
210    //      }
211    //    }
212    //  }
213    //}
214
215    private void UpdateResourceGenealogy() {
216      resourceAncestors.Clear();
217      resourceDescendants.Clear();
218
219      // fetch resource ancestor set
220      HiveServiceLocator.Instance.CallHiveService(service => {
221        var ra = service.GetResourceGenealogy();
222        ra.Keys.ToList().ForEach(k => resourceAncestors.Add(k, new HashSet<Guid>()));
223        resourceAncestors.Keys.ToList().ForEach(k => resourceAncestors[k].UnionWith(ra[k]));
224      });
225
226      // build resource descendant set
227      resourceAncestors.Keys.ToList().ForEach(k => resourceDescendants.Add(k, new HashSet<Guid>()));
228      foreach (var ra in resourceAncestors) {
229        foreach (var ancestor in ra.Value) {
230          resourceDescendants[ancestor].Add(ra.Key);
231        }
232      }
233    }
234
235    private void UpdateProjectGenealogy() {
236      projectAncestors.Clear();
237      projectDescendants.Clear();
238
239      // fetch project ancestor list
240      HiveServiceLocator.Instance.CallHiveService(service => {
241        var pa = service.GetProjectGenealogy();
242        pa.Keys.ToList().ForEach(k => projectAncestors.Add(k, new HashSet<Guid>()));
243        projectAncestors.Keys.ToList().ForEach(k => projectAncestors[k].UnionWith(pa[k]));
244      });
245
246      // build project descendant list
247      projectAncestors.Keys.ToList().ForEach(k => projectDescendants.Add(k, new HashSet<Guid>()));
248      foreach (var pa in projectAncestors) {
249        foreach (var ancestor in pa.Value) {
250          projectDescendants[ancestor].Add(pa.Key);
251        }
252      }
253    }
254
255    #endregion
256
257    #region Refresh downtime calendar
258    public void RefreshCalendar() {
259      if (downtimeForResourceId != null && downtimeForResourceId != Guid.Empty) {
260        OnRefreshing();
261
262        try {
263          downtimes = new ItemList<Downtime>();
264
265          HiveServiceLocator.Instance.CallHiveService(service => {
266            service.GetDowntimesForResource(downtimeForResourceId).ForEach(d => downtimes.Add(d));
267          });
268        }
269        catch {
270          throw;
271        }
272        finally {
273          OnRefreshed();
274        }
275      }
276    }
277    #endregion
278
279    #region Store
280    public static void Store(IHiveItem item, CancellationToken cancellationToken) {
281      if (item.Id == Guid.Empty) {
282        if (item is SlaveGroup) {
283          item.Id = HiveServiceLocator.Instance.CallHiveService((s) => s.AddSlaveGroup((SlaveGroup)item));
284        }
285        if (item is Slave) {
286          item.Id = HiveServiceLocator.Instance.CallHiveService((s) => s.AddSlave((Slave)item));
287        }
288        if (item is Downtime) {
289          item.Id = HiveServiceLocator.Instance.CallHiveService((s) => s.AddDowntime((Downtime)item));
290        }
291        if (item is Project) {
292          item.Id = HiveServiceLocator.Instance.CallHiveService(s => s.AddProject((Project)item));
293        }
294      } else {
295        if (item is SlaveGroup) {
296          HiveServiceLocator.Instance.CallHiveService((s) => s.UpdateSlaveGroup((SlaveGroup)item));
297        }
298        if (item is Slave) {
299          HiveServiceLocator.Instance.CallHiveService((s) => s.UpdateSlave((Slave)item));
300        }
301        if (item is Downtime) {
302          HiveServiceLocator.Instance.CallHiveService((s) => s.UpdateDowntime((Downtime)item));
303        }
304        if (item is Project) {
305          HiveServiceLocator.Instance.CallHiveService((s) => s.UpdateProject((Project)item));
306        }
307      }
308    }
309    #endregion
310
311    #region Delete
312    public static void Delete(IHiveItem item) {
313      if (item is SlaveGroup) {
314        HiveServiceLocator.Instance.CallHiveService((s) => s.DeleteSlaveGroup(item.Id));
315      } else if (item is Slave) {
316        HiveServiceLocator.Instance.CallHiveService((s) => s.DeleteSlave(item.Id));
317      } else if (item is Downtime) {
318        HiveServiceLocator.Instance.CallHiveService((s) => s.DeleteDowntime(item.Id));
319      } else if (item is Project) {
320        HiveServiceLocator.Instance.CallHiveService((s) => s.DeleteProject(item.Id));
321      }
322    }
323    #endregion
324
325    public void ResetDowntime() {
326      downtimeForResourceId = Guid.Empty;
327      if (downtimes != null) {
328        downtimes.Clear();
329      }
330    }
331
332    #region Helper
333    public IEnumerable<Project> GetAvailableProjectAncestors(Guid id) {
334      if (projectAncestors.ContainsKey(id)) return projects.Where(x => projectAncestors[id].Contains(x.Id));
335      else return Enumerable.Empty<Project>();
336    }
337
338    public IEnumerable<Project> GetAvailableProjectDescendants(Guid id) {
339      if(projectDescendants.ContainsKey(id)) return projects.Where(x => projectDescendants[id].Contains(x.Id));
340      else return Enumerable.Empty<Project>();
341    }
342
343    public IEnumerable<Resource> GetAvailableResourceAncestors(Guid id) {
344      if (resourceAncestors.ContainsKey(id)) return resources.Where(x => resourceAncestors[id].Contains(x.Id));
345      else return Enumerable.Empty<Resource>();
346    }
347
348    public IEnumerable<Resource> GetAvailableResourceDescendants(Guid id) {
349      if (resourceDescendants.ContainsKey(id)) return resources.Where(x => resourceDescendants[id].Contains(x.Id));
350      else return Enumerable.Empty<Resource>();
351    }
352
353    public bool CheckAccessToAdminAreaGranted() {
354      if(projects != null) {
355        return projects.Count > 0;
356      } else {
357        bool accessGranted = false;
358        HiveServiceLocator.Instance.CallHiveService(s => {
359          accessGranted = s.CheckAccessToAdminAreaGranted();
360        });
361        return accessGranted;
362      }
363    }
364
365    public bool CheckOwnershipOfResource(Resource res, Guid userId) {
366      if (res == null || userId == Guid.Empty) return false;
367
368      if (res.OwnerUserId == userId) {
369        return true;
370      } else if(resourceAncestors.ContainsKey(res.Id)) {
371        return GetAvailableResourceAncestors(res.Id).Where(x => x.OwnerUserId == userId).Any();
372      }
373
374      return false;
375    }
376
377    public bool CheckOwnershipOfProject(Project pro, Guid userId) {
378      if (pro == null || userId == Guid.Empty) return false;
379
380      if (pro.OwnerUserId == userId) {
381        return true;
382      } else if (projectAncestors.ContainsKey(pro.Id)) {
383        return GetAvailableProjectAncestors(pro.Id).Where(x => x.OwnerUserId == userId).Any();
384      }
385
386      return false;
387    }
388
389    public bool CheckOwnershipOfParentProject(Project pro, Guid userId) {
390      if (pro == null || userId == Guid.Empty) return false;
391
392      if(projectAncestors.ContainsKey(pro.Id)) {
393        return GetAvailableProjectAncestors(pro.Id).Where(x => x.OwnerUserId == userId).Any();
394      }
395
396      return false;
397    }
398
399    public bool CheckParentChange(Project child, Project parent) {
400      bool changePossible = true;
401
402      // change is not possible...
403      // ... if the moved project is null
404      // ... or the new parent is not stored yet
405      // ... or there is not parental change
406      if (child == null 
407        || (parent != null && parent.Id == Guid.Empty)
408        || (parent != null && parent.Id == child.ParentProjectId)) {
409        changePossible = false;
410      } else if(parent != null && projectDescendants.ContainsKey(child.Id)) {
411        // ... if the new parent is among the moved project's descendants
412        changePossible = !GetAvailableProjectDescendants(child.Id).Where(x => x.Id == parent.Id).Any();
413      }
414
415      return changePossible;
416    }
417
418    public bool CheckParentChange(Resource child, Resource parent) {
419      bool changePossible = true;
420
421      // change is not possisble...
422      // ... if the child resource is null
423      // ... or the child resource equals the parent
424      // ... or the new parent is not stored yet
425      // ... or the new parent is a slave
426      // ... or there is not parental change
427      if (child == null 
428        || child == parent
429        || (parent != null && parent.Id == Guid.Empty)
430        || (parent != null && parent is Slave)
431        || (parent != null && parent.Id == child.ParentResourceId)) {
432        changePossible = false;
433      } else if (parent != null && resourceDescendants.ContainsKey(child.Id)) {
434        // ... or if the new parent is among the moved resource's descendants
435        changePossible = !GetAvailableResourceDescendants(child.Id).Where(x => x.Id == parent.Id).Any();
436      }
437
438      return changePossible;
439    }
440    #endregion
441  }
442}
Note: See TracBrowser for help on using the repository browser.