Free cookie consent management tool by TermsFeed Policy Generator

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

Last change on this file since 17590 was 16072, checked in by jzenisek, 6 years ago

#2839: worked on HiveProjectMgmt:

  • adapted enabled state of buttons
File size: 19.0 KB
RevLine 
[6976]1#region License Information
2/* HeuristicLab
[16057]3 * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
[6976]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;
[15658]26using System.Collections.Generic;
[15742]27using System.Linq;
[6976]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
[15658]40    #region Properties
[6976]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
[15401]62    private IItemList<Project> projects;
63    public IItemList<Project> Projects {
64      get { return projects; }
65    }
66
[15819]67    private IItemList<AssignedProjectResource> projectResourceAssignments;
68    public IItemList<AssignedProjectResource> ProjectResourceAssignments {
69      get { return projectResourceAssignments; }
70    }
71
[15966]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
[15922]81    private Dictionary<Guid, HashSet<Guid>> projectAncestors;
82    public Dictionary<Guid, HashSet<Guid>> ProjectAncestors {
[15742]83      get { return projectAncestors; }
84    }
85
[15922]86    private Dictionary<Guid, HashSet<Guid>> projectDescendants;
87    public Dictionary<Guid, HashSet<Guid>> ProjectDescendants {
[15742]88      get { return projectDescendants; }
89    }
90
[15922]91    private Dictionary<Guid, HashSet<Guid>> resourceAncestors;
92    public Dictionary<Guid, HashSet<Guid>> ResourceAncestors {
[15792]93      get { return resourceAncestors; }
[15742]94    }
95
[15922]96    private Dictionary<Guid, HashSet<Guid>> resourceDescendants;
97    public Dictionary<Guid, HashSet<Guid>> ResourceDescendants {
[15792]98      get { return resourceDescendants; }
[15742]99    }
[15995]100
101    private Dictionary<Guid, string> projectNames;
102    public Dictionary<Guid, string> ProjectNames {
103      get { return projectNames; }
104    }
105
106    private HashSet<Project> disabledParentProjects;
107    public HashSet<Project> DisabledParentProjects {
108      get { return disabledParentProjects; }
109    }
110
111    private Dictionary<Guid, string> resourceNames;
112    public Dictionary<Guid, string> ResourceNames {
113      get { return resourceNames; }
114    }
115
116    private HashSet<Resource> disabledParentResources;
117    public HashSet<Resource> DisabledParentResources {
118      get { return disabledParentResources; }
119    }
[15658]120    #endregion
121
[6976]122    #region Events
123    public event EventHandler Refreshing;
124    private void OnRefreshing() {
125      EventHandler handler = Refreshing;
126      if (handler != null) handler(this, EventArgs.Empty);
127    }
128    public event EventHandler Refreshed;
129    private void OnRefreshed() {
130      var handler = Refreshed;
131      if (handler != null) handler(this, EventArgs.Empty);
132    }
133    #endregion
134
135    private HiveAdminClient() { }
136
137    #region Refresh
138    public void Refresh() {
139      OnRefreshing();
140
141      try {
142        resources = new ItemList<Resource>();
[15401]143        projects = new ItemList<Project>();
[15819]144        projectResourceAssignments = new ItemList<AssignedProjectResource>();
[15966]145        jobs = new Dictionary<Guid, HiveItemCollection<Job>>();
[15995]146        projectNames = new Dictionary<Guid, string>();
147        resourceNames = new Dictionary<Guid, string>();
[6976]148
[15922]149        projectAncestors = new Dictionary<Guid, HashSet<Guid>>();
150        projectDescendants = new Dictionary<Guid, HashSet<Guid>>();
151        resourceAncestors = new Dictionary<Guid, HashSet<Guid>>();
152        resourceDescendants = new Dictionary<Guid, HashSet<Guid>>();
[15742]153
[7132]154        HiveServiceLocator.Instance.CallHiveService(service => {
[15658]155          service.GetSlaveGroupsForAdministration().ForEach(g => resources.Add(g));
156          service.GetSlavesForAdministration().ForEach(s => resources.Add(s));
[15576]157          service.GetProjectsForAdministration().ForEach(p => projects.Add(p));
[15819]158          var projectIds = projects.Select(p => p.Id).ToList();
[15966]159          if (projectIds.Any()) {
[15819]160            service.GetAssignedResourcesForProjectsAdministration(projectIds)
[15966]161              .ForEach(a => projectResourceAssignments.Add(a));
162            projectIds.ForEach(p => jobs.Add(p, new HiveItemCollection<Job>()));
[15969]163            var unsortedJobs = service.GetJobsByProjectIds(projectIds)
164              .OrderBy(x => x.DateCreated).ToList();
[16072]165
[15969]166            unsortedJobs.Where(j => j.State == JobState.DeletionPending).ToList().ForEach(j => jobs[j.ProjectId].Add(j));
167            unsortedJobs.Where(j => j.State == JobState.StatisticsPending).ToList().ForEach(j => jobs[j.ProjectId].Add(j));
168            unsortedJobs.Where(j => j.State == JobState.Online).ToList().ForEach(j => jobs[j.ProjectId].Add(j));
[15995]169
170            projectNames = service.GetProjectNames();
171            resourceNames = service.GetResourceNames();
[15966]172          }
[6976]173        });
[15742]174
[15922]175        UpdateResourceGenealogy();
176        UpdateProjectGenealogy();
[15995]177        RefreshDisabledParentProjects();
178        RefreshDisabledParentResources();
[6976]179      }
180      catch {
181        throw;
182      }
183      finally {
184        OnRefreshed();
185      }
186    }
[15742]187
[15922]188    //public void UpdateResourceGenealogy(IItemList<Resource> resources) {
189    //  resourceAncestors.Clear();
190    //  resourceDescendants.Clear();
191
192    //  foreach (var r in resources) {
193    //    resourceAncestors.Add(r.Id, new HashSet<Resource>());
194    //    resourceDescendants.Add(r.Id, new HashSet<Resource>());
195    //  }
196
197    //  foreach (var r in resources) {
198    //    var parentResourceId = r.ParentResourceId;
199    //    while (parentResourceId != null) {
200    //      var parent = resources.SingleOrDefault(x => x.Id == parentResourceId);
201    //      if (parent != null) {
202    //        resourceAncestors[r.Id].Add(parent);
203    //        resourceDescendants[parent.Id].Add(r);
204    //        parentResourceId = parent.ParentResourceId;
205    //      } else {
206    //        parentResourceId = null;
207    //      }
208    //    }
209    //  }
210    //}
211
212    //public void UpdateProjectGenealogy(IItemList<Project> projects) {
213    //  projectAncestors.Clear();
214    //  projectDescendants.Clear();
215
216    //  foreach (var p in projects) {
217    //    projectAncestors.Add(p.Id, new HashSet<Project>());
218    //    projectDescendants.Add(p.Id, new HashSet<Project>());
219    //  }
220
221    //  foreach (var p in projects) {
222    //    var parentProjectId = p.ParentProjectId;
223    //    while (parentProjectId != null) {
224    //      var parent = projects.SingleOrDefault(x => x.Id == parentProjectId);
225    //      if (parent != null) {
226    //        projectAncestors[p.Id].Add(parent);
227    //        projectDescendants[parent.Id].Add(p);
228    //        parentProjectId = parent.ParentProjectId;
229    //      } else {
230    //        parentProjectId = null;
231    //      }
232    //    }
233    //  }
234    //}
235
236    private void UpdateResourceGenealogy() {
[15742]237      resourceAncestors.Clear();
238      resourceDescendants.Clear();
239
[15922]240      // fetch resource ancestor set
241      HiveServiceLocator.Instance.CallHiveService(service => {
242        var ra = service.GetResourceGenealogy();
243        ra.Keys.ToList().ForEach(k => resourceAncestors.Add(k, new HashSet<Guid>()));
244        resourceAncestors.Keys.ToList().ForEach(k => resourceAncestors[k].UnionWith(ra[k]));
245      });
[15742]246
[15922]247      // build resource descendant set
248      resourceAncestors.Keys.ToList().ForEach(k => resourceDescendants.Add(k, new HashSet<Guid>()));
249      foreach (var ra in resourceAncestors) {
250        foreach (var ancestor in ra.Value) {
251          resourceDescendants[ancestor].Add(ra.Key);
[15742]252        }
253      }
254    }
255
[15922]256    private void UpdateProjectGenealogy() {
[15742]257      projectAncestors.Clear();
258      projectDescendants.Clear();
259
[15922]260      // fetch project ancestor list
261      HiveServiceLocator.Instance.CallHiveService(service => {
262        var pa = service.GetProjectGenealogy();
263        pa.Keys.ToList().ForEach(k => projectAncestors.Add(k, new HashSet<Guid>()));
264        projectAncestors.Keys.ToList().ForEach(k => projectAncestors[k].UnionWith(pa[k]));
265      });
[15742]266
[15922]267      // build project descendant list
268      projectAncestors.Keys.ToList().ForEach(k => projectDescendants.Add(k, new HashSet<Guid>()));
269      foreach (var pa in projectAncestors) {
270        foreach (var ancestor in pa.Value) {
271          projectDescendants[ancestor].Add(pa.Key);
[15742]272        }
273      }
274    }
[15922]275
[15995]276    private void RefreshDisabledParentProjects() {
277      disabledParentProjects = new HashSet<Project>();
278
279      foreach (var pid in projects
280        .Where(x => x.ParentProjectId.HasValue)
281        .SelectMany(x => projectAncestors[x.Id]).Distinct()
282        .Where(x => !projects.Select(y => y.Id).Contains(x))) {
283        var p = new Project();
284        p.Id = pid;
285        p.ParentProjectId = projectAncestors[pid].FirstOrDefault();
286        p.Name = projectNames[pid];
287        disabledParentProjects.Add(p);
288      }
289    }
290
291    private void RefreshDisabledParentResources() {
292      disabledParentResources = new HashSet<Resource>();
293
294      foreach (var rid in resources
295        .Where(x => x.ParentResourceId.HasValue)
296        .SelectMany(x => resourceAncestors[x.Id]).Distinct()
297        .Where(x => !resources.Select(y => y.Id).Contains(x))) {
298        var r = new SlaveGroup();
299        r.Id = rid;
300        r.ParentResourceId = resourceAncestors[rid].FirstOrDefault();
301        r.Name = resourceNames[rid];
302        disabledParentResources.Add(r);
303      }
304    }
305
[15969]306    public void RefreshJobs() {
307      var projectIds = new List<Guid>();
308      jobs = new Dictionary<Guid, HiveItemCollection<Job>>();
309
310      HiveServiceLocator.Instance.CallHiveService(service => {
311        service.GetProjectsForAdministration().ForEach(p => projectIds.Add(p.Id));
312        if(projectIds.Any()) {
313          projectIds.ForEach(p => jobs.Add(p, new HiveItemCollection<Job>()));
314          var unsortedJobs = service.GetJobsByProjectIds(projectIds)
315            .OrderBy(x => x.DateCreated).ToList();
316          unsortedJobs.Where(j => j.State == JobState.DeletionPending).ToList().ForEach(j => jobs[j.ProjectId].Add(j));
317          unsortedJobs.Where(j => j.State == JobState.StatisticsPending).ToList().ForEach(j => jobs[j.ProjectId].Add(j));
318          unsortedJobs.Where(j => j.State == JobState.Online).ToList().ForEach(j => jobs[j.ProjectId].Add(j));
319        }
320      });
321    }
322
323    public void SortJobs() {
324      for(int i = 0; i < jobs.Count; i++) {
325        var projectId = jobs.Keys.ElementAt(i);
326        var unsortedJobs = jobs.Values.ElementAt(i);
327
328        var sortedJobs = new HiveItemCollection<Job>();
329        sortedJobs.AddRange(unsortedJobs.Where(j => j.State == JobState.DeletionPending));
330        sortedJobs.AddRange(unsortedJobs.Where(j => j.State == JobState.StatisticsPending));
331        sortedJobs.AddRange(unsortedJobs.Where(j => j.State == JobState.Online));
332
333        jobs[projectId] = sortedJobs;
334      }
335    }
336
[6976]337    #endregion
338
339    #region Refresh downtime calendar
340    public void RefreshCalendar() {
341      if (downtimeForResourceId != null && downtimeForResourceId != Guid.Empty) {
342        OnRefreshing();
343
344        try {
345          downtimes = new ItemList<Downtime>();
346
[7132]347          HiveServiceLocator.Instance.CallHiveService(service => {
[6976]348            service.GetDowntimesForResource(downtimeForResourceId).ForEach(d => downtimes.Add(d));
349          });
350        }
351        catch {
352          throw;
353        }
354        finally {
355          OnRefreshed();
356        }
357      }
358    }
359    #endregion
360
361    #region Store
362    public static void Store(IHiveItem item, CancellationToken cancellationToken) {
363      if (item.Id == Guid.Empty) {
364        if (item is SlaveGroup) {
[7132]365          item.Id = HiveServiceLocator.Instance.CallHiveService((s) => s.AddSlaveGroup((SlaveGroup)item));
[6976]366        }
367        if (item is Slave) {
[7132]368          item.Id = HiveServiceLocator.Instance.CallHiveService((s) => s.AddSlave((Slave)item));
[6976]369        }
370        if (item is Downtime) {
[7132]371          item.Id = HiveServiceLocator.Instance.CallHiveService((s) => s.AddDowntime((Downtime)item));
[6976]372        }
[15401]373        if (item is Project) {
374          item.Id = HiveServiceLocator.Instance.CallHiveService(s => s.AddProject((Project)item));
375        }
[6976]376      } else {
377        if (item is SlaveGroup) {
[7132]378          HiveServiceLocator.Instance.CallHiveService((s) => s.UpdateSlaveGroup((SlaveGroup)item));
[6976]379        }
380        if (item is Slave) {
[7132]381          HiveServiceLocator.Instance.CallHiveService((s) => s.UpdateSlave((Slave)item));
[6976]382        }
383        if (item is Downtime) {
[7132]384          HiveServiceLocator.Instance.CallHiveService((s) => s.UpdateDowntime((Downtime)item));
[6976]385        }
[15401]386        if (item is Project) {
387          HiveServiceLocator.Instance.CallHiveService((s) => s.UpdateProject((Project)item));
388        }
[6976]389      }
390    }
391    #endregion
392
393    #region Delete
394    public static void Delete(IHiveItem item) {
395      if (item is SlaveGroup) {
[7132]396        HiveServiceLocator.Instance.CallHiveService((s) => s.DeleteSlaveGroup(item.Id));
[6976]397      } else if (item is Slave) {
[7132]398        HiveServiceLocator.Instance.CallHiveService((s) => s.DeleteSlave(item.Id));
[6976]399      } else if (item is Downtime) {
[7132]400        HiveServiceLocator.Instance.CallHiveService((s) => s.DeleteDowntime(item.Id));
[15401]401      } else if (item is Project) {
402        HiveServiceLocator.Instance.CallHiveService((s) => s.DeleteProject(item.Id));
[6976]403      }
404    }
[15969]405
406    public static void DeleteJobs(List<Guid> jobIds) {
407
408      HiveServiceLocator.Instance.CallHiveService((s) => s.UpdateJobStates(jobIds, JobState.StatisticsPending));
409    }
[6976]410    #endregion
411
412    public void ResetDowntime() {
413      downtimeForResourceId = Guid.Empty;
414      if (downtimes != null) {
415        downtimes.Clear();
416      }
417    }
[15658]418
[15742]419    #region Helper
[15922]420    public IEnumerable<Project> GetAvailableProjectAncestors(Guid id) {
421      if (projectAncestors.ContainsKey(id)) return projects.Where(x => projectAncestors[id].Contains(x.Id));
422      else return Enumerable.Empty<Project>();
423    }
424
425    public IEnumerable<Project> GetAvailableProjectDescendants(Guid id) {
426      if(projectDescendants.ContainsKey(id)) return projects.Where(x => projectDescendants[id].Contains(x.Id));
427      else return Enumerable.Empty<Project>();
428    }
429
430    public IEnumerable<Resource> GetAvailableResourceAncestors(Guid id) {
431      if (resourceAncestors.ContainsKey(id)) return resources.Where(x => resourceAncestors[id].Contains(x.Id));
432      else return Enumerable.Empty<Resource>();
433    }
434
435    public IEnumerable<Resource> GetAvailableResourceDescendants(Guid id) {
436      if (resourceDescendants.ContainsKey(id)) return resources.Where(x => resourceDescendants[id].Contains(x.Id));
437      else return Enumerable.Empty<Resource>();
438    }
439
[15658]440    public bool CheckAccessToAdminAreaGranted() {
441      if(projects != null) {
442        return projects.Count > 0;
443      } else {
444        bool accessGranted = false;
445        HiveServiceLocator.Instance.CallHiveService(s => {
446          accessGranted = s.CheckAccessToAdminAreaGranted();
447        });
448        return accessGranted;
449      }
450    }
[15742]451
452    public bool CheckOwnershipOfResource(Resource res, Guid userId) {
453      if (res == null || userId == Guid.Empty) return false;
454
455      if (res.OwnerUserId == userId) {
456        return true;
457      } else if(resourceAncestors.ContainsKey(res.Id)) {
[15922]458        return GetAvailableResourceAncestors(res.Id).Where(x => x.OwnerUserId == userId).Any();
[15742]459      }
460
461      return false;
462    }
463
464    public bool CheckOwnershipOfProject(Project pro, Guid userId) {
465      if (pro == null || userId == Guid.Empty) return false;
466
467      if (pro.OwnerUserId == userId) {
468        return true;
469      } else if (projectAncestors.ContainsKey(pro.Id)) {
[15922]470        return GetAvailableProjectAncestors(pro.Id).Where(x => x.OwnerUserId == userId).Any();
[15742]471      }
472
473      return false;
474    }
475
476    public bool CheckOwnershipOfParentProject(Project pro, Guid userId) {
477      if (pro == null || userId == Guid.Empty) return false;
478
479      if(projectAncestors.ContainsKey(pro.Id)) {
[15922]480        return GetAvailableProjectAncestors(pro.Id).Where(x => x.OwnerUserId == userId).Any();
[15742]481      }
482
483      return false;
484    }
[15768]485
486    public bool CheckParentChange(Project child, Project parent) {
[15777]487      bool changePossible = true;
[15768]488
[15777]489      // change is not possible...
490      // ... if the moved project is null
491      // ... or the new parent is not stored yet
492      // ... or there is not parental change
[15768]493      if (child == null
494        || (parent != null && parent.Id == Guid.Empty)
495        || (parent != null && parent.Id == child.ParentProjectId)) {
[15777]496        changePossible = false;
[15768]497      } else if(parent != null && projectDescendants.ContainsKey(child.Id)) {
[15777]498        // ... if the new parent is among the moved project's descendants
[15922]499        changePossible = !GetAvailableProjectDescendants(child.Id).Where(x => x.Id == parent.Id).Any();
[15768]500      }
501
[15777]502      return changePossible;
[15768]503    }
504
505    public bool CheckParentChange(Resource child, Resource parent) {
[15777]506      bool changePossible = true;
[15768]507
[15777]508      // change is not possisble...
[15813]509      // ... if the child resource is null
510      // ... or the child resource equals the parent
[15777]511      // ... or the new parent is not stored yet
512      // ... or the new parent is a slave
513      // ... or there is not parental change
[15768]514      if (child == null
[15813]515        || child == parent
[15768]516        || (parent != null && parent.Id == Guid.Empty)
[15777]517        || (parent != null && parent is Slave)
[15768]518        || (parent != null && parent.Id == child.ParentResourceId)) {
[15777]519        changePossible = false;
[15768]520      } else if (parent != null && resourceDescendants.ContainsKey(child.Id)) {
[15777]521        // ... or if the new parent is among the moved resource's descendants
[15922]522        changePossible = !GetAvailableResourceDescendants(child.Id).Where(x => x.Id == parent.Id).Any();
[15768]523      }
524
[15777]525      return changePossible;
[15768]526    }
[15658]527    #endregion
[6976]528  }
529}
Note: See TracBrowser for help on using the repository browser.