[6976] | 1 | #region License Information
|
---|
| 2 | /* HeuristicLab
|
---|
[14185] | 3 | * Copyright (C) 2002-2016 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 |
|
---|
| 22 | using System;
|
---|
| 23 | using System.Threading;
|
---|
| 24 | using HeuristicLab.Common;
|
---|
| 25 | using HeuristicLab.Core;
|
---|
[15658] | 26 | using System.Collections.Generic;
|
---|
[15742] | 27 | using System.Linq;
|
---|
[6976] | 28 |
|
---|
| 29 | namespace 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 |
|
---|
[15742] | 67 | private Dictionary<Guid, HashSet<Project>> projectAncestors;
|
---|
| 68 | public Dictionary<Guid, HashSet<Project>> ProjectAncestors {
|
---|
| 69 | get { return projectAncestors; }
|
---|
| 70 | }
|
---|
| 71 |
|
---|
| 72 | private Dictionary<Guid, HashSet<Project>> projectDescendants;
|
---|
| 73 | public Dictionary<Guid, HashSet<Project>> ProjectDescendants {
|
---|
| 74 | get { return projectDescendants; }
|
---|
| 75 | }
|
---|
| 76 |
|
---|
| 77 | private Dictionary<Guid, HashSet<Resource>> resourceAncestors;
|
---|
| 78 | public Dictionary<Guid, HashSet<Resource>> ResourceAncestors {
|
---|
| 79 | get { return ResourceAncestors; }
|
---|
| 80 | }
|
---|
| 81 |
|
---|
| 82 | private Dictionary<Guid, HashSet<Resource>> resourceDescendants;
|
---|
| 83 | public Dictionary<Guid, HashSet<Resource>> ResourceDescendants {
|
---|
| 84 | get { return ResourceDescendants; }
|
---|
| 85 | }
|
---|
| 86 |
|
---|
| 87 |
|
---|
[15658] | 88 | #endregion
|
---|
| 89 |
|
---|
[6976] | 90 | #region Events
|
---|
| 91 | public event EventHandler Refreshing;
|
---|
| 92 | private void OnRefreshing() {
|
---|
| 93 | EventHandler handler = Refreshing;
|
---|
| 94 | if (handler != null) handler(this, EventArgs.Empty);
|
---|
| 95 | }
|
---|
| 96 | public event EventHandler Refreshed;
|
---|
| 97 | private void OnRefreshed() {
|
---|
| 98 | var handler = Refreshed;
|
---|
| 99 | if (handler != null) handler(this, EventArgs.Empty);
|
---|
| 100 | }
|
---|
| 101 | #endregion
|
---|
| 102 |
|
---|
| 103 | private HiveAdminClient() { }
|
---|
| 104 |
|
---|
| 105 | #region Refresh
|
---|
| 106 | public void Refresh() {
|
---|
| 107 | OnRefreshing();
|
---|
| 108 |
|
---|
| 109 | try {
|
---|
| 110 | resources = new ItemList<Resource>();
|
---|
[15401] | 111 | projects = new ItemList<Project>();
|
---|
[6976] | 112 |
|
---|
[15742] | 113 | projectAncestors = new Dictionary<Guid, HashSet<Project>>();
|
---|
| 114 | projectDescendants = new Dictionary<Guid, HashSet<Project>>();
|
---|
| 115 | resourceAncestors = new Dictionary<Guid, HashSet<Resource>>();
|
---|
| 116 | resourceDescendants = new Dictionary<Guid, HashSet<Resource>>();
|
---|
| 117 |
|
---|
[7132] | 118 | HiveServiceLocator.Instance.CallHiveService(service => {
|
---|
[15658] | 119 | service.GetSlaveGroupsForAdministration().ForEach(g => resources.Add(g));
|
---|
| 120 | service.GetSlavesForAdministration().ForEach(s => resources.Add(s));
|
---|
[15576] | 121 | service.GetProjectsForAdministration().ForEach(p => projects.Add(p));
|
---|
[6976] | 122 | });
|
---|
[15742] | 123 |
|
---|
| 124 | UpdateResourceGenealogy();
|
---|
| 125 | UpdateProjectGenealogy();
|
---|
[6976] | 126 | }
|
---|
| 127 | catch {
|
---|
| 128 | throw;
|
---|
| 129 | }
|
---|
| 130 | finally {
|
---|
| 131 | OnRefreshed();
|
---|
| 132 | }
|
---|
| 133 | }
|
---|
[15742] | 134 |
|
---|
| 135 | private void UpdateResourceGenealogy() {
|
---|
| 136 | resourceAncestors.Clear();
|
---|
| 137 | resourceDescendants.Clear();
|
---|
| 138 |
|
---|
| 139 | foreach (var r in resources) {
|
---|
| 140 | resourceAncestors.Add(r.Id, new HashSet<Resource>());
|
---|
| 141 | resourceDescendants.Add(r.Id, new HashSet<Resource>());
|
---|
| 142 | }
|
---|
| 143 |
|
---|
| 144 | foreach (var r in resources) {
|
---|
| 145 | var parentResourceId = r.ParentResourceId;
|
---|
| 146 | while (parentResourceId != null) {
|
---|
| 147 | var parent = resources.SingleOrDefault(x => x.Id == parentResourceId);
|
---|
| 148 | if (parent != null) {
|
---|
| 149 | resourceAncestors[r.Id].Add(parent);
|
---|
| 150 | resourceDescendants[parent.Id].Add(r);
|
---|
| 151 | parentResourceId = parent.ParentResourceId;
|
---|
| 152 | } else {
|
---|
| 153 | parentResourceId = null;
|
---|
| 154 | }
|
---|
| 155 | }
|
---|
| 156 | }
|
---|
| 157 | }
|
---|
| 158 |
|
---|
| 159 | private void UpdateProjectGenealogy() {
|
---|
| 160 | projectAncestors.Clear();
|
---|
| 161 | projectDescendants.Clear();
|
---|
| 162 |
|
---|
| 163 | foreach (var p in projects) {
|
---|
| 164 | projectAncestors.Add(p.Id, new HashSet<Project>());
|
---|
| 165 | projectDescendants.Add(p.Id, new HashSet<Project>());
|
---|
| 166 | }
|
---|
| 167 |
|
---|
| 168 | foreach (var p in projects) {
|
---|
| 169 | var parentProjectId = p.ParentProjectId;
|
---|
| 170 | while (parentProjectId != null) {
|
---|
| 171 | var parent = projects.SingleOrDefault(x => x.Id == parentProjectId);
|
---|
| 172 | if (parent != null) {
|
---|
| 173 | projectAncestors[p.Id].Add(parent);
|
---|
| 174 | projectDescendants[parent.Id].Add(p);
|
---|
| 175 | parentProjectId = parent.ParentProjectId;
|
---|
| 176 | } else {
|
---|
| 177 | parentProjectId = null;
|
---|
| 178 | }
|
---|
| 179 | }
|
---|
| 180 | }
|
---|
| 181 | }
|
---|
[6976] | 182 | #endregion
|
---|
| 183 |
|
---|
| 184 | #region Refresh downtime calendar
|
---|
| 185 | public void RefreshCalendar() {
|
---|
| 186 | if (downtimeForResourceId != null && downtimeForResourceId != Guid.Empty) {
|
---|
| 187 | OnRefreshing();
|
---|
| 188 |
|
---|
| 189 | try {
|
---|
| 190 | downtimes = new ItemList<Downtime>();
|
---|
| 191 |
|
---|
[7132] | 192 | HiveServiceLocator.Instance.CallHiveService(service => {
|
---|
[6976] | 193 | service.GetDowntimesForResource(downtimeForResourceId).ForEach(d => downtimes.Add(d));
|
---|
| 194 | });
|
---|
| 195 | }
|
---|
| 196 | catch {
|
---|
| 197 | throw;
|
---|
| 198 | }
|
---|
| 199 | finally {
|
---|
| 200 | OnRefreshed();
|
---|
| 201 | }
|
---|
| 202 | }
|
---|
| 203 | }
|
---|
| 204 | #endregion
|
---|
| 205 |
|
---|
| 206 | #region Store
|
---|
| 207 | public static void Store(IHiveItem item, CancellationToken cancellationToken) {
|
---|
| 208 | if (item.Id == Guid.Empty) {
|
---|
| 209 | if (item is SlaveGroup) {
|
---|
[7132] | 210 | item.Id = HiveServiceLocator.Instance.CallHiveService((s) => s.AddSlaveGroup((SlaveGroup)item));
|
---|
[6976] | 211 | }
|
---|
| 212 | if (item is Slave) {
|
---|
[7132] | 213 | item.Id = HiveServiceLocator.Instance.CallHiveService((s) => s.AddSlave((Slave)item));
|
---|
[6976] | 214 | }
|
---|
| 215 | if (item is Downtime) {
|
---|
[7132] | 216 | item.Id = HiveServiceLocator.Instance.CallHiveService((s) => s.AddDowntime((Downtime)item));
|
---|
[6976] | 217 | }
|
---|
[15401] | 218 | if (item is Project) {
|
---|
| 219 | item.Id = HiveServiceLocator.Instance.CallHiveService(s => s.AddProject((Project)item));
|
---|
| 220 | }
|
---|
[6976] | 221 | } else {
|
---|
| 222 | if (item is SlaveGroup) {
|
---|
[7132] | 223 | HiveServiceLocator.Instance.CallHiveService((s) => s.UpdateSlaveGroup((SlaveGroup)item));
|
---|
[6976] | 224 | }
|
---|
| 225 | if (item is Slave) {
|
---|
[7132] | 226 | HiveServiceLocator.Instance.CallHiveService((s) => s.UpdateSlave((Slave)item));
|
---|
[6976] | 227 | }
|
---|
| 228 | if (item is Downtime) {
|
---|
[7132] | 229 | HiveServiceLocator.Instance.CallHiveService((s) => s.UpdateDowntime((Downtime)item));
|
---|
[6976] | 230 | }
|
---|
[15401] | 231 | if (item is Project) {
|
---|
| 232 | HiveServiceLocator.Instance.CallHiveService((s) => s.UpdateProject((Project)item));
|
---|
| 233 | }
|
---|
[6976] | 234 | }
|
---|
| 235 | }
|
---|
| 236 | #endregion
|
---|
| 237 |
|
---|
| 238 | #region Delete
|
---|
| 239 | public static void Delete(IHiveItem item) {
|
---|
| 240 | if (item is SlaveGroup) {
|
---|
[7132] | 241 | HiveServiceLocator.Instance.CallHiveService((s) => s.DeleteSlaveGroup(item.Id));
|
---|
[6976] | 242 | } else if (item is Slave) {
|
---|
[7132] | 243 | HiveServiceLocator.Instance.CallHiveService((s) => s.DeleteSlave(item.Id));
|
---|
[6976] | 244 | } else if (item is Downtime) {
|
---|
[7132] | 245 | HiveServiceLocator.Instance.CallHiveService((s) => s.DeleteDowntime(item.Id));
|
---|
[15401] | 246 | } else if (item is Project) {
|
---|
| 247 | HiveServiceLocator.Instance.CallHiveService((s) => s.DeleteProject(item.Id));
|
---|
[6976] | 248 | }
|
---|
| 249 | }
|
---|
| 250 | #endregion
|
---|
| 251 |
|
---|
| 252 | public void ResetDowntime() {
|
---|
| 253 | downtimeForResourceId = Guid.Empty;
|
---|
| 254 | if (downtimes != null) {
|
---|
| 255 | downtimes.Clear();
|
---|
| 256 | }
|
---|
| 257 | }
|
---|
[15658] | 258 |
|
---|
[15742] | 259 | #region Helper
|
---|
[15658] | 260 | public bool CheckAccessToAdminAreaGranted() {
|
---|
| 261 | if(projects != null) {
|
---|
| 262 | return projects.Count > 0;
|
---|
| 263 | } else {
|
---|
| 264 | bool accessGranted = false;
|
---|
| 265 | HiveServiceLocator.Instance.CallHiveService(s => {
|
---|
| 266 | accessGranted = s.CheckAccessToAdminAreaGranted();
|
---|
| 267 | });
|
---|
| 268 | return accessGranted;
|
---|
| 269 | }
|
---|
| 270 | }
|
---|
[15742] | 271 |
|
---|
| 272 | public bool CheckOwnershipOfResource(Resource res, Guid userId) {
|
---|
| 273 | if (res == null || userId == Guid.Empty) return false;
|
---|
| 274 |
|
---|
| 275 | if (res.OwnerUserId == userId) {
|
---|
| 276 | return true;
|
---|
| 277 | } else if(resourceAncestors.ContainsKey(res.Id)) {
|
---|
| 278 | return resourceAncestors[res.Id].Where(x => x.OwnerUserId == userId).Any();
|
---|
| 279 | }
|
---|
| 280 |
|
---|
| 281 | return false;
|
---|
| 282 | }
|
---|
| 283 |
|
---|
| 284 | public bool CheckOwnershipOfProject(Project pro, Guid userId) {
|
---|
| 285 | if (pro == null || userId == Guid.Empty) return false;
|
---|
| 286 |
|
---|
| 287 | if (pro.OwnerUserId == userId) {
|
---|
| 288 | return true;
|
---|
| 289 | } else if (projectAncestors.ContainsKey(pro.Id)) {
|
---|
| 290 | return projectAncestors[pro.Id].Where(x => x.OwnerUserId == userId).Any();
|
---|
| 291 | }
|
---|
| 292 |
|
---|
| 293 | return false;
|
---|
| 294 | }
|
---|
| 295 |
|
---|
| 296 | public bool CheckOwnershipOfParentProject(Project pro, Guid userId) {
|
---|
| 297 | if (pro == null || userId == Guid.Empty) return false;
|
---|
| 298 |
|
---|
| 299 | if(projectAncestors.ContainsKey(pro.Id)) {
|
---|
| 300 | return projectAncestors[pro.Id].Where(x => x.OwnerUserId == userId).Any();
|
---|
| 301 | }
|
---|
| 302 |
|
---|
| 303 | return false;
|
---|
| 304 | }
|
---|
[15768] | 305 |
|
---|
| 306 | public bool CheckParentChange(Project child, Project parent) {
|
---|
| 307 | bool changeGranted = true;
|
---|
| 308 |
|
---|
| 309 | // change is not granted, if the moved project is null
|
---|
| 310 | // or the new parent is not stored yet
|
---|
| 311 | // or there is not parental change
|
---|
| 312 | if (child == null
|
---|
| 313 | || (parent != null && parent.Id == Guid.Empty)
|
---|
| 314 | || (parent != null && parent.Id == child.ParentProjectId)) {
|
---|
| 315 | changeGranted = false;
|
---|
| 316 | } else if(parent != null && projectDescendants.ContainsKey(child.Id)) {
|
---|
| 317 | // change is not granted, if the new parent is among the moved project's descendants
|
---|
| 318 | changeGranted = !projectDescendants[child.Id].Where(x => x.Id == parent.Id).Any();
|
---|
| 319 | }
|
---|
| 320 |
|
---|
| 321 | return changeGranted;
|
---|
| 322 | }
|
---|
| 323 |
|
---|
| 324 | public bool CheckParentChange(Resource child, Resource parent) {
|
---|
| 325 | bool changeGranted = true;
|
---|
| 326 |
|
---|
| 327 | // change is not granted, if the moved resource is null
|
---|
| 328 | // or the new parent is not stored yet
|
---|
| 329 | // or there is not parental change
|
---|
| 330 | if (child == null
|
---|
| 331 | || (parent != null && parent.Id == Guid.Empty)
|
---|
| 332 | || (parent != null && parent.Id == child.ParentResourceId)) {
|
---|
| 333 | changeGranted = false;
|
---|
| 334 | } else if (parent != null && resourceDescendants.ContainsKey(child.Id)) {
|
---|
| 335 | // change is not granted, if the new parent is among the moved resource's descendants
|
---|
| 336 | changeGranted = !resourceDescendants[child.Id].Where(x => x.Id == parent.Id).Any();
|
---|
| 337 | }
|
---|
| 338 |
|
---|
| 339 | return changeGranted;
|
---|
| 340 | }
|
---|
[15658] | 341 | #endregion
|
---|
[6976] | 342 | }
|
---|
| 343 | }
|
---|