diff --git a/src/main/java/org/olat/course/CourseFactory.java b/src/main/java/org/olat/course/CourseFactory.java index bfe3f59174a0202b90fe876fa7f02c7e87ef0853..a8710a9bbd716604ae0257c89206b6563729b136 100644 --- a/src/main/java/org/olat/course/CourseFactory.java +++ b/src/main/java/org/olat/course/CourseFactory.java @@ -112,6 +112,7 @@ import org.olat.course.nodes.BCCourseNode; import org.olat.course.nodes.CourseNode; import org.olat.course.nodes.STCourseNode; import org.olat.course.nodes.TACourseNode; +import org.olat.course.nodes.gta.GTAManager; import org.olat.course.properties.CoursePropertyManager; import org.olat.course.properties.PersistingCoursePropertyManager; import org.olat.course.run.RunMainController; @@ -298,7 +299,7 @@ public class CourseFactory extends BasicManager { * * @param res */ - public static void deleteCourse(OLATResource res) { + public static void deleteCourse(RepositoryEntry entry, OLATResource res) { final long start = System.currentTimeMillis(); log.info("deleteCourse: starting to delete course. res="+res); @@ -321,6 +322,7 @@ public class CourseFactory extends BasicManager { TreeVisitor tv = new TreeVisitor(visitor, course.getRunStructure().getRootNode(), true); tv.visitAll(); } + // delete assessment notifications OLATResourceable assessmentOres = OresHelper.createOLATResourceableInstance(CourseModule.ORES_COURSE_ASSESSMENT, res.getResourceableId()); @@ -348,6 +350,8 @@ public class CourseFactory extends BasicManager { calManager.deleteCourseCalendar(res); // delete IM messages CoreSpringFactory.getImpl(InstantMessagingService.class).deleteMessages(res); + //delete tasks + CoreSpringFactory.getImpl(GTAManager.class).deleteAllTaskLists(entry); // cleanup cache removeFromCache(res.getResourceableId()); diff --git a/src/main/java/org/olat/course/CourseModule.java b/src/main/java/org/olat/course/CourseModule.java index 655082193e5a44683db7651374c1253f865a3807..4b6b4d3eb35a70bd329b03ef1148b92c2554ada6 100644 --- a/src/main/java/org/olat/course/CourseModule.java +++ b/src/main/java/org/olat/course/CourseModule.java @@ -277,7 +277,7 @@ public class CourseModule extends AbstractOLATModule { try { propertyManager.deleteProperty(prop); repositoryService.deleteRepositoryEntryAndBaseGroups(re); - CourseFactory.deleteCourse(re.getOlatResource()); + CourseFactory.deleteCourse(re, re.getOlatResource()); OLATResource ores = olatResourceManager.findResourceable(re.getOlatResource()); olatResourceManager.deleteOLATResource(ores); } catch (Exception e) { diff --git a/src/main/java/org/olat/course/nodes/gta/GTAManager.java b/src/main/java/org/olat/course/nodes/gta/GTAManager.java index c6eae46524ef1f69ca984a2f35fa96177235bfc6..41dd51f6d8cf0951b465de0996c965c2a213388a 100644 --- a/src/main/java/org/olat/course/nodes/gta/GTAManager.java +++ b/src/main/java/org/olat/course/nodes/gta/GTAManager.java @@ -164,8 +164,21 @@ public interface GTAManager { public int updateTaskName(TaskList taskList, String currentTaskName, String newTaskName); + /** + * Delete the task list and the tasks of the specified course element of the course. + * @param entry The repository entry of the course + * @param cNode The course element + * @return + */ public int deleteTaskList(RepositoryEntryRef entry, GTACourseNode cNode); + /** + * Delete all the task list and tasks of a course specified by its repository entry. + * @param entry + * @return + */ + public int deleteAllTaskLists(RepositoryEntryRef entry); + public Membership getMembership(IdentityRef identity, RepositoryEntryRef entry, GTACourseNode cNode); diff --git a/src/main/java/org/olat/course/nodes/gta/manager/GTAManagerImpl.java b/src/main/java/org/olat/course/nodes/gta/manager/GTAManagerImpl.java index c7756d8529aa5a4e1320d0bfad42a038127623d8..342cc27f43eda50406bf9c502fe690f8493d1487 100644 --- a/src/main/java/org/olat/course/nodes/gta/manager/GTAManagerImpl.java +++ b/src/main/java/org/olat/course/nodes/gta/manager/GTAManagerImpl.java @@ -30,6 +30,7 @@ import java.util.Iterator; import java.util.List; import java.util.Set; +import javax.persistence.Query; import javax.persistence.LockModeType; import org.olat.basesecurity.GroupRoles; @@ -483,6 +484,30 @@ public class GTAManagerImpl implements GTAManager { return numOfDeletedObjects; } + @Override + public int deleteAllTaskLists(RepositoryEntryRef entry) { + String q = "select tasks from gtatasklist tasks where tasks.entry.key=:entryKey"; + List<TaskList> taskLists = dbInstance.getCurrentEntityManager().createQuery(q, TaskList.class) + .setParameter("entryKey", entry.getKey()) + .getResultList(); + + String deleteTasks = "delete from gtatask as task where task.taskList.key=:taskListKey"; + Query deleteTaskQuery = dbInstance.getCurrentEntityManager().createQuery(deleteTasks); + + int numOfDeletedObjects = 0; + for(TaskList taskList:taskLists) { + int numOfTasks = deleteTaskQuery.setParameter("taskListKey", taskList.getKey()).executeUpdate(); + numOfDeletedObjects += numOfTasks; + } + + String deleteTaskLists = "delete from gtatasklist as tasks where tasks.entry.key=:entryKey"; + numOfDeletedObjects += dbInstance.getCurrentEntityManager() + .createQuery(deleteTaskLists) + .setParameter("entryKey", entry.getKey()) + .executeUpdate(); + return numOfDeletedObjects; + } + @Override public List<Task> getTasks(TaskList taskList, GTACourseNode cNode) { StringBuilder sb = new StringBuilder(); diff --git a/src/main/java/org/olat/repository/handlers/BlogHandler.java b/src/main/java/org/olat/repository/handlers/BlogHandler.java index c8108b44faaba9aad877d7c1716dd707f6e87b65..49fc7b6f01df6597896fe1153300fe5f9f92a04c 100644 --- a/src/main/java/org/olat/repository/handlers/BlogHandler.java +++ b/src/main/java/org/olat/repository/handlers/BlogHandler.java @@ -138,7 +138,7 @@ public class BlogHandler implements RepositoryHandler { } @Override - public boolean cleanupOnDelete(OLATResourceable res) { + public boolean cleanupOnDelete(RepositoryEntry entry, OLATResourceable res) { CoordinatorManager.getInstance().getCoordinator().getEventBus().fireEventToListenersOf(new OLATResourceableJustBeforeDeletedEvent(res), res); // For now, notifications are not implemented since a blog feed is meant // to be subscriped to anyway. diff --git a/src/main/java/org/olat/repository/handlers/CourseHandler.java b/src/main/java/org/olat/repository/handlers/CourseHandler.java index 35c1a28f708d2b293e347ec484e9db6b5fd8c805..16c041736559349d8f20d208a1cfad0dd4ceba3f 100644 --- a/src/main/java/org/olat/repository/handlers/CourseHandler.java +++ b/src/main/java/org/olat/repository/handlers/CourseHandler.java @@ -563,13 +563,13 @@ public class CourseHandler implements RepositoryHandler { } @Override - public boolean cleanupOnDelete(OLATResourceable res) { + public boolean cleanupOnDelete(RepositoryEntry entry, OLATResourceable res) { // notify all current users of this resource (course) that it will be deleted now. CoordinatorManager.getInstance().getCoordinator().getEventBus().fireEventToListenersOf(new OLATResourceableJustBeforeDeletedEvent(res), res); //archiving is done within readyToDelete OLATResourceManager rm = OLATResourceManager.getInstance(); OLATResource resource = rm.findResourceable(res); - CourseFactory.deleteCourse(resource); + CourseFactory.deleteCourse(entry, resource); return true; } diff --git a/src/main/java/org/olat/repository/handlers/FileHandler.java b/src/main/java/org/olat/repository/handlers/FileHandler.java index a1a784b46d9bb225da45217d355f637b95e764ca..18e82e8cf59119ae285c5241a2a6813a4e92a523 100644 --- a/src/main/java/org/olat/repository/handlers/FileHandler.java +++ b/src/main/java/org/olat/repository/handlers/FileHandler.java @@ -62,7 +62,7 @@ public abstract class FileHandler implements RepositoryHandler { } @Override - public boolean cleanupOnDelete(OLATResourceable res) { + public boolean cleanupOnDelete(RepositoryEntry entry, OLATResourceable res) { // notify all current users of this resource (content packaging file resource) that it will be deleted now. CoordinatorManager.getInstance().getCoordinator().getEventBus().fireEventToListenersOf(new OLATResourceableJustBeforeDeletedEvent(res), res); FileResourceManager.getInstance().deleteFileResource(res); diff --git a/src/main/java/org/olat/repository/handlers/GlossaryHandler.java b/src/main/java/org/olat/repository/handlers/GlossaryHandler.java index d1df58402696981fbada8c8b95665f3d674967a3..f5556d9cc37772aac82474c2b3b07ff0d69e431f 100644 --- a/src/main/java/org/olat/repository/handlers/GlossaryHandler.java +++ b/src/main/java/org/olat/repository/handlers/GlossaryHandler.java @@ -221,7 +221,7 @@ public class GlossaryHandler implements RepositoryHandler { } @Override - public boolean cleanupOnDelete(OLATResourceable res) { + public boolean cleanupOnDelete(RepositoryEntry entry, OLATResourceable res) { // FIXME fg // do not need to notify all current users of this resource, since the only // way to access this resource diff --git a/src/main/java/org/olat/repository/handlers/PodcastHandler.java b/src/main/java/org/olat/repository/handlers/PodcastHandler.java index 50bd4aa6e93ce87bab44b523362b032c8773d92e..0b6427469174c04e61eac9bb0e8699bc6e420455 100644 --- a/src/main/java/org/olat/repository/handlers/PodcastHandler.java +++ b/src/main/java/org/olat/repository/handlers/PodcastHandler.java @@ -138,7 +138,7 @@ public class PodcastHandler implements RepositoryHandler { } @Override - public boolean cleanupOnDelete(OLATResourceable res) { + public boolean cleanupOnDelete(RepositoryEntry entry, OLATResourceable res) { CoordinatorManager.getInstance().getCoordinator().getEventBus().fireEventToListenersOf(new OLATResourceableJustBeforeDeletedEvent(res), res); // For now, notifications are not implemented since a podcast feed is meant // to be subscriped to anyway. diff --git a/src/main/java/org/olat/repository/handlers/PortfolioHandler.java b/src/main/java/org/olat/repository/handlers/PortfolioHandler.java index c1b8ced8a4d22f3f9a8ed49e3eb3873a7925dd70..e3400c43198fd35e63bfd593c9790d975bed555e 100644 --- a/src/main/java/org/olat/repository/handlers/PortfolioHandler.java +++ b/src/main/java/org/olat/repository/handlers/PortfolioHandler.java @@ -196,7 +196,7 @@ public class PortfolioHandler implements RepositoryHandler { } @Override - public boolean cleanupOnDelete(OLATResourceable res) { + public boolean cleanupOnDelete(RepositoryEntry entry, OLATResourceable res) { CoreSpringFactory.getImpl(EPFrontendManager.class).deletePortfolioMapTemplate(res); return true; } diff --git a/src/main/java/org/olat/repository/handlers/RepositoryHandler.java b/src/main/java/org/olat/repository/handlers/RepositoryHandler.java index 6f0aaf1399c2d2e09e66fdecb90c19f92528306e..ac76a5641a4377fa3b97306718fa901f15d07b0c 100644 --- a/src/main/java/org/olat/repository/handlers/RepositoryHandler.java +++ b/src/main/java/org/olat/repository/handlers/RepositoryHandler.java @@ -176,7 +176,7 @@ public interface RepositoryHandler { * @param wControl * @return true if delete successfull, false if not. */ - public boolean cleanupOnDelete(OLATResourceable res); + public boolean cleanupOnDelete(RepositoryEntry entry, OLATResourceable res); /** * Called if the repository entry referencing the given Resourceable will be deleted diff --git a/src/main/java/org/olat/repository/handlers/SharedFolderHandler.java b/src/main/java/org/olat/repository/handlers/SharedFolderHandler.java index 70109f1bd1d4efa6da55c3e774886b2477c980ba..f932ab4e93428db964211c2a00a06d9604700b82 100644 --- a/src/main/java/org/olat/repository/handlers/SharedFolderHandler.java +++ b/src/main/java/org/olat/repository/handlers/SharedFolderHandler.java @@ -209,7 +209,7 @@ public class SharedFolderHandler implements RepositoryHandler { } @Override - public boolean cleanupOnDelete(OLATResourceable res) { + public boolean cleanupOnDelete(RepositoryEntry entry, OLATResourceable res) { // do not need to notify all current users of this resource, since the only // way to access this resource CoordinatorManager.getInstance().getCoordinator().getEventBus().fireEventToListenersOf(new OLATResourceableJustBeforeDeletedEvent(res), res); diff --git a/src/main/java/org/olat/repository/handlers/WikiHandler.java b/src/main/java/org/olat/repository/handlers/WikiHandler.java index 310c8d626127470f1f46a715121d588587f7fb1c..192137d51580fd30145e71e2020ac2a7232adecc 100644 --- a/src/main/java/org/olat/repository/handlers/WikiHandler.java +++ b/src/main/java/org/olat/repository/handlers/WikiHandler.java @@ -275,7 +275,7 @@ public class WikiHandler implements RepositoryHandler { } @Override - public boolean cleanupOnDelete(OLATResourceable res) { + public boolean cleanupOnDelete(RepositoryEntry entry, OLATResourceable res) { CoordinatorManager.getInstance().getCoordinator().getEventBus().fireEventToListenersOf(new OLATResourceableJustBeforeDeletedEvent(res), res); //delete also notifications NotificationsManager.getInstance().deletePublishersOf(res); diff --git a/src/main/java/org/olat/repository/manager/RepositoryServiceImpl.java b/src/main/java/org/olat/repository/manager/RepositoryServiceImpl.java index a183b4ad66078c6fb9d50f9e2a37c907f24ecbfe..c7e34902061a9c45e2e733c9f4bf9154d4fadfed 100644 --- a/src/main/java/org/olat/repository/manager/RepositoryServiceImpl.java +++ b/src/main/java/org/olat/repository/manager/RepositoryServiceImpl.java @@ -327,7 +327,7 @@ public class RepositoryServiceImpl implements RepositoryService { // inform handler to do any cleanup work... handler must delete the // referenced resourceable a swell. - handler.cleanupOnDelete(resource); + handler.cleanupOnDelete(entry, resource); dbInstance.commit(); diff --git a/src/test/java/org/olat/course/nodes/gta/manager/GTAManagerTest.java b/src/test/java/org/olat/course/nodes/gta/manager/GTAManagerTest.java index db1cfc1066d12f3c12f3e606467abb886d4b5c42..91eb3470a0007e6da262471151204cbc6eeb1190 100644 --- a/src/test/java/org/olat/course/nodes/gta/manager/GTAManagerTest.java +++ b/src/test/java/org/olat/course/nodes/gta/manager/GTAManagerTest.java @@ -25,6 +25,7 @@ import java.util.List; import org.junit.Assert; import org.junit.Test; +import org.olat.basesecurity.GroupRoles; import org.olat.core.commons.persistence.DB; import org.olat.core.id.Identity; import org.olat.course.nodes.GTACourseNode; @@ -39,6 +40,7 @@ import org.olat.group.manager.BusinessGroupDAO; import org.olat.group.manager.BusinessGroupRelationDAO; import org.olat.modules.vitero.model.GroupRole; import org.olat.repository.RepositoryEntry; +import org.olat.repository.manager.RepositoryEntryRelationDAO; import org.olat.test.JunitTestHelper; import org.olat.test.OlatTestCase; import org.springframework.beans.factory.annotation.Autowired; @@ -59,6 +61,8 @@ public class GTAManagerTest extends OlatTestCase { private BusinessGroupDAO businessGroupDao; @Autowired private BusinessGroupRelationDAO businessGroupRelationDao; + @Autowired + private RepositoryEntryRelationDAO repositoryEntryRelationDao; @Test public void createIfNotExists() { @@ -467,6 +471,123 @@ public class GTAManagerTest extends OlatTestCase { Assert.assertEquals(1, notDeletedAssignedTasks2.size()); } + @Test + public void deleteAllTaskLists() { + Identity coach = JunitTestHelper.createAndPersistIdentityAsRndUser("gta-user-9"); + Identity participant = JunitTestHelper.createAndPersistIdentityAsRndUser("gta-user-10"); + dbInstance.commit(); + RepositoryEntry re = JunitTestHelper.createAndPersistRepositoryEntry("", false); + repositoryEntryRelationDao.addRole(coach, re, GroupRoles.coach.name()); + repositoryEntryRelationDao.addRole(participant, re, GroupRoles.participant.name()); + + GTACourseNode node = new GTACourseNode(); + node.getModuleConfiguration().setStringValue(GTACourseNode.GTASK_TYPE, GTAType.individual.name()); + TaskList tasks = gtaManager.createIfNotExists(re, node); + File taskFile = new File("bg.txt"); + Assert.assertNotNull(tasks); + dbInstance.commit(); + + //select + AssignmentResponse response = gtaManager.selectTask(participant, tasks, node, taskFile); + dbInstance.commitAndCloseSession(); + Assert.assertNotNull(response); + + //check that there is tasks + List<Task> assignedTasks = gtaManager.getTasks(participant, re, node); + Assert.assertNotNull(assignedTasks); + Assert.assertEquals(1, assignedTasks.size()); + + //delete + int numOfDeletedObjects = gtaManager.deleteAllTaskLists(re); + Assert.assertEquals(2, numOfDeletedObjects); + dbInstance.commitAndCloseSession(); + + //check that there isn't any tasks + List<Task> deletedAssignedTasks = gtaManager.getTasks(participant, re, node); + Assert.assertNotNull(deletedAssignedTasks); + Assert.assertEquals(0, deletedAssignedTasks.size()); + } + + /** + * Create 2 pseudo courses in a course, and delete the task of the first course + * and check that the task of second are always there. + * + */ + @Test + public void deleteAllTaskLists_parano() { + Identity coach = JunitTestHelper.createAndPersistIdentityAsRndUser("gta-user-20"); + Identity participant1 = JunitTestHelper.createAndPersistIdentityAsRndUser("gta-user-21"); + Identity participant2 = JunitTestHelper.createAndPersistIdentityAsRndUser("gta-user-22"); + + RepositoryEntry re1 = JunitTestHelper.createAndPersistRepositoryEntry("", false); + repositoryEntryRelationDao.addRole(coach, re1, GroupRoles.coach.name()); + repositoryEntryRelationDao.addRole(participant1, re1, GroupRoles.participant.name()); + repositoryEntryRelationDao.addRole(participant2, re1, GroupRoles.participant.name()); + + //course 1 + GTACourseNode node1 = new GTACourseNode(); + node1.getModuleConfiguration().setStringValue(GTACourseNode.GTASK_TYPE, GTAType.individual.name()); + TaskList tasks1 = gtaManager.createIfNotExists(re1, node1); + File taskFile = new File("bg.txt"); + Assert.assertNotNull(tasks1); + dbInstance.commit(); + + RepositoryEntry re2 = JunitTestHelper.createAndPersistRepositoryEntry("", false); + repositoryEntryRelationDao.addRole(coach, re2, GroupRoles.coach.name()); + repositoryEntryRelationDao.addRole(participant1, re2, GroupRoles.participant.name()); + + //participant 2 course 2 + GTACourseNode node2 = new GTACourseNode(); + node2.getModuleConfiguration().setStringValue(GTACourseNode.GTASK_TYPE, GTAType.individual.name()); + TaskList tasks2 = gtaManager.createIfNotExists(re2, node2); + Assert.assertNotNull(tasks2); + dbInstance.commit(); + + //participant 1 and 2 select course 1 + AssignmentResponse response1_1 = gtaManager.selectTask(participant1, tasks1, node1, taskFile); + AssignmentResponse response1_2 = gtaManager.selectTask(participant2, tasks1, node1, taskFile); + dbInstance.commitAndCloseSession(); + Assert.assertNotNull(response1_1); + Assert.assertNotNull(response1_2); + + //participant 2 select node 2 + AssignmentResponse response2_2 = gtaManager.selectTask(participant2, tasks2, node2, taskFile); + dbInstance.commitAndCloseSession(); + Assert.assertNotNull(response2_2); + + //check that there is tasks + List<Task> assignedTasks1_1 = gtaManager.getTasks(participant1, re1, node1); + Assert.assertNotNull(assignedTasks1_1); + Assert.assertEquals(1, assignedTasks1_1.size()); + + List<Task> assignedTasks1_2 = gtaManager.getTasks(participant2, re1, node1); + Assert.assertNotNull(assignedTasks1_2); + Assert.assertEquals(1, assignedTasks1_2.size()); + + List<Task> assignedTasks2_2 = gtaManager.getTasks(participant2, re2, node2); + Assert.assertNotNull(assignedTasks2_2); + Assert.assertEquals(1, assignedTasks2_2.size()); + + //delete + int numOfDeletedObjects = gtaManager.deleteAllTaskLists(re1); + Assert.assertEquals(3, numOfDeletedObjects); + dbInstance.commitAndCloseSession(); + + //check that there isn't any tasks in node 1 + List<Task> deletedAssignedTasks1_1 = gtaManager.getTasks(participant1, re1, node1); + Assert.assertNotNull(deletedAssignedTasks1_1); + Assert.assertEquals(0, deletedAssignedTasks1_1.size()); + + List<Task> deletedAssignedTasks1_2 = gtaManager.getTasks(participant2, re1, node1); + Assert.assertNotNull(deletedAssignedTasks1_2); + Assert.assertEquals(0, deletedAssignedTasks1_2.size()); + + //but always in node 2 + List<Task> notDeletedAssignedTasks2_2 = gtaManager.getTasks(participant2, re2, node2); + Assert.assertNotNull(notDeletedAssignedTasks2_2); + Assert.assertEquals(1, notDeletedAssignedTasks2_2.size()); + } + @Test public void roundRobin() { String[] slots = new String[]{ "A", "B", "C" };