From 16d938f77217998d8976b2c3bb6a010065724e6b Mon Sep 17 00:00:00 2001
From: srosse <none@none>
Date: Fri, 27 Jul 2012 17:09:44 +0200
Subject: [PATCH] OO-291: optimize memory usage of the main search controllers

---
 .../olat/group/manager/BusinessGroupDAO.java  |  18 ++++
 .../AbstractBusinessGroupListController.java  |  51 +++++----
 .../group/ui/main/BGMarkCellRenderer.java     |   2 +-
 .../ui/main/BGResourcesCellRenderer.java      |  43 ++------
 .../group/ui/main/BGRoleCellRenderer.java     |   2 +-
 .../org/olat/group/ui/main/BGTableItem.java   | 100 ++++++++++++++----
 .../ui/main/BusinessGroupMainController.java  |  19 ++++
 .../main/BusinessGroupSearchController.java   |   1 -
 .../main/BusinessGroupTableModelWithType.java |  26 ++---
 .../group/ui/main/RepositoryEntryShort.java   |  69 ++++++++++++
 .../group/ui/portlet/BusinessGroupEntry.java  |  63 +++++++++++
 .../portlet/GroupsPortletRunController.java   |  92 ++++++++--------
 .../ui/wizard/BGUserStatusCellRenderer.java   |   2 +
 13 files changed, 331 insertions(+), 157 deletions(-)
 create mode 100644 src/main/java/org/olat/group/ui/main/RepositoryEntryShort.java
 create mode 100644 src/main/java/org/olat/group/ui/portlet/BusinessGroupEntry.java

diff --git a/src/main/java/org/olat/group/manager/BusinessGroupDAO.java b/src/main/java/org/olat/group/manager/BusinessGroupDAO.java
index 47d433eea22..afc398d9de1 100644
--- a/src/main/java/org/olat/group/manager/BusinessGroupDAO.java
+++ b/src/main/java/org/olat/group/manager/BusinessGroupDAO.java
@@ -218,6 +218,24 @@ public class BusinessGroupDAO {
 		return group;
 	}
 	
+	public int countMembershipInfoInBusinessGroups(Identity identity, List<Long> groupKeys) {
+		StringBuilder sb = new StringBuilder(); 
+		sb.append("select count(membership) from ").append(BusinessGroupMembershipImpl.class.getName()).append(" as membership ")
+		  .append(" where membership.identityKey=:identId ");
+		if(groupKeys != null && !groupKeys.isEmpty()) {
+		  sb.append(" and (membership.ownerGroupKey in (:groupKeys) or membership.participantGroupKey in (:groupKeys) or membership.waitingGroupKey in (:groupKeys))");
+		}
+		
+		TypedQuery<Number> query = dbInstance.getCurrentEntityManager().createQuery(sb.toString(), Number.class)
+				.setParameter("identId", identity.getKey());
+		if(groupKeys != null && !groupKeys.isEmpty()) {
+			query.setParameter("groupKeys", groupKeys);
+		}
+		
+		Number res = query.getSingleResult();
+		return res.intValue();
+	}
+	
 	public List<BusinessGroupMembership> getMembershipInfoInBusinessGroups(Identity identity, List<BusinessGroup> groups) {
 		StringBuilder sb = new StringBuilder(); 
 		sb.append("select membership from ").append(BusinessGroupMembershipImpl.class.getName()).append(" as membership ")
diff --git a/src/main/java/org/olat/group/ui/main/AbstractBusinessGroupListController.java b/src/main/java/org/olat/group/ui/main/AbstractBusinessGroupListController.java
index b1909d65ddd..c4c4d234471 100644
--- a/src/main/java/org/olat/group/ui/main/AbstractBusinessGroupListController.java
+++ b/src/main/java/org/olat/group/ui/main/AbstractBusinessGroupListController.java
@@ -56,17 +56,18 @@ import org.olat.core.gui.control.generic.wizard.StepRunnerCallback;
 import org.olat.core.gui.control.generic.wizard.StepsMainRunController;
 import org.olat.core.gui.control.generic.wizard.StepsRunContext;
 import org.olat.core.id.Identity;
+import org.olat.core.id.OLATResourceable;
 import org.olat.core.id.Roles;
-import org.olat.core.id.context.BusinessControl;
-import org.olat.core.id.context.BusinessControlFactory;
 import org.olat.core.logging.activity.ThreadLocalUserActivityLogger;
 import org.olat.core.util.mail.MailNotificationEditController;
 import org.olat.core.util.mail.MailTemplate;
+import org.olat.core.util.resource.OresHelper;
 import org.olat.core.util.vfs.Quota;
 import org.olat.group.BusinessGroup;
 import org.olat.group.BusinessGroupMembership;
 import org.olat.group.BusinessGroupModule;
 import org.olat.group.BusinessGroupService;
+import org.olat.group.BusinessGroupShort;
 import org.olat.group.GroupLoggingAction;
 import org.olat.group.model.BGMembership;
 import org.olat.group.model.BGRepositoryEntryRelation;
@@ -81,7 +82,6 @@ import org.olat.group.ui.wizard.BGEmailSelectReceiversStep;
 import org.olat.group.ui.wizard.BGMergeStep;
 import org.olat.group.ui.wizard.BGUserMailTemplate;
 import org.olat.group.ui.wizard.BGUserManagementController;
-import org.olat.resource.OLATResource;
 import org.olat.resource.accesscontrol.manager.ACFrontendManager;
 import org.olat.resource.accesscontrol.model.OLATResourceAccess;
 import org.olat.resource.accesscontrol.model.PriceMethodBundle;
@@ -105,7 +105,7 @@ abstract class AbstractBusinessGroupListController extends BasicController {
 	protected final VelocityContainer mainVC;
 
 	protected final TableController groupListCtr;
-	protected BusinessGroupTableModelWithType groupListModel;
+	protected final BusinessGroupTableModelWithType groupListModel;
 	protected SearchBusinessGroupParams lastSearchParams;
 	
 	private DialogBoxController leaveDialogBox;
@@ -192,16 +192,12 @@ abstract class AbstractBusinessGroupListController extends BasicController {
 	protected void event(UserRequest ureq, Component source, Event event) {
 		if (source instanceof Link && source.getComponentName().startsWith("repo_entry_")) {
 			Object uobj = ((Link)source).getUserObject();
-			if (uobj instanceof Long) {
-				Long repoEntryKey = (Long)((Link)source).getUserObject();
-				BusinessControl bc = BusinessControlFactory.getInstance().createFromString("[RepositoryEntry:" + repoEntryKey + "]");
-				WindowControl bwControl = BusinessControlFactory.getInstance().createBusinessWindowControl(bc, getWindowControl());
-				NewControllerFactory.getInstance().launch(ureq, bwControl);
-			} else if(uobj instanceof BusinessGroup) {
-				BusinessGroup bg = (BusinessGroup)uobj;
-				BusinessControl bc = BusinessControlFactory.getInstance().createFromString("[BusinessGroup:" + bg.getKey() + "][toolresources:0]");
-				WindowControl bwControl = BusinessControlFactory.getInstance().createBusinessWindowControl(bc, getWindowControl());
-				NewControllerFactory.getInstance().launch(ureq, bwControl);
+			if (uobj instanceof RepositoryEntryShort) {
+				RepositoryEntryShort re = (RepositoryEntryShort)((Link)source).getUserObject();
+				NewControllerFactory.getInstance().launch("[RepositoryEntry:" + re.getKey() + "]", ureq, getWindowControl());
+			} else if(uobj instanceof BusinessGroupShort) {
+				BusinessGroupShort bg = (BusinessGroupShort)uobj;
+				NewControllerFactory.getInstance().launch("[BusinessGroup:" + bg.getKey() + "][toolresources:0]", ureq, getWindowControl());
 			}
 		} else if (source instanceof Link && source.getComponentName().startsWith("marked_")) {
 			Object uobj = ((Link)source).getUserObject();
@@ -218,12 +214,13 @@ abstract class AbstractBusinessGroupListController extends BasicController {
 	 * @param item
 	 */
 	private void toogleMark(BGTableItem item) {
-		OLATResource bgResource = item.getBusinessGroup().getResource();
+		OLATResourceable bgResource = OresHelper.createOLATResourceableInstance("BusinessGroup", item.getBusinessGroupKey());
+		//		item.getBusinessGroup().getResource();
 		if(markManager.isMarked(bgResource, getIdentity(), null)) {
 			markManager.removeMark(bgResource, getIdentity(), null);
 			item.setMarked(false);
 		} else {
-			String businessPath = "[BusinessGroup:" + item.getBusinessGroup().getKey() + "]";
+			String businessPath = "[BusinessGroup:" + item.getBusinessGroupKey() + "]";
 			markManager.setMark(bgResource, getIdentity(), null, businessPath);
 			item.setMarked(true);
 		}
@@ -237,14 +234,14 @@ abstract class AbstractBusinessGroupListController extends BasicController {
 				TableEvent te = (TableEvent) event;
 				String actionid = te.getActionId();
 
-				BusinessGroup businessGroup = groupListModel.getObject(te.getRowId()).getBusinessGroup();
-				businessGroup = businessGroupService.loadBusinessGroup(businessGroup);
+				Long businessGroupKey = groupListModel.getObject(te.getRowId()).getBusinessGroupKey();
+				BusinessGroup businessGroup = businessGroupService.loadBusinessGroup(businessGroupKey);
 				//prevent rs after a group is deleted by someone else
 				if(businessGroup == null) {
 					groupListModel.removeBusinessGroup(businessGroup);
 					groupListCtr.modelChanged();
 				} else if(actionid.equals(TABLE_ACTION_LAUNCH)) {
-					String businessPath = "[BusinessGroup:" + businessGroup.getKey() + "]";
+					String businessPath = "[BusinessGroup:" + businessGroupKey + "]";
 					NewControllerFactory.getInstance().launch(businessPath, ureq, getWindowControl());
 				} else if(actionid.equals(TABLE_ACTION_LEAVE)) {
 					leaveDialogBox = activateYesNoDialog(ureq, null, translate("dialog.modal.bg.leave.text", businessGroup.getName()), leaveDialogBox);
@@ -326,15 +323,19 @@ abstract class AbstractBusinessGroupListController extends BasicController {
 	}
 	
 	/**
-	 * Clean up all popup controllers
+	 * Aggressive clean up all popup controllers
 	 */
 	private void cleanUpPopups() {
 		removeAsListenerAndDispose(cmc);
 		removeAsListenerAndDispose(deleteDialogBox);
 		removeAsListenerAndDispose(groupCreateController);
+		removeAsListenerAndDispose(businessGroupWizard);
+		removeAsListenerAndDispose(leaveDialogBox);
 		cmc = null;
+		leaveDialogBox = null;
 		deleteDialogBox = null;
 		groupCreateController = null;
+		businessGroupWizard = null;
 	}
 	
 	/**
@@ -405,10 +406,7 @@ abstract class AbstractBusinessGroupListController extends BasicController {
 		removeAsListenerAndDispose(businessGroupWizard);
 		if(items == null || items.isEmpty()) return;
 		
-		List<BusinessGroup> groups = new ArrayList<BusinessGroup>();
-		for(BGTableItem item:items) {
-			groups.add(item.getBusinessGroup());
-		}
+		List<BusinessGroup> groups = toBusinessGroups(items);
 
 		Step start = new BGCopyPreparationStep(ureq, groups);
 		StepRunnerCallback finish = new StepRunnerCallback() {
@@ -618,10 +616,11 @@ abstract class AbstractBusinessGroupListController extends BasicController {
 	}
 	
 	private List<BusinessGroup> toBusinessGroups(List<BGTableItem> items) {
-		List<BusinessGroup> groups = new ArrayList<BusinessGroup>();
+		List<Long> groupKeys = new ArrayList<Long>();
 		for(BGTableItem item:items) {
-			groups.add(item.getBusinessGroup());
+			groupKeys.add(item.getBusinessGroupKey());
 		}
+		List<BusinessGroup> groups = businessGroupService.loadBusinessGroups(groupKeys);
 		return groups;
 	}
 	
diff --git a/src/main/java/org/olat/group/ui/main/BGMarkCellRenderer.java b/src/main/java/org/olat/group/ui/main/BGMarkCellRenderer.java
index b14aa2f0ac9..561225a9d82 100644
--- a/src/main/java/org/olat/group/ui/main/BGMarkCellRenderer.java
+++ b/src/main/java/org/olat/group/ui/main/BGMarkCellRenderer.java
@@ -42,7 +42,7 @@ import org.olat.core.gui.translator.Translator;
 public class BGMarkCellRenderer implements CustomCellRenderer {
 	
 	private final Translator translator;
-	private VelocityContainer container;
+	private final VelocityContainer container;
 	private final Controller listeningController;
 	
 	public BGMarkCellRenderer(Controller listeningController, VelocityContainer container, Translator translator) {
diff --git a/src/main/java/org/olat/group/ui/main/BGResourcesCellRenderer.java b/src/main/java/org/olat/group/ui/main/BGResourcesCellRenderer.java
index ef5135de669..5aeb2e5baa1 100644
--- a/src/main/java/org/olat/group/ui/main/BGResourcesCellRenderer.java
+++ b/src/main/java/org/olat/group/ui/main/BGResourcesCellRenderer.java
@@ -33,8 +33,6 @@ import org.olat.core.gui.render.Renderer;
 import org.olat.core.gui.render.StringOutput;
 import org.olat.core.gui.render.URLBuilder;
 import org.olat.core.gui.translator.Translator;
-import org.olat.group.model.BGRepositoryEntryRelation;
-import org.olat.repository.RepositoryEntry;
 
 /**
  * 
@@ -61,15 +59,15 @@ public class BGResourcesCellRenderer implements CustomCellRenderer {
 	public void render(StringOutput sb, Renderer renderer, Object val, Locale locale, int alignment, String action) {
 		if(val instanceof BGTableItem) {
 			BGTableItem item = (BGTableItem)val;
-			List<RepositoryEntry> resources = item.getResources();
-			if(resources != null && !resources.isEmpty()) {
+			if (item.getRelations() != null && !item.getRelations().isEmpty()) {
+				List<RepositoryEntryShort> relations = item.getRelations();
 				int count = 0;
-				for(RepositoryEntry resource:resources) {
+				for(RepositoryEntryShort relation:relations) {
 					if(renderer == null) {//fxdiff: FXOLAT-267 for XSL export
 						if(sb.length() > 0) {
 							sb.append(", ");
 						}
-						sb.append(resource.getDisplayname());
+						sb.append(relation.getDisplayName());
 					} else if(count >= 2) {
 						Link link = LinkFactory.createLink("repo_entry_" + UUID.randomUUID().toString(), container, listeningController);
 						link.setCustomDisplayText("...");
@@ -81,37 +79,8 @@ public class BGResourcesCellRenderer implements CustomCellRenderer {
 						break;
 					} else {
 						Link link = LinkFactory.createLink("repo_entry_" + UUID.randomUUID().toString(), container, listeningController);
-						link.setCustomDisplayText(resource.getDisplayname());
-						link.setUserObject(resource.getKey());
-						
-						URLBuilder ubu = renderer.getUrlBuilder().createCopyFor(link);
-						RenderResult renderResult = new RenderResult();
-						link.getHTMLRendererSingleton().render(renderer, sb, link, ubu, translator, renderResult, null);
-						count++;
-					}
-				}
-			} else if (item.getRelations() != null && !item.getRelations().isEmpty()) {
-				List<BGRepositoryEntryRelation> relations = item.getRelations();
-				int count = 0;
-				for(BGRepositoryEntryRelation relation:relations) {
-					if(renderer == null) {//fxdiff: FXOLAT-267 for XSL export
-						if(sb.length() > 0) {
-							sb.append(", ");
-						}
-						sb.append(relation.getRepositoryEntryDisplayName());
-					} else if(count >= 2) {
-						Link link = LinkFactory.createLink("repo_entry_" + UUID.randomUUID().toString(), container, listeningController);
-						link.setCustomDisplayText("...");
-						link.setUserObject(item.getBusinessGroup());
-						
-						URLBuilder ubu = renderer.getUrlBuilder().createCopyFor(link);
-						RenderResult renderResult = new RenderResult();
-						link.getHTMLRendererSingleton().render(renderer, sb, link, ubu, translator, renderResult, null);
-						break;
-					} else {
-						Link link = LinkFactory.createLink("repo_entry_" + UUID.randomUUID().toString(), container, listeningController);
-						link.setCustomDisplayText(relation.getRepositoryEntryDisplayName());
-						link.setUserObject(relation.getRepositoryEntryKey());
+						link.setCustomDisplayText(relation.getDisplayName());
+						link.setUserObject(relation);
 						
 						URLBuilder ubu = renderer.getUrlBuilder().createCopyFor(link);
 						RenderResult renderResult = new RenderResult();
diff --git a/src/main/java/org/olat/group/ui/main/BGRoleCellRenderer.java b/src/main/java/org/olat/group/ui/main/BGRoleCellRenderer.java
index a12794723bf..f1c55efe155 100644
--- a/src/main/java/org/olat/group/ui/main/BGRoleCellRenderer.java
+++ b/src/main/java/org/olat/group/ui/main/BGRoleCellRenderer.java
@@ -37,7 +37,7 @@ public class BGRoleCellRenderer implements CustomCellRenderer {
 	private final Translator translator;
 	
 	public BGRoleCellRenderer(Locale locale) {
-		this.translator = Util.createPackageTranslator(BGRoleCellRenderer.class, locale);
+		translator = Util.createPackageTranslator(BGRoleCellRenderer.class, locale);
 	}
 
 	@Override
diff --git a/src/main/java/org/olat/group/ui/main/BGTableItem.java b/src/main/java/org/olat/group/ui/main/BGTableItem.java
index e089530a22a..dcbd5cc5a75 100644
--- a/src/main/java/org/olat/group/ui/main/BGTableItem.java
+++ b/src/main/java/org/olat/group/ui/main/BGTableItem.java
@@ -20,12 +20,13 @@
 package org.olat.group.ui.main;
 
 import java.util.ArrayList;
+import java.util.Date;
 import java.util.List;
 
 import org.olat.group.BusinessGroup;
+import org.olat.group.BusinessGroupShort;
 import org.olat.group.model.BGMembership;
 import org.olat.group.model.BGRepositoryEntryRelation;
-import org.olat.repository.RepositoryEntry;
 import org.olat.resource.accesscontrol.model.PriceMethodBundle;
 
 /**
@@ -42,13 +43,17 @@ public class BGTableItem {
 	private boolean marked;
 	private final Boolean allowLeave;
 	private final Boolean allowDelete;
-	private final BusinessGroup businessGroup;
-	private List<RepositoryEntry> resources;
-	private List<BGRepositoryEntryRelation> relations;
+	private final String businessGroupDescription;
+	private final Date businessGroupLastUsage;
+	
+	private final BusinessGroupShort businessGroup;
+	private List<RepositoryEntryShort> relations;
 	private List<PriceMethodBundle> access;
 	
 	public BGTableItem(BusinessGroup businessGroup, boolean marked, BGMembership member, Boolean allowLeave, Boolean allowDelete, List<PriceMethodBundle> access) {
-		this.businessGroup = businessGroup;
+		this.businessGroup = new BGShort(businessGroup);
+		this.businessGroupDescription = businessGroup.getDescription();
+		this.businessGroupLastUsage = businessGroup.getLastUsage();
 		this.marked = marked;
 		this.member = member;
 		this.allowLeave = allowLeave;
@@ -56,6 +61,22 @@ public class BGTableItem {
 		this.access = access;
 	}
 
+	public Long getBusinessGroupKey() {
+		return businessGroup.getKey();
+	}
+	
+	public String getBusinessGroupName() {
+		return businessGroup.getName();
+	}
+
+	public String getBusinessGroupDescription() {
+		return businessGroupDescription;
+	}
+
+	public Date getBusinessGroupLastUsage() {
+		return businessGroupLastUsage;
+	}
+
 	public boolean isMarked() {
 		return marked;
 	}
@@ -84,35 +105,23 @@ public class BGTableItem {
 		return allowDelete;
 	}
 
-	public BusinessGroup getBusinessGroup() {
+	public BusinessGroupShort getBusinessGroup() {
 		return businessGroup;
 	}
 	
-	public List<RepositoryEntry> getResources() {
-		return resources;
-	}
-
-	public void setResources(List<RepositoryEntry> resources) {
-		this.resources = resources;
-	}
-
-	public List<BGRepositoryEntryRelation> getRelations() {
+	public List<RepositoryEntryShort> getRelations() {
 		return relations;
 	}
-
-	public void setRelations(List<BGRepositoryEntryRelation> relations) {
-		this.relations = relations;
-	}
 	
 	/**
 	 * Give the item a list of relations, it found alone which are its own
 	 * @param resources
 	 */
 	public void setUnfilteredRelations(List<BGRepositoryEntryRelation> resources) {
-		relations = new ArrayList<BGRepositoryEntryRelation>();
+		relations = new ArrayList<RepositoryEntryShort>(3);
 		for(BGRepositoryEntryRelation resource:resources) {
 			if(businessGroup.getKey().equals(resource.getGroupKey())) {
-				relations.add(resource);
+				relations.add(new RepositoryEntryShort(resource));
 				if(relations.size() >= 3) {
 					return;
 				}
@@ -132,8 +141,55 @@ public class BGTableItem {
 		}
 		if(obj instanceof BGTableItem) {
 			BGTableItem item = (BGTableItem)obj;
-			return businessGroup != null && businessGroup.equalsByPersistableKey(item.businessGroup);
+			return businessGroup != null && businessGroup.equals(item.businessGroup);
 		}
 		return false;
 	}
+	
+	private static class BGShort implements BusinessGroupShort {
+		private final Long key;
+		private final String name;
+		
+		public BGShort(BusinessGroup group) {
+			this.key = group.getKey();
+			this.name = group.getName().intern();
+		}
+
+		@Override
+		public String getResourceableTypeName() {
+			return "BusinessGroup";
+		}
+
+		@Override
+		public Long getResourceableId() {
+			return key;
+		}
+
+		@Override
+		public Long getKey() {
+			return key;
+		}
+
+		@Override
+		public String getName() {
+			return name;
+		}
+
+		@Override
+		public int hashCode() {
+			return key.hashCode();
+		}
+
+		@Override
+		public boolean equals(Object obj) {
+			if(this == obj) {
+				return true;
+			}
+			if(obj instanceof BGShort) {
+				BGShort sh = (BGShort)obj;
+				return key != null && key.equals(sh.key);
+			}
+			return false;
+		}
+	}
 }
\ No newline at end of file
diff --git a/src/main/java/org/olat/group/ui/main/BusinessGroupMainController.java b/src/main/java/org/olat/group/ui/main/BusinessGroupMainController.java
index 6d3fa77e5c1..ab7e7d9ee9b 100644
--- a/src/main/java/org/olat/group/ui/main/BusinessGroupMainController.java
+++ b/src/main/java/org/olat/group/ui/main/BusinessGroupMainController.java
@@ -1,3 +1,22 @@
+/**
+ * <a href="http://www.openolat.org">
+ * OpenOLAT - Online Learning and Training</a><br>
+ * <p>
+ * Licensed under the Apache License, Version 2.0 (the "License"); <br>
+ * you may not use this file except in compliance with the License.<br>
+ * You may obtain a copy of the License at the
+ * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a>
+ * <p>
+ * Unless required by applicable law or agreed to in writing,<br>
+ * software distributed under the License is distributed on an "AS IS" BASIS, <br>
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br>
+ * See the License for the specific language governing permissions and <br>
+ * limitations under the License.
+ * <p>
+ * Initial code contributed and copyrighted by<br>
+ * frentix GmbH, http://www.frentix.com
+ * <p>
+ */
 package org.olat.group.ui.main;
 
 import java.util.List;
diff --git a/src/main/java/org/olat/group/ui/main/BusinessGroupSearchController.java b/src/main/java/org/olat/group/ui/main/BusinessGroupSearchController.java
index 21f3dbedd92..9580c070189 100644
--- a/src/main/java/org/olat/group/ui/main/BusinessGroupSearchController.java
+++ b/src/main/java/org/olat/group/ui/main/BusinessGroupSearchController.java
@@ -17,7 +17,6 @@
  * frentix GmbH, http://www.frentix.com
  * <p>
  */
-
 package org.olat.group.ui.main;
 
 import org.olat.core.gui.UserRequest;
diff --git a/src/main/java/org/olat/group/ui/main/BusinessGroupTableModelWithType.java b/src/main/java/org/olat/group/ui/main/BusinessGroupTableModelWithType.java
index fc298016fe2..bc8cbbbba08 100644
--- a/src/main/java/org/olat/group/ui/main/BusinessGroupTableModelWithType.java
+++ b/src/main/java/org/olat/group/ui/main/BusinessGroupTableModelWithType.java
@@ -39,6 +39,7 @@ import org.olat.group.BusinessGroupMembership;
 
 /**
  * @author gnaegi
+ * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
  */
 public class BusinessGroupTableModelWithType extends DefaultTableDataModel<BGTableItem> {
 	private final int columnCount;
@@ -52,7 +53,6 @@ public class BusinessGroupTableModelWithType extends DefaultTableDataModel<BGTab
 	public BusinessGroupTableModelWithType(Translator trans, int columnCount) {
 		super(new ArrayList<BGTableItem>());
 		this.trans = trans;
-		//fxdiff VCRP-1,2: access control of resources
 		this.columnCount = columnCount;
 	}
 
@@ -68,19 +68,16 @@ public class BusinessGroupTableModelWithType extends DefaultTableDataModel<BGTab
 	 */
 	public Object getValueAt(int row, int col) {
 		BGTableItem wrapped = (BGTableItem)objects.get(row);
-		BusinessGroup businessGroup = wrapped.getBusinessGroup();
 		switch (Cols.values()[col]) {
 			case name:
-				String name = businessGroup.getName();
+				String name = wrapped.getBusinessGroup().getName();
 				name = StringEscapeUtils.escapeHtml(name).toString();
 				return name;
 			case description:
-				String description = businessGroup.getDescription();
+				String description = wrapped.getBusinessGroupDescription();
 				description = FilterFactory.getHtmlTagsFilter().filter(description);
 				description = Formatter.truncate(description, 256);
 				return description;
-			case groupType:
-				return trans.translate(businessGroup.getType());
 			case allowLeave:
 				return wrapped.getAllowLeave();
 			case allowDelete:
@@ -103,18 +100,18 @@ public class BusinessGroupTableModelWithType extends DefaultTableDataModel<BGTab
 			case mark:
 				return new Boolean(wrapped.isMarked());
 			case lastUsage:
-				return wrapped.getBusinessGroup().getLastUsage();
+				return wrapped.getBusinessGroupLastUsage();
 			case role:
 				return wrapped.getMembership();
 			case firstTime:
 				if(memberships != null) {
-					BusinessGroupMembership membership = memberships.get(businessGroup.getKey());
+					BusinessGroupMembership membership = memberships.get(wrapped.getBusinessGroupKey());
 					return membership == null ? null : membership.getCreationDate();
 				}
 				return null;
 			case lastTime:
 				if(memberships != null) {
-					BusinessGroupMembership membership = memberships.get(businessGroup.getKey());
+					BusinessGroupMembership membership = memberships.get(wrapped.getBusinessGroupKey());
 					return membership == null ? null : membership.getLastModified();
 				}
 				return null;
@@ -136,20 +133,11 @@ public class BusinessGroupTableModelWithType extends DefaultTableDataModel<BGTab
 		setObjects(owned);
 		this.memberships = memberships;
 	}
-
-	/**
-	 * @param row
-	 * @return the business group at the given row
-	 */
-	public BusinessGroup getBusinessGroupAt(int row) {
-		BGTableItem wrapped = (BGTableItem)objects.get(row);
-		return wrapped.getBusinessGroup();
-	}
 	
 	public void removeBusinessGroup(BusinessGroup bg) {
 		for(int i=objects.size(); i-->0; ) {
 			BGTableItem wrapped = (BGTableItem)objects.get(i);
-			if(bg.equals(wrapped.getBusinessGroup())) {
+			if(bg.getKey().equals(wrapped.getBusinessGroupKey())) {
 				objects.remove(i);
 				return;
 			}
diff --git a/src/main/java/org/olat/group/ui/main/RepositoryEntryShort.java b/src/main/java/org/olat/group/ui/main/RepositoryEntryShort.java
new file mode 100644
index 00000000000..aa9f7ce018a
--- /dev/null
+++ b/src/main/java/org/olat/group/ui/main/RepositoryEntryShort.java
@@ -0,0 +1,69 @@
+/**
+ * <a href="http://www.openolat.org">
+ * OpenOLAT - Online Learning and Training</a><br>
+ * <p>
+ * Licensed under the Apache License, Version 2.0 (the "License"); <br>
+ * you may not use this file except in compliance with the License.<br>
+ * You may obtain a copy of the License at the
+ * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a>
+ * <p>
+ * Unless required by applicable law or agreed to in writing,<br>
+ * software distributed under the License is distributed on an "AS IS" BASIS, <br>
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br>
+ * See the License for the specific language governing permissions and <br>
+ * limitations under the License.
+ * <p>
+ * Initial code contributed and copyrighted by<br>
+ * frentix GmbH, http://www.frentix.com
+ * <p>
+ */
+package org.olat.group.ui.main;
+
+import org.olat.group.model.BGRepositoryEntryRelation;
+import org.olat.repository.RepositoryEntry;
+
+
+/**
+ * 
+ * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
+ */
+public class RepositoryEntryShort {
+	
+	private final Long key;
+	private final String displayName;
+	
+	public RepositoryEntryShort(RepositoryEntry re) {
+		this.key = re.getKey();
+		this.displayName = re.getDisplayname();
+	}
+	
+	public RepositoryEntryShort(BGRepositoryEntryRelation rel) {
+		this.key = rel.getRepositoryEntryKey();
+		this.displayName = rel.getRepositoryEntryDisplayName();
+	}
+
+	public Long getKey() {
+		return key;
+	}
+
+	public String getDisplayName() {
+		return displayName;
+	}
+
+	@Override
+	public int hashCode() {
+		return key.hashCode();
+	}
+
+	@Override
+	public boolean equals(Object obj) {
+		if(this == obj) {
+			return true;
+		}
+		if(obj instanceof RepositoryEntryShort) {
+			RepositoryEntryShort re = (RepositoryEntryShort)obj;
+			return key != null && key.equals(re.key);
+		}
+		return false;
+	}
+}
diff --git a/src/main/java/org/olat/group/ui/portlet/BusinessGroupEntry.java b/src/main/java/org/olat/group/ui/portlet/BusinessGroupEntry.java
new file mode 100644
index 00000000000..028ed69e0ad
--- /dev/null
+++ b/src/main/java/org/olat/group/ui/portlet/BusinessGroupEntry.java
@@ -0,0 +1,63 @@
+/**
+ * <a href="http://www.openolat.org">
+ * OpenOLAT - Online Learning and Training</a><br>
+ * <p>
+ * Licensed under the Apache License, Version 2.0 (the "License"); <br>
+ * you may not use this file except in compliance with the License.<br>
+ * You may obtain a copy of the License at the
+ * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a>
+ * <p>
+ * Unless required by applicable law or agreed to in writing,<br>
+ * software distributed under the License is distributed on an "AS IS" BASIS, <br>
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br>
+ * See the License for the specific language governing permissions and <br>
+ * limitations under the License.
+ * <p>
+ * Initial code contributed and copyrighted by<br>
+ * frentix GmbH, http://www.frentix.com
+ * <p>
+ */
+package org.olat.group.ui.portlet;
+
+import java.util.Date;
+
+import org.olat.group.BusinessGroup;
+
+/**
+ * Short version of group for the portlet
+ * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
+ */
+class BusinessGroupEntry {
+	
+	private final String name;
+	private String description;
+	private final Date creationDate;
+	
+	public BusinessGroupEntry(String name, Date creationDate) {
+		this.name = name.intern();
+		this.creationDate = creationDate;
+	}
+	
+	public BusinessGroupEntry(BusinessGroup group) {
+		this.name = group.getName().intern();
+		this.creationDate = group.getCreationDate();
+	}
+	
+	public String getName() {
+		return name;
+	}
+	
+	public String getDescription() {
+		return description;
+	}
+	
+	public void setDescription(String description) {
+		this.description = description;
+	}
+	
+
+	
+	public Date getCreationDate() {
+		return creationDate;
+	}
+}
diff --git a/src/main/java/org/olat/group/ui/portlet/GroupsPortletRunController.java b/src/main/java/org/olat/group/ui/portlet/GroupsPortletRunController.java
index 15085c2a3cf..098d91d1292 100644
--- a/src/main/java/org/olat/group/ui/portlet/GroupsPortletRunController.java
+++ b/src/main/java/org/olat/group/ui/portlet/GroupsPortletRunController.java
@@ -62,7 +62,6 @@ import org.olat.group.BusinessGroup;
 import org.olat.group.BusinessGroupOrder;
 import org.olat.group.BusinessGroupService;
 import org.olat.group.model.SearchBusinessGroupParams;
-import org.olat.group.ui.BGControllerFactory;
 import org.olat.group.ui.edit.BusinessGroupModifiedEvent;
 
 /**
@@ -73,7 +72,7 @@ import org.olat.group.ui.edit.BusinessGroupModifiedEvent;
  * 
  * @author gnaegi
  */
-public class GroupsPortletRunController extends AbstractPortletRunController<BusinessGroup> implements GenericEventListener {
+public class GroupsPortletRunController extends AbstractPortletRunController<BusinessGroupEntry> implements GenericEventListener {
 	
 	private static final String CMD_LAUNCH = "cmd.launch";
 
@@ -119,7 +118,7 @@ public class GroupsPortletRunController extends AbstractPortletRunController<Bus
 		tableCtr.addColumnDescriptor(new DefaultColumnDescriptor("groupsPortlet.bgname", 0, CMD_LAUNCH, trans.getLocale()));
 		
 		sortingCriteria = getPersistentSortingConfiguration(ureq);
-		groupListModel = new GroupTableDataModel(Collections.<PortletEntry<BusinessGroup>>emptyList());
+		groupListModel = new GroupTableDataModel(Collections.<PortletEntry<BusinessGroupEntry>>emptyList());
 		tableCtr.setTableDataModel(groupListModel);
 		reloadModel(sortingCriteria);
      
@@ -130,10 +129,14 @@ public class GroupsPortletRunController extends AbstractPortletRunController<Bus
 		CoordinatorManager.getInstance().getCoordinator().getEventBus().registerFor(this, ureq.getIdentity(), OresHelper.lookupType(BusinessGroup.class));
 	}
 	
-	private List<PortletEntry<BusinessGroup>> convertBusinessGroupToPortletEntryList(List<BusinessGroup> groups) {
-		List<PortletEntry<BusinessGroup>> convertedList = new ArrayList<PortletEntry<BusinessGroup>>();
+	private List<PortletEntry<BusinessGroupEntry>> convertBusinessGroupToPortletEntryList(List<BusinessGroup> groups, boolean withDescription) {
+		List<PortletEntry<BusinessGroupEntry>> convertedList = new ArrayList<PortletEntry<BusinessGroupEntry>>();
 		for(BusinessGroup group:groups) {
-			convertedList.add(new GroupPortletEntry(group));
+			GroupPortletEntry entry = new GroupPortletEntry(group);
+			if(withDescription) {
+				entry.getValue().setDescription(group.getDescription());
+			}
+			convertedList.add(entry);
 		}
 		return convertedList;
 	}
@@ -148,7 +151,7 @@ public class GroupsPortletRunController extends AbstractPortletRunController<Bus
 		  	order = sortingCriteria.isAscending() ? BusinessGroupOrder.creationDateAsc : BusinessGroupOrder.creationDateDesc;
 		  }
 			List<BusinessGroup> groupList = businessGroupService.findBusinessGroups(params, null, 0, sortingCriteria.getMaxEntries(), order);
-			List<PortletEntry<BusinessGroup>> entries = convertBusinessGroupToPortletEntryList(groupList);
+			List<PortletEntry<BusinessGroupEntry>> entries = convertBusinessGroupToPortletEntryList(groupList, false);
 			groupListModel.setObjects(entries);
 			tableCtr.modelChanged();
 		} else {
@@ -156,7 +159,7 @@ public class GroupsPortletRunController extends AbstractPortletRunController<Bus
 		}
 	}
 	
-	protected void reloadModel(List<PortletEntry<BusinessGroup>> sortedItems) {						
+	protected void reloadModel(List<PortletEntry<BusinessGroupEntry>> sortedItems) {						
 		groupListModel.setObjects(sortedItems);
 		tableCtr.modelChanged();
 	}
@@ -182,14 +185,8 @@ public class GroupsPortletRunController extends AbstractPortletRunController<Bus
 				TableEvent te = (TableEvent) event;
 				String actionid = te.getActionId();
 				if (actionid.equals(CMD_LAUNCH)) {
-					int rowid = te.getRowId();
-					BusinessGroup currBusinessGroup = groupListModel.getBusinessGroupAt(rowid);
-					boolean isInBusinessGroup = businessGroupService.isIdentityInBusinessGroup(ureq.getIdentity(), currBusinessGroup);
-					if(isInBusinessGroup) {
-					  BGControllerFactory.getInstance().createRunControllerAsTopNavTab(currBusinessGroup, ureq, getWindowControl());
-					} else {
-						showInfo("groupsPortlet.no_member");
-					}
+					PortletEntry<BusinessGroupEntry> entry = groupListModel.getObject(te.getRowId());
+					NewControllerFactory.getInstance().launch("[BusinessGroup:" + entry.getKey() + "]", ureq, getWindowControl());
 				}
 			}
 		}	
@@ -209,16 +206,15 @@ public class GroupsPortletRunController extends AbstractPortletRunController<Bus
 	public void event(Event event) {
 		if (event instanceof BusinessGroupModifiedEvent) {
 			BusinessGroupModifiedEvent mev = (BusinessGroupModifiedEvent) event;
-			if(getIdentity().getKey().equals(mev.getAffectedIdentityKey())) {
+			if(BusinessGroupModifiedEvent.IDENTITY_REMOVED_EVENT.equals(event.getCommand()) &&
+					getIdentity().getKey().equals(mev.getAffectedIdentityKey())) {
+				
 				Long modifiedKey = mev.getModifiedGroupKey();
-				for(PortletEntry<BusinessGroup> portlet:groupListModel.getObjects()) {
-					if(modifiedKey.equals(portlet.getKey())) {
-						GroupPortletEntry groupPortlet = (GroupPortletEntry)portlet;
-						if(BusinessGroupModifiedEvent.IDENTITY_REMOVED_EVENT.equals(event.getCommand())) {
-							groupListModel.getObjects().remove(groupPortlet);
-							tableCtr.modelChanged();
-							break;
-						}
+				for(PortletEntry<BusinessGroupEntry> portlet:groupListModel.getObjects()) {
+					if(modifiedKey.equals(portlet.getKey())) {;
+						groupListModel.getObjects().remove(portlet);
+						tableCtr.modelChanged();
+						break;
 					}
 				}
 			}
@@ -232,15 +228,15 @@ public class GroupsPortletRunController extends AbstractPortletRunController<Bus
 	 * @param wControl
 	 * @return a PortletToolSortingControllerImpl instance.
 	 */
-	protected PortletToolSortingControllerImpl<BusinessGroup> createSortingTool(UserRequest ureq, WindowControl wControl) {
+	protected PortletToolSortingControllerImpl<BusinessGroupEntry> createSortingTool(UserRequest ureq, WindowControl wControl) {
 		if(portletToolsController==null) {
 			SearchBusinessGroupParams params = new SearchBusinessGroupParams(getIdentity(), true, true);
 			List<BusinessGroup> groupList = businessGroupService.findBusinessGroups(params, null, 0, -1);
-			List<PortletEntry<BusinessGroup>> portletEntryList = convertBusinessGroupToPortletEntryList(groupList);
+			List<PortletEntry<BusinessGroupEntry>> portletEntryList = convertBusinessGroupToPortletEntryList(groupList, true);
 			GroupsManualSortingTableDataModel tableDataModel = new GroupsManualSortingTableDataModel(portletEntryList);
-			List<PortletEntry<BusinessGroup>> sortedItems = getPersistentManuallySortedItems();
+			List<PortletEntry<BusinessGroupEntry>> sortedItems = getPersistentManuallySortedItems();
 			
-			portletToolsController = new PortletToolSortingControllerImpl<BusinessGroup>(ureq, wControl, getTranslator(), sortingCriteria, tableDataModel, sortedItems);
+			portletToolsController = new PortletToolSortingControllerImpl<BusinessGroupEntry>(ureq, wControl, getTranslator(), sortingCriteria, tableDataModel, sortedItems);
 			portletToolsController.setConfigManualSorting(true);
 			portletToolsController.setConfigAutoSorting(true);
 			portletToolsController.addControllerListener(this);
@@ -253,14 +249,14 @@ public class GroupsPortletRunController extends AbstractPortletRunController<Bus
    * @param ureq
    * @return
    */
-  private List<PortletEntry<BusinessGroup>> getPersistentManuallySortedItems() { 
+  private List<PortletEntry<BusinessGroupEntry>> getPersistentManuallySortedItems() { 
   	@SuppressWarnings("unchecked")
 		Map<Long, Integer> storedPrefs = (Map<Long, Integer>)guiPreferences.get(Map.class, getPreferenceKey(SORTED_ITEMS_PREF));
   	
   	SearchBusinessGroupParams params = new SearchBusinessGroupParams(getIdentity(), true, true);
   	params.setGroupKeys(storedPrefs.keySet());
   	List<BusinessGroup> groups = businessGroupService.findBusinessGroups(params, null, 0, -1);
-  	List<PortletEntry<BusinessGroup>> portletEntryList = convertBusinessGroupToPortletEntryList(groups);
+  	List<PortletEntry<BusinessGroupEntry>> portletEntryList = convertBusinessGroupToPortletEntryList(groups, false);
 		return getPersistentManuallySortedItems(portletEntryList);
 	}
   
@@ -271,9 +267,9 @@ public class GroupsPortletRunController extends AbstractPortletRunController<Bus
 	 * @param sortingCriteria
 	 * @return a Comparator for the input sortingCriteria
 	 */
-  protected Comparator<BusinessGroup> getComparator(final SortingCriteria sortingCriteria) {
-		return new Comparator<BusinessGroup>(){			
-			public int compare(final BusinessGroup group1, final BusinessGroup group2) {
+  protected Comparator<BusinessGroupEntry> getComparator(final SortingCriteria sortingCriteria) {
+		return new Comparator<BusinessGroupEntry>(){			
+			public int compare(final BusinessGroupEntry group1, final BusinessGroupEntry group2) {
 				int comparisonResult = 0;
 			  if(sortingCriteria.getSortingTerm()==SortingCriteria.ALPHABETICAL_SORTING) {			  	
 			  	comparisonResult = collator.compare(group1.getName(), group2.getName());			  		  	
@@ -296,14 +292,14 @@ public class GroupsPortletRunController extends AbstractPortletRunController<Bus
    * Initial Date:  10.12.2007 <br>
    * @author Lavinia Dumitrescu
    */
-  private class GroupTableDataModel extends PortletDefaultTableDataModel<BusinessGroup> {  	
-  	public GroupTableDataModel(List<PortletEntry<BusinessGroup>> objects) {
+  private class GroupTableDataModel extends PortletDefaultTableDataModel<BusinessGroupEntry> {  	
+  	public GroupTableDataModel(List<PortletEntry<BusinessGroupEntry>> objects) {
   		super(objects, 1);
   	}
   	
   	public Object getValueAt(int row, int col) {
-  		PortletEntry<BusinessGroup> entry = getObject(row);
-  		BusinessGroup businessGroup = entry.getValue();
+  		PortletEntry<BusinessGroupEntry> entry = getObject(row);
+  		BusinessGroupEntry businessGroup = entry.getValue();
   		switch (col) {
   			case 0:
   				String name = businessGroup.getName();
@@ -313,10 +309,6 @@ public class GroupsPortletRunController extends AbstractPortletRunController<Bus
   				return "ERROR";
   		}
   	}
-  	
-  	public BusinessGroup getBusinessGroupAt(int row) {
-  		return getPortletValue(row);
-  	}
   }
 
   /**
@@ -327,12 +319,12 @@ public class GroupsPortletRunController extends AbstractPortletRunController<Bus
    * Initial Date:  10.12.2007 <br>
    * @author Lavinia Dumitrescu
    */
-	private class GroupsManualSortingTableDataModel extends PortletDefaultTableDataModel<BusinessGroup>  {		
+	private class GroupsManualSortingTableDataModel extends PortletDefaultTableDataModel<BusinessGroupEntry>  {		
 		/**
 		 * @param objects
 		 * @param locale
 		 */
-		public GroupsManualSortingTableDataModel(List<PortletEntry<BusinessGroup>> objects) {
+		public GroupsManualSortingTableDataModel(List<PortletEntry<BusinessGroupEntry>> objects) {
 			super(objects, 3);
 		}
 
@@ -340,8 +332,8 @@ public class GroupsPortletRunController extends AbstractPortletRunController<Bus
 		 * @see org.olat.core.gui.components.table.TableDataModel#getValueAt(int, int)
 		 */
 		public final Object getValueAt(int row, int col) {
-			PortletEntry<BusinessGroup> portletEntry = getObject(row);
-			BusinessGroup group = (BusinessGroup) portletEntry.getValue();
+			PortletEntry<BusinessGroupEntry> portletEntry = getObject(row);
+			BusinessGroupEntry group = portletEntry.getValue();
 			switch (col) {
 				case 0:
 					return group.getName();
@@ -358,12 +350,12 @@ public class GroupsPortletRunController extends AbstractPortletRunController<Bus
 		}	
 	}
 	
-	private class GroupPortletEntry implements PortletEntry<BusinessGroup> {
-	  	private BusinessGroup value;
+	private class GroupPortletEntry implements PortletEntry<BusinessGroupEntry> {
+	  	private BusinessGroupEntry value;
 	  	private Long key;
 	  	
 	  	public GroupPortletEntry(BusinessGroup group) {
-	  		value = group;
+	  		value = new BusinessGroupEntry(group);
 	  		key = group.getKey();
 	  	}
 	  	
@@ -371,7 +363,7 @@ public class GroupsPortletRunController extends AbstractPortletRunController<Bus
 	  		return key;
 	  	}
 	  	
-	  	public BusinessGroup getValue() {
+	  	public BusinessGroupEntry getValue() {
 	  		return value;
 	  	}
 	}
diff --git a/src/main/java/org/olat/group/ui/wizard/BGUserStatusCellRenderer.java b/src/main/java/org/olat/group/ui/wizard/BGUserStatusCellRenderer.java
index 01e12a25ec0..f4383bfd7c7 100644
--- a/src/main/java/org/olat/group/ui/wizard/BGUserStatusCellRenderer.java
+++ b/src/main/java/org/olat/group/ui/wizard/BGUserStatusCellRenderer.java
@@ -54,6 +54,8 @@ public class BGUserStatusCellRenderer implements CustomCellRenderer {
 				}
 				case removed: {
 					sb.append("-"); break;
+				} case current: {
+					break;
 				}
 			}
 			sb.append("</span></div>");
-- 
GitLab