Index: /branches/HiveProjectManagement/HeuristicLab.Services.Hive.DataAccess/3.3/Daos/AssignedJobResourceDao.cs
===================================================================
--- /branches/HiveProjectManagement/HeuristicLab.Services.Hive.DataAccess/3.3/Daos/AssignedJobResourceDao.cs	(revision 15736)
+++ /branches/HiveProjectManagement/HeuristicLab.Services.Hive.DataAccess/3.3/Daos/AssignedJobResourceDao.cs	(revision 15737)
@@ -96,5 +96,5 @@
 		      SELECT j.JobId
 		      FROM [Job] j
-		      WHERE j.ProjectId = '{0}'
+		      WHERE j.ProjectId = {0}
 	      )
     ";
@@ -105,5 +105,5 @@
 		      SELECT j.JobId
 		      FROM [Job] j
-		      WHERE j.ProjectId = '{0}'
+		      WHERE j.ProjectId = {0}
           AND j.OwnerUserId IN ({1})
 	      )
Index: /branches/HiveProjectManagement/HeuristicLab.Services.Hive.DataAccess/3.3/Daos/ProjectDao.cs
===================================================================
--- /branches/HiveProjectManagement/HeuristicLab.Services.Hive.DataAccess/3.3/Daos/ProjectDao.cs	(revision 15736)
+++ /branches/HiveProjectManagement/HeuristicLab.Services.Hive.DataAccess/3.3/Daos/ProjectDao.cs	(revision 15737)
@@ -37,4 +37,12 @@
     public override Project GetById(Guid id) {
       return GetByIdQuery(DataContext, id);
+    }
+
+    public void DeleteByIds(IEnumerable<Guid> ids) {
+      string paramProjectIds = string.Join(",", ids.ToList().Select(x => string.Format("'{0}'", x)));
+      if(!string.IsNullOrWhiteSpace(paramProjectIds)) {
+        string queryString = string.Format(DeleteByIdsQueryString, paramProjectIds);
+        DataContext.ExecuteCommand(queryString);
+      }
     }
 
@@ -93,4 +101,9 @@
 
     #region String queries
+    private const string DeleteByIdsQueryString = @"
+      DELETE FROM [Project]
+      WHERE ProjectId IN ({0})
+    ";
+
     private const string GetUsageStatsPerProjectQueryString = @"
       SELECT j.ProjectId, SUM(t.CoresNeeded) AS Cores, SUM(t.MemoryNeeded) AS Memory
Index: /branches/HiveProjectManagement/HeuristicLab.Services.Hive.DataAccess/3.3/Daos/ResourceDao.cs
===================================================================
--- /branches/HiveProjectManagement/HeuristicLab.Services.Hive.DataAccess/3.3/Daos/ResourceDao.cs	(revision 15736)
+++ /branches/HiveProjectManagement/HeuristicLab.Services.Hive.DataAccess/3.3/Daos/ResourceDao.cs	(revision 15737)
@@ -35,4 +35,12 @@
     public Resource GetByName(string name) {
       return GetByNameQuery(DataContext, name);
+    }
+
+    public void DeleteByIds(IEnumerable<Guid> ids) {
+      string paramResourceIds = string.Join(",", ids.ToList().Select(x => string.Format("'{0}'", x)));
+      if (!string.IsNullOrWhiteSpace(paramResourceIds)) {
+        string queryString = string.Format(DeleteByIdsQueryString, paramResourceIds);
+        DataContext.ExecuteCommand(queryString);
+      }
     }
 
@@ -89,4 +97,8 @@
 
     #region String queries
+    private const string DeleteByIdsQueryString = @"
+      DELETE FROM [Resource]
+      WHERE ResourceId IN ({0})
+    ";
     private const string CountExistenceQuery = @"
       SELECT COUNT(DISTINCT r.ResourceId)
Index: /branches/HiveProjectManagement/HeuristicLab.Services.Hive.DataAccess/3.3/SQL Scripts/Initialize Hive Database.sql
===================================================================
--- /branches/HiveProjectManagement/HeuristicLab.Services.Hive.DataAccess/3.3/SQL Scripts/Initialize Hive Database.sql	(revision 15736)
+++ /branches/HiveProjectManagement/HeuristicLab.Services.Hive.DataAccess/3.3/SQL Scripts/Initialize Hive Database.sql	(revision 15737)
@@ -182,7 +182,7 @@
   ADD CONSTRAINT [Resource_Resource] FOREIGN KEY ([ParentResourceId]) REFERENCES [dbo].[Resource]([ResourceId]);
 ALTER TABLE [dbo].[Task]
-  ADD CONSTRAINT [Task_Task] FOREIGN KEY ([ParentTaskId]) REFERENCES [dbo].[Task]([TaskId]) ON UPDATE CASCADE ON DELETE CASCADE;
+  ADD CONSTRAINT [Task_Task] FOREIGN KEY ([ParentTaskId]) REFERENCES [dbo].[Task]([TaskId]);
 ALTER TABLE [dbo].[Task]
-  ADD CONSTRAINT [Job_Job] FOREIGN KEY ([JobId]) REFERENCES [dbo].[Job]([JobId]) ON UPDATE CASCADE ON DELETE CASCADE;
+  ADD CONSTRAINT [Job_Task] FOREIGN KEY ([JobId]) REFERENCES [dbo].[Job]([JobId]) ON UPDATE CASCADE ON DELETE CASCADE;
 ALTER TABLE [dbo].[Downtime]
   ADD CONSTRAINT [Resource_Downtime] FOREIGN KEY ([ResourceId]) REFERENCES [dbo].[Resource]([ResourceId]) ON UPDATE CASCADE ON DELETE CASCADE;
@@ -200,5 +200,5 @@
   ADD CONSTRAINT [Job_JobPermission] FOREIGN KEY ([JobId]) REFERENCES [dbo].[Job]([JobId]) ON UPDATE CASCADE ON DELETE CASCADE;
 ALTER TABLE [dbo].[Project]
-  ADD CONSTRAINT [Project_Project] FOREIGN KEY ([ParentProjectId]) REFERENCES [dbo].[Project]([ProjectId]) ON UPDATE CASCADE ON DELETE CASCADE;
+  ADD CONSTRAINT [Project_Project] FOREIGN KEY ([ParentProjectId]) REFERENCES [dbo].[Project]([ProjectId]);
 ALTER TABLE [dbo].[ProjectPermission]
   ADD CONSTRAINT [Project_ProjectPermission] FOREIGN KEY ([ProjectId]) REFERENCES [dbo].[Project]([ProjectId]) ON UPDATE CASCADE ON DELETE CASCADE;
@@ -219,11 +219,10 @@
 CREATE TABLE [statistics].[DimClient] (
     [Id]               UNIQUEIDENTIFIER CONSTRAINT [DF_DimClient_Id] DEFAULT (newsequentialid()) NOT NULL,
-    [Name]             VARCHAR (MAX)    NOT NULL,
     [ResourceId]       UNIQUEIDENTIFIER NOT NULL,
-    [ExpirationTime]   DATETIME         NULL,
-    [ResourceGroupId]  UNIQUEIDENTIFIER NULL,
-    [ResourceGroup2Id] UNIQUEIDENTIFIER NULL,
-    [GroupName]        VARCHAR (MAX)    NULL,
-    [GroupName2]       VARCHAR (MAX)    NULL,
+	[ParentResourceId] UNIQUEIDENTIFIER NULL,
+	[Name]             VARCHAR (MAX)    NOT NULL,
+	[ResourceType]     VARCHAR (MAX)    NULL,
+	[DateCreated]      DATETIME         NOT NULL,
+    [DateExpired]      DATETIME         NULL
     CONSTRAINT [PK_DimClient] PRIMARY KEY CLUSTERED ([Id] ASC)
 );
@@ -231,4 +230,5 @@
     [JobId]          UNIQUEIDENTIFIER NOT NULL,
     [UserId]         UNIQUEIDENTIFIER NOT NULL,
+	[ProjectId]      UNIQUEIDENTIFIER NOT NULL,
     [JobName]        VARCHAR (MAX)    NOT NULL,
     [UserName]       VARCHAR (MAX)    NOT NULL,
@@ -239,8 +239,35 @@
     CONSTRAINT [PK_DimJob] PRIMARY KEY CLUSTERED ([JobId] ASC)
 );
+CREATE TABLE [statistics].[DimProject] (
+    [Id]               UNIQUEIDENTIFIER CONSTRAINT [DF_DimProject_Id] DEFAULT (newsequentialid()) NOT NULL,
+    [ProjectId]        UNIQUEIDENTIFIER NOT NULL,
+	[ParentProjectId]  UNIQUEIDENTIFIER NULL,
+	[Name]             VARCHAR (MAX)    NOT NULL,
+	[Description]      VARCHAR (MAX)    NULL,
+	[OwnerUserId]      UNIQUEIDENTIFIER NOT NULL,
+	[StartDate]        DATETIME         NOT NULL,
+    [EndDate]          DATETIME         NULL,
+	[DateCreated]      DATETIME         NOT NULL,
+    [DateExpired]      DATETIME         NULL
+	CONSTRAINT [PK_DimProject] PRIMARY KEY CLUSTERED ([Id] ASC)
+);
 CREATE TABLE [statistics].[DimUser] (
     [UserId] UNIQUEIDENTIFIER NOT NULL,
     [Name]   VARCHAR (MAX)    NOT NULL,
     CONSTRAINT [PK_DimUser] PRIMARY KEY CLUSTERED ([UserId] ASC)
+);
+
+
+
+CREATE TABLE [statistics].[FactProjectInfo] (
+	[ProjectId]		UNIQUEIDENTIFIER NOT NULL,
+	[Time]			DATETIME		 NOT NULL,
+	[NumTotalCores]	INT				 NOT NULL,
+	[NumUsedCores]  INT				 NOT NULL,
+	[TotalMemory]	INT				 NOT NULL,
+	[UsedMemory]	INT				 NOT NULL
+	CONSTRAINT [PK_FactProjectInfo] PRIMARY KEY CLUSTERED ([ProjectId] ASC, [Time] ASC),
+	CONSTRAINT [FK_FactProjectInfo_DimTime] FOREIGN KEY ([Time]) REFERENCES [statistics].[DimTime] ([Time]),
+	CONSTRAINT [FK_FactProjectInfo_DimProject] FOREIGN KEY ([ProjectId]) REFERENCES [statistics].[DimProject] ([Id])
 );
 CREATE TABLE [statistics].[FactClientInfo] (
Index: /branches/HiveProjectManagement/HeuristicLab.Services.Hive.DataAccess/3.3/SQL Scripts/Prepare Hive Database.sql
===================================================================
--- /branches/HiveProjectManagement/HeuristicLab.Services.Hive.DataAccess/3.3/SQL Scripts/Prepare Hive Database.sql	(revision 15736)
+++ /branches/HiveProjectManagement/HeuristicLab.Services.Hive.DataAccess/3.3/SQL Scripts/Prepare Hive Database.sql	(revision 15737)
@@ -145,5 +145,5 @@
 
 
--- OBSOLETE (start)
+-- OBSOLETE - DO NOT PERFORM (start)
 /****** Object:  Trigger [dbo].[tr_JobDeleteCascade]    Script Date: 04/19/2011 16:31:53 ******/
 SET ANSI_NULLS ON
Index: /branches/HiveProjectManagement/HeuristicLab.Services.Hive/3.3/HiveService.cs
===================================================================
--- /branches/HiveProjectManagement/HeuristicLab.Services.Hive/3.3/HiveService.cs	(revision 15736)
+++ /branches/HiveProjectManagement/HeuristicLab.Services.Hive/3.3/HiveService.cs	(revision 15737)
@@ -680,5 +680,5 @@
       if (!RoleVerifier.IsInRole(HiveRoles.Administrator)) {
         if(projectDto.ParentProjectId.HasValue) {
-          AuthorizationManager.AuthorizeForProjectAdministration(projectDto.ParentProjectId.Value);
+          AuthorizationManager.AuthorizeForProjectAdministration(projectDto.ParentProjectId.Value, false);
         } else {
           throw new SecurityException(NOT_AUTHORIZED_USERPROJECT);
@@ -701,5 +701,5 @@
       // check if current (non-admin) user is owner of the project or the projectDto's-parents
       if (!RoleVerifier.IsInRole(HiveRoles.Administrator)) {
-        AuthorizationManager.AuthorizeForProjectAdministration(projectDto.Id);
+        AuthorizationManager.AuthorizeForProjectAdministration(projectDto.Id, false);
       }
 
@@ -720,8 +720,9 @@
 
     public void DeleteProject(Guid projectId) {
-      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
-      // check if current (non-admin) user is owner of the project or the projectDto's-parents
+      if (projectId == Guid.Empty) return;
+      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
+      // check if current (non-admin) user is owner of one of the projectDto's-parents
       if (!RoleVerifier.IsInRole(HiveRoles.Administrator)) {
-        AuthorizationManager.AuthorizeForProjectAdministration(projectId);
+        AuthorizationManager.AuthorizeForProjectAdministration(projectId, true);
       }
 
@@ -731,6 +732,9 @@
         var assignedJobResourceDao = pm.AssignedJobResourceDao;
         pm.UseTransaction(() => {
-          assignedJobResourceDao.DeleteByProjectId(projectId);
-          projectDao.Delete(projectId);
+          var projectIds = new HashSet<Guid> { projectId };
+          projectIds.Union(projectDao.GetChildProjectIdsById(projectId));
+
+          assignedJobResourceDao.DeleteByProjectIds(projectIds);
+          projectDao.DeleteByIds(projectIds);
           pm.SubmitChanges();
         });
@@ -797,5 +801,5 @@
       RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
       if (projectId == null || grantedUserIds == null) return;
-      AuthorizationManager.AuthorizeForProjectAdministration(projectId);
+      AuthorizationManager.AuthorizeForProjectAdministration(projectId, false);
       var pm = PersistenceManager;
       using (new PerformanceLogger("SaveProjectPermissions")) {
@@ -883,5 +887,5 @@
       RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
       if (projectId == null || grantedUserIds == null || !grantedUserIds.Any()) return;
-      AuthorizationManager.AuthorizeForProjectAdministration(projectId);
+      AuthorizationManager.AuthorizeForProjectAdministration(projectId, false);
       var pm = PersistenceManager;
       using (new PerformanceLogger("RevokeProjectPermissions")) {
@@ -904,5 +908,5 @@
     public IEnumerable<DT.ProjectPermission> GetProjectPermissions(Guid projectId) {
       RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
-      AuthorizationManager.AuthorizeForProjectAdministration(projectId);
+      AuthorizationManager.AuthorizeForProjectAdministration(projectId, false);
       var pm = PersistenceManager;
       using (new PerformanceLogger("GetProjectPermissions")) {
@@ -1040,5 +1044,5 @@
     public IEnumerable<DT.AssignedProjectResource> GetAssignedResourcesForProjectAdministration(Guid projectId) {
       RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
-      AuthorizationManager.AuthorizeForProjectAdministration(projectId);
+      AuthorizationManager.AuthorizeForProjectAdministration(projectId, false);
       var pm = PersistenceManager;
       using (new PerformanceLogger("GetAssignedResourcesForProject")) {
@@ -1263,4 +1267,5 @@
 
     public void DeleteSlave(Guid slaveId) {
+      if (slaveId == Guid.Empty) return;
       RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
       AuthorizationManager.AuthorizeForResourceAdministration(slaveId);
@@ -1276,11 +1281,14 @@
 
     public void DeleteSlaveGroup(Guid slaveGroupId) {
+      if (slaveGroupId == Guid.Empty) return;
       RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
       AuthorizationManager.AuthorizeForResourceAdministration(slaveGroupId);
       var pm = PersistenceManager;
       using (new PerformanceLogger("DeleteSlaveGroup")) {
-        var slaveGroupDao = pm.SlaveGroupDao;
-        pm.UseTransaction(() => {
-          slaveGroupDao.Delete(slaveGroupId);
+        var resourceDao = pm.ResourceDao;
+        pm.UseTransaction(() => {
+          var resourceIds = new HashSet<Guid> { slaveGroupId };
+          resourceIds.Union(resourceDao.GetChildResourceIdsById(slaveGroupId));
+          resourceDao.DeleteByIds(resourceIds);
           pm.SubmitChanges();
         });
Index: /branches/HiveProjectManagement/HeuristicLab.Services.Hive/3.3/Interfaces/IAuthorizationManager.cs
===================================================================
--- /branches/HiveProjectManagement/HeuristicLab.Services.Hive/3.3/Interfaces/IAuthorizationManager.cs	(revision 15736)
+++ /branches/HiveProjectManagement/HeuristicLab.Services.Hive/3.3/Interfaces/IAuthorizationManager.cs	(revision 15737)
@@ -37,5 +37,5 @@
     void AuthorizeForResourceAdministration(Guid resourceId);
 
-    void AuthorizeForProjectAdministration(Guid projectId);
+    void AuthorizeForProjectAdministration(Guid projectId, bool parentalOwnership);
 
     void AuthorizeForProjectResourceAdministration(Guid projectId, IEnumerable<Guid> resourceIds);
Index: /branches/HiveProjectManagement/HeuristicLab.Services.Hive/3.3/Manager/AuthorizationManager.cs
===================================================================
--- /branches/HiveProjectManagement/HeuristicLab.Services.Hive/3.3/Manager/AuthorizationManager.cs	(revision 15736)
+++ /branches/HiveProjectManagement/HeuristicLab.Services.Hive/3.3/Manager/AuthorizationManager.cs	(revision 15737)
@@ -92,5 +92,5 @@
 
     // authorize if user is admin, project owner or owner of a parent project
-    public void AuthorizeForProjectAdministration(Guid projectId) {
+    public void AuthorizeForProjectAdministration(Guid projectId, bool parentalOwnership) {
       if (projectId == null) return;
       var currentUserId = UserManager.CurrentUserId;
@@ -98,7 +98,10 @@
       var projectDao = pm.ProjectDao;
       pm.UseTransaction(() => {
-        var projectBranch = projectDao.GetCurrentAndParentProjectsById(projectId).ToList();
-        if(!projectBranch.Select(x => x.OwnerUserId).Contains(currentUserId)
-            && !RoleVerifier.IsInRole(HiveRoles.Administrator)) {
+        List<Project> projectBranch = null;
+        if(parentalOwnership) projectDao.GetParentProjectsById(projectId).ToList();
+        else projectBranch = projectDao.GetCurrentAndParentProjectsById(projectId).ToList();
+
+        if(!RoleVerifier.IsInRole(HiveRoles.Administrator)
+            && !projectBranch.Select(x => x.OwnerUserId).Contains(currentUserId)) {
           throw new SecurityException(NOT_AUTHORIZED_USERPROJECT);
         }
