diff --git a/src/main/java/org/olat/admin/user/groups/GroupOverviewController.java b/src/main/java/org/olat/admin/user/groups/GroupOverviewController.java index c4a8b5d646eef2d7565c471c82163d8e4c44c3ba..5d97dfdeba7ae74466f4a1e9a095a95b1ce89255 100644 --- a/src/main/java/org/olat/admin/user/groups/GroupOverviewController.java +++ b/src/main/java/org/olat/admin/user/groups/GroupOverviewController.java @@ -29,7 +29,6 @@ import org.olat.NewControllerFactory; import org.olat.basesecurity.BaseSecurity; import org.olat.basesecurity.BaseSecurityManager; import org.olat.core.CoreSpringFactory; -import org.olat.core.commons.persistence.DBFactory; import org.olat.core.gui.UserRequest; import org.olat.core.gui.components.Component; import org.olat.core.gui.components.link.Link; @@ -331,14 +330,6 @@ public class GroupOverviewController extends BasicController { // 2) remove as participant businessGroupService.removeParticipants(getIdentity(), Collections.singletonList(identity), group, mailing); MailHelper.printErrorsAndWarnings(mailing.getResult(), getWindowControl(), getLocale()); - - // 3) notify user about this action: - /*if(doSendMail){ - MailTemplate mailTemplate = BGMailHelper.createRemoveParticipantMailTemplate(group, getIdentity()); - MailerWithTemplate mailer = MailerWithTemplate.getInstance(); - MailerResult mailerResult = mailer.sendMailAsSeparateMails(null, Collections.singletonList(identity), null, mailTemplate, null); - - }*/ } } diff --git a/src/main/java/org/olat/course/nodes/en/ENRunController.java b/src/main/java/org/olat/course/nodes/en/ENRunController.java index feac296c5a98557afb9229bac053866e801888e4..99b688d27b15919295d0cc274f7609d871f1e829 100644 --- a/src/main/java/org/olat/course/nodes/en/ENRunController.java +++ b/src/main/java/org/olat/course/nodes/en/ENRunController.java @@ -56,6 +56,7 @@ import org.olat.group.BusinessGroup; import org.olat.group.BusinessGroupService; import org.olat.group.area.BGAreaManager; import org.olat.group.ui.BusinessGroupTableModelWithMaxSize; +import org.olat.group.ui.edit.BusinessGroupModifiedEvent; import org.olat.modules.ModuleConfiguration; import org.olat.util.logging.activity.LoggingResourceable; @@ -174,6 +175,7 @@ public class ENRunController extends BasicController implements GenericEventList /** * @see org.olat.core.gui.control.DefaultController#event(org.olat.core.gui.UserRequest, org.olat.core.gui.control.Controller, org.olat.core.gui.control.Event) */ + @Override public void event(UserRequest ureq, Controller source, Event event) { String cmd = event.getCommand(); if (source == tableCtr) { @@ -196,9 +198,15 @@ public class ENRunController extends BasicController implements GenericEventList getWindowControl().setError(enrollStatus.getErrorMessage()); } // events are already fired BusinessGroupManager level :: BusinessGroupModifiedEvent.fireModifiedGroupEvents(BusinessGroupModifiedEvent.IDENTITY_ADDED_EVENT, choosenGroup, ureq.getIdentity()); + // but async doEnrollView(ureq); // fire event to indicate runmaincontroller that the menuview is to update - fireEvent(ureq, Event.DONE_EVENT); + + if (enrollStatus.isEnrolled() ) { + fireEvent(ureq, new BusinessGroupModifiedEvent(BusinessGroupModifiedEvent.IDENTITY_ADDED_EVENT, enrolledGroup, getIdentity())); + } else { + fireEvent(ureq, Event.DONE_EVENT); + } } else if (actionid.equals(CMD_ENROLLED_CANCEL)) { if (waitingListGroup != null) { enrollmentManager.doCancelEnrollmentInWaitingList(ureq.getIdentity(), choosenGroup, enNode, coursePropertyManager, getWindowControl(), getTranslator()); @@ -210,10 +218,10 @@ public class ENRunController extends BasicController implements GenericEventList doEnrollView(ureq); if (enrolledGroup == null) { // fire event to indicate runmaincontroller that the menuview is to update - fireEvent(ureq, Event.DONE_EVENT); + fireEvent(ureq, new BusinessGroupModifiedEvent(BusinessGroupModifiedEvent.IDENTITY_REMOVED_EVENT, choosenGroup, getIdentity())); } // events are already fired BusinessGroupManager level :: BusinessGroupModifiedEvent.fireModifiedGroupEvents(BusinessGroupModifiedEvent.IDENTITY_REMOVED_EVENT, group, ureq.getIdentity()); - + // but async } } } diff --git a/src/main/java/org/olat/course/nodes/en/EnrollmentManager.java b/src/main/java/org/olat/course/nodes/en/EnrollmentManager.java index 9c37e64be7e3e5a7f6a472a8499bbcc3d7741a93..fad6ce3783e2e61ac8494c60139ae1390904d145 100644 --- a/src/main/java/org/olat/course/nodes/en/EnrollmentManager.java +++ b/src/main/java/org/olat/course/nodes/en/EnrollmentManager.java @@ -94,12 +94,13 @@ public class EnrollmentManager extends BasicManager { // and: why can't we just have a group here and a max participants count and an identity to enrol? // the group was chosen, so why do we need the groupNames and areaNames here??? - EnrollState state =businessGroupService.enroll(identity, roles, identity, group, null); + EnrollState state = businessGroupService.enroll(identity, roles, identity, group, null); if(state.isFailed()) { enrollStatus.setErrorMessage(trans.translate(state.getI18nErrorMessage())); } else { if(state.getEnrolled() == BGMembership.participant) { addUserToParticipantList(identity, group, enNode, coursePropertyManager, wControl, trans); + enrollStatus.setIsEnrolled(true); } else if(state.getEnrolled() == BGMembership.waiting) { addUserToWaitingList(identity, group, enNode, coursePropertyManager, wControl, trans); } diff --git a/src/main/java/org/olat/course/run/RunMainController.java b/src/main/java/org/olat/course/run/RunMainController.java index f7b4e8948b0caab532fd6ce26fc7a3543a49e3ad..cd422e416dbe4ab3bcb280d815d561dbec2b5935 100644 --- a/src/main/java/org/olat/course/run/RunMainController.java +++ b/src/main/java/org/olat/course/run/RunMainController.java @@ -422,7 +422,7 @@ public class RunMainController extends MainLayoutBasicController implements Gene nclr = navHandler.evaluateJumpToCourseNode(ureq, getWindowControl(), null, null, null); } if (!nclr.isVisible()) { - MessageController msgController = MessageUIFactory.createInfoMessage(ureq, this.getWindowControl(), translate("course.noaccess.title"), translate("course.noaccess.text")); + MessageController msgController = MessageUIFactory.createInfoMessage(ureq, getWindowControl(), translate("course.noaccess.title"), translate("course.noaccess.text")); contentP.setContent(msgController.getInitialComponent()); luTree.setTreeModel(new GenericTreeModel()); return false; @@ -630,8 +630,10 @@ public class RunMainController extends MainLayoutBasicController implements Gene luTree.setSelectedNodeId(newCpTreeNode.getIdent()); } else if (event == Event.CHANGED_EVENT) { updateTreeAndContent(ureq, currentCourseNode, null); + } else if (event instanceof BusinessGroupModifiedEvent) { + processBusinessGroupModifiedEvent((BusinessGroupModifiedEvent)event); + updateTreeAndContent(ureq, currentCourseNode, null); } - } else if (source == toolC) { String cmd = event.getCommand(); doHandleToolEvents(ureq, cmd); @@ -935,11 +937,40 @@ public class RunMainController extends MainLayoutBasicController implements Gene needsRebuildAfterRunDone = true; } } else if (event instanceof BusinessGroupModifiedEvent) { - BusinessGroupModifiedEvent bgme = (BusinessGroupModifiedEvent) event; - Identity identity = uce.getIdentityEnvironment().getIdentity(); - // only do something if this identity is affected by change and the action - // was adding or removing of the user - if (bgme.wasMyselfAdded(identity) || bgme.wasMyselfRemoved(identity)) { + processBusinessGroupModifiedEvent((BusinessGroupModifiedEvent)event); + } else if (event instanceof CourseConfigEvent) { + doDisposeAfterEvent(); + } else if (event instanceof EntryChangedEvent && ((EntryChangedEvent)event).getChange()!=EntryChangedEvent.MODIFIED_AT_PUBLISH) { + //courseRepositoryEntry changed (e.g. fired at course access rule change) + EntryChangedEvent repoEvent = (EntryChangedEvent) event; + if (courseRepositoryEntry.getKey().equals(repoEvent.getChangedEntryKey()) && repoEvent.getChange() == EntryChangedEvent.MODIFIED) { + doDisposeAfterEvent(); + } + } + } + + private void processBusinessGroupModifiedEvent(BusinessGroupModifiedEvent bgme) { + Identity identity = uce.getIdentityEnvironment().getIdentity(); + // only do something if this identity is affected by change and the action + // was adding or removing of the user + if (bgme.wasMyselfAdded(identity) || bgme.wasMyselfRemoved(identity)) { + // 1) reinitialize all group memberships + reloadGroupMemberships(identity); + // 2) reinitialize the users roles and rights + reloadUserRolesAndRights(identity); + // 3) rebuild toolboxes with link to groups and tools + removeAsListenerAndDispose(toolC); + toolC = initToolController(identity, null); + listenTo(toolC); + Component toolComp = (toolC == null ? null : toolC.getInitialComponent()); + columnLayoutCtr.setCol2(toolComp); + needsRebuildAfterRunDone = true; + } else if (bgme.getCommand().equals(BusinessGroupModifiedEvent.GROUPRIGHTS_MODIFIED_EVENT)) { + // check if this affects a right group where the user does participate. + // if so, we need + // to rebuild the toolboxes + if (PersistenceHelper.listContainsObjectByKey(uce.getParticipatingGroups(), bgme.getModifiedGroupKey()) || + PersistenceHelper.listContainsObjectByKey(uce.getCoachedGroups(), bgme.getModifiedGroupKey())) { // 1) reinitialize all group memberships reloadGroupMemberships(identity); // 2) reinitialize the users roles and rights @@ -950,33 +981,6 @@ public class RunMainController extends MainLayoutBasicController implements Gene listenTo(toolC); Component toolComp = (toolC == null ? null : toolC.getInitialComponent()); columnLayoutCtr.setCol2(toolComp); - needsRebuildAfterRunDone = true; - } else if (bgme.getCommand().equals(BusinessGroupModifiedEvent.GROUPRIGHTS_MODIFIED_EVENT)) { - // check if this affects a right group where the user does participate. - // if so, we need - // to rebuild the toolboxes - if (PersistenceHelper.listContainsObjectByKey(uce.getParticipatingGroups(), bgme.getModifiedGroupKey()) || - PersistenceHelper.listContainsObjectByKey(uce.getCoachedGroups(), bgme.getModifiedGroupKey())) { - // 1) reinitialize all group memberships - reloadGroupMemberships(identity); - // 2) reinitialize the users roles and rights - reloadUserRolesAndRights(identity); - // 3) rebuild toolboxes with link to groups and tools - removeAsListenerAndDispose(toolC); - toolC = initToolController(identity, null); - listenTo(toolC); - Component toolComp = (toolC == null ? null : toolC.getInitialComponent()); - columnLayoutCtr.setCol2(toolComp); - } - } - - } else if (event instanceof CourseConfigEvent) { - doDisposeAfterEvent(); - } else if (event instanceof EntryChangedEvent && ((EntryChangedEvent)event).getChange()!=EntryChangedEvent.MODIFIED_AT_PUBLISH) { - //courseRepositoryEntry changed (e.g. fired at course access rule change) - EntryChangedEvent repoEvent = (EntryChangedEvent) event; - if (courseRepositoryEntry.getKey().equals(repoEvent.getChangedEntryKey()) && repoEvent.getChange() == EntryChangedEvent.MODIFIED) { - doDisposeAfterEvent(); } } } diff --git a/src/main/java/org/olat/group/manager/BusinessGroupServiceImpl.java b/src/main/java/org/olat/group/manager/BusinessGroupServiceImpl.java index 679a897a22f2036c4f77fcf0b96ff9c608a63f9f..947616f645d7055875c09635dca5c96fc25cdf88 100644 --- a/src/main/java/org/olat/group/manager/BusinessGroupServiceImpl.java +++ b/src/main/java/org/olat/group/manager/BusinessGroupServiceImpl.java @@ -223,9 +223,11 @@ public class BusinessGroupServiceImpl implements BusinessGroupService, UserDataD bg.setMinParticipants(minParticipants); bg.setLastUsage(new Date(System.currentTimeMillis())); //auto rank if possible - autoRankCheck(ureqIdentity, bg, previousMaxParticipants); + List<BusinessGroupModifiedEvent.Deferred> events = new ArrayList<BusinessGroupModifiedEvent.Deferred>(); + autoRankCheck(ureqIdentity, bg, previousMaxParticipants, events); BusinessGroup updatedGroup = businessGroupDAO.merge(bg); dbInstance.commit(); + BusinessGroupModifiedEvent.fireDeferredEvents(events); return updatedGroup; } @@ -249,13 +251,17 @@ public class BusinessGroupServiceImpl implements BusinessGroupService, UserDataD bg.setAutoCloseRanksEnabled(autoCloseRanks); bg.setLastUsage(new Date(System.currentTimeMillis())); //auto rank if possible - autoRankCheck(ureqIdentity, bg, previousMaxParticipants); + + List<BusinessGroupModifiedEvent.Deferred> events = new ArrayList<BusinessGroupModifiedEvent.Deferred>(); + autoRankCheck(ureqIdentity, bg, previousMaxParticipants, events); BusinessGroup mergedGroup = businessGroupDAO.merge(bg); dbInstance.commit(); + BusinessGroupModifiedEvent.fireDeferredEvents(events); return mergedGroup; } - private void autoRankCheck(Identity identity, BusinessGroup updatedGroup, Integer previousMaxParticipants) { + private void autoRankCheck(Identity identity, BusinessGroup updatedGroup, Integer previousMaxParticipants, + List<BusinessGroupModifiedEvent.Deferred> events) { if(updatedGroup.getWaitingListEnabled() == null || !updatedGroup.getWaitingListEnabled().booleanValue() || updatedGroup.getAutoCloseRanksEnabled() == null || !updatedGroup.getAutoCloseRanksEnabled().booleanValue()) { //do not check further, no waiting list, no automatic ranks @@ -269,7 +275,7 @@ public class BusinessGroupServiceImpl implements BusinessGroupService, UserDataD if(currentMaxNumber > previousMaxNumber) { //I can rank up some users - transferFirstIdentityFromWaitingToParticipant(identity, updatedGroup, null); + transferFirstIdentityFromWaitingToParticipant(identity, updatedGroup, null, events); } } @@ -485,21 +491,24 @@ public class BusinessGroupServiceImpl implements BusinessGroupService, UserDataD } } } + + List<BusinessGroupModifiedEvent.Deferred> events = new ArrayList<BusinessGroupModifiedEvent.Deferred>(); for(Identity newOwner:newOwners) { - addOwner(ureqIdentity, ureqRoles, newOwner, targetGroup, mailing); + addOwner(ureqIdentity, ureqRoles, newOwner, targetGroup, mailing, events); } for(Identity newParticipant:newParticipants) { - addParticipant(ureqIdentity, ureqRoles, newParticipant, targetGroup, mailing); + addParticipant(ureqIdentity, ureqRoles, newParticipant, targetGroup, mailing, events); } for(Identity newWaiter:newWaiters) { - addToWaitingList(ureqIdentity, newWaiter, targetGroup, mailing); + addToWaitingList(ureqIdentity, newWaiter, targetGroup, mailing, events); } for(BusinessGroup group:groupsToMerge) { deleteBusinessGroup(group); } dbInstance.commit(); + BusinessGroupModifiedEvent.fireDeferredEvents(events); return targetGroup; } @@ -519,38 +528,38 @@ public class BusinessGroupServiceImpl implements BusinessGroupService, UserDataD List<Identity> currentOwners = securityManager.getIdentitiesOfSecurityGroup(group.getOwnerGroup()); List<Identity> currentParticipants = securityManager.getIdentitiesOfSecurityGroup(group.getPartipiciantGroup()); List<Identity> currentWaitingList = securityManager.getIdentitiesOfSecurityGroup(group.getWaitingGroup()); + List<BusinessGroupModifiedEvent.Deferred> events = new ArrayList<BusinessGroupModifiedEvent.Deferred>(); for(Identity owner:membersMod.getAddOwners()) { if(!currentOwners.contains(owner)) { - addOwner(ureqIdentity, ureqRoles, owner, group, mailing); + addOwner(ureqIdentity, ureqRoles, owner, group, mailing, events); } } for(Identity participant:membersMod.getAddParticipants()) { if(!currentParticipants.contains(participant)) { - addParticipant(ureqIdentity, ureqRoles, participant, group, mailing); + addParticipant(ureqIdentity, ureqRoles, participant, group, mailing, events); } } for(Identity waitingIdentity:membersMod.getAddToWaitingList()) { if(!currentWaitingList.contains(waitingIdentity)) { - addToWaitingList(ureqIdentity, waitingIdentity, group, mailing); + addToWaitingList(ureqIdentity, waitingIdentity, group, mailing, events); } } - - //remove owners - List<Identity> ownerToRemove = new ArrayList<Identity>(); + for(Identity removed:membersMod.getRemovedIdentities()) { if(currentOwners.contains(removed)) { - ownerToRemove.add(removed); + removeOwner(ureqIdentity, removed, group, events); } if(currentParticipants.contains(removed)) { - removeParticipant(ureqIdentity, removed, group, mailing); + removeParticipant(ureqIdentity, removed, group, mailing, events); } if(currentWaitingList.contains(removed)) { - removeFromWaitingList(ureqIdentity, removed, group, mailing); + removeFromWaitingList(ureqIdentity, removed, group, mailing, events); } } - removeOwners(ureqIdentity, ownerToRemove, group); + dbInstance.commit(); + BusinessGroupModifiedEvent.fireDeferredEvents(events); } @Override @@ -592,33 +601,35 @@ public class BusinessGroupServiceImpl implements BusinessGroupService, UserDataD } } } - + List<BusinessGroupModifiedEvent.Deferred> events = new ArrayList<BusinessGroupModifiedEvent.Deferred>(); List<BusinessGroup> groups = loadBusinessGroups(changesMap.keySet()); for(BusinessGroup group:groups) { BusinessGroupMembershipsChanges changesWrapper = changesMap.get(group.getKey()); group = businessGroupDAO.loadForUpdate(group.getKey()); for(Identity id:changesWrapper.addToWaitingList) { - addToWaitingList(ureqIdentity, id, group, mailing); + addToWaitingList(ureqIdentity, id, group, mailing, events); } for(Identity id:changesWrapper.removeFromWaitingList) { - removeFromWaitingList(ureqIdentity, id, group, mailing); + removeFromWaitingList(ureqIdentity, id, group, mailing, events); } for(Identity id:changesWrapper.addTutors) { - addOwner(ureqIdentity, ureqRoles, id, group, mailing); + addOwner(ureqIdentity, ureqRoles, id, group, mailing, events); } for(Identity id:changesWrapper.removeTutors) { - removeOwner(ureqIdentity, id, group); + removeOwner(ureqIdentity, id, group, events); } for(Identity id:changesWrapper.addParticipants) { - addParticipant(ureqIdentity, ureqRoles, id, group, mailing); + addParticipant(ureqIdentity, ureqRoles, id, group, mailing, events); } for(Identity id:changesWrapper.removeParticipants) { - removeParticipant(ureqIdentity, id, group, mailing); + removeParticipant(ureqIdentity, id, group, mailing, events); } //release lock dbInstance.commit(); } + + BusinessGroupModifiedEvent.fireDeferredEvents(events); } @Override @@ -820,20 +831,25 @@ public class BusinessGroupServiceImpl implements BusinessGroupService, UserDataD public BusinessGroupAddResponse addOwners(Identity ureqIdentity, Roles ureqRoles, List<Identity> addIdentities, BusinessGroup group, MailPackage mailing) { BusinessGroupAddResponse response = new BusinessGroupAddResponse(); + List<BusinessGroupModifiedEvent.Deferred> events = new ArrayList<BusinessGroupModifiedEvent.Deferred>(); for (Identity identity : addIdentities) { group = loadBusinessGroup(group); // reload business group if (securityManager.isIdentityPermittedOnResourceable(identity, Constants.PERMISSION_HASROLE, Constants.ORESOURCE_GUESTONLY)) { response.getIdentitiesWithoutPermission().add(identity); - } else if(addOwner(ureqIdentity, ureqRoles, identity, group, mailing)) { + } else if(addOwner(ureqIdentity, ureqRoles, identity, group, mailing, events)) { response.getAddedIdentities().add(identity); } else { response.getIdentitiesAlreadyInGroup().add(identity); } } + + dbInstance.commit(); + BusinessGroupModifiedEvent.fireDeferredEvents(events); return response; } - private boolean addOwner(Identity ureqIdentity, Roles ureqRoles, Identity identityToAdd, BusinessGroup group, MailPackage mailing) { + private boolean addOwner(Identity ureqIdentity, Roles ureqRoles, Identity identityToAdd, BusinessGroup group, MailPackage mailing, + List<BusinessGroupModifiedEvent.Deferred> events) { if (!securityManager.isIdentityInSecurityGroup(identityToAdd, group.getOwnerGroup())) { boolean mustAccept = true; if(ureqIdentity != null && ureqIdentity.equals(identityToAdd)) { @@ -859,7 +875,7 @@ public class BusinessGroupServiceImpl implements BusinessGroupService, UserDataD } } } else { - internalAddCoach(ureqIdentity, identityToAdd, group); + internalAddCoach(ureqIdentity, identityToAdd, group, events); BusinessGroupMailing.sendEmail(ureqIdentity, identityToAdd, group, MailType.addCoach, mailing, mailer); } return true; @@ -867,17 +883,22 @@ public class BusinessGroupServiceImpl implements BusinessGroupService, UserDataD return false; } - private void internalAddCoach(Identity ureqIdentity, Identity identityToAdd, BusinessGroup group) { + private void internalAddCoach(Identity ureqIdentity, Identity identityToAdd, BusinessGroup group, + List<BusinessGroupModifiedEvent.Deferred> events) { + securityManager.addIdentityToSecurityGroup(identityToAdd, group.getOwnerGroup()); // notify currently active users of this business group - BusinessGroupModifiedEvent.fireModifiedGroupEvents(BusinessGroupModifiedEvent.IDENTITY_ADDED_EVENT, group, identityToAdd); + BusinessGroupModifiedEvent.Deferred event = BusinessGroupModifiedEvent.createDeferredEvent(BusinessGroupModifiedEvent.IDENTITY_ADDED_EVENT, group, identityToAdd); + if(events != null) { + events.add(event); + } // do logging ThreadLocalUserActivityLogger.log(GroupLoggingAction.GROUP_OWNER_ADDED, getClass(), LoggingResourceable.wrap(group), LoggingResourceable.wrap(identityToAdd)); log.audit("Idenitity(.key):" + ureqIdentity.getKey() + " added identity '" + identityToAdd.getName() + "' to securitygroup with key " + group.getOwnerGroup().getKey()); } private boolean addParticipant(Identity ureqIdentity, Roles ureqRoles, Identity identityToAdd, BusinessGroup group, - MailPackage mailing) { + MailPackage mailing, List<BusinessGroupModifiedEvent.Deferred> events) { if(!securityManager.isIdentityInSecurityGroup(identityToAdd, group.getPartipiciantGroup())) { boolean mustAccept = true; @@ -902,7 +923,7 @@ public class BusinessGroupServiceImpl implements BusinessGroupService, UserDataD } } } else { - internalAddParticipant(ureqIdentity, identityToAdd, group); + internalAddParticipant(ureqIdentity, identityToAdd, group, events); BusinessGroupMailing.sendEmail(ureqIdentity, identityToAdd, group, MailType.addParticipant, mailing, mailer); } return true; @@ -918,11 +939,16 @@ public class BusinessGroupServiceImpl implements BusinessGroupService, UserDataD * @param group * @param syncIM */ - private void internalAddParticipant(Identity ureqIdentity, Identity identityToAdd, BusinessGroup group) { + private void internalAddParticipant(Identity ureqIdentity, Identity identityToAdd, BusinessGroup group, + List<BusinessGroupModifiedEvent.Deferred> events) { + securityManager.addIdentityToSecurityGroup(identityToAdd, group.getPartipiciantGroup()); // notify currently active users of this business group - BusinessGroupModifiedEvent.fireModifiedGroupEvents(BusinessGroupModifiedEvent.IDENTITY_ADDED_EVENT, group, identityToAdd); + BusinessGroupModifiedEvent.Deferred event = BusinessGroupModifiedEvent.createDeferredEvent(BusinessGroupModifiedEvent.IDENTITY_ADDED_EVENT, group, identityToAdd); + if(events != null) { + events.add(event); + } // do logging ThreadLocalUserActivityLogger.log(GroupLoggingAction.GROUP_PARTICIPANT_ADDED, getClass(), LoggingResourceable.wrap(group), LoggingResourceable.wrap(identityToAdd)); log.audit("Idenitity(.key):" + ureqIdentity.getKey() + " added identity '" + identityToAdd.getName() + "' to securitygroup with key " + group.getPartipiciantGroup().getKey()); @@ -933,18 +959,20 @@ public class BusinessGroupServiceImpl implements BusinessGroupService, UserDataD public BusinessGroupAddResponse addParticipants(Identity ureqIdentity, Roles ureqRoles, List<Identity> addIdentities, BusinessGroup group, MailPackage mailing) { BusinessGroupAddResponse response = new BusinessGroupAddResponse(); + List<BusinessGroupModifiedEvent.Deferred> events = new ArrayList<BusinessGroupModifiedEvent.Deferred>(); BusinessGroup currBusinessGroup = businessGroupDAO.loadForUpdate(group.getKey()); for (final Identity identity : addIdentities) { if (securityManager.isIdentityPermittedOnResourceable(identity, Constants.PERMISSION_HASROLE, Constants.ORESOURCE_GUESTONLY)) { response.getIdentitiesWithoutPermission().add(identity); - } else if(addParticipant(ureqIdentity, ureqRoles, identity, currBusinessGroup, mailing)) { + } else if(addParticipant(ureqIdentity, ureqRoles, identity, currBusinessGroup, mailing, events)) { response.getAddedIdentities().add(identity); } else { response.getIdentitiesAlreadyInGroup().add(identity); } } dbInstance.commit(); + BusinessGroupModifiedEvent.fireDeferredEvents(events); return response; } @@ -953,8 +981,10 @@ public class BusinessGroupServiceImpl implements BusinessGroupService, UserDataD if(reservation != null && "BusinessGroup".equals(reservation.getResource().getResourceableTypeName())) { BusinessGroup group = businessGroupDAO.loadForUpdate(reservation.getResource().getResourceableId()); if(group != null) { - transferFirstIdentityFromWaitingToParticipant(ureqIdentity, group, null); + List<BusinessGroupModifiedEvent.Deferred> events = new ArrayList<BusinessGroupModifiedEvent.Deferred>(); + transferFirstIdentityFromWaitingToParticipant(ureqIdentity, group, null, events); dbInstance.commit(); + BusinessGroupModifiedEvent.fireDeferredEvents(events); } } } @@ -964,24 +994,27 @@ public class BusinessGroupServiceImpl implements BusinessGroupService, UserDataD ResourceReservation reservation = acService.getReservation(reservationOwner, resource); if(reservation != null && "BusinessGroup".equals(resource.getResourceableTypeName())) { BusinessGroup group = businessGroupDAO.loadForUpdate(resource.getResourceableId()); + List<BusinessGroupModifiedEvent.Deferred> events = new ArrayList<BusinessGroupModifiedEvent.Deferred>(); if(group != null) { String type = reservation.getType(); if("group_coach".equals(type)) { if(!securityManager.isIdentityInSecurityGroup(reservationOwner, group.getOwnerGroup())) { - internalAddCoach(ureqIdentity, reservationOwner, group); + internalAddCoach(ureqIdentity, reservationOwner, group, events); } } else if("group_participant".equals(type)) { if(!securityManager.isIdentityInSecurityGroup(reservationOwner, group.getPartipiciantGroup())) { - internalAddParticipant(ureqIdentity, reservationOwner, group); + internalAddParticipant(ureqIdentity, reservationOwner, group, events); } } } reservationDao.deleteReservation(reservation); dbInstance.commit(); + BusinessGroupModifiedEvent.fireDeferredEvents(events); } } - private void removeParticipant(Identity ureqIdentity, Identity identity, BusinessGroup group, MailPackage mailing) { + private void removeParticipant(Identity ureqIdentity, Identity identity, BusinessGroup group, MailPackage mailing, + List<BusinessGroupModifiedEvent.Deferred> events) { boolean removed = securityManager.removeIdentityFromSecurityGroup(identity, group.getPartipiciantGroup()); if(removed) { @@ -989,14 +1022,17 @@ public class BusinessGroupServiceImpl implements BusinessGroupService, UserDataD removeSubscriptions(identity, group); // notify currently active users of this business group - BusinessGroupModifiedEvent.fireModifiedGroupEvents(BusinessGroupModifiedEvent.IDENTITY_REMOVED_EVENT, group, identity); + BusinessGroupModifiedEvent.Deferred event = BusinessGroupModifiedEvent.createDeferredEvent(BusinessGroupModifiedEvent.IDENTITY_REMOVED_EVENT, group, identity); + if(events != null) { + events.add(event); + } // do logging ThreadLocalUserActivityLogger.log(GroupLoggingAction.GROUP_PARTICIPANT_REMOVED, getClass(), LoggingResourceable.wrap(identity), LoggingResourceable.wrap(group)); log.audit("Idenitity(.key):" + ureqIdentity.getKey() + " removed identity '" + identity.getName() + "' from securitygroup with key " + group.getPartipiciantGroup().getKey()); // Check if a waiting-list with auto-close-ranks is configurated if ( group.getWaitingListEnabled().booleanValue() && group.getAutoCloseRanksEnabled().booleanValue() ) { // even when doOnlyPostRemovingStuff is set to true we really transfer the first Identity here - transferFirstIdentityFromWaitingToParticipant(ureqIdentity, group, null); + transferFirstIdentityFromWaitingToParticipant(ureqIdentity, group, null, events); } // send mail BusinessGroupMailing.sendEmail(ureqIdentity, identity, group, MailType.removeParticipant, mailing, mailer); @@ -1006,10 +1042,12 @@ public class BusinessGroupServiceImpl implements BusinessGroupService, UserDataD @Override public void removeParticipants(Identity ureqIdentity, List<Identity> identities, BusinessGroup group, MailPackage mailing) { group = businessGroupDAO.loadForUpdate(group.getKey()); + List<BusinessGroupModifiedEvent.Deferred> events = new ArrayList<BusinessGroupModifiedEvent.Deferred>(); for (Identity identity : identities) { - removeParticipant(ureqIdentity, identity, group, mailing); + removeParticipant(ureqIdentity, identity, group, mailing, events); } dbInstance.commit(); + BusinessGroupModifiedEvent.fireDeferredEvents(events); } @Override @@ -1040,7 +1078,8 @@ public class BusinessGroupServiceImpl implements BusinessGroupService, UserDataD for(Identity identity:identities) { keyToIdentityMap.put(identity.getKey(), identity); } - + + List<BusinessGroupModifiedEvent.Deferred> events = new ArrayList<BusinessGroupModifiedEvent.Deferred>(); List<BusinessGroupMembershipViewImpl> memberships = businessGroupDAO.getMembershipInfoInBusinessGroups(groups, identities); Collections.sort(memberships, new BusinessGroupMembershipViewComparator()); @@ -1056,7 +1095,7 @@ public class BusinessGroupServiceImpl implements BusinessGroupService, UserDataD Long groupKey = currentMembership.getGroupKey(); BusinessGroup nextGroup = businessGroupDAO.loadForUpdate(groupKey); - nextGroupMembership = removeGroupMembers(ureqIdentity, currentMembership, nextGroup, keyToIdentityMap, itMembership, mailing); + nextGroupMembership = removeGroupMembers(ureqIdentity, currentMembership, nextGroup, keyToIdentityMap, itMembership, mailing, events); //release the lock dbInstance.commit(); } @@ -1068,11 +1107,12 @@ public class BusinessGroupServiceImpl implements BusinessGroupService, UserDataD } } dbInstance.commit(); + BusinessGroupModifiedEvent.fireDeferredEvents(events); } private final BusinessGroupMembershipViewImpl removeGroupMembers(Identity ureqIdentity, BusinessGroupMembershipViewImpl currentMembership, BusinessGroup currentGroup, Map<Long,Identity> keyToIdentityMap, Iterator<BusinessGroupMembershipViewImpl> itMembership, - MailPackage mailing) { + MailPackage mailing, List<BusinessGroupModifiedEvent.Deferred> events) { BusinessGroupMembershipViewImpl previsousComputedMembership = currentMembership; BusinessGroupMembershipViewImpl membership; @@ -1091,13 +1131,13 @@ public class BusinessGroupServiceImpl implements BusinessGroupService, UserDataD if(currentGroup.getKey().equals(membership.getGroupKey())) { Identity id = keyToIdentityMap.get(membership.getIdentityKey()); if(membership.getOwnerGroupKey() != null) { - removeOwner(ureqIdentity, id, currentGroup); + removeOwner(ureqIdentity, id, currentGroup, events); } if(membership.getParticipantGroupKey() != null) { - removeParticipant(ureqIdentity, id, currentGroup, mailing); + removeParticipant(ureqIdentity, id, currentGroup, mailing, events); } if(membership.getWaitingGroupKey() != null) { - removeFromWaitingList(ureqIdentity, id, currentGroup, mailing); + removeFromWaitingList(ureqIdentity, id, currentGroup, mailing, events); } } else { return membership; @@ -1107,11 +1147,15 @@ public class BusinessGroupServiceImpl implements BusinessGroupService, UserDataD return null; } - private void addToWaitingList(Identity ureqIdentity, Identity identity, BusinessGroup group, MailPackage mailing) { + private void addToWaitingList(Identity ureqIdentity, Identity identity, BusinessGroup group, MailPackage mailing, + List<BusinessGroupModifiedEvent.Deferred> events) { securityManager.addIdentityToSecurityGroup(identity, group.getWaitingGroup()); // notify currently active users of this business group - BusinessGroupModifiedEvent.fireModifiedGroupEvents(BusinessGroupModifiedEvent.IDENTITY_ADDED_EVENT, group, identity); + BusinessGroupModifiedEvent.Deferred event = BusinessGroupModifiedEvent.createDeferredEvent(BusinessGroupModifiedEvent.IDENTITY_ADDED_EVENT, group, identity); + if(events != null) { + events.add(event); + } // do logging ThreadLocalUserActivityLogger.log(GroupLoggingAction.GROUP_TO_WAITING_LIST_ADDED, getClass(), LoggingResourceable.wrap(identity)); log.audit("Idenitity(.key):" + ureqIdentity.getKey() + " added identity '" + identity.getName() + "' to securitygroup with key " + group.getPartipiciantGroup().getKey()); @@ -1123,6 +1167,7 @@ public class BusinessGroupServiceImpl implements BusinessGroupService, UserDataD public BusinessGroupAddResponse addToWaitingList(Identity ureqIdentity, List<Identity> addIdentities, BusinessGroup group, MailPackage mailing) { BusinessGroupAddResponse response = new BusinessGroupAddResponse(); BusinessGroup currBusinessGroup = businessGroupDAO.loadForUpdate(group.getKey()); // reload business group + List<BusinessGroupModifiedEvent.Deferred> events = new ArrayList<BusinessGroupModifiedEvent.Deferred>(); for (final Identity identity : addIdentities) { if (securityManager.isIdentityPermittedOnResourceable(identity, Constants.PERMISSION_HASROLE, Constants.ORESOURCE_GUESTONLY)) { @@ -1136,18 +1181,23 @@ public class BusinessGroupServiceImpl implements BusinessGroupService, UserDataD response.getIdentitiesAlreadyInGroup().add(identity); } else { // identity has permission and is not already in group => add it - addToWaitingList(ureqIdentity, identity, currBusinessGroup, mailing); + addToWaitingList(ureqIdentity, identity, currBusinessGroup, mailing, events); response.getAddedIdentities().add(identity); } } dbInstance.commit(); + BusinessGroupModifiedEvent.fireDeferredEvents(events); return response; } - private final void removeFromWaitingList(Identity ureqIdentity, Identity identity, BusinessGroup group, MailPackage mailing) { + private final void removeFromWaitingList(Identity ureqIdentity, Identity identity, BusinessGroup group, MailPackage mailing, + List<BusinessGroupModifiedEvent.Deferred> events) { securityManager.removeIdentityFromSecurityGroup(identity, group.getWaitingGroup()); // notify currently active users of this business group - BusinessGroupModifiedEvent.fireModifiedGroupEvents(BusinessGroupModifiedEvent.IDENTITY_REMOVED_EVENT, group, identity); + BusinessGroupModifiedEvent.Deferred event = BusinessGroupModifiedEvent.createDeferredEvent(BusinessGroupModifiedEvent.IDENTITY_REMOVED_EVENT, group, identity); + if(events != null) { + events.add(event); + } // do logging ThreadLocalUserActivityLogger.log(GroupLoggingAction.GROUP_FROM_WAITING_LIST_REMOVED, getClass(), LoggingResourceable.wrap(identity)); log.audit("Idenitity(.key):" + ureqIdentity.getKey() + " removed identity '" + identity.getName() + "' from securitygroup with key " + group.getOwnerGroup().getKey()); @@ -1157,11 +1207,13 @@ public class BusinessGroupServiceImpl implements BusinessGroupService, UserDataD @Override public void removeFromWaitingList(Identity ureqIdentity, List<Identity> identities, BusinessGroup businessGroup, MailPackage mailing) { + List<BusinessGroupModifiedEvent.Deferred> events = new ArrayList<BusinessGroupModifiedEvent.Deferred>(); businessGroup = businessGroupDAO.loadForUpdate(businessGroup.getKey()); for (Identity identity : identities) { - removeFromWaitingList(ureqIdentity, identity, businessGroup, mailing); + removeFromWaitingList(ureqIdentity, identity, businessGroup, mailing, events); } dbInstance.commit(); + BusinessGroupModifiedEvent.fireDeferredEvents(events); } @Override @@ -1185,14 +1237,15 @@ public class BusinessGroupServiceImpl implements BusinessGroupService, UserDataD Roles ureqRoles = securityManager.getRoles(ureqIdentity); BusinessGroupAddResponse response = new BusinessGroupAddResponse(); + List<BusinessGroupModifiedEvent.Deferred> events = new ArrayList<BusinessGroupModifiedEvent.Deferred>(); currBusinessGroup = businessGroupDAO.loadForUpdate(currBusinessGroup.getKey()); for (Identity identity : identities) { // check if identity is already in participant if (!securityManager.isIdentityInSecurityGroup(identity,currBusinessGroup.getPartipiciantGroup()) ) { // Identity is not in participant-list => move idenity from waiting-list to participant-list - addParticipant(ureqIdentity, ureqRoles, identity, currBusinessGroup, mailing); - removeFromWaitingList(ureqIdentity, identity, currBusinessGroup, mailing); + addParticipant(ureqIdentity, ureqRoles, identity, currBusinessGroup, mailing, events); + removeFromWaitingList(ureqIdentity, identity, currBusinessGroup, mailing, events); response.getAddedIdentities().add(identity); // notification mail is handled in controller } else { @@ -1201,6 +1254,7 @@ public class BusinessGroupServiceImpl implements BusinessGroupService, UserDataD } dbInstance.commit(); + BusinessGroupModifiedEvent.fireDeferredEvents(events); return response; } @@ -1219,12 +1273,13 @@ public class BusinessGroupServiceImpl implements BusinessGroupService, UserDataD log.info("doEnroll start: group=" + OresHelper.createStringRepresenting(group), identity.getName()); EnrollState enrollStatus = new EnrollState(); + List<BusinessGroupModifiedEvent.Deferred> events = new ArrayList<BusinessGroupModifiedEvent.Deferred>(); ResourceReservation reservation = acService.getReservation(identity, reloadedGroup.getResource()); //reservation has the highest priority over max participant or other settings if(reservation != null) { - addParticipant(ureqIdentity, ureqRoles, identity, reloadedGroup, mailing); + addParticipant(ureqIdentity, ureqRoles, identity, reloadedGroup, mailing, events); enrollStatus.setEnrolled(BGMembership.participant); log.info("doEnroll (reservation) - setIsEnrolled ", identity.getName()); if(reservation != null) { @@ -1238,7 +1293,7 @@ public class BusinessGroupServiceImpl implements BusinessGroupService, UserDataD if (reservation == null && (participantsCounter + reservations) >= reloadedGroup.getMaxParticipants().intValue()) { // already full, show error and updated choose page again if (reloadedGroup.getWaitingListEnabled().booleanValue()) { - addToWaitingList(ureqIdentity, identity, reloadedGroup, mailing); + addToWaitingList(ureqIdentity, identity, reloadedGroup, mailing, events); enrollStatus.setEnrolled(BGMembership.waiting); } else { // No Waiting List => List is full @@ -1247,18 +1302,19 @@ public class BusinessGroupServiceImpl implements BusinessGroupService, UserDataD } } else { //enough place - addParticipant(ureqIdentity, ureqRoles, identity, reloadedGroup, mailing); + addParticipant(ureqIdentity, ureqRoles, identity, reloadedGroup, mailing, events); enrollStatus.setEnrolled(BGMembership.participant); log.info("doEnroll - setIsEnrolled ", identity.getName()); } } else { if (log.isDebug()) log.debug("doEnroll as participant beginTransaction"); - addParticipant(ureqIdentity, ureqRoles, identity, reloadedGroup, mailing); + addParticipant(ureqIdentity, ureqRoles, identity, reloadedGroup, mailing, events); enrollStatus.setEnrolled(BGMembership.participant); if (log.isDebug()) log.debug("doEnroll as participant committed"); } dbInstance.commit(); + BusinessGroupModifiedEvent.fireDeferredEvents(events); log.info("doEnroll end", identity.getName()); return enrollStatus; } @@ -1271,7 +1327,7 @@ public class BusinessGroupServiceImpl implements BusinessGroupService, UserDataD * @param syncIM */ private void transferFirstIdentityFromWaitingToParticipant(Identity ureqIdentity, BusinessGroup group, - MailPackage mailing) { + MailPackage mailing, List<BusinessGroupModifiedEvent.Deferred> events) { // Check if waiting-list is enabled and auto-rank-up if (group.getWaitingListEnabled() != null && group.getWaitingListEnabled().booleanValue() @@ -1304,8 +1360,8 @@ public class BusinessGroupServiceImpl implements BusinessGroupService, UserDataD // This is needed to make sure the targetIdentity ends up in the o_loggingtable ThreadLocalUserActivityLogger.setStickyActionType(ActionType.admin); MailPackage subMailing = new MailPackage(false);//doesn0t send these emails but a specific one - addParticipant(ureqIdentity, null, firstWaitingListIdentity, group, subMailing); - removeFromWaitingList(ureqIdentity, firstWaitingListIdentity, group, subMailing); + addParticipant(ureqIdentity, null, firstWaitingListIdentity, group, subMailing, events); + removeFromWaitingList(ureqIdentity, firstWaitingListIdentity, group, subMailing, events); } finally { ThreadLocalUserActivityLogger.setStickyActionType(formerStickyActionType); } @@ -1318,18 +1374,25 @@ public class BusinessGroupServiceImpl implements BusinessGroupService, UserDataD } } - private void removeOwner(Identity ureqIdentity, Identity identityToRemove, BusinessGroup group) { + private void removeOwner(Identity ureqIdentity, Identity identityToRemove, BusinessGroup group, + List<BusinessGroupModifiedEvent.Deferred> events) { + securityManager.removeIdentityFromSecurityGroup(identityToRemove, group.getOwnerGroup()); //remove subsciptions if user gets removed removeSubscriptions(identityToRemove, group); // notify currently active users of this business group + BusinessGroupModifiedEvent.Deferred event; if (identityToRemove.getKey().equals(ureqIdentity.getKey()) ) { - BusinessGroupModifiedEvent.fireModifiedGroupEvents(BusinessGroupModifiedEvent.MYSELF_ASOWNER_REMOVED_EVENT, group, identityToRemove); + event = BusinessGroupModifiedEvent.createDeferredEvent(BusinessGroupModifiedEvent.MYSELF_ASOWNER_REMOVED_EVENT, group, identityToRemove); } else { - BusinessGroupModifiedEvent.fireModifiedGroupEvents(BusinessGroupModifiedEvent.IDENTITY_REMOVED_EVENT, group, identityToRemove); + event = BusinessGroupModifiedEvent.createDeferredEvent(BusinessGroupModifiedEvent.IDENTITY_REMOVED_EVENT, group, identityToRemove); } + if(events != null) { + events.add(event); + } + // do logging log.audit("Idenitity(.key):" + ureqIdentity.getKey() + " removed identiy '" + identityToRemove.getName() + "' from securitygroup with key " + group.getOwnerGroup().getKey()); ThreadLocalUserActivityLogger.log(GroupLoggingAction.GROUP_OWNER_REMOVED, getClass(), LoggingResourceable.wrap(group), LoggingResourceable.wrap(identityToRemove)); @@ -1337,9 +1400,12 @@ public class BusinessGroupServiceImpl implements BusinessGroupService, UserDataD @Override public void removeOwners(Identity ureqIdentity, Collection<Identity> identitiesToRemove, BusinessGroup group) { + List<BusinessGroupModifiedEvent.Deferred> events = new ArrayList<BusinessGroupModifiedEvent.Deferred>(); for(Identity identityToRemove:identitiesToRemove) { - removeOwner(ureqIdentity, identityToRemove, group); + removeOwner(ureqIdentity, identityToRemove, group, events); } + dbInstance.commit(); + BusinessGroupModifiedEvent.fireDeferredEvents(events); } private void removeSubscriptions(Identity identity, BusinessGroup group) { diff --git a/src/main/java/org/olat/group/ui/edit/BusinessGroupModifiedEvent.java b/src/main/java/org/olat/group/ui/edit/BusinessGroupModifiedEvent.java index ef57741530d1287b8bbe4e15130d5999b920c5d6..a2baf989204121025eef40597704ad8a6de145d1 100644 --- a/src/main/java/org/olat/group/ui/edit/BusinessGroupModifiedEvent.java +++ b/src/main/java/org/olat/group/ui/edit/BusinessGroupModifiedEvent.java @@ -181,7 +181,33 @@ public class BusinessGroupModifiedEvent extends MultiUserEvent { } } + public static Deferred createDeferredEvent(String command, BusinessGroup group, Identity identity) { + Deferred modifiedEvent = new Deferred(command, group, identity); + return modifiedEvent; + } + + public static void fireDeferredEvents(List<Deferred> events) { + if(events == null || events.isEmpty()) return; + + for(Deferred deferedEvent:events) { + fireModifiedGroupEvents(deferedEvent.command, deferedEvent.group, deferedEvent.identity); + } + } + + @Override public String toString() { return "groupkey:"+groupKey+",identityKey:"+identityKey+", isTutor:"+isTutor+"|"+super.toString(); } + + public static class Deferred { + private final String command; + private final Identity identity; + private final BusinessGroup group; + + public Deferred(String command, BusinessGroup group, Identity identity) { + this.command = command; + this.group = group; + this.identity = identity; + } + } }