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

Last change on this file since 15819 was 15819, checked in by jzenisek, 18 months ago

#2839: implemented refreshing list of available (i.e. for non-admins assignable) resources depending on currently selected project

File size: 12.0 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
93    #endregion
94
95    #region Events
96    public event EventHandler Refreshing;
97    private void OnRefreshing() {
98      EventHandler handler = Refreshing;
99      if (handler != null) handler(this, EventArgs.Empty);
100    }
101    public event EventHandler Refreshed;
102    private void OnRefreshed() {
103      var handler = Refreshed;
104      if (handler != null) handler(this, EventArgs.Empty);
105    }
106    #endregion
107
108    private HiveAdminClient() { }
109
110    #region Refresh
111    public void Refresh() {
112      OnRefreshing();
113
114      try {
115        resources = new ItemList<Resource>();
116        projects = new ItemList<Project>();
117        projectResourceAssignments = new ItemList<AssignedProjectResource>();
118
119        projectAncestors = new Dictionary<Guid, HashSet<Project>>();
120        projectDescendants = new Dictionary<Guid, HashSet<Project>>();
121        resourceAncestors = new Dictionary<Guid, HashSet<Resource>>();
122        resourceDescendants = new Dictionary<Guid, HashSet<Resource>>();
123
124        HiveServiceLocator.Instance.CallHiveService(service => {
125          service.GetSlaveGroupsForAdministration().ForEach(g => resources.Add(g));
126          service.GetSlavesForAdministration().ForEach(s => resources.Add(s));
127          service.GetProjectsForAdministration().ForEach(p => projects.Add(p));
128          var projectIds = projects.Select(p => p.Id).ToList();
129          if(projectIds.Any())
130            service.GetAssignedResourcesForProjectsAdministration(projectIds)
131            .ForEach(a => projectResourceAssignments.Add(a));
132        });
133
134        UpdateResourceGenealogy(resources);
135        UpdateProjectGenealogy(projects);
136      }
137      catch {
138        throw;
139      }
140      finally {
141        OnRefreshed();
142      }
143    }
144
145    public void UpdateResourceGenealogy(IItemList<Resource> resources) {
146      resourceAncestors.Clear();
147      resourceDescendants.Clear();
148
149      foreach (var r in resources) {
150        resourceAncestors.Add(r.Id, new HashSet<Resource>());
151        resourceDescendants.Add(r.Id, new HashSet<Resource>());
152      }
153
154      foreach (var r in resources) {
155        var parentResourceId = r.ParentResourceId;
156        while (parentResourceId != null) {
157          var parent = resources.SingleOrDefault(x => x.Id == parentResourceId);
158          if (parent != null) {
159            resourceAncestors[r.Id].Add(parent);
160            resourceDescendants[parent.Id].Add(r);
161            parentResourceId = parent.ParentResourceId;
162          } else {
163            parentResourceId = null;
164          }
165        }
166      }
167    }
168
169    public void UpdateProjectGenealogy(IItemList<Project> projects) {
170      projectAncestors.Clear();
171      projectDescendants.Clear();
172
173      foreach (var p in projects) {
174        projectAncestors.Add(p.Id, new HashSet<Project>());
175        projectDescendants.Add(p.Id, new HashSet<Project>());
176      }
177
178      foreach (var p in projects) {
179        var parentProjectId = p.ParentProjectId;
180        while (parentProjectId != null) {
181          var parent = projects.SingleOrDefault(x => x.Id == parentProjectId);
182          if (parent != null) {
183            projectAncestors[p.Id].Add(parent);
184            projectDescendants[parent.Id].Add(p);
185            parentProjectId = parent.ParentProjectId;
186          } else {
187            parentProjectId = null;
188          }
189        }
190      }
191    }
192    #endregion
193
194    #region Refresh downtime calendar
195    public void RefreshCalendar() {
196      if (downtimeForResourceId != null && downtimeForResourceId != Guid.Empty) {
197        OnRefreshing();
198
199        try {
200          downtimes = new ItemList<Downtime>();
201
202          HiveServiceLocator.Instance.CallHiveService(service => {
203            service.GetDowntimesForResource(downtimeForResourceId).ForEach(d => downtimes.Add(d));
204          });
205        }
206        catch {
207          throw;
208        }
209        finally {
210          OnRefreshed();
211        }
212      }
213    }
214    #endregion
215
216    #region Store
217    public static void Store(IHiveItem item, CancellationToken cancellationToken) {
218      if (item.Id == Guid.Empty) {
219        if (item is SlaveGroup) {
220          item.Id = HiveServiceLocator.Instance.CallHiveService((s) => s.AddSlaveGroup((SlaveGroup)item));
221        }
222        if (item is Slave) {
223          item.Id = HiveServiceLocator.Instance.CallHiveService((s) => s.AddSlave((Slave)item));
224        }
225        if (item is Downtime) {
226          item.Id = HiveServiceLocator.Instance.CallHiveService((s) => s.AddDowntime((Downtime)item));
227        }
228        if (item is Project) {
229          item.Id = HiveServiceLocator.Instance.CallHiveService(s => s.AddProject((Project)item));
230        }
231      } else {
232        if (item is SlaveGroup) {
233          HiveServiceLocator.Instance.CallHiveService((s) => s.UpdateSlaveGroup((SlaveGroup)item));
234        }
235        if (item is Slave) {
236          HiveServiceLocator.Instance.CallHiveService((s) => s.UpdateSlave((Slave)item));
237        }
238        if (item is Downtime) {
239          HiveServiceLocator.Instance.CallHiveService((s) => s.UpdateDowntime((Downtime)item));
240        }
241        if (item is Project) {
242          HiveServiceLocator.Instance.CallHiveService((s) => s.UpdateProject((Project)item));
243        }
244      }
245    }
246    #endregion
247
248    #region Delete
249    public static void Delete(IHiveItem item) {
250      if (item is SlaveGroup) {
251        HiveServiceLocator.Instance.CallHiveService((s) => s.DeleteSlaveGroup(item.Id));
252      } else if (item is Slave) {
253        HiveServiceLocator.Instance.CallHiveService((s) => s.DeleteSlave(item.Id));
254      } else if (item is Downtime) {
255        HiveServiceLocator.Instance.CallHiveService((s) => s.DeleteDowntime(item.Id));
256      } else if (item is Project) {
257        HiveServiceLocator.Instance.CallHiveService((s) => s.DeleteProject(item.Id));
258      }
259    }
260    #endregion
261
262    public void ResetDowntime() {
263      downtimeForResourceId = Guid.Empty;
264      if (downtimes != null) {
265        downtimes.Clear();
266      }
267    }
268
269    #region Helper
270    public bool CheckAccessToAdminAreaGranted() {
271      if(projects != null) {
272        return projects.Count > 0;
273      } else {
274        bool accessGranted = false;
275        HiveServiceLocator.Instance.CallHiveService(s => {
276          accessGranted = s.CheckAccessToAdminAreaGranted();
277        });
278        return accessGranted;
279      }
280    }
281
282    public bool CheckOwnershipOfResource(Resource res, Guid userId) {
283      if (res == null || userId == Guid.Empty) return false;
284
285      if (res.OwnerUserId == userId) {
286        return true;
287      } else if(resourceAncestors.ContainsKey(res.Id)) {
288        return resourceAncestors[res.Id].Where(x => x.OwnerUserId == userId).Any();
289      }
290
291      return false;
292    }
293
294    public bool CheckOwnershipOfProject(Project pro, Guid userId) {
295      if (pro == null || userId == Guid.Empty) return false;
296
297      if (pro.OwnerUserId == userId) {
298        return true;
299      } else if (projectAncestors.ContainsKey(pro.Id)) {
300        return projectAncestors[pro.Id].Where(x => x.OwnerUserId == userId).Any();
301      }
302
303      return false;
304    }
305
306    public bool CheckOwnershipOfParentProject(Project pro, Guid userId) {
307      if (pro == null || userId == Guid.Empty) return false;
308
309      if(projectAncestors.ContainsKey(pro.Id)) {
310        return projectAncestors[pro.Id].Where(x => x.OwnerUserId == userId).Any();
311      }
312
313      return false;
314    }
315
316    public bool CheckParentChange(Project child, Project parent) {
317      bool changePossible = true;
318
319      // change is not possible...
320      // ... if the moved project is null
321      // ... or the new parent is not stored yet
322      // ... or there is not parental change
323      if (child == null 
324        || (parent != null && parent.Id == Guid.Empty)
325        || (parent != null && parent.Id == child.ParentProjectId)) {
326        changePossible = false;
327      } else if(parent != null && projectDescendants.ContainsKey(child.Id)) {
328        // ... if the new parent is among the moved project's descendants
329        changePossible = !projectDescendants[child.Id].Where(x => x.Id == parent.Id).Any();
330      }
331
332      return changePossible;
333    }
334
335    public bool CheckParentChange(Resource child, Resource parent) {
336      bool changePossible = true;
337
338      // change is not possisble...
339      // ... if the child resource is null
340      // ... or the child resource equals the parent
341      // ... or the new parent is not stored yet
342      // ... or the new parent is a slave
343      // ... or there is not parental change
344      if (child == null 
345        || child == parent
346        || (parent != null && parent.Id == Guid.Empty)
347        || (parent != null && parent is Slave)
348        || (parent != null && parent.Id == child.ParentResourceId)) {
349        changePossible = false;
350      } else if (parent != null && resourceDescendants.ContainsKey(child.Id)) {
351        // ... or if the new parent is among the moved resource's descendants
352        changePossible = !resourceDescendants[child.Id].Where(x => x.Id == parent.Id).Any();
353      }
354
355      return changePossible;
356    }
357    #endregion
358  }
359}
Note: See TracBrowser for help on using the repository browser.