#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 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();
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));
});
UpdateResourceGenealogy(resources);
UpdateProjectGenealogy(projects);
}
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;
}
}
}
}
#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 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 resourceAncestors[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 projectAncestors[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 projectAncestors[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 = !projectDescendants[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 moved resource is null
// ... or the new parent is not stored yet
// ... or the new parent is a slave
// ... or there is not parental change
if (child == null
|| (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 = !resourceDescendants[child.Id].Where(x => x.Id == parent.Id).Any();
}
return changePossible;
}
#endregion
}
}