source: trunk/HeuristicLab.Clients.Hive/3.3/HiveAdminClient.cs @ 16208

Last change on this file since 16208 was 16208, checked in by jzenisek, 12 months ago

#2839: updated job execution implementation in ProjectJobsView

File size: 23.8 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2018 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;
28using HeuristicLab.Clients.Access;
29
30namespace HeuristicLab.Clients.Hive {
31  [Item("Hive Administrator", "Hive Administrator")]
32  public sealed class HiveAdminClient : IContent {
33    private static HiveAdminClient instance;
34    public static HiveAdminClient Instance {
35      get {
36        if (instance == null) instance = new HiveAdminClient();
37        return instance;
38      }
39    }
40
41    #region Properties
42    private IItemList<Resource> resources;
43    public IItemList<Resource> Resources {
44      get { return resources; }
45    }
46
47    private IItemList<Downtime> downtimes;
48    public IItemList<Downtime> Downtimes {
49      get { return downtimes; }
50    }
51
52    private Guid downtimeForResourceId;
53    public Guid DowntimeForResourceId {
54      get { return downtimeForResourceId; }
55      set {
56        downtimeForResourceId = value;
57        if (downtimes != null) {
58          downtimes.Clear();
59        }
60      }
61    }
62
63    private IItemList<Project> projects;
64    public IItemList<Project> Projects {
65      get { return projects; }
66    }
67
68    private IItemList<AssignedProjectResource> projectResourceAssignments;
69    public IItemList<AssignedProjectResource> ProjectResourceAssignments {
70      get { return projectResourceAssignments; }
71    }
72
73    private Dictionary<Guid, HiveItemCollection<RefreshableJob>> jobs;
74    public Dictionary<Guid, HiveItemCollection<RefreshableJob>> Jobs {
75      get { return jobs; }
76      set {
77        if (value != jobs)
78          jobs = value;
79        }
80    }
81
82    private Dictionary<Guid, HashSet<Guid>> projectAncestors;
83    public Dictionary<Guid, HashSet<Guid>> ProjectAncestors {
84      get { return projectAncestors; }
85    }
86
87    private Dictionary<Guid, HashSet<Guid>> projectDescendants;
88    public Dictionary<Guid, HashSet<Guid>> ProjectDescendants {
89      get { return projectDescendants; }
90    }
91
92    private Dictionary<Guid, HashSet<Guid>> resourceAncestors;
93    public Dictionary<Guid, HashSet<Guid>> ResourceAncestors {
94      get { return resourceAncestors; }
95    }
96
97    private Dictionary<Guid, HashSet<Guid>> resourceDescendants;
98    public Dictionary<Guid, HashSet<Guid>> ResourceDescendants {
99      get { return resourceDescendants; }
100    }
101
102    private Dictionary<Guid, string> projectNames;
103    public Dictionary<Guid, string> ProjectNames {
104      get { return projectNames; }
105    }
106
107    private HashSet<Project> disabledParentProjects;
108    public HashSet<Project> DisabledParentProjects {
109      get { return disabledParentProjects; }
110    }
111
112    private Dictionary<Guid, string> resourceNames;
113    public Dictionary<Guid, string> ResourceNames {
114      get { return resourceNames; }
115    }
116
117    private HashSet<Resource> disabledParentResources;
118    public HashSet<Resource> DisabledParentResources {
119      get { return disabledParentResources; }
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<RefreshableJob>>();
147        projectNames = new Dictionary<Guid, string>();
148        resourceNames = new Dictionary<Guid, string>();
149
150        projectAncestors = new Dictionary<Guid, HashSet<Guid>>();
151        projectDescendants = new Dictionary<Guid, HashSet<Guid>>();
152        resourceAncestors = new Dictionary<Guid, HashSet<Guid>>();
153        resourceDescendants = new Dictionary<Guid, HashSet<Guid>>();
154
155        HiveServiceLocator.Instance.CallHiveService(service => {
156          service.GetSlaveGroupsForAdministration().ForEach(g => resources.Add(g));
157          service.GetSlavesForAdministration().ForEach(s => resources.Add(s));
158          service.GetProjectsForAdministration().ForEach(p => projects.Add(p));
159          var projectIds = projects.Select(p => p.Id).ToList();
160          if (projectIds.Any()) {
161            service.GetAssignedResourcesForProjectsAdministration(projectIds)
162              .ForEach(a => projectResourceAssignments.Add(a));
163            projectIds.ForEach(p => jobs.Add(p, new HiveItemCollection<RefreshableJob>()));
164            var unsortedJobs = service.GetJobsByProjectIds(projectIds)
165              .OrderBy(x => x.DateCreated).ToList();
166
167            unsortedJobs.Where(j => j.State == JobState.DeletionPending).ToList().ForEach(j => jobs[j.ProjectId].Add(new RefreshableJob(j)));
168            unsortedJobs.Where(j => j.State == JobState.StatisticsPending).ToList().ForEach(j => jobs[j.ProjectId].Add(new RefreshableJob(j)));
169            unsortedJobs.Where(j => j.State == JobState.Online).ToList().ForEach(j => jobs[j.ProjectId].Add(new RefreshableJob(j)));
170
171            foreach (var job in jobs.SelectMany(x => x.Value))
172              LoadLightweightJob(job);
173
174            projectNames = service.GetProjectNames();
175            resourceNames = service.GetResourceNames();
176          }
177        });
178
179        UpdateResourceGenealogy();
180        UpdateProjectGenealogy();
181        RefreshDisabledParentProjects();
182        RefreshDisabledParentResources();
183      }
184      catch {
185        throw;
186      }
187      finally {
188        OnRefreshed();
189      }
190    }
191
192    //public void UpdateResourceGenealogy(IItemList<Resource> resources) {
193    //  resourceAncestors.Clear();
194    //  resourceDescendants.Clear();
195
196    //  foreach (var r in resources) {
197    //    resourceAncestors.Add(r.Id, new HashSet<Resource>());
198    //    resourceDescendants.Add(r.Id, new HashSet<Resource>());
199    //  }
200
201    //  foreach (var r in resources) {
202    //    var parentResourceId = r.ParentResourceId;
203    //    while (parentResourceId != null) {
204    //      var parent = resources.SingleOrDefault(x => x.Id == parentResourceId);
205    //      if (parent != null) {
206    //        resourceAncestors[r.Id].Add(parent);
207    //        resourceDescendants[parent.Id].Add(r);
208    //        parentResourceId = parent.ParentResourceId;
209    //      } else {
210    //        parentResourceId = null;
211    //      }
212    //    }
213    //  }
214    //}
215
216    //public void UpdateProjectGenealogy(IItemList<Project> projects) {
217    //  projectAncestors.Clear();
218    //  projectDescendants.Clear();
219
220    //  foreach (var p in projects) {
221    //    projectAncestors.Add(p.Id, new HashSet<Project>());
222    //    projectDescendants.Add(p.Id, new HashSet<Project>());
223    //  }
224
225    //  foreach (var p in projects) {
226    //    var parentProjectId = p.ParentProjectId;
227    //    while (parentProjectId != null) {
228    //      var parent = projects.SingleOrDefault(x => x.Id == parentProjectId);
229    //      if (parent != null) {
230    //        projectAncestors[p.Id].Add(parent);
231    //        projectDescendants[parent.Id].Add(p);
232    //        parentProjectId = parent.ParentProjectId;
233    //      } else {
234    //        parentProjectId = null;
235    //      }
236    //    }
237    //  }
238    //}
239
240    private void UpdateResourceGenealogy() {
241      resourceAncestors.Clear();
242      resourceDescendants.Clear();
243
244      // fetch resource ancestor set
245      HiveServiceLocator.Instance.CallHiveService(service => {
246        var ra = service.GetResourceGenealogy();
247        ra.Keys.ToList().ForEach(k => resourceAncestors.Add(k, new HashSet<Guid>()));
248        resourceAncestors.Keys.ToList().ForEach(k => resourceAncestors[k].UnionWith(ra[k]));
249      });
250
251      // build resource descendant set
252      resourceAncestors.Keys.ToList().ForEach(k => resourceDescendants.Add(k, new HashSet<Guid>()));
253      foreach (var ra in resourceAncestors) {
254        foreach (var ancestor in ra.Value) {
255          resourceDescendants[ancestor].Add(ra.Key);
256        }
257      }
258    }
259
260    private void UpdateProjectGenealogy() {
261      projectAncestors.Clear();
262      projectDescendants.Clear();
263
264      // fetch project ancestor list
265      HiveServiceLocator.Instance.CallHiveService(service => {
266        var pa = service.GetProjectGenealogy();
267        pa.Keys.ToList().ForEach(k => projectAncestors.Add(k, new HashSet<Guid>()));
268        projectAncestors.Keys.ToList().ForEach(k => projectAncestors[k].UnionWith(pa[k]));
269      });
270
271      // build project descendant list
272      projectAncestors.Keys.ToList().ForEach(k => projectDescendants.Add(k, new HashSet<Guid>()));
273      foreach (var pa in projectAncestors) {
274        foreach (var ancestor in pa.Value) {
275          projectDescendants[ancestor].Add(pa.Key);
276        }
277      }
278    }
279
280    private void RefreshDisabledParentProjects() {
281      disabledParentProjects = new HashSet<Project>();
282
283      foreach (var pid in projects
284        .Where(x => x.ParentProjectId.HasValue)
285        .SelectMany(x => projectAncestors[x.Id]).Distinct()
286        .Where(x => !projects.Select(y => y.Id).Contains(x))) {
287        var p = new Project();
288        p.Id = pid;
289        p.ParentProjectId = projectAncestors[pid].FirstOrDefault();
290        p.Name = projectNames[pid];
291        disabledParentProjects.Add(p);
292      }
293    }
294
295    private void RefreshDisabledParentResources() {
296      disabledParentResources = new HashSet<Resource>();
297
298      foreach (var rid in resources
299        .Where(x => x.ParentResourceId.HasValue)
300        .SelectMany(x => resourceAncestors[x.Id]).Distinct()
301        .Where(x => !resources.Select(y => y.Id).Contains(x))) {
302        var r = new SlaveGroup();
303        r.Id = rid;
304        r.ParentResourceId = resourceAncestors[rid].FirstOrDefault();
305        r.Name = resourceNames[rid];
306        disabledParentResources.Add(r);
307      }
308    }
309
310    public void RefreshJobs() {
311      var projectIds = new List<Guid>();
312      jobs = new Dictionary<Guid, HiveItemCollection<RefreshableJob>>();
313
314      HiveServiceLocator.Instance.CallHiveService(service => {
315        service.GetProjectsForAdministration().ForEach(p => projectIds.Add(p.Id));
316        if(projectIds.Any()) {
317          projectIds.ForEach(p => jobs.Add(p, new HiveItemCollection<RefreshableJob>()));
318          var unsortedJobs = service.GetJobsByProjectIds(projectIds)
319            .OrderBy(x => x.DateCreated).ToList();
320         
321          unsortedJobs.Where(j => j.State == JobState.DeletionPending).ToList().ForEach(j => jobs[j.ProjectId].Add(new RefreshableJob(j)));
322          unsortedJobs.Where(j => j.State == JobState.StatisticsPending).ToList().ForEach(j => jobs[j.ProjectId].Add(new RefreshableJob(j)));
323          unsortedJobs.Where(j => j.State == JobState.Online).ToList().ForEach(j => jobs[j.ProjectId].Add(new RefreshableJob(j)));
324
325          foreach(var job in jobs.SelectMany(x => x.Value))
326            LoadLightweightJob(job);
327        }
328      });
329    }
330
331    public static void LoadLightweightJob(RefreshableJob refreshableJob) {
332      var job = refreshableJob.Job;
333      var tasks = HiveServiceLocator.Instance.CallHiveService(s => s.GetLightweightJobTasksWithoutStateLog(job.Id));
334      if (tasks != null && tasks.Count > 0 && tasks.All(x => x.Id != Guid.Empty)) {
335        if (tasks.All(x =>
336          x.State == TaskState.Finished
337          || x.State == TaskState.Aborted
338          || x.State == TaskState.Failed)) {
339          refreshableJob.ExecutionState = ExecutionState.Stopped;
340          refreshableJob.RefreshAutomatically = false;
341        } else if (
342          tasks
343            .Where(x => x.ParentTaskId != null)
344            .All(x =>
345              x.State != TaskState.Waiting
346              || x.State != TaskState.Transferring
347              || x.State != TaskState.Calculating)
348          && tasks
349             .Where(x => x.ParentTaskId != null)
350             .Any(x => x.State == TaskState.Paused)) {
351          refreshableJob.ExecutionState = ExecutionState.Paused;
352          refreshableJob.RefreshAutomatically = false;
353        } else if (tasks.Any(x => x.State == TaskState.Calculating
354                                  || x.State == TaskState.Transferring
355                                  || x.State == TaskState.Waiting)) {
356          refreshableJob.ExecutionState = ExecutionState.Started;
357        }
358      }
359    }
360
361    public void SortJobs() {
362      for(int i = 0; i < jobs.Count; i++) {
363        var projectId = jobs.Keys.ElementAt(i);
364        var unsortedJobs = jobs.Values.ElementAt(i);
365
366        var sortedJobs = new HiveItemCollection<RefreshableJob>();
367        sortedJobs.AddRange(unsortedJobs.Where(j => j.Job.State == JobState.DeletionPending));
368        sortedJobs.AddRange(unsortedJobs.Where(j => j.Job.State == JobState.StatisticsPending));
369        sortedJobs.AddRange(unsortedJobs.Where(j => j.Job.State == JobState.Online));
370
371        jobs[projectId] = sortedJobs;
372      }
373    }
374
375    #endregion
376
377    #region Refresh downtime calendar
378    public void RefreshCalendar() {
379      if (downtimeForResourceId != null && downtimeForResourceId != Guid.Empty) {
380        OnRefreshing();
381
382        try {
383          downtimes = new ItemList<Downtime>();
384
385          HiveServiceLocator.Instance.CallHiveService(service => {
386            service.GetDowntimesForResource(downtimeForResourceId).ForEach(d => downtimes.Add(d));
387          });
388        }
389        catch {
390          throw;
391        }
392        finally {
393          OnRefreshed();
394        }
395      }
396    }
397    #endregion
398
399    #region Store
400    public static void Store(IHiveItem item, CancellationToken cancellationToken) {
401      if (item.Id == Guid.Empty) {
402        if (item is SlaveGroup) {
403          item.Id = HiveServiceLocator.Instance.CallHiveService((s) => s.AddSlaveGroup((SlaveGroup)item));
404        }
405        if (item is Slave) {
406          item.Id = HiveServiceLocator.Instance.CallHiveService((s) => s.AddSlave((Slave)item));
407        }
408        if (item is Downtime) {
409          item.Id = HiveServiceLocator.Instance.CallHiveService((s) => s.AddDowntime((Downtime)item));
410        }
411        if (item is Project) {
412          item.Id = HiveServiceLocator.Instance.CallHiveService(s => s.AddProject((Project)item));
413        }
414      } else {
415        if (item is SlaveGroup) {
416          HiveServiceLocator.Instance.CallHiveService((s) => s.UpdateSlaveGroup((SlaveGroup)item));
417        }
418        if (item is Slave) {
419          HiveServiceLocator.Instance.CallHiveService((s) => s.UpdateSlave((Slave)item));
420        }
421        if (item is Downtime) {
422          HiveServiceLocator.Instance.CallHiveService((s) => s.UpdateDowntime((Downtime)item));
423        }
424        if (item is Project) {
425          HiveServiceLocator.Instance.CallHiveService((s) => s.UpdateProject((Project)item));
426        }
427      }
428    }
429    #endregion
430
431    #region Delete
432    public static void Delete(IHiveItem item) {
433      if (item is SlaveGroup) {
434        HiveServiceLocator.Instance.CallHiveService((s) => s.DeleteSlaveGroup(item.Id));
435      } else if (item is Slave) {
436        HiveServiceLocator.Instance.CallHiveService((s) => s.DeleteSlave(item.Id));
437      } else if (item is Downtime) {
438        HiveServiceLocator.Instance.CallHiveService((s) => s.DeleteDowntime(item.Id));
439      } else if (item is Project) {
440        HiveServiceLocator.Instance.CallHiveService((s) => s.DeleteProject(item.Id));
441      }
442    }
443
444    public static void RemoveJobs(List<Guid> jobIds) {
445      HiveServiceLocator.Instance.CallHiveService((s) => s.UpdateJobStates(jobIds, JobState.StatisticsPending));
446    }
447    #endregion
448
449    #region Job Handling
450
451    public static void ResumeJob(RefreshableJob refreshableJob) {
452      HiveServiceLocator.Instance.CallHiveService(service => {
453        foreach (HiveTask task in refreshableJob.GetAllHiveTasks()) {
454          if (task.Task.State == TaskState.Paused) {
455            service.RestartTask(task.Task.Id);
456          }
457        }
458      });
459      refreshableJob.ExecutionState = ExecutionState.Started;
460    }
461
462    public static void PauseJob(RefreshableJob refreshableJob) {
463      HiveServiceLocator.Instance.CallHiveService(service => {
464        foreach (HiveTask task in refreshableJob.GetAllHiveTasks()) {
465          if (task.Task.State != TaskState.Finished && task.Task.State != TaskState.Aborted && task.Task.State != TaskState.Failed)
466            service.PauseTask(task.Task.Id);
467        }
468      });
469      refreshableJob.ExecutionState = ExecutionState.Paused;
470    }
471
472    public static void StopJob(RefreshableJob refreshableJob) {
473      HiveServiceLocator.Instance.CallHiveService(service => {
474        foreach (HiveTask task in refreshableJob.GetAllHiveTasks()) {
475          if (task.Task.State != TaskState.Finished && task.Task.State != TaskState.Aborted && task.Task.State != TaskState.Failed)
476            service.StopTask(task.Task.Id);
477        }
478      });
479      refreshableJob.ExecutionState = ExecutionState.Stopped;
480    }
481
482    public static void RemoveJob(RefreshableJob refreshableJob) {
483      HiveServiceLocator.Instance.CallHiveService((s) => {
484        s.UpdateJobState(refreshableJob.Id, JobState.StatisticsPending);
485      });
486    }
487    #endregion
488
489    public void ResetDowntime() {
490      downtimeForResourceId = Guid.Empty;
491      if (downtimes != null) {
492        downtimes.Clear();
493      }
494    }
495
496    #region Helper
497    public IEnumerable<Project> GetAvailableProjectAncestors(Guid id) {
498      if (projectAncestors.ContainsKey(id)) return projects.Where(x => projectAncestors[id].Contains(x.Id));
499      else return Enumerable.Empty<Project>();
500    }
501
502    public IEnumerable<Project> GetAvailableProjectDescendants(Guid id) {
503      if(projectDescendants.ContainsKey(id)) return projects.Where(x => projectDescendants[id].Contains(x.Id));
504      else return Enumerable.Empty<Project>();
505    }
506
507    public IEnumerable<Resource> GetAvailableResourceAncestors(Guid id) {
508      if (resourceAncestors.ContainsKey(id)) return resources.Where(x => resourceAncestors[id].Contains(x.Id));
509      else return Enumerable.Empty<Resource>();
510    }
511
512    public IEnumerable<Resource> GetAvailableResourceDescendants(Guid id) {
513      if (resourceDescendants.ContainsKey(id)) return resources.Where(x => resourceDescendants[id].Contains(x.Id));
514      else return Enumerable.Empty<Resource>();
515    }
516
517    public IEnumerable<Resource> GetDisabledResourceAncestors(IEnumerable<Resource> availableResources) {
518      var missingParentIds = availableResources
519        .Where(x => x.ParentResourceId.HasValue)
520        .SelectMany(x => resourceAncestors[x.Id]).Distinct()
521        .Where(x => !availableResources.Select(y => y.Id).Contains(x));
522
523      return resources.OfType<SlaveGroup>().Union(disabledParentResources).Where(x => missingParentIds.Contains(x.Id));
524    }
525
526    public bool CheckAccessToAdminAreaGranted() {
527      if(projects != null) {
528        return projects.Count > 0;
529      } else {
530        bool accessGranted = false;
531        HiveServiceLocator.Instance.CallHiveService(s => {
532          accessGranted = s.CheckAccessToAdminAreaGranted();
533        });
534        return accessGranted;
535      }
536    }
537
538    public bool CheckOwnershipOfResource(Resource res, Guid userId) {
539      if (res == null || userId == Guid.Empty) return false;
540
541      if (res.OwnerUserId == userId) {
542        return true;
543      } else if(resourceAncestors.ContainsKey(res.Id)) {
544        return GetAvailableResourceAncestors(res.Id).Where(x => x.OwnerUserId == userId).Any();
545      }
546
547      return false;
548    }
549
550    public bool CheckOwnershipOfProject(Project pro, Guid userId) {
551      if (pro == null || userId == Guid.Empty) return false;
552
553      if (pro.OwnerUserId == userId) {
554        return true;
555      } else if (projectAncestors.ContainsKey(pro.Id)) {
556        return GetAvailableProjectAncestors(pro.Id).Where(x => x.OwnerUserId == userId).Any();
557      }
558
559      return false;
560    }
561
562    public bool CheckOwnershipOfParentProject(Project pro, Guid userId) {
563      if (pro == null || userId == Guid.Empty) return false;
564
565      if(projectAncestors.ContainsKey(pro.Id)) {
566        return GetAvailableProjectAncestors(pro.Id).Any(x => x.OwnerUserId == userId);
567      }
568
569      if (pro.ParentProjectId != null && pro.ParentProjectId != Guid.Empty) {
570        var parent = projects.FirstOrDefault(x => x.Id == pro.ParentProjectId.Value);
571        if (parent != null)
572          return parent.OwnerUserId == userId || GetAvailableProjectAncestors(parent.Id).Any(x => x.OwnerUserId == userId);
573      }
574
575      return false;
576    }
577
578    public bool CheckParentChange(Project child, Project parent) {
579      bool changePossible = true;
580
581      // change is not possible...
582      // ... if the moved project is null
583      // ... or the new parent is not stored yet
584      // ... or there is not parental change
585      if (child == null
586          || (parent != null && parent.Id == Guid.Empty)
587          || (parent != null && parent.Id == child.ParentProjectId)) {
588        changePossible = false;
589      } else if (parent == null && !IsAdmin()) {
590        // ... if parent is null, but user is no admin (only admins are allowed to create root projects)
591        changePossible = false;
592      } else if (parent != null && (!IsAdmin() && parent.OwnerUserId != UserInformation.Instance.User.Id && !CheckOwnershipOfParentProject(parent, UserInformation.Instance.User.Id))) {
593        // ... if the user is no admin nor owner of the new parent or grand..grandparents
594        changePossible = false;
595      } else if(parent != null && projectDescendants.ContainsKey(child.Id)) {
596        // ... if the new parent is among the moved project's descendants
597        changePossible = !GetAvailableProjectDescendants(child.Id).Where(x => x.Id == parent.Id).Any();
598      }
599
600      return changePossible;
601    }
602
603    public bool CheckParentChange(Resource child, Resource parent) {
604      bool changePossible = true;
605
606      // change is not possisble...
607      // ... if the child resource is null
608      // ... or the child resource equals the parent
609      // ... or the new parent is not stored yet
610      // ... or the new parent is a slave
611      // ... or there is not parental change
612      if (child == null 
613        || child == parent
614        || (parent != null && parent.Id == Guid.Empty)
615        || (parent != null && parent is Slave)
616        || (parent != null && parent.Id == child.ParentResourceId)) {
617        changePossible = false;
618      } else if (parent != null && resourceDescendants.ContainsKey(child.Id)) {
619        // ... or if the new parent is among the moved resource's descendants
620        changePossible = !GetAvailableResourceDescendants(child.Id).Where(x => x.Id == parent.Id).Any();
621      }
622
623      return changePossible;
624    }
625
626    private bool IsAdmin() {
627      return HiveRoles.CheckAdminUserPermissions();
628    }
629    #endregion
630  }
631}
Note: See TracBrowser for help on using the repository browser.