#region License Information /* HeuristicLab * Copyright (C) 2002-2016 Heuristic and Evolutionary Algorithms Laboratory (HEAL) * * This file is part of HeuristicLab. * * HeuristicLab is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * HeuristicLab is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with HeuristicLab. If not, see . */ #endregion using System; using System.Threading; using HeuristicLab.Common; using HeuristicLab.Core; using System.Collections.Generic; using System.Linq; namespace HeuristicLab.Clients.Hive { [Item("Hive Administrator", "Hive Administrator")] public sealed class HiveAdminClient : IContent { private static HiveAdminClient instance; public static HiveAdminClient Instance { get { if (instance == null) instance = new HiveAdminClient(); return instance; } } #region Properties private IItemList resources; public IItemList Resources { get { return resources; } } private IItemList downtimes; public IItemList Downtimes { get { return downtimes; } } private Guid downtimeForResourceId; public Guid DowntimeForResourceId { get { return downtimeForResourceId; } set { downtimeForResourceId = value; if (downtimes != null) { downtimes.Clear(); } } } private IItemList projects; public IItemList Projects { get { return projects; } } private IItemList projectResourceAssignments; public IItemList ProjectResourceAssignments { get { return projectResourceAssignments; } } private Dictionary> jobs; public Dictionary> Jobs { get { return jobs; } set { if (value != jobs) jobs = value; } } //private Dictionary> projectAncestors; //public Dictionary> ProjectAncestors { // get { return projectAncestors; } //} //private Dictionary> projectDescendants; //public Dictionary> ProjectDescendants { // get { return projectDescendants; } //} //private Dictionary> resourceAncestors; //public Dictionary> ResourceAncestors { // get { return resourceAncestors; } //} //private Dictionary> resourceDescendants; //public Dictionary> ResourceDescendants { // get { return resourceDescendants; } //} private Dictionary> projectAncestors; public Dictionary> ProjectAncestors { get { return projectAncestors; } } private Dictionary> projectDescendants; public Dictionary> ProjectDescendants { get { return projectDescendants; } } private Dictionary> resourceAncestors; public Dictionary> ResourceAncestors { get { return resourceAncestors; } } private Dictionary> resourceDescendants; public Dictionary> ResourceDescendants { get { return resourceDescendants; } } #endregion #region Events public event EventHandler Refreshing; private void OnRefreshing() { EventHandler handler = Refreshing; if (handler != null) handler(this, EventArgs.Empty); } public event EventHandler Refreshed; private void OnRefreshed() { var handler = Refreshed; if (handler != null) handler(this, EventArgs.Empty); } #endregion private HiveAdminClient() { } #region Refresh public void Refresh() { OnRefreshing(); try { resources = new ItemList(); projects = new ItemList(); projectResourceAssignments = new ItemList(); jobs = new Dictionary>(); projectAncestors = new Dictionary>(); projectDescendants = new Dictionary>(); resourceAncestors = new Dictionary>(); resourceDescendants = new Dictionary>(); HiveServiceLocator.Instance.CallHiveService(service => { service.GetSlaveGroupsForAdministration().ForEach(g => resources.Add(g)); service.GetSlavesForAdministration().ForEach(s => resources.Add(s)); service.GetProjectsForAdministration().ForEach(p => projects.Add(p)); var projectIds = projects.Select(p => p.Id).ToList(); if (projectIds.Any()) { service.GetAssignedResourcesForProjectsAdministration(projectIds) .ForEach(a => projectResourceAssignments.Add(a)); projectIds.ForEach(p => jobs.Add(p, new HiveItemCollection())); service.GetJobsByProjectIds(projectIds) .ForEach(j => jobs[j.ProjectId].Add(j)); } }); UpdateResourceGenealogy(); UpdateProjectGenealogy(); } catch { throw; } finally { OnRefreshed(); } } //public void UpdateResourceGenealogy(IItemList resources) { // resourceAncestors.Clear(); // resourceDescendants.Clear(); // foreach (var r in resources) { // resourceAncestors.Add(r.Id, new HashSet()); // resourceDescendants.Add(r.Id, new HashSet()); // } // foreach (var r in resources) { // var parentResourceId = r.ParentResourceId; // while (parentResourceId != null) { // var parent = resources.SingleOrDefault(x => x.Id == parentResourceId); // if (parent != null) { // resourceAncestors[r.Id].Add(parent); // resourceDescendants[parent.Id].Add(r); // parentResourceId = parent.ParentResourceId; // } else { // parentResourceId = null; // } // } // } //} //public void UpdateProjectGenealogy(IItemList projects) { // projectAncestors.Clear(); // projectDescendants.Clear(); // foreach (var p in projects) { // projectAncestors.Add(p.Id, new HashSet()); // projectDescendants.Add(p.Id, new HashSet()); // } // foreach (var p in projects) { // var parentProjectId = p.ParentProjectId; // while (parentProjectId != null) { // var parent = projects.SingleOrDefault(x => x.Id == parentProjectId); // if (parent != null) { // projectAncestors[p.Id].Add(parent); // projectDescendants[parent.Id].Add(p); // parentProjectId = parent.ParentProjectId; // } else { // parentProjectId = null; // } // } // } //} private void UpdateResourceGenealogy() { resourceAncestors.Clear(); resourceDescendants.Clear(); // fetch resource ancestor set HiveServiceLocator.Instance.CallHiveService(service => { var ra = service.GetResourceGenealogy(); ra.Keys.ToList().ForEach(k => resourceAncestors.Add(k, new HashSet())); resourceAncestors.Keys.ToList().ForEach(k => resourceAncestors[k].UnionWith(ra[k])); }); // build resource descendant set resourceAncestors.Keys.ToList().ForEach(k => resourceDescendants.Add(k, new HashSet())); foreach (var ra in resourceAncestors) { foreach (var ancestor in ra.Value) { resourceDescendants[ancestor].Add(ra.Key); } } } private void UpdateProjectGenealogy() { projectAncestors.Clear(); projectDescendants.Clear(); // fetch project ancestor list HiveServiceLocator.Instance.CallHiveService(service => { var pa = service.GetProjectGenealogy(); pa.Keys.ToList().ForEach(k => projectAncestors.Add(k, new HashSet())); projectAncestors.Keys.ToList().ForEach(k => projectAncestors[k].UnionWith(pa[k])); }); // build project descendant list projectAncestors.Keys.ToList().ForEach(k => projectDescendants.Add(k, new HashSet())); foreach (var pa in projectAncestors) { foreach (var ancestor in pa.Value) { projectDescendants[ancestor].Add(pa.Key); } } } #endregion #region Refresh downtime calendar public void RefreshCalendar() { if (downtimeForResourceId != null && downtimeForResourceId != Guid.Empty) { OnRefreshing(); try { downtimes = new ItemList(); HiveServiceLocator.Instance.CallHiveService(service => { service.GetDowntimesForResource(downtimeForResourceId).ForEach(d => downtimes.Add(d)); }); } catch { throw; } finally { OnRefreshed(); } } } #endregion #region Store public static void Store(IHiveItem item, CancellationToken cancellationToken) { if (item.Id == Guid.Empty) { if (item is SlaveGroup) { item.Id = HiveServiceLocator.Instance.CallHiveService((s) => s.AddSlaveGroup((SlaveGroup)item)); } if (item is Slave) { item.Id = HiveServiceLocator.Instance.CallHiveService((s) => s.AddSlave((Slave)item)); } if (item is Downtime) { item.Id = HiveServiceLocator.Instance.CallHiveService((s) => s.AddDowntime((Downtime)item)); } if (item is Project) { item.Id = HiveServiceLocator.Instance.CallHiveService(s => s.AddProject((Project)item)); } } else { if (item is SlaveGroup) { HiveServiceLocator.Instance.CallHiveService((s) => s.UpdateSlaveGroup((SlaveGroup)item)); } if (item is Slave) { HiveServiceLocator.Instance.CallHiveService((s) => s.UpdateSlave((Slave)item)); } if (item is Downtime) { HiveServiceLocator.Instance.CallHiveService((s) => s.UpdateDowntime((Downtime)item)); } if (item is Project) { HiveServiceLocator.Instance.CallHiveService((s) => s.UpdateProject((Project)item)); } } } #endregion #region Delete public static void Delete(IHiveItem item) { if (item is SlaveGroup) { HiveServiceLocator.Instance.CallHiveService((s) => s.DeleteSlaveGroup(item.Id)); } else if (item is Slave) { HiveServiceLocator.Instance.CallHiveService((s) => s.DeleteSlave(item.Id)); } else if (item is Downtime) { HiveServiceLocator.Instance.CallHiveService((s) => s.DeleteDowntime(item.Id)); } else if (item is Project) { HiveServiceLocator.Instance.CallHiveService((s) => s.DeleteProject(item.Id)); } } #endregion public void ResetDowntime() { downtimeForResourceId = Guid.Empty; if (downtimes != null) { downtimes.Clear(); } } #region Helper public IEnumerable GetAvailableProjectAncestors(Guid id) { if (projectAncestors.ContainsKey(id)) return projects.Where(x => projectAncestors[id].Contains(x.Id)); else return Enumerable.Empty(); } public IEnumerable GetAvailableProjectDescendants(Guid id) { if(projectDescendants.ContainsKey(id)) return projects.Where(x => projectDescendants[id].Contains(x.Id)); else return Enumerable.Empty(); } public IEnumerable GetAvailableResourceAncestors(Guid id) { if (resourceAncestors.ContainsKey(id)) return resources.Where(x => resourceAncestors[id].Contains(x.Id)); else return Enumerable.Empty(); } public IEnumerable GetAvailableResourceDescendants(Guid id) { if (resourceDescendants.ContainsKey(id)) return resources.Where(x => resourceDescendants[id].Contains(x.Id)); else return Enumerable.Empty(); } public bool CheckAccessToAdminAreaGranted() { if(projects != null) { return projects.Count > 0; } else { bool accessGranted = false; HiveServiceLocator.Instance.CallHiveService(s => { accessGranted = s.CheckAccessToAdminAreaGranted(); }); return accessGranted; } } public bool CheckOwnershipOfResource(Resource res, Guid userId) { if (res == null || userId == Guid.Empty) return false; if (res.OwnerUserId == userId) { return true; } else if(resourceAncestors.ContainsKey(res.Id)) { return GetAvailableResourceAncestors(res.Id).Where(x => x.OwnerUserId == userId).Any(); } return false; } public bool CheckOwnershipOfProject(Project pro, Guid userId) { if (pro == null || userId == Guid.Empty) return false; if (pro.OwnerUserId == userId) { return true; } else if (projectAncestors.ContainsKey(pro.Id)) { return GetAvailableProjectAncestors(pro.Id).Where(x => x.OwnerUserId == userId).Any(); } return false; } public bool CheckOwnershipOfParentProject(Project pro, Guid userId) { if (pro == null || userId == Guid.Empty) return false; if(projectAncestors.ContainsKey(pro.Id)) { return GetAvailableProjectAncestors(pro.Id).Where(x => x.OwnerUserId == userId).Any(); } return false; } public bool CheckParentChange(Project child, Project parent) { bool changePossible = true; // change is not possible... // ... if the moved project is null // ... or the new parent is not stored yet // ... or there is not parental change if (child == null || (parent != null && parent.Id == Guid.Empty) || (parent != null && parent.Id == child.ParentProjectId)) { changePossible = false; } else if(parent != null && projectDescendants.ContainsKey(child.Id)) { // ... if the new parent is among the moved project's descendants changePossible = !GetAvailableProjectDescendants(child.Id).Where(x => x.Id == parent.Id).Any(); } return changePossible; } public bool CheckParentChange(Resource child, Resource parent) { bool changePossible = true; // change is not possisble... // ... if the child resource is null // ... or the child resource equals the parent // ... or the new parent is not stored yet // ... or the new parent is a slave // ... or there is not parental change if (child == null || child == parent || (parent != null && parent.Id == Guid.Empty) || (parent != null && parent is Slave) || (parent != null && parent.Id == child.ParentResourceId)) { changePossible = false; } else if (parent != null && resourceDescendants.ContainsKey(child.Id)) { // ... or if the new parent is among the moved resource's descendants changePossible = !GetAvailableResourceDescendants(child.Id).Where(x => x.Id == parent.Id).Any(); } return changePossible; } #endregion } }