From b1085d5315e06875b9b7053c1144eae4af9f82f8 Mon Sep 17 00:00:00 2001 From: srosse <none@none> Date: Thu, 12 Jan 2012 14:30:21 +0100 Subject: [PATCH] OO-55: fix more issues with concurrent edit/view/delete of business group, fix broken equals method of BusinessGroup which generate a lot of invisible exceptions (which consume CPU) --- .../basesecurity/SecurityGroupImpl.hbm.xml | 4 +- .../olat/basesecurity/SecurityGroupImpl.java | 19 +++- .../org/olat/group/BusinessGroupImpl.java | 19 ++-- .../org/olat/group/BusinessGroupManager.java | 2 +- .../olat/group/BusinessGroupManagerImpl.java | 28 +++-- .../delete/service/GroupDeletionManager.java | 26 +++-- .../group/ui/_i18n/LocalStrings_de.properties | 1 + .../ui/edit/BusinessGroupEditController.java | 104 ++++++++++-------- .../olat/group/ui/edit/_content/deleted.html | 4 + .../ui/edit/_i18n/LocalStrings_de.properties | 1 + .../ui/edit/_i18n/LocalStrings_en.properties | 1 + .../ui/management/BGManagementController.java | 16 +-- .../run/BusinessGroupMainRunController.java | 54 ++++----- .../olat/group/ui/run/_content/deleted.html | 4 + .../ui/run/_i18n/LocalStrings_de.properties | 1 + .../ui/run/_i18n/LocalStrings_en.properties | 1 + 16 files changed, 169 insertions(+), 116 deletions(-) create mode 100644 src/main/java/org/olat/group/ui/edit/_content/deleted.html create mode 100644 src/main/java/org/olat/group/ui/run/_content/deleted.html diff --git a/src/main/java/org/olat/basesecurity/SecurityGroupImpl.hbm.xml b/src/main/java/org/olat/basesecurity/SecurityGroupImpl.hbm.xml index d40cf9ff86b..e4b4e1c5e44 100644 --- a/src/main/java/org/olat/basesecurity/SecurityGroupImpl.hbm.xml +++ b/src/main/java/org/olat/basesecurity/SecurityGroupImpl.hbm.xml @@ -2,14 +2,14 @@ <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping default-lazy="false"> - <class proxy = "org.olat.basesecurity.SecurityGroup" name="org.olat.basesecurity.SecurityGroupImpl" table="o_bs_secgroup"> + <class proxy="org.olat.basesecurity.SecurityGroup" name="org.olat.basesecurity.SecurityGroupImpl" table="o_bs_secgroup"> <!-- the default columns --> <id name="key" column="id" type="long" unsaved-value="null"> <generator class="hilo"/> </id> <version name="version" access="field" column="version" type="int"/> - <property name="creationDate" column="creationdate" type="timestamp" /> + <property name="creationDate" column="creationdate" type="timestamp" insert="true" update="false" /> </class> </hibernate-mapping> diff --git a/src/main/java/org/olat/basesecurity/SecurityGroupImpl.java b/src/main/java/org/olat/basesecurity/SecurityGroupImpl.java index b24318a64b2..1df72d61aa5 100644 --- a/src/main/java/org/olat/basesecurity/SecurityGroupImpl.java +++ b/src/main/java/org/olat/basesecurity/SecurityGroupImpl.java @@ -29,6 +29,7 @@ import org.olat.core.commons.persistence.PersistentObject; import org.olat.core.logging.AssertException; /** + * The object is immutable * @author Felix Jost */ public class SecurityGroupImpl extends PersistentObject implements SecurityGroup { @@ -54,5 +55,21 @@ public class SecurityGroupImpl extends PersistentObject implements SecurityGroup if (key == null) throw new AssertException("not persisted yet"); return key; } - + + @Override + public int hashCode() { + return getKey() == null ? 29851 : getKey().hashCode(); + } + + @Override + public boolean equals(Object obj) { + if(this == obj) { + return true; + } + if(obj instanceof SecurityGroup) { + SecurityGroup sec = (SecurityGroup)obj; + return getKey() != null && getKey().equals(sec.getKey()); + } + return false; + } } \ No newline at end of file diff --git a/src/main/java/org/olat/group/BusinessGroupImpl.java b/src/main/java/org/olat/group/BusinessGroupImpl.java index 3da70416270..4d16bffb5c0 100644 --- a/src/main/java/org/olat/group/BusinessGroupImpl.java +++ b/src/main/java/org/olat/group/BusinessGroupImpl.java @@ -285,23 +285,20 @@ public class BusinessGroupImpl extends PersistentObject implements BusinessGroup * Compares the keys. * @see java.lang.Object#equals(java.lang.Object) */ + @Override public boolean equals(Object obj) { - try { - BusinessGroupImpl that = (BusinessGroupImpl)obj; - if(this.getKey().equals(that.getKey())) { - return true; - } - } catch (Exception ex) { - //nothing to do + if(this == obj) { + return true; + } else if (obj instanceof BusinessGroup) { + BusinessGroup bg = (BusinessGroup)obj; + return getKey() != null && getKey().equals(bg.getKey()); } return false; } + @Override public int hashCode() { - if(this.getKey()!=null) { - return getKey().intValue(); - } - return 0; + return getKey() == null ? 2901 : getKey().hashCode(); } /** diff --git a/src/main/java/org/olat/group/BusinessGroupManager.java b/src/main/java/org/olat/group/BusinessGroupManager.java index f2fe0c04335..78fccfea0bf 100644 --- a/src/main/java/org/olat/group/BusinessGroupManager.java +++ b/src/main/java/org/olat/group/BusinessGroupManager.java @@ -488,7 +488,7 @@ public interface BusinessGroupManager { * Set certain business-group as active (set last-usage and delete time stamp for 'SEND_DELETE_EMAIL_ACTION' in LifeCycleManager): * @param currBusinessGroup */ - public void setLastUsageFor(BusinessGroup currBusinessGroup); + public BusinessGroup setLastUsageFor(BusinessGroup currBusinessGroup); /** * Creates business-groups with certain name when no group in a given BGContext with this names already exists. diff --git a/src/main/java/org/olat/group/BusinessGroupManagerImpl.java b/src/main/java/org/olat/group/BusinessGroupManagerImpl.java index 4edc4a7f2fe..ed1997563e7 100644 --- a/src/main/java/org/olat/group/BusinessGroupManagerImpl.java +++ b/src/main/java/org/olat/group/BusinessGroupManagerImpl.java @@ -40,6 +40,7 @@ import java.util.Locale; import java.util.Map; import java.util.Set; +import org.hibernate.ObjectNotFoundException; import org.hibernate.StaleObjectStateException; import org.olat.admin.user.delete.service.UserDeletionManager; import org.olat.basesecurity.BaseSecurity; @@ -558,6 +559,10 @@ public class BusinessGroupManagerImpl extends BasicManager implements BusinessGr Tracing.logAudit("Deleted Business Group", businessGroupTodelete.toString(), this.getClass()); } catch(DBRuntimeException dbre) { Throwable th = dbre.getCause(); + if ((th instanceof ObjectNotFoundException) && th.getMessage().contains("org.olat.group.BusinessGroupImpl")) { + //group already deleted + return; + } if ((th instanceof StaleObjectStateException) && (th.getMessage().startsWith("Row was updated or deleted by another transaction"))) { // known issue OLAT-3654 @@ -1734,18 +1739,27 @@ public class BusinessGroupManagerImpl extends BasicManager implements BusinessGr /** * @see org.olat.group.BusinessGroupManager#setLastUsageFor(org.olat.group.BusinessGroup) */ - public void setLastUsageFor(final BusinessGroup currBusinessGroup) { + public BusinessGroup setLastUsageFor(final BusinessGroup currBusinessGroup) { //o_clusterOK by:cg - CoordinatorManager.getInstance().getCoordinator().getSyncer().doInSync(currBusinessGroup, new SyncerExecutor(){ - public void execute() { + return CoordinatorManager.getInstance().getCoordinator().getSyncer().doInSync(currBusinessGroup, new SyncerCallback<BusinessGroup>() { + public BusinessGroup execute() { // force a reload from db loadObject(..., true) by evicting it from // hibernates session // cache to catch up on a different thread having commited the update of // the launchcounter - BusinessGroup reloadedBusinessGroup = BusinessGroupManagerImpl.getInstance().loadBusinessGroup(currBusinessGroup); - reloadedBusinessGroup.setLastUsage(new Date()); - LifeCycleManager.createInstanceFor(reloadedBusinessGroup).deleteTimestampFor(GroupDeletionManager.SEND_DELETE_EMAIL_ACTION); - BusinessGroupManagerImpl.getInstance().updateBusinessGroup(reloadedBusinessGroup); + try { + BusinessGroup reloadedBusinessGroup = loadBusinessGroup(currBusinessGroup); + reloadedBusinessGroup.setLastUsage(new Date()); + LifeCycleManager.createInstanceFor(reloadedBusinessGroup).deleteTimestampFor(GroupDeletionManager.SEND_DELETE_EMAIL_ACTION); + updateBusinessGroup(reloadedBusinessGroup); + return reloadedBusinessGroup; + } catch(DBRuntimeException e) { + if(e.getCause() instanceof ObjectNotFoundException) { + //group deleted + return null; + } + throw e; + } } }); } diff --git a/src/main/java/org/olat/group/delete/service/GroupDeletionManager.java b/src/main/java/org/olat/group/delete/service/GroupDeletionManager.java index fcda234a8a8..1e211e94eab 100644 --- a/src/main/java/org/olat/group/delete/service/GroupDeletionManager.java +++ b/src/main/java/org/olat/group/delete/service/GroupDeletionManager.java @@ -45,6 +45,8 @@ import org.olat.core.id.Identity; import org.olat.core.id.UserConstants; import org.olat.core.manager.BasicManager; import org.olat.core.util.Util; +import org.olat.core.util.coordinate.CoordinatorManager; +import org.olat.core.util.coordinate.SyncerCallback; import org.olat.core.util.filter.FilterFactory; import org.olat.core.util.i18n.I18nManager; import org.olat.core.util.mail.MailTemplate; @@ -336,15 +338,19 @@ public class GroupDeletionManager extends BasicManager { } - public void setLastUsageNowFor(BusinessGroup group) { - group = (BusinessGroup) DBFactory.getInstance().loadObject(group, true); - group.setLastUsage(new Date()); - LifeCycleManager lcManager = LifeCycleManager.createInstanceFor(group); - if (lcManager.lookupLifeCycleEntry(SEND_DELETE_EMAIL_ACTION) != null) { - logAudit("Group-Deletion: Remove from delete-list group=" + group); - LifeCycleManager.createInstanceFor(group).deleteTimestampFor(SEND_DELETE_EMAIL_ACTION); - } - BusinessGroupManagerImpl.getInstance().updateBusinessGroup(group); + public void setLastUsageNowFor(final BusinessGroup group) { + CoordinatorManager.getInstance().getCoordinator().getSyncer().doInSync(group, new SyncerCallback<BusinessGroup>() { + public BusinessGroup execute() { + BusinessGroup bg = (BusinessGroup) DBFactory.getInstance().loadObject(group, true); + bg.setLastUsage(new Date()); + LifeCycleManager lcManager = LifeCycleManager.createInstanceFor(bg); + if (lcManager.lookupLifeCycleEntry(SEND_DELETE_EMAIL_ACTION) != null) { + logAudit("Group-Deletion: Remove from delete-list group=" + bg); + LifeCycleManager.createInstanceFor(bg).deleteTimestampFor(SEND_DELETE_EMAIL_ACTION); + } + BusinessGroupManagerImpl.getInstance().updateBusinessGroup(bg); + return bg; + } + }); } - } \ No newline at end of file diff --git a/src/main/java/org/olat/group/ui/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/group/ui/_i18n/LocalStrings_de.properties index 727bb1dc920..8b79302f343 100644 --- a/src/main/java/org/olat/group/ui/_i18n/LocalStrings_de.properties +++ b/src/main/java/org/olat/group/ui/_i18n/LocalStrings_de.properties @@ -24,6 +24,7 @@ create.form.businesspath=Link zu dieser Gruppe error.group.name.exists=Dieser Gruppenname wird in diesem Kontext bereits verwendet, w\u00E4hlen Sie einen anderen Namen. form.error.disableNonEmptyWaitingList=Die Warteliste ist nicht leer. Zum Ausschalten der Warteliste m\u00FCssen alle Teilnehmer ausgetragen werden. group.type=Arbeitsgruppe +group.deleted=Diese Gruppe wurde gel\u00F6scht. groupsPortlet.description=Schnellzugriff zu den wichtigsten Lern-, Rechte- und Arbeitsgruppen groupsPortlet.no_member=Sie wurden aus dieser Gruppe ausgetragen oder die Gruppe ist gel\u00F6scht worden. groupsPortlet.nogroups=Sie sind in keiner Gruppe diff --git a/src/main/java/org/olat/group/ui/edit/BusinessGroupEditController.java b/src/main/java/org/olat/group/ui/edit/BusinessGroupEditController.java index 16f2ecdd870..59da90bcd07 100644 --- a/src/main/java/org/olat/group/ui/edit/BusinessGroupEditController.java +++ b/src/main/java/org/olat/group/ui/edit/BusinessGroupEditController.java @@ -67,6 +67,7 @@ import org.olat.core.logging.activity.ThreadLocalUserActivityLogger; import org.olat.core.util.Util; import org.olat.core.util.coordinate.CoordinatorManager; import org.olat.core.util.coordinate.LockResult; +import org.olat.core.util.coordinate.SyncerCallback; import org.olat.core.util.event.GenericEventListener; import org.olat.core.util.mail.MailContext; import org.olat.core.util.mail.MailContextImpl; @@ -84,7 +85,6 @@ import org.olat.group.GroupLoggingAction; import org.olat.group.area.BGArea; import org.olat.group.area.BGAreaManager; import org.olat.group.area.BGAreaManagerImpl; -import org.olat.group.context.BGContext; import org.olat.group.delete.service.GroupDeletionManager; import org.olat.group.properties.BusinessGroupPropertyManager; import org.olat.group.right.BGRightManager; @@ -126,10 +126,9 @@ public class BusinessGroupEditController extends BasicController implements Cont private BGRightManager rightManager; private RightsToGroupDataModel rightDataModel; private Choice areasChoice, rightsChoice; - private List allAreas, selectedAreas; - private List selectedRights; + private List<BGArea> selectedAreas; + private List<String> selectedRights; private BGRights bgRights; - private BGContext bgContext; private TabbedPane tabbedPane; private VelocityContainer vc_edit; private VelocityContainer vc_tab_bgDetails; @@ -157,14 +156,14 @@ public class BusinessGroupEditController extends BasicController implements Cont * controller does no type specific stuff implicit just by looking at * the group type. Type specifig features must be flagged. */ - public BusinessGroupEditController(UserRequest ureq, WindowControl wControl, BusinessGroup currBusinessGroup, + public BusinessGroupEditController(UserRequest ureq, WindowControl wControl, BusinessGroup businessGroup, BGConfigFlags configurationFlags) { super(ureq, wControl); // OLAT-4955: setting the stickyActionType here passes it on to any controller defined in the scope of the editor, // basically forcing any logging action called within the bg editor to be of type 'admin' getUserActivityLogger().setStickyActionType(ActionType.admin); - addLoggingResourceable(LoggingResourceable.wrap(currBusinessGroup)); + addLoggingResourceable(LoggingResourceable.wrap(businessGroup)); // Initialize managers this.areaManager = BGAreaManagerImpl.getInstance(); @@ -172,14 +171,12 @@ public class BusinessGroupEditController extends BasicController implements Cont this.bgm = BusinessGroupManagerImpl.getInstance(); // Initialize other members - this.currBusinessGroup = bgm.loadBusinessGroup(currBusinessGroup); // reload // group this.flags = configurationFlags; - this.bgContext = currBusinessGroup.getGroupContext(); // Initialize translator: // package translator with default group fallback translators and type // translator - setTranslator(BGTranslatorFactory.createBGPackageTranslator(PACKAGE, currBusinessGroup.getType(), ureq.getLocale())); + setTranslator(BGTranslatorFactory.createBGPackageTranslator(PACKAGE, businessGroup.getType(), ureq.getLocale())); // Initialize available rights if (flags.isEnabled(BGConfigFlags.RIGHTS)) { // for now only course rights are relevant @@ -189,15 +186,18 @@ public class BusinessGroupEditController extends BasicController implements Cont } // try to acquire edit lock on business group String locksubkey = "groupEdit"; - lockEntry = CoordinatorManager.getInstance().getCoordinator().getLocker().acquireLock(currBusinessGroup, ureq.getIdentity(), locksubkey); + lockEntry = CoordinatorManager.getInstance().getCoordinator().getLocker().acquireLock(businessGroup, ureq.getIdentity(), locksubkey); if (lockEntry.isSuccess()) { // reload group to minimize stale object exception and update last usage // timestamp - currBusinessGroup = BusinessGroupManagerImpl.getInstance().loadBusinessGroup(currBusinessGroup); - currBusinessGroup.setLastUsage(new Date(System.currentTimeMillis())); - LifeCycleManager.createInstanceFor(currBusinessGroup).deleteTimestampFor(GroupDeletionManager.SEND_DELETE_EMAIL_ACTION); - BusinessGroupManagerImpl.getInstance().updateBusinessGroup(currBusinessGroup); - + currBusinessGroup = BusinessGroupManagerImpl.getInstance().setLastUsageFor(businessGroup); + if(currBusinessGroup == null) { + VelocityContainer vc = createVelocityContainer("deleted"); + vc.contextPut("name", businessGroup.getName()); + putInitialPanel(vc); + return; + } + // add as listener to BusinessGroup so we are being notified about // changes. CoordinatorManager.getInstance().getCoordinator().getEventBus().registerFor(this, ureq.getIdentity(), currBusinessGroup); @@ -419,33 +419,39 @@ public class BusinessGroupEditController extends BasicController implements Cont * persist the updates */ private void updateBusinessGroup() { - // refresh group to prevent stale object exception and context proxy issues - this.currBusinessGroup = this.bgm.loadBusinessGroup(this.currBusinessGroup); - String bgName = this.modifyBusinessGroupController.getGroupName(); - String bgDesc = this.modifyBusinessGroupController.getGroupDescription(); - Integer bgMax = this.modifyBusinessGroupController.getGroupMax(); - Integer bgMin = this.modifyBusinessGroupController.getGroupMin(); - Boolean waitingListEnabled = this.modifyBusinessGroupController.isWaitingListEnabled(); - Boolean autoCloseRanksEnabled = this.modifyBusinessGroupController.isAutoCloseRanksEnabled(); - - this.currBusinessGroup.setName(bgName); - this.currBusinessGroup.setDescription(bgDesc); - this.currBusinessGroup.setMaxParticipants(bgMax); - this.currBusinessGroup.setMinParticipants(bgMin); - this.currBusinessGroup.setWaitingListEnabled(waitingListEnabled); - if (waitingListEnabled.booleanValue() && (this.currBusinessGroup.getWaitingGroup() == null) ) { - // Waitinglist is enabled but not created => Create waitingGroup - BaseSecurity securityManager = BaseSecurityManager.getInstance(); - SecurityGroup waitingGroup = securityManager.createAndPersistSecurityGroup(); - currBusinessGroup.setWaitingGroup(waitingGroup); - } - currBusinessGroup.setAutoCloseRanksEnabled(autoCloseRanksEnabled); - currBusinessGroup.setLastUsage(new Date(System.currentTimeMillis())); - LifeCycleManager.createInstanceFor(currBusinessGroup).deleteTimestampFor(GroupDeletionManager.SEND_DELETE_EMAIL_ACTION); - // switch on/off waiting-list in member tab - vc_tab_grpmanagement.contextPut("hasWaitingGrp", waitingListEnabled); + final BusinessGroup businessGroup = currBusinessGroup; + currBusinessGroup = CoordinatorManager.getInstance().getCoordinator().getSyncer().doInSync(businessGroup, new SyncerCallback<BusinessGroup>() { + public BusinessGroup execute() { + // refresh group to prevent stale object exception and context proxy issues + BusinessGroup bg = bgm.loadBusinessGroup(businessGroup); + String bgName = modifyBusinessGroupController.getGroupName(); + String bgDesc = modifyBusinessGroupController.getGroupDescription(); + Integer bgMax = modifyBusinessGroupController.getGroupMax(); + Integer bgMin = modifyBusinessGroupController.getGroupMin(); + Boolean waitingListEnabled = modifyBusinessGroupController.isWaitingListEnabled(); + Boolean autoCloseRanksEnabled = modifyBusinessGroupController.isAutoCloseRanksEnabled(); - bgm.updateBusinessGroup(currBusinessGroup); + bg.setName(bgName); + bg.setDescription(bgDesc); + bg.setMaxParticipants(bgMax); + bg.setMinParticipants(bgMin); + bg.setWaitingListEnabled(waitingListEnabled); + if (waitingListEnabled.booleanValue() && (bg.getWaitingGroup() == null) ) { + // Waitinglist is enabled but not created => Create waitingGroup + BaseSecurity securityManager = BaseSecurityManager.getInstance(); + SecurityGroup waitingGroup = securityManager.createAndPersistSecurityGroup(); + bg.setWaitingGroup(waitingGroup); + } + bg.setAutoCloseRanksEnabled(autoCloseRanksEnabled); + bg.setLastUsage(new Date(System.currentTimeMillis())); + LifeCycleManager.createInstanceFor(bg).deleteTimestampFor(GroupDeletionManager.SEND_DELETE_EMAIL_ACTION); + // switch on/off waiting-list in member tab + vc_tab_grpmanagement.contextPut("hasWaitingGrp", waitingListEnabled); + + bgm.updateBusinessGroup(bg); + return bg; + } + }); } /** @@ -527,14 +533,14 @@ public class BusinessGroupEditController extends BasicController implements Cont */ private VelocityContainer createTabAreas() { VelocityContainer tmp = createVelocityContainer("tab_bgAreas"); - this.allAreas = areaManager.findBGAreasOfBGContext(this.bgContext); - this.selectedAreas = areaManager.findBGAreasOfBusinessGroup(this.currBusinessGroup); - this.areaDataModel = new AreasToGroupDataModel(this.allAreas, this.selectedAreas); + List allAreas = areaManager.findBGAreasOfBGContext(currBusinessGroup.getGroupContext()); + selectedAreas = areaManager.findBGAreasOfBusinessGroup(currBusinessGroup); + areaDataModel = new AreasToGroupDataModel(allAreas, selectedAreas); areasChoice = new Choice("areasChoice", getTranslator()); areasChoice.setSubmitKey("submit"); areasChoice.setCancelKey("cancel"); - areasChoice.setTableDataModel(this.areaDataModel); + areasChoice.setTableDataModel(areaDataModel); areasChoice.addListener(this); tmp.put("areasChoice", areasChoice); tmp.contextPut("noAreasFound", (allAreas.size() > 0 ? Boolean.FALSE : Boolean.TRUE)); @@ -694,9 +700,11 @@ public class BusinessGroupEditController extends BasicController implements Cont */ @Override protected void doDispose() { - CoordinatorManager.getInstance().getCoordinator().getEventBus().deregisterFor(this, this.currBusinessGroup); - //release lock on dispose - releaseBusinessGroupEditLock(); + if(currBusinessGroup != null) { + CoordinatorManager.getInstance().getCoordinator().getEventBus().deregisterFor(this, currBusinessGroup); + //release lock on dispose + releaseBusinessGroupEditLock(); + } } private void releaseBusinessGroupEditLock() { diff --git a/src/main/java/org/olat/group/ui/edit/_content/deleted.html b/src/main/java/org/olat/group/ui/edit/_content/deleted.html new file mode 100644 index 00000000000..0b3ed42a49e --- /dev/null +++ b/src/main/java/org/olat/group/ui/edit/_content/deleted.html @@ -0,0 +1,4 @@ +<h4 class="b_with_small_icon_left b_group_icon"> + $name +</h4> +$r.translate("group.deleted") \ No newline at end of file diff --git a/src/main/java/org/olat/group/ui/edit/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/group/ui/edit/_i18n/LocalStrings_de.properties index 72ec5b41607..e2c67b1fe78 100644 --- a/src/main/java/org/olat/group/ui/edit/_i18n/LocalStrings_de.properties +++ b/src/main/java/org/olat/group/ui/edit/_i18n/LocalStrings_de.properties @@ -129,3 +129,4 @@ group.edit.tab.members=Mitglieder group.edit.tab.rights=Berechtigungen group.edit.tab.accesscontrol=Veröffentlichung und Buchungskonfiguration group.edit.title=Gruppe <i>{0}</i> editieren +group.deleted=$org.olat.group.ui\:group.deleted diff --git a/src/main/java/org/olat/group/ui/edit/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/group/ui/edit/_i18n/LocalStrings_en.properties index c5cb3e907a4..03870ef1a15 100644 --- a/src/main/java/org/olat/group/ui/edit/_i18n/LocalStrings_en.properties +++ b/src/main/java/org/olat/group/ui/edit/_i18n/LocalStrings_en.properties @@ -119,3 +119,4 @@ group.edit.tab.details=Description group.edit.tab.members=Members group.edit.tab.rights=Rights group.edit.title=Edit group <i>{0}</i> +group.deleted=$org.olat.group.ui\:group.deleted diff --git a/src/main/java/org/olat/group/ui/management/BGManagementController.java b/src/main/java/org/olat/group/ui/management/BGManagementController.java index 83a354bd1fb..2d2254bb74a 100644 --- a/src/main/java/org/olat/group/ui/management/BGManagementController.java +++ b/src/main/java/org/olat/group/ui/management/BGManagementController.java @@ -41,6 +41,7 @@ import org.olat.collaboration.CollaborationTools; import org.olat.collaboration.CollaborationToolsFactory; import org.olat.core.commons.fullWebApp.LayoutMain3ColsController; import org.olat.core.dispatcher.jumpin.JumpInManager; +import org.olat.core.gui.ShortName; import org.olat.core.gui.UserRequest; import org.olat.core.gui.components.Component; import org.olat.core.gui.components.link.Link; @@ -96,7 +97,6 @@ import org.olat.group.ui.BusinessGroupTableModel; import org.olat.group.ui.NewAreaController; import org.olat.group.ui.NewBGController; import org.olat.group.ui.area.BGAreaEditController; -import org.olat.group.ui.area.BGAreaFormController; import org.olat.group.ui.area.BGAreaTableModel; import org.olat.group.ui.context.BGContextEditController; import org.olat.group.ui.context.BGContextEvent; @@ -108,6 +108,7 @@ import org.olat.group.ui.wizard.BGCopyWizardController; import org.olat.group.ui.wizard.BGMultipleCopyWizardController; import org.olat.group.ui.wizard.MemberListWizardController; import org.olat.modules.co.ContactFormController; +import org.olat.repository.RepositoryEntry; import org.olat.repository.RepositoryTableModel; import org.olat.user.HomePageConfig; import org.olat.user.HomePageConfigManagerImpl; @@ -157,7 +158,7 @@ public class BGManagementController extends MainLayoutBasicController implements private static final String CMD_LIST_MEMBERS_WITH_GROUPS = "cmd.list.members.with.groups"; private static final String CMD_LIST_MEMBERS_WITH_AREAS = "cmd.list.members.with.areas"; - private Translator areaTrans, userTrans; + private Translator userTrans; private BGContext bgContext; private String groupType; private BGConfigFlags flags; @@ -207,7 +208,7 @@ public class BGManagementController extends MainLayoutBasicController implements private BGAreaManager areaManager; // Workflow variables - private List areaFilters; + private List<ShortName> areaFilters; private BGArea currentAreaFilter; private Component backComponent, currentComponent; private BusinessGroup currentGroup; @@ -245,11 +246,6 @@ public class BGManagementController extends MainLayoutBasicController implements // 1 - package translator with default group fallback translators and type // translator setTranslator(BGTranslatorFactory.createBGPackageTranslator(PACKAGE, this.groupType, ureq.getLocale())); - // 2 - area specific translator - if (flags.isEnabled(BGConfigFlags.AREAS)) { - //areaTrans = new PackageTranslator(Util.getPackageName(BGAreaForm.class), ureq.getLocale(), trans); - areaTrans = Util.createPackageTranslator(BGAreaFormController.class, ureq.getLocale(), getTranslator()); - } // user translator this.userTrans = Util.createPackageTranslator(UserManager.class, ureq.getLocale()); @@ -538,7 +534,6 @@ public class BGManagementController extends MainLayoutBasicController implements } else if (source == confirmDeleteGroup) { if (DialogBoxUIFactory.isYesEvent(event)) { // yes case releaseAdminLockAndGroupMUE(); - String deletedGroupName = this.currentGroup.getName(); LoggingResourceable lri = LoggingResourceable.wrap(currentGroup); doGroupDelete(); doGroupList(ureq, false); @@ -550,7 +545,6 @@ public class BGManagementController extends MainLayoutBasicController implements // TODO event: changed area: update models } else if (source == confirmDeleteArea) { if (DialogBoxUIFactory.isYesEvent(event)) { // yes case - String deletedAreaName = this.currentArea.getName(); LoggingResourceable lri = LoggingResourceable.wrap(currentArea); doAreaDelete(); doAreaList(ureq, false); @@ -886,7 +880,7 @@ public class BGManagementController extends MainLayoutBasicController implements } private void doAddOtherResourcesList(UserRequest ureq) { - List repoTableModelEntries = contextManager.findRepositoryEntriesForBGContext(this.bgContext); + List<RepositoryEntry> repoTableModelEntries = contextManager.findRepositoryEntriesForBGContext(this.bgContext); if (repoTableModelEntries.size() > 1) { Translator resourceTrans = Util.createPackageTranslator(RepositoryTableModel.class, ureq.getLocale(), getTranslator()); diff --git a/src/main/java/org/olat/group/ui/run/BusinessGroupMainRunController.java b/src/main/java/org/olat/group/ui/run/BusinessGroupMainRunController.java index 7c9fe7f3202..44cd753186b 100644 --- a/src/main/java/org/olat/group/ui/run/BusinessGroupMainRunController.java +++ b/src/main/java/org/olat/group/ui/run/BusinessGroupMainRunController.java @@ -173,14 +173,12 @@ public class BusinessGroupMainRunController extends MainLayoutBasicController im private Panel mainPanel; private VelocityContainer main, vc_sendToChooserForm, resourcesVC; - private Identity identity; private PackageTranslator resourceTrans; private BusinessGroup businessGroup; private MenuTree bgTree; private LayoutMain3ColsController columnLayoutCtr; - private Panel all; private Controller collabToolCtr; private Controller chatCtr; @@ -203,7 +201,6 @@ public class BusinessGroupMainRunController extends MainLayoutBasicController im private BusinessGroupPropertyManager bgpm; private UserSession userSession; private String adminNodeId; // reference to admin menu item - private String acNodeId;//fxdiff VCRP-1,2: access control of resources // not null indicates tool is enabled private GenericTreeNode nodeFolder; @@ -231,30 +228,44 @@ public class BusinessGroupMainRunController extends MainLayoutBasicController im * @param flags * @param initialViewIdentifier supported are null, "toolforum", "toolfolder" */ - public BusinessGroupMainRunController(UserRequest ureq, WindowControl control, BusinessGroup currBusinessGroup, BGConfigFlags flags, + public BusinessGroupMainRunController(UserRequest ureq, WindowControl control, BusinessGroup bGroup, BGConfigFlags flags, String initialViewIdentifier) { super(ureq, control); - addLoggingResourceable(LoggingResourceable.wrap(currBusinessGroup)); - ThreadLocalUserActivityLogger.log(GroupLoggingAction.GROUP_OPEN, getClass()); - this.bgpm = new BusinessGroupPropertyManager(currBusinessGroup); this.flags = flags; - this.businessGroup = currBusinessGroup; - this.identity = ureq.getIdentity(); + /* + * lastUsage, update lastUsage if group is run if you can acquire the lock + * on the group for a very short time. If this is not possible, then the + * lastUsage is already up to date within one-day-precision. + */ + businessGroup = BusinessGroupManagerImpl.getInstance().setLastUsageFor(bGroup); + if(businessGroup == null) { + VelocityContainer vc = createVelocityContainer("deleted"); + vc.contextPut("name", bGroup.getName()); + columnLayoutCtr = new LayoutMain3ColsController(ureq, getWindowControl(), null, null, vc, "grouprun"); + listenTo(columnLayoutCtr); // cleanup on dispose + putInitialPanel(columnLayoutCtr.getInitialComponent()); + return; + } + + addLoggingResourceable(LoggingResourceable.wrap(businessGroup)); + ThreadLocalUserActivityLogger.log(GroupLoggingAction.GROUP_OPEN, getClass()); + bgpm = new BusinessGroupPropertyManager(businessGroup); + this.userSession = ureq.getUserSession(); this.assessmentEventOres = OresHelper.createOLATResourceableType(AssessmentEvent.class); - boolean isOwner = BaseSecurityManager.getInstance().isIdentityPermittedOnResourceable(identity, Constants.PERMISSION_ACCESS, businessGroup); + boolean isOwner = BaseSecurityManager.getInstance().isIdentityPermittedOnResourceable(getIdentity(), Constants.PERMISSION_ACCESS, businessGroup); this.isAdmin = isOwner || flags.isEnabled(BGConfigFlags.IS_GM_ADMIN); // Initialize translator: // package translator with default group fallback translators and type // translator - setTranslator(BGTranslatorFactory.createBGPackageTranslator(PACKAGE, currBusinessGroup.getType(), ureq.getLocale())); + setTranslator(BGTranslatorFactory.createBGPackageTranslator(PACKAGE, businessGroup.getType(), ureq.getLocale())); this.resourceTrans = new PackageTranslator(Util.getPackageName(RepositoryTableModel.class), ureq.getLocale(), getTranslator()); // main component layed out in panel main = createVelocityContainer("bgrun"); - exposeGroupDetailsToVC(currBusinessGroup); + exposeGroupDetailsToVC(businessGroup); mainPanel = new Panel("p_buddygroupRun"); mainPanel.setContent(main); @@ -268,16 +279,9 @@ public class BusinessGroupMainRunController extends MainLayoutBasicController im listenTo(columnLayoutCtr); // cleanup on dispose // - all = putInitialPanel(columnLayoutCtr.getInitialComponent()); + putInitialPanel(columnLayoutCtr.getInitialComponent()); // register for AssessmentEvents triggered by this user userSession.getSingleUserEventCenter().registerFor(this, userSession.getIdentity(), assessmentEventOres); - /* - * lastUsage, update lastUsage if group is run if you can acquire the lock - * on the group for a very short time. If this is not possible, then the - * lastUsage is already up to date within one-day-precision. - */ - - BusinessGroupManagerImpl.getInstance().setLastUsageFor(currBusinessGroup); //disposed message controller //must be created beforehand @@ -288,7 +292,7 @@ public class BusinessGroupMainRunController extends MainLayoutBasicController im setDisposedMsgController(disposedController); // add as listener to BusinessGroup so we are being notified about changes. - CoordinatorManager.getInstance().getCoordinator().getEventBus().registerFor(this, ureq.getIdentity(), currBusinessGroup); + CoordinatorManager.getInstance().getCoordinator().getEventBus().registerFor(this, ureq.getIdentity(), businessGroup); // show disabled message when collaboration is disabled (e.g. in a test) if(AssessmentEvent.isAssessmentStarted(ureq.getUserSession())){ @@ -299,10 +303,10 @@ public class BusinessGroupMainRunController extends MainLayoutBasicController im //check managed //fxdiff VCRP-1,2: access control of resources ACFrontendManager acFrontendManager = (ACFrontendManager)CoreSpringFactory.getBean("acFrontendManager"); - AccessResult acResult = acFrontendManager.isAccessible(currBusinessGroup, getIdentity(), false); + AccessResult acResult = acFrontendManager.isAccessible(businessGroup, getIdentity(), false); if(acResult.isAccessible()) { //ok - } else if (currBusinessGroup != null && acResult.getAvailableMethods().size() > 0) { + } else if (businessGroup != null && acResult.getAvailableMethods().size() > 0) { accessController = ACUIFactory.createAccessController(ureq, getWindowControl(), acResult.getAvailableMethods()); listenTo(accessController); mainPanel.setContent(accessController.getInitialComponent()); @@ -987,7 +991,7 @@ public class BusinessGroupMainRunController extends MainLayoutBasicController im // Activate edit menu item bgTree.setSelectedNodeId(ACTIVITY_MENUSELECT_ADMINISTRATION); } - } else if (bgmfe.wasMyselfRemoved(identity)) { + } else if (bgmfe.wasMyselfRemoved(getIdentity())) { //nothing more here!! The message will be created and displayed upon disposing dispose();//disposed message controller will be set } @@ -1188,7 +1192,7 @@ public class BusinessGroupMainRunController extends MainLayoutBasicController im gtnChild.setAltText(translate("menutree.ac.alt")); gtnChild.setIconCssClass("b_order_icon"); root.addChild(gtnChild); - acNodeId = gtnChild.getIdent(); + //acNodeId = gtnChild.getIdent(); } } } diff --git a/src/main/java/org/olat/group/ui/run/_content/deleted.html b/src/main/java/org/olat/group/ui/run/_content/deleted.html new file mode 100644 index 00000000000..0b3ed42a49e --- /dev/null +++ b/src/main/java/org/olat/group/ui/run/_content/deleted.html @@ -0,0 +1,4 @@ +<h4 class="b_with_small_icon_left b_group_icon"> + $name +</h4> +$r.translate("group.deleted") \ No newline at end of file diff --git a/src/main/java/org/olat/group/ui/run/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/group/ui/run/_i18n/LocalStrings_de.properties index c294eb3cbee..2f5b19c28f3 100644 --- a/src/main/java/org/olat/group/ui/run/_i18n/LocalStrings_de.properties +++ b/src/main/java/org/olat/group/ui/run/_i18n/LocalStrings_de.properties @@ -1,6 +1,7 @@ #Mon Mar 02 09:54:04 CET 2009 businessgroup.contact.bodytext=\n\n---\nGehe direkt zur Gruppe {0} \: "{1}" businessgroup.contact.subject={0} \: +group.deleted=$org.olat.group.ui\:group.deleted grouprun.configurationchanged=Die Konfiguration dieser Gruppe wurde ver\u00E4ndert. Die Gruppe wurde neu gestartet. grouprun.details.description=Beschreibung grouprun.details.name=Name der Gruppe diff --git a/src/main/java/org/olat/group/ui/run/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/group/ui/run/_i18n/LocalStrings_en.properties index 0b3a0125ad1..c908d6c5d55 100644 --- a/src/main/java/org/olat/group/ui/run/_i18n/LocalStrings_en.properties +++ b/src/main/java/org/olat/group/ui/run/_i18n/LocalStrings_en.properties @@ -1,6 +1,7 @@ #Thu May 26 09:55:51 CEST 2011 businessgroup.contact.bodytext=\n\n---\nGo immediately to group {0} \: "{1}" businessgroup.contact.subject={0} \: +group.deleted=$org.olat.group.ui\:group.deleted grouprun.configurationchanged=This group's configuration has been altered. The group has been restarted. grouprun.details.description=Description grouprun.details.name=Group name -- GitLab