diff --git a/src/main/java/org/olat/NewControllerFactory.java b/src/main/java/org/olat/NewControllerFactory.java
index d5c8aa14617136cb0cf1474e92b225a76504bc44..ad23f07a04ae4b0422881d11148c5cf13f9c500c 100644
--- a/src/main/java/org/olat/NewControllerFactory.java
+++ b/src/main/java/org/olat/NewControllerFactory.java
@@ -124,6 +124,18 @@ public class NewControllerFactory extends LogDelegator {
 		}
 		return false;
 	}
+	
+	/**
+	 * Launch a controller in a tab or a site with the business path
+	 * @param businessPath
+	 * @param ureq
+	 * @param origControl
+	 */
+	public void launch(String businessPath, UserRequest ureq, WindowControl origControl) {
+		BusinessControl bc = BusinessControlFactory.getInstance().createFromString(businessPath);
+	  WindowControl bwControl = BusinessControlFactory.getInstance().createBusinessWindowControl(bc, origControl);
+	  launch(ureq, bwControl);
+	}
 
 	/**
 	 * Launch a controller in a tab or site in the given window from a user
diff --git a/src/main/java/org/olat/commons/coordinate/cluster/jms/JmsTestSer.java b/src/main/java/org/olat/commons/coordinate/cluster/jms/JmsTestSer.java
index 5aa97eb2378e70f90ac948e2ff3b3bd6800df0a7..3a8c0b97fca8b37317f8d05361937b9b4a7f0b53 100644
--- a/src/main/java/org/olat/commons/coordinate/cluster/jms/JmsTestSer.java
+++ b/src/main/java/org/olat/commons/coordinate/cluster/jms/JmsTestSer.java
@@ -35,6 +35,7 @@ import org.olat.core.util.ObjectCloner;
 import org.olat.course.assessment.AssessmentChangedEvent;
 import org.olat.group.BusinessGroup;
 import org.olat.group.ui.edit.BusinessGroupModifiedEvent;
+import org.olat.resource.OLATResource;
 
 public class JmsTestSer {
 
@@ -153,6 +154,11 @@ public class JmsTestSer {
 			public String getName() {
 				return null;
 			}
+			
+			@Override
+			public OLATResource getResource() {
+				return null;
+			}
 
 			public SecurityGroup getOwnerGroup() {
 				return null;
diff --git a/src/main/java/org/olat/group/BusinessGroup.java b/src/main/java/org/olat/group/BusinessGroup.java
index ff9b280dace703108dd82b212bae7c04df892c1b..d1831350a6038df746f8b756b2785ca91fe88f66 100644
--- a/src/main/java/org/olat/group/BusinessGroup.java
+++ b/src/main/java/org/olat/group/BusinessGroup.java
@@ -32,6 +32,7 @@ import org.olat.core.id.CreateInfo;
 import org.olat.core.id.ModifiedInfo;
 import org.olat.core.id.OLATResourceable;
 import org.olat.core.id.Persistable;
+import org.olat.resource.OLATResource;
 
 /**
  * Initial Date: Aug 2, 2004
@@ -87,6 +88,8 @@ public interface BusinessGroup extends Persistable, CreateInfo, ModifiedInfo, OL
 	 * @param description the description of this group. Might be NULL
 	 */
 	public void setDescription(String description);
+	
+	public OLATResource getResource();
 
 	/**
 	 * The BusinessGroup has 1..n Owners acting as <i>administrators </i>.
diff --git a/src/main/java/org/olat/group/BusinessGroupContextEntryControllerCreator.java b/src/main/java/org/olat/group/BusinessGroupContextEntryControllerCreator.java
index 33be7acd36459ed3f3fb04a4ba1ee78815a8210a..cdcb9e2067f45e082b1025861954037f8622446d 100644
--- a/src/main/java/org/olat/group/BusinessGroupContextEntryControllerCreator.java
+++ b/src/main/java/org/olat/group/BusinessGroupContextEntryControllerCreator.java
@@ -29,8 +29,6 @@ import org.olat.core.id.OLATResourceable;
 import org.olat.core.id.context.ContextEntry;
 import org.olat.core.id.context.DefaultContextEntryControllerCreator;
 import org.olat.group.ui.BGControllerFactory;
-import org.olat.resource.OLATResource;
-import org.olat.resource.OLATResourceManager;
 import org.olat.resource.accesscontrol.AccessControlModule;
 import org.olat.resource.accesscontrol.manager.ACFrontendManager;
 
@@ -59,7 +57,8 @@ public class BusinessGroupContextEntryControllerCreator extends DefaultContextEn
 		Controller ctrl = null;
 		BusinessGroup bgroup = bgs.loadBusinessGroup(gKey);
 		if(bgroup != null) {
-			boolean isOlatAdmin = ureq.getUserSession().getRoles().isOLATAdmin();
+			boolean isOlatAdmin = ureq.getUserSession().getRoles().isOLATAdmin()
+					|| ureq.getUserSession().getRoles().isGroupManager();
 			// check if allowed to start (must be member or admin)
 			//fxdiff VCRP-1,2: access control of resources
 			if (isOlatAdmin || bgs.isIdentityInBusinessGroup(ureq.getIdentity(), bgroup) || isAccessControlled(bgroup)) {
@@ -87,22 +86,22 @@ public class BusinessGroupContextEntryControllerCreator extends DefaultContextEn
 		Long gKey = ores.getResourceableId();
 		BusinessGroupService bgs = CoreSpringFactory.getImpl(BusinessGroupService.class);
 		BusinessGroup bgroup = bgs.loadBusinessGroup(gKey);
-		if (bgroup != null){
-			return bgs.isIdentityInBusinessGroup(ureq.getIdentity(), bgroup) || isAccessControlled(bgroup);
-		}
-		return false;
+		if (bgroup == null) {
+			return false;
+		}	
+		return ureq.getUserSession().getRoles().isOLATAdmin() ||
+				ureq.getUserSession().getRoles().isGroupManager() ||
+				bgs.isIdentityInBusinessGroup(ureq.getIdentity(), bgroup) || isAccessControlled(bgroup);
 	}
 	
 	private boolean isAccessControlled(BusinessGroup bgroup) {
 		AccessControlModule acModule = (AccessControlModule)CoreSpringFactory.getBean("acModule");
 		if(acModule.isEnabled()) {
 			ACFrontendManager acFrontendManager = (ACFrontendManager)CoreSpringFactory.getBean("acFrontendManager");
-			OLATResource resource = OLATResourceManager.getInstance().findResourceable(bgroup);
-			if(acFrontendManager.isResourceAccessControled(resource, new Date())) {
+			if(acFrontendManager.isResourceAccessControled(bgroup.getResource(), new Date())) {
 				return true;
 			}
 		}
 		return false;
 	}
-
 }
diff --git a/src/main/java/org/olat/group/BusinessGroupImpl.hbm.xml b/src/main/java/org/olat/group/BusinessGroupImpl.hbm.xml
index 7f8e5052eb8e20e5f250e814cedfc2756075dc52..5de4089fde7f0343b3e1dfe7d5d7f5c27880d365 100644
--- a/src/main/java/org/olat/group/BusinessGroupImpl.hbm.xml
+++ b/src/main/java/org/olat/group/BusinessGroupImpl.hbm.xml
@@ -38,19 +38,11 @@
 		<property name="autoCloseRanksEnabled" type="boolean" column="autocloseranks_enabled" unique="false" not-null="false"/>	
 		
 		<property name="groupContextKey" type="long" column="groupcontext_fk" />	
-		
-		<!--
-		<many-to-one 
- 		   	name="groupContext" 
-    		class="org.olat.group.context.BGContextImpl"
-    		outer-join="true" 
-    		cascade="none">  
-			<column 
-				name="groupcontext_fk" 
-				not-null="false" 
-				unique="false" />    	
+
+		<many-to-one name="resource" class="org.olat.resource.OLATResourceImpl"
+    		outer-join="true" cascade="none" lazy="false">  
+			<column name="fk_resource" not-null="false" unique="true" />    	
     	</many-to-one> 
-    	-->
 
 		<!--
 		Implementation Note:
diff --git a/src/main/java/org/olat/group/BusinessGroupImpl.java b/src/main/java/org/olat/group/BusinessGroupImpl.java
index 6cc5e5d7a3c98e6f2a0384c097232f086eb7a540..7877bb52259d90e87f97a978610a2d363009e188 100644
--- a/src/main/java/org/olat/group/BusinessGroupImpl.java
+++ b/src/main/java/org/olat/group/BusinessGroupImpl.java
@@ -33,6 +33,7 @@ import org.olat.core.logging.AssertException;
 import org.olat.core.logging.OLog;
 import org.olat.core.logging.Tracing;
 import org.olat.core.util.resource.OresHelper;
+import org.olat.resource.OLATResource;
 
 /**
  * Description: <br>
@@ -53,6 +54,7 @@ public class BusinessGroupImpl extends PersistentObject implements BusinessGroup
 	private String type;
 	private Integer minParticipants;
 	private Integer maxParticipants;
+	private OLATResource resource;
 	private SecurityGroup ownerGroup;
 	private SecurityGroup partipiciantGroup;
 	private SecurityGroup waitingGroup;
@@ -99,14 +101,14 @@ public class BusinessGroupImpl extends PersistentObject implements BusinessGroup
 	/**
 	 * @param partipiciantGroupP
 	 */
-	private void setPartipiciantGroup(SecurityGroup partipiciantGroupP) {
+	public void setPartipiciantGroup(SecurityGroup partipiciantGroupP) {
 		this.partipiciantGroup = partipiciantGroupP;
 	}
 
 	/**
 	 * @param ownerGroupP
 	 */
-	private void setOwnerGroup(SecurityGroup ownerGroupP) {
+	public void setOwnerGroup(SecurityGroup ownerGroupP) {
 		this.ownerGroup = ownerGroupP;
 	}
 
@@ -139,6 +141,14 @@ public class BusinessGroupImpl extends PersistentObject implements BusinessGroup
 		return this.name;
 	}
 
+	public OLATResource getResource() {
+		return resource;
+	}
+
+	public void setResource(OLATResource resource) {
+		this.resource = resource;
+	}
+
 	/**
 	 * @see org.olat.group.BusinessGroup#getOwnerGroup()
 	 */
diff --git a/src/main/java/org/olat/group/BusinessGroupService.java b/src/main/java/org/olat/group/BusinessGroupService.java
index 835786ae10562f8522ca94ea2c2e8829c4e2a88b..79985afe65c6eeeeffed0554d72b3531b7a8384e 100644
--- a/src/main/java/org/olat/group/BusinessGroupService.java
+++ b/src/main/java/org/olat/group/BusinessGroupService.java
@@ -33,6 +33,7 @@ import org.olat.core.util.mail.MailTemplate;
 import org.olat.core.util.mail.MailerResult;
 import org.olat.group.area.BGArea;
 import org.olat.group.model.AddToGroupsEvent;
+import org.olat.group.model.BGRepositoryEntryRelation;
 import org.olat.group.model.DisplayMembers;
 import org.olat.group.model.SearchBusinessGroupParams;
 import org.olat.group.ui.BGConfigFlags;
@@ -130,6 +131,8 @@ public interface BusinessGroupService {
 	
 	public List<RepositoryEntry> findRepositoryEntries(Collection<BusinessGroup> groups, int firstResult, int maxResults);
 	
+	public List<BGRepositoryEntryRelation> findRelationToRepositoryEntries(Collection<BusinessGroup> groups, int firstResult, int maxResults);
+	
 	public List<OLATResource> findResources(Collection<BusinessGroup> groups, int firstResult, int maxResults);
 	
 	
@@ -181,6 +184,8 @@ public interface BusinessGroupService {
 	
 	//security
 	public boolean isIdentityInBusinessGroup(Identity identity, BusinessGroup businessGroup);
+	
+	public List<Long> isIdentityInBusinessGroups(Identity identity, List<BusinessGroup> businessGroups);
 	/**
 	 * 
 	 * @param identity
diff --git a/src/main/java/org/olat/group/manager/BusinessGroupDAO.java b/src/main/java/org/olat/group/manager/BusinessGroupDAO.java
index 85074f816695b764eba4703dd4ce425916c48590..51a5ffbdc5b8b795331ddbf2db483f0519ad5d56 100644
--- a/src/main/java/org/olat/group/manager/BusinessGroupDAO.java
+++ b/src/main/java/org/olat/group/manager/BusinessGroupDAO.java
@@ -19,6 +19,7 @@
  */
 package org.olat.group.manager;
 
+import java.util.ArrayList;
 import java.util.Calendar;
 import java.util.Collection;
 import java.util.Collections;
@@ -105,6 +106,8 @@ public class BusinessGroupDAO {
 		 */
 		OLATResource businessgroupOlatResource =  olatResourceManager.createOLATResourceInstance(businessgroup);
 		olatResourceManager.saveOLATResource(businessgroupOlatResource);
+		businessgroup.setResource(businessgroupOlatResource);
+		em.merge(businessgroup);
 
 		//		securityManager.createAndPersistPolicy(ownerGroup, Constants.PERMISSION_ACCESS, businessgroup);
 		securityManager.createAndPersistPolicyWithResource(ownerGroup, Constants.PERMISSION_ACCESS, businessgroupOlatResource);
@@ -133,9 +136,10 @@ public class BusinessGroupDAO {
 		}
 		StringBuilder sb = new StringBuilder();
 		sb.append("select bgi from ").append(BusinessGroupImpl.class.getName()).append(" bgi ")
-			.append(" left join fetch bgi.ownerGroup ownerGroup")
-			.append(" left join fetch bgi.partipiciantGroup participantGroup")
-			.append(" left join fetch bgi.waitingGroup waitingGroup")
+			.append(" inner join fetch bgi.ownerGroup ownerGroup")
+			.append(" inner join fetch bgi.partipiciantGroup participantGroup")
+			.append(" inner join fetch bgi.waitingGroup waitingGroup")
+			.append(" inner join fetch bgi.resource resource")
 		  .append(" where bgi.key in (:ids)");
 
 		List<BusinessGroup> groups = dbInstance.getCurrentEntityManager()
@@ -148,9 +152,10 @@ public class BusinessGroupDAO {
 	public List<BusinessGroup> loadAll() {
 		StringBuilder sb = new StringBuilder();
 		sb.append("select bgi from ").append(BusinessGroupImpl.class.getName()).append(" bgi ")
-			.append(" left join fetch bgi.ownerGroup ownerGroup")
-			.append(" left join fetch bgi.partipiciantGroup participantGroup")
-			.append(" left join fetch bgi.waitingGroup waitingGroup");
+			.append(" inner join fetch bgi.ownerGroup ownerGroup")
+			.append(" inner join fetch bgi.partipiciantGroup participantGroup")
+			.append(" inner join fetch bgi.waitingGroup waitingGroup")
+			.append(" inner join fetch bgi.resource resource");
 
 		List<BusinessGroup> groups = dbInstance.getCurrentEntityManager()
 				.createQuery(sb.toString(), BusinessGroup.class)
@@ -256,6 +261,50 @@ public class BusinessGroupDAO {
 		return group;
 	}
 	
+
+	public List<Long> isIdentityInBusinessGroups(Identity identity, boolean owner, boolean attendee, List<BusinessGroup> groups) {
+		if(groups == null || groups.isEmpty() || (!owner && !attendee)) {
+			return Collections.emptyList();
+		}
+		
+		StringBuilder sb = new StringBuilder(); 
+		sb.append("select bgi.key from ").append(BusinessGroupImpl.class.getName()).append(" as bgi ");
+		if(owner && attendee) {
+			sb.append(" left join bgi.ownerGroup ownerGroup");
+			sb.append(" left join bgi.partipiciantGroup participantGroup");
+		} else if(owner) {
+			sb.append(" inner join bgi.ownerGroup ownerGroup");
+		} else if(attendee) {
+			sb.append(" inner join bgi.partipiciantGroup participantGroup");
+		}
+		sb.append(" where bgi.key in (:groupKeys) and (");
+
+		boolean or = false;
+		if(owner) {
+			or = or(sb, or);
+			sb.append("ownerGroup.key in (select ownerMemberShip.securityGroup.key from ").append(SecurityGroupMembershipImpl.class.getName()).append(" ownerMemberShip ")
+				.append(" where ownerMemberShip.identity.key=:identId ")
+				 .append(")");
+		}
+		if(attendee) {
+			or = or(sb, or);
+			sb.append(" participantGroup.key in (select partMembership.securityGroup.key from ").append(SecurityGroupMembershipImpl.class.getName()).append(" as partMembership ")
+				.append("  where partMembership.identity.key=:identId")
+				.append(" )");
+		}
+		sb.append(")");
+
+		List<Long> groupKeys = new ArrayList<Long>();
+		for(BusinessGroup group:groups) {
+			groupKeys.add(group.getKey());
+		}
+		List<Long> res = dbInstance.getCurrentEntityManager().createQuery(sb.toString(), Long.class)
+				.setParameter("groupKeys", groupKeys)
+				.setParameter("identId", identity.getKey())
+				.getResultList();
+		return res;
+	}
+	
 	
 	public BusinessGroup findBusinessGroup(SecurityGroup secGroup) {
 		StringBuilder sb = new StringBuilder(); 
@@ -263,6 +312,7 @@ public class BusinessGroupDAO {
 			.append(" left join fetch bgi.ownerGroup ownerGroup")
 			.append(" left join fetch bgi.partipiciantGroup participantGroup")
 			.append(" left join fetch bgi.waitingGroup waitingGroup")
+			.append(" inner join fetch bgi.resource resource")
 			.append(" where (bgi.partipiciantGroup=:secGroup or bgi.ownerGroup=:secGroup or bgi.waitingGroup=:secGroup)");
 
 		List<BusinessGroup> res = dbInstance.getCurrentEntityManager().createQuery(sb.toString(), BusinessGroup.class)
@@ -278,15 +328,17 @@ public class BusinessGroupDAO {
 		if(resource == null) {
 			sb.append("select bgs from ").append(BusinessGroupImpl.class.getName()).append(" as bgs ")
 		    .append(" inner join fetch bgs.waitingGroup waitingList ")
-			  .append(" left join fetch bgs.ownerGroup ownerGroup ")
-			  .append(" left join fetch bgs.partipiciantGroup participantGroup ")
+			  .append(" inner join fetch bgs.ownerGroup ownerGroup ")
+			  .append(" inner join fetch bgs.partipiciantGroup participantGroup ")
+				.append(" inner join fetch bgs.resource bgResource")
 		    .append(" where ");
 		} else {
 			sb.append("select bgs from ").append(BGResourceRelation.class.getName()).append(" as rel ")
 			  .append(" inner join rel.group bgs ")
 			  .append(" inner join fetch bgs.waitingGroup waitingList ")
-			  .append(" left join fetch bgs.ownerGroup ownerGroup ")
-			  .append(" left join fetch bgs.partipiciantGroup participantGroup ")
+			  .append(" inner join fetch bgs.ownerGroup ownerGroup ")
+			  .append(" inner join fetch bgs.partipiciantGroup participantGroup ")
+				.append(" inner join fetch bgs.resource bgResource")
 		    .append(" where rel.resource.key=:resourceKey and ");
 		}
 		sb.append(" waitingList in (select memberShip.securityGroup from ").append(SecurityGroupMembershipImpl.class.getName()).append(" memberShip ")
@@ -339,13 +391,14 @@ public class BusinessGroupDAO {
 		}
 		//inner joins
 		if(BusinessGroup.class.equals(resultClass)) {
-			query.append("left join fetch bgi.ownerGroup ownerGroup ");
-			query.append("left join fetch bgi.partipiciantGroup participantGroup ");
-			query.append("left join fetch bgi.waitingGroup waitingGroup ");
+			query.append("inner join fetch bgi.ownerGroup ownerGroup ")
+			     .append("inner join fetch bgi.partipiciantGroup participantGroup ")
+			     .append("inner join fetch bgi.waitingGroup waitingGroup ")
+			     .append("inner join fetch bgi.resource bgResource ");
 		} else {
-			query.append("left join bgi.ownerGroup ownerGroup ");
-			query.append("left join bgi.partipiciantGroup participantGroup ");
-			query.append("left join bgi.waitingGroup waitingGroup ");
+			query.append("inner join bgi.ownerGroup ownerGroup ");
+			query.append("inner join bgi.partipiciantGroup participantGroup ");
+			query.append("inner join bgi.waitingGroup waitingGroup ");
 		}
 
 		boolean where = false;
@@ -566,5 +619,9 @@ public class BusinessGroupDAO {
 		}
 		return true;
 	}
-
+	
+	private boolean or(StringBuilder sb, boolean or) {
+		if(or) sb.append(" or ");
+		return true;
+	}
 }
diff --git a/src/main/java/org/olat/group/manager/BusinessGroupRelationDAO.java b/src/main/java/org/olat/group/manager/BusinessGroupRelationDAO.java
index 4dc4e1ef1db58f142a170623d8301e040c4a9c2d..535af1a1e5edf6a5f58d0f0f34db525a4e08fb80 100644
--- a/src/main/java/org/olat/group/manager/BusinessGroupRelationDAO.java
+++ b/src/main/java/org/olat/group/manager/BusinessGroupRelationDAO.java
@@ -33,6 +33,7 @@ import org.olat.core.commons.persistence.DB;
 import org.olat.core.id.Identity;
 import org.olat.group.BusinessGroup;
 import org.olat.group.BusinessGroupImpl;
+import org.olat.group.model.BGRepositoryEntryRelation;
 import org.olat.group.model.BGResourceRelation;
 import org.olat.repository.RepositoryEntry;
 import org.olat.resource.OLATResource;
@@ -201,7 +202,7 @@ public class BusinessGroupRelationDAO {
 	public int countResources(BusinessGroup group) {
 		if(group == null) return 0;
 		StringBuilder sb = new StringBuilder();
-		sb.append("select count(bgcr) from ").append(BGResourceRelation.class.getName()).append(" bgcr where bgcr.group.key=:groupKeys");
+		sb.append("select count(bgcr) from ").append(BGResourceRelation.class.getName()).append(" bgcr where bgcr.group.key=:groupKey");
 		
 		Number count = dbInstance.getCurrentEntityManager().createQuery(sb.toString(), Number.class)
 				.setParameter("groupKey", group.getKey())
@@ -259,4 +260,27 @@ public class BusinessGroupRelationDAO {
 		query.setParameter("groupKeys", groupKeys);
 		return query.getResultList();
 	}
+	
+	public List<BGRepositoryEntryRelation> findRelationToRepositoryEntries(Collection<BusinessGroup> groups, int firstResult, int maxResults) {
+		if(groups == null || groups.isEmpty()) {
+			return Collections.emptyList();
+		}
+
+		StringBuilder sb = new StringBuilder();
+		sb.append("select rel from ").append(BGRepositoryEntryRelation.class.getName()).append(" as rel ")
+			.append(" where rel.groupKey in (:groupKeys)");
+
+		TypedQuery<BGRepositoryEntryRelation> query = dbInstance.getCurrentEntityManager().createQuery(sb.toString(), BGRepositoryEntryRelation.class);
+		query.setFirstResult(firstResult);
+		if(maxResults > 0) {
+			query.setMaxResults(maxResults);
+		}
+		
+		List<Long> groupKeys = new ArrayList<Long>();
+		for(BusinessGroup group:groups) {
+			groupKeys.add(group.getKey());
+		}
+		query.setParameter("groupKeys", groupKeys);
+		return query.getResultList();
+	}
 }
diff --git a/src/main/java/org/olat/group/manager/BusinessGroupServiceImpl.java b/src/main/java/org/olat/group/manager/BusinessGroupServiceImpl.java
index f3c01c15e9459137e55522d18ecbd76a08293954..ef1a87c141e2e72349f027859b45b002284030a8 100644
--- a/src/main/java/org/olat/group/manager/BusinessGroupServiceImpl.java
+++ b/src/main/java/org/olat/group/manager/BusinessGroupServiceImpl.java
@@ -71,6 +71,7 @@ import org.olat.group.GroupLoggingAction;
 import org.olat.group.area.BGArea;
 import org.olat.group.area.BGAreaManager;
 import org.olat.group.model.AddToGroupsEvent;
+import org.olat.group.model.BGRepositoryEntryRelation;
 import org.olat.group.model.DisplayMembers;
 import org.olat.group.model.SearchBusinessGroupParams;
 import org.olat.group.right.BGRightManager;
@@ -1086,6 +1087,11 @@ public class BusinessGroupServiceImpl implements BusinessGroupService {
 	public List<RepositoryEntry> findRepositoryEntries(Collection<BusinessGroup> groups, int firstResult, int maxResults) {
 		return businessGroupRelationDAO.findRepositoryEntries(groups, firstResult, maxResults);
 	}
+	
+	@Override
+	public List<BGRepositoryEntryRelation> findRelationToRepositoryEntries(Collection<BusinessGroup> groups, int firstResult, int maxResults) {
+		return businessGroupRelationDAO.findRelationToRepositoryEntries(groups, firstResult, maxResults);
+	}
 
 	@Override
 	@Transactional(readOnly=true)
@@ -1101,6 +1107,11 @@ public class BusinessGroupServiceImpl implements BusinessGroupService {
 		return false;
 	}
 
+	@Override
+	public List<Long> isIdentityInBusinessGroups(Identity identity, List<BusinessGroup> groups) {
+		return businessGroupDAO.isIdentityInBusinessGroups(identity, true, true, groups);
+	}
+
 	@Override
 	@Transactional(readOnly=true)
 	public boolean isIdentityInBusinessGroup(Identity identity, String groupName,
diff --git a/src/main/java/org/olat/group/model/BGRepositoryEntryRelation.java b/src/main/java/org/olat/group/model/BGRepositoryEntryRelation.java
new file mode 100644
index 0000000000000000000000000000000000000000..fc772feba4cc1126f790221e07bf19a5790a0ed4
--- /dev/null
+++ b/src/main/java/org/olat/group/model/BGRepositoryEntryRelation.java
@@ -0,0 +1,82 @@
+/**
+ * <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.model;
+
+import java.io.Serializable;
+
+/**
+ * 
+ * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
+ */
+public class BGRepositoryEntryRelation implements Serializable {
+
+	private static final long serialVersionUID = -589388325515371455L;
+	
+	private Long groupKey;
+	private Long repositoryEntryKey;
+	private String repositoryEntryDisplayName;
+	
+	public BGRepositoryEntryRelation() {
+		//
+	}
+	
+	public Long getGroupKey() {
+		return groupKey;
+	}
+	
+	public void setGroupKey(Long groupKey) {
+		this.groupKey = groupKey;
+	}
+	
+	public Long getRepositoryEntryKey() {
+		return repositoryEntryKey;
+	}
+	
+	public void setRepositoryEntryKey(Long repositoryEntryKey) {
+		this.repositoryEntryKey = repositoryEntryKey;
+	}
+	
+	public String getRepositoryEntryDisplayName() {
+		return repositoryEntryDisplayName;
+	}
+	
+	public void setRepositoryEntryDisplayName(String repositoryEntryDisplayName) {
+		this.repositoryEntryDisplayName = repositoryEntryDisplayName;
+	}
+	
+	@Override
+	public int hashCode() {
+		return (groupKey == null ? 8934 : groupKey.hashCode()) +
+				(repositoryEntryKey == null ? 8934 : repositoryEntryKey.hashCode());
+	}
+	
+	@Override
+	public boolean equals(Object obj) {
+		if(this == obj) {
+			return true;
+		}
+		if(obj instanceof BGRepositoryEntryRelation) {
+			BGRepositoryEntryRelation rel = (BGRepositoryEntryRelation)obj;
+			return groupKey != null && groupKey.equals(rel.groupKey)
+					&& repositoryEntryKey != null && repositoryEntryKey.equals(rel.repositoryEntryKey);
+		}
+		return false;
+	}
+}
\ No newline at end of file
diff --git a/src/main/java/org/olat/group/model/BGResourceRelation.hbm.xml b/src/main/java/org/olat/group/model/BGResourceRelation.hbm.xml
index 0f48ca769a237daeb3c9bd010048eff9780bbae9..c8bfcb7290822453837d6d6f8dc93f833c2439e7 100644
--- a/src/main/java/org/olat/group/model/BGResourceRelation.hbm.xml
+++ b/src/main/java/org/olat/group/model/BGResourceRelation.hbm.xml
@@ -25,4 +25,13 @@
     	</many-to-one>
 			  	
 	</class>
+	
+	<class name="org.olat.group.model.BGRepositoryEntryRelation" table="o_gp_business_to_repository_v" mutable="false">
+		<composite-id>
+			<key-property name="groupKey" column="grp_id" type="long" />
+			<key-property name="repositoryEntryKey" column="re_id" type="long" />
+		</composite-id>
+  		<property name="repositoryEntryDisplayName" column="re_displayname" />	  	
+	</class>
+	
 </hibernate-mapping>
\ No newline at end of file
diff --git a/src/main/java/org/olat/group/ui/main/BGAccessControlledCellRenderer.java b/src/main/java/org/olat/group/ui/main/BGAccessControlledCellRenderer.java
index f09675cc6276b18a313c9c23b2cce33692efdf97..2b4900308bbebc97ab4dbe5ecb6cb7f7ea4d9604 100644
--- a/src/main/java/org/olat/group/ui/main/BGAccessControlledCellRenderer.java
+++ b/src/main/java/org/olat/group/ui/main/BGAccessControlledCellRenderer.java
@@ -26,7 +26,6 @@ import java.util.Locale;
 import org.olat.core.gui.components.table.CustomCellRenderer;
 import org.olat.core.gui.render.Renderer;
 import org.olat.core.gui.render.StringOutput;
-import org.olat.resource.accesscontrol.model.OLATResourceAccess;
 import org.olat.resource.accesscontrol.model.Price;
 import org.olat.resource.accesscontrol.model.PriceMethodBundle;
 import org.olat.resource.accesscontrol.ui.PriceFormat;
diff --git a/src/main/java/org/olat/group/ui/main/BGMainController.java b/src/main/java/org/olat/group/ui/main/BGMainController.java
index 9f6eb205a3c1cb4102023f1352953da761e7a705..d4aae9bd7b04ea1797c6d7192463d207a7f9df75 100644
--- a/src/main/java/org/olat/group/ui/main/BGMainController.java
+++ b/src/main/java/org/olat/group/ui/main/BGMainController.java
@@ -161,6 +161,7 @@ public class BGMainController extends MainLayoutBasicController implements Activ
 	private Link searchOpenLink;
 	private SegmentViewComponent segmentView;
 	private BGSearchController searchController;
+	private BusinessGroupListController groupsCtr;
 
 	// group list table rows
 	private static final String TABLE_ACTION_LEAVE = "bgTblLeave";
@@ -169,6 +170,7 @@ public class BGMainController extends MainLayoutBasicController implements Activ
 	//fxdiff VCRP-1,2: access control of resources
 	private static final String TABLE_ACTION_ACCESS = "bgTblAccess";
 	private static final String CMD_MENU_INDEX = "cmd.menu.index";
+	private static final String CMD_MENU_LIST = "cmd.menu.list";
 	//fxdiff VCRP-1,2: access control of resources
 	private static final String CMD_MENU_OPEN = "cmd.menu.open";
 	private static final String CMD_MENU_OPEN_SEARCH = "cmd.menu.open.search";
@@ -282,6 +284,8 @@ public class BGMainController extends MainLayoutBasicController implements Activ
 			doOpenGroupList(ureq, getWindowControl());
 		} else if (userObject.equals(CMD_MENU_OPEN_SEARCH)) {
 			doSearchOpenGroupList(ureq, getWindowControl());
+		} else if (userObject.equals(CMD_MENU_LIST)) {
+			doList(ureq, getWindowControl());
 		}
 	}
 
@@ -525,6 +529,16 @@ public class BGMainController extends MainLayoutBasicController implements Activ
 		ThreadLocalUserActivityLogger.log(GroupLoggingAction.GROUP_CREATED, getClass());
 		return newGroup;
 	}
+	
+	private void doList(UserRequest ureq, WindowControl wControl) {
+		if(groupsCtr == null) {
+			groupsCtr = new BusinessGroupListController(ureq, wControl);
+			listenTo(groupsCtr);
+		}
+
+		columnLayoutCtr.setCol3(groupsCtr.getInitialComponent());
+		columnLayoutCtr.hideCol2(false);
+	}
 
 	/**
 	 * Prepare everything and show all groups
@@ -540,6 +554,7 @@ public class BGMainController extends MainLayoutBasicController implements Activ
 		// 3) set correct page
 		main.setPage(Util.getPackageVelocityRoot(this.getClass()) + "/index.html");
 		// 4) update toolboxe
+		columnLayoutCtr.setCol3(main);
 		columnLayoutCtr.hideCol2(false);
 		//fxdiff BAKS-7 Resume function
 		OLATResourceable ores = OresHelper.createOLATResourceableInstance(CMD_MENU_INDEX, 0l);
@@ -570,6 +585,7 @@ public class BGMainController extends MainLayoutBasicController implements Activ
 		}
 
 		// 4) update toolboxe
+		columnLayoutCtr.setCol3(main);
 		columnLayoutCtr.hideCol2(true);
 		//fxdiff BAKS-7 Resume function
 		OLATResourceable ores = OresHelper.createOLATResourceableInstance(CMD_MENU_OPEN, 0l);
@@ -598,6 +614,7 @@ public class BGMainController extends MainLayoutBasicController implements Activ
 		}
 
 		// 4) update toolboxe
+		columnLayoutCtr.setCol3(main);
 		columnLayoutCtr.hideCol2(true);
 		
 		//fxdiff BAKS-7 Resume function
@@ -719,7 +736,7 @@ public class BGMainController extends MainLayoutBasicController implements Activ
 		for(BusinessGroup group:groups) {
 			OLATResource ores = OLATResourceManager.getInstance().findResourceable(group);
 			resourceKeys.put(group.getKey(), ores.getKey());
-			if(businessGroupService.isIdentityInBusinessGroup(this.getIdentity(), group)) {
+			if(businessGroupService.isIdentityInBusinessGroup(getIdentity(), group)) {
 				membership.add(group.getKey());
 			}
 		}
@@ -778,7 +795,12 @@ public class BGMainController extends MainLayoutBasicController implements Activ
 		myEntriesTn.setUserObject(CMD_MENU_INDEX);
 		myEntriesTn.setAltText(translate("menu.learninggroups.alt"));
 		rootNode.addChild(myEntriesTn);
-		rootNode.setDelegate(myEntriesTn);
+		
+		GenericTreeNode listEntriesTn = new GenericTreeNode();
+		listEntriesTn.setTitle(translate("menu.groups"));
+		listEntriesTn.setUserObject(CMD_MENU_LIST);
+		listEntriesTn.setAltText(translate("menu.groups.alt"));
+		rootNode.addChild(listEntriesTn);
 
 		//fxdiff VCRP-1,2: access control of resources
 		myEntriesTn = new GenericTreeNode();
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 2949d4d2c464cd70a132c8f5ec25f7a8c84d1689..ef5135de669dbc3efa302849bcbfed0b18b8e6c1 100644
--- a/src/main/java/org/olat/group/ui/main/BGResourcesCellRenderer.java
+++ b/src/main/java/org/olat/group/ui/main/BGResourcesCellRenderer.java
@@ -27,11 +27,13 @@ import org.olat.core.gui.components.link.Link;
 import org.olat.core.gui.components.link.LinkFactory;
 import org.olat.core.gui.components.table.CustomCellRenderer;
 import org.olat.core.gui.components.velocity.VelocityContainer;
+import org.olat.core.gui.control.Controller;
 import org.olat.core.gui.render.RenderResult;
 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;
 
 /**
@@ -47,9 +49,9 @@ public class BGResourcesCellRenderer implements CustomCellRenderer {
 	
 	private final Translator translator;
 	private VelocityContainer container;
-	private final BGMainController listeningController;
+	private final Controller listeningController;
 	
-	public BGResourcesCellRenderer(BGMainController listeningController, VelocityContainer container, Translator translator) {
+	public BGResourcesCellRenderer(Controller listeningController, VelocityContainer container, Translator translator) {
 		this.listeningController = listeningController;
 		this.container = container;
 		this.translator = translator;
@@ -60,35 +62,62 @@ public class BGResourcesCellRenderer implements CustomCellRenderer {
 		if(val instanceof BGTableItem) {
 			BGTableItem item = (BGTableItem)val;
 			List<RepositoryEntry> resources = item.getResources();
-			if(resources == null || resources.isEmpty()) {
-				return;
-			}
-			
-			int count = 0;
-			for(RepositoryEntry resource:resources) {
-				if(renderer == null) {//fxdiff: FXOLAT-267 for XSL export
-					if(sb.length() > 0) {
-						sb.append(", ");
+			if(resources != null && !resources.isEmpty()) {
+				int count = 0;
+				for(RepositoryEntry resource:resources) {
+					if(renderer == null) {//fxdiff: FXOLAT-267 for XSL export
+						if(sb.length() > 0) {
+							sb.append(", ");
+						}
+						sb.append(resource.getDisplayname());
+					} 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(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());
+						
+						URLBuilder ubu = renderer.getUrlBuilder().createCopyFor(link);
+						RenderResult renderResult = new RenderResult();
+						link.getHTMLRendererSingleton().render(renderer, sb, link, ubu, translator, renderResult, null);
+						count++;
 					}
-					sb.append(resource.getDisplayname());
-				} 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(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++;
 				}
 			}
 		}
diff --git a/src/main/java/org/olat/group/ui/main/BGSearchController.java b/src/main/java/org/olat/group/ui/main/BGSearchController.java
index c62a4862db907a1910c869961701acca2befeaad..5a6060ac450acb9315115d3a1a744fe6e23ba91e 100644
--- a/src/main/java/org/olat/group/ui/main/BGSearchController.java
+++ b/src/main/java/org/olat/group/ui/main/BGSearchController.java
@@ -24,6 +24,7 @@ import org.olat.core.gui.UserRequest;
 import org.olat.core.gui.components.form.flexible.FormItem;
 import org.olat.core.gui.components.form.flexible.FormItemContainer;
 import org.olat.core.gui.components.form.flexible.elements.FormLink;
+import org.olat.core.gui.components.form.flexible.elements.MultipleSelectionElement;
 import org.olat.core.gui.components.form.flexible.elements.TextElement;
 import org.olat.core.gui.components.form.flexible.impl.FormBasicController;
 import org.olat.core.gui.components.form.flexible.impl.FormEvent;
@@ -50,6 +51,9 @@ public class BGSearchController extends FormBasicController{
 	private TextElement owner;
 	private TextElement description;
 	private FormLink searchButton;
+	private MultipleSelectionElement attendeeEl;
+	private MultipleSelectionElement ownerEl;
+	private MultipleSelectionElement waitingEl;
 	
 	private String limitUsername;
 	private boolean isAdmin;
@@ -68,24 +72,49 @@ public class BGSearchController extends FormBasicController{
 		initForm(ureq);
 	}
 	
+	public BGSearchController(UserRequest ureq, WindowControl wControl, boolean isAdmin, boolean extended) {
+		super(ureq, wControl, "group_search");
+		this.isAdmin = isAdmin;
+		initForm(ureq);
+	}
+	
 	@Override
 	protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) {
-		displayName = uifactory.addTextElement("cif_displayname", "cif.displayname", 255, "", formLayout);
+		FormLayoutContainer leftContainer = FormLayoutContainer.createDefaultFormLayout("left_1", getTranslator());
+		leftContainer.setRootForm(mainForm);
+		formLayout.add(leftContainer);
+
+		displayName = uifactory.addTextElement("cif_displayname", "cif.displayname", 255, "", leftContainer);
 		displayName.setFocus(true);
 		
-		owner = uifactory.addTextElement("cif_owner", "cif.owner", 255, "", formLayout);
+		owner = uifactory.addTextElement("cif_owner", "cif.owner", 255, "", leftContainer);
 		if (limitUsername != null) {
 			owner.setValue(limitUsername);
 			owner.setEnabled(false);
 		}
-		description = uifactory.addTextElement("cif_description", "cif.description", 255, "", formLayout);
+		description = uifactory.addTextElement("cif_description", "cif.description", 255, "", leftContainer);
 		
 		if(isAdmin) {
-			id = uifactory.addTextElement("cif_id", "cif.id", 12, "", formLayout);
+			id = uifactory.addTextElement("cif_id", "cif.id", 12, "", leftContainer);
 			id.setVisible(isAdmin);
 			id.setRegexMatchCheck("\\d*", "search.id.format");
 		}
 		
+		FormLayoutContainer rightContainer = FormLayoutContainer.createDefaultFormLayout("right_1", getTranslator());
+		rightContainer.setRootForm(mainForm);
+		formLayout.add(rightContainer);
+
+		String[] ownerValues = new String[]{ translate("search.owner") };
+		ownerEl = uifactory.addCheckboxesVertical("search.owner", rightContainer, new String[]{"owner"}, ownerValues, null, 1);
+		
+		String[] attendeeValues = new String[]{ translate("search.attendee") };
+		attendeeEl = uifactory.addCheckboxesVertical("search.attendee", rightContainer, new String[]{"attendee"}, attendeeValues, null, 1);
+		
+		String[] waitingValues = new String[]{ translate("search.waiting") };
+		waitingEl = uifactory.addCheckboxesVertical("search.waiting", rightContainer, new String[]{"waiting"}, waitingValues, null, 1);
+		
+		
+		
 		FormLayoutContainer buttonLayout = FormLayoutContainer.createButtonLayout("button_layout", getTranslator());
 		formLayout.add(buttonLayout);
 		searchButton = uifactory.addFormLink("search", buttonLayout, Link.BUTTON);
@@ -101,7 +130,12 @@ public class BGSearchController extends FormBasicController{
 	 */
 	public Long getId() {
 		if (id != null && !id.isEmpty()) {
-			return new Long(id.getValue());
+			try {
+				return new Long(id.getValue());
+			} catch (NumberFormatException e) {
+				id.setValue("");
+				return null;
+			}
 		}
 		return null;
 	}
@@ -161,7 +195,16 @@ public class BGSearchController extends FormBasicController{
 	@Override
 	protected void formInnerEvent (UserRequest ureq, FormItem source, FormEvent event) {
 		if (source == searchButton) {
-			fireEvent (ureq, Event.DONE_EVENT); 
+			SearchEvent e = new SearchEvent();
+			e.setId(getId());
+			e.setName(getName());
+			e.setDescription(getDescription());
+			e.setOwnerName(getOwner());
+			e.setOwner(ownerEl.isAtLeastSelected(1));
+			e.setAttendee(attendeeEl.isAtLeastSelected(1));
+			e.setWaiting(waitingEl.isAtLeastSelected(1));
+			fireEvent(ureq, e);
+			fireEvent(ureq, Event.DONE_EVENT);
 		}
 	}
 }
\ No newline at end of file
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 ba08b7c66abdfa30d059762a640a4cb85a0b86e2..dd767dfcb8e3b05d934cbce2140514ed6de1f99b 100644
--- a/src/main/java/org/olat/group/ui/main/BGTableItem.java
+++ b/src/main/java/org/olat/group/ui/main/BGTableItem.java
@@ -19,12 +19,11 @@
  */
 package org.olat.group.ui.main;
 
-import java.util.ArrayList;
 import java.util.List;
 
 import org.olat.group.BusinessGroup;
+import org.olat.group.model.BGRepositoryEntryRelation;
 import org.olat.repository.RepositoryEntry;
-import org.olat.resource.accesscontrol.model.OLATResourceAccess;
 import org.olat.resource.accesscontrol.model.PriceMethodBundle;
 
 /**
@@ -43,6 +42,7 @@ public class BGTableItem {
 	private final Boolean allowDelete;
 	private final BusinessGroup businessGroup;
 	private List<RepositoryEntry> resources;
+	private List<BGRepositoryEntryRelation> relations;
 	private List<PriceMethodBundle> access;
 	
 	public BGTableItem(BusinessGroup businessGroup, boolean member, Boolean allowLeave, Boolean allowDelete,
@@ -92,6 +92,14 @@ public class BGTableItem {
 		this.resources = resources;
 	}
 
+	public List<BGRepositoryEntryRelation> getRelations() {
+		return relations;
+	}
+
+	public void setRelations(List<BGRepositoryEntryRelation> relations) {
+		this.relations = relations;
+	}
+
 	@Override
 	public int hashCode() {
 		return businessGroup.getKey().hashCode();
diff --git a/src/main/java/org/olat/group/ui/main/BusinessGroupListController.java b/src/main/java/org/olat/group/ui/main/BusinessGroupListController.java
new file mode 100644
index 0000000000000000000000000000000000000000..cc5e219c409012f9d7274279ce7a999aa4abf12f
--- /dev/null
+++ b/src/main/java/org/olat/group/ui/main/BusinessGroupListController.java
@@ -0,0 +1,301 @@
+package org.olat.group.ui.main;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Date;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.olat.NewControllerFactory;
+import org.olat.basesecurity.BaseSecurity;
+import org.olat.core.CoreSpringFactory;
+import org.olat.core.gui.UserRequest;
+import org.olat.core.gui.components.Component;
+import org.olat.core.gui.components.link.Link;
+import org.olat.core.gui.components.table.BooleanColumnDescriptor;
+import org.olat.core.gui.components.table.ColumnDescriptor;
+import org.olat.core.gui.components.table.CustomCellRenderer;
+import org.olat.core.gui.components.table.CustomRenderColumnDescriptor;
+import org.olat.core.gui.components.table.DefaultColumnDescriptor;
+import org.olat.core.gui.components.table.Table;
+import org.olat.core.gui.components.table.TableController;
+import org.olat.core.gui.components.table.TableEvent;
+import org.olat.core.gui.components.table.TableGuiConfiguration;
+import org.olat.core.gui.components.velocity.VelocityContainer;
+import org.olat.core.gui.control.Controller;
+import org.olat.core.gui.control.Event;
+import org.olat.core.gui.control.WindowControl;
+import org.olat.core.gui.control.controller.BasicController;
+import org.olat.core.gui.control.generic.modal.DialogBoxController;
+import org.olat.core.gui.control.generic.modal.DialogBoxUIFactory;
+import org.olat.core.id.Identity;
+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.StringHelper;
+import org.olat.group.BusinessGroup;
+import org.olat.group.BusinessGroupService;
+import org.olat.group.GroupLoggingAction;
+import org.olat.group.model.BGRepositoryEntryRelation;
+import org.olat.group.model.SearchBusinessGroupParams;
+import org.olat.group.ui.BGConfigFlags;
+import org.olat.resource.accesscontrol.manager.ACFrontendManager;
+import org.olat.resource.accesscontrol.model.OLATResourceAccess;
+import org.olat.resource.accesscontrol.model.PriceMethodBundle;
+import org.olat.util.logging.activity.LoggingResourceable;
+
+/**
+ * 
+ * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
+ */
+public class BusinessGroupListController extends BasicController {
+	private static final String TABLE_ACTION_LEAVE = "bgTblLeave";
+	private static final String TABLE_ACTION_DELETE = "bgTblDelete";
+	private static final String TABLE_ACTION_LAUNCH = "bgTblLaunch";
+	private static final String TABLE_ACTION_ACCESS = "bgTblAccess";
+	
+	private final VelocityContainer mainVC;
+	private final TableController groupListCtr;
+	private final BGSearchController searchController;
+	private BusinessGroupTableModelWithType groupListModel;
+	
+	private DialogBoxController deleteDialogBox;
+	private DialogBoxController sendEMailOnDeleteDialogBox;
+	private DialogBoxController leaveDialogBox;
+	
+	private final boolean admin;
+	private final BaseSecurity securityManager;
+	private final ACFrontendManager acFrontendManager;
+	private final BusinessGroupService businessGroupService;
+	
+	public BusinessGroupListController(UserRequest ureq, WindowControl wControl) {
+		super(ureq, wControl);
+		
+		admin = ureq.getUserSession().getRoles().isOLATAdmin() || ureq.getUserSession().getRoles().isGroupManager();
+		businessGroupService = CoreSpringFactory.getImpl(BusinessGroupService.class);
+		acFrontendManager = CoreSpringFactory.getImpl(ACFrontendManager.class);
+		securityManager = CoreSpringFactory.getImpl(BaseSecurity.class);
+		
+		mainVC = createVelocityContainer("group_list");
+		//search controller
+		searchController = new BGSearchController(ureq, wControl, admin, true);
+		listenTo(searchController);
+		
+		//table
+		TableGuiConfiguration tableConfig = new TableGuiConfiguration();
+		tableConfig.setPreferencesOffered(true, "group.list");
+		tableConfig.setTableEmptyMessage(translate("open.nogroup"));			
+		groupListCtr = new TableController(tableConfig, ureq, getWindowControl(), getTranslator(), false);
+		listenTo(groupListCtr);
+
+		CustomCellRenderer acRenderer = new BGAccessControlledCellRenderer();
+		groupListCtr.addColumnDescriptor(new CustomRenderColumnDescriptor("table.header.ac", 8, null, getLocale(), ColumnDescriptor.ALIGNMENT_LEFT, acRenderer));
+		groupListCtr.addColumnDescriptor(new DefaultColumnDescriptor("table.header.bgname", 0, TABLE_ACTION_LAUNCH, getLocale()));
+		groupListCtr.addColumnDescriptor(false, new DefaultColumnDescriptor("table.header.description", 1, null, getLocale()));
+		CustomCellRenderer resourcesRenderer = new BGResourcesCellRenderer(this, mainVC, getTranslator());
+		groupListCtr.addColumnDescriptor(false, new CustomRenderColumnDescriptor("table.header.resources", 5, null, getLocale(),  ColumnDescriptor.ALIGNMENT_LEFT, resourcesRenderer));
+		groupListCtr.addColumnDescriptor(false, new BooleanColumnDescriptor("table.header.leave", 3, TABLE_ACTION_LEAVE, translate("table.header.leave"), null));
+		if(admin) {
+			groupListCtr.addColumnDescriptor(false, new BooleanColumnDescriptor("table.header.delete", 4, TABLE_ACTION_DELETE, translate("table.header.delete"), null));
+		}
+		groupListCtr.addColumnDescriptor(false, new DefaultColumnDescriptor("table.header.ac", 7, TABLE_ACTION_ACCESS, getLocale()));
+
+		groupListModel = new BusinessGroupTableModelWithType(new ArrayList<BGTableItem>(), getTranslator(), 7);
+		groupListCtr.setTableDataModel(groupListModel);
+
+		mainVC.put("searchPanel", searchController.getInitialComponent());
+		mainVC.put("groupList", groupListCtr.getInitialComponent());
+		putInitialPanel(mainVC);
+	}
+	
+	@Override
+	protected void doDispose() {
+		//
+	}
+	
+	@Override
+	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);
+			}
+		}
+	}
+
+	@Override
+	protected void event(UserRequest ureq, Controller source, Event event) {
+		if(source == searchController) {
+			if(event instanceof SearchEvent) {
+				doSearch((SearchEvent)event);
+			}
+		} else if (source == groupListCtr) {
+			if (event.getCommand().equals(Table.COMMANDLINK_ROWACTION_CLICKED)) {
+				TableEvent te = (TableEvent) event;
+				String actionid = te.getActionId();
+
+				BusinessGroup businessGroup = groupListModel.getObject(te.getRowId()).getBusinessGroup();
+				businessGroup = businessGroupService.loadBusinessGroup(businessGroup);
+				//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() + "]";
+					NewControllerFactory.getInstance().launch(businessPath, ureq, getWindowControl());
+				} else if (actionid.equals(TABLE_ACTION_DELETE)) {
+					deleteDialogBox = activateYesNoDialog(ureq, null, translate("dialog.modal.bg.delete.text", businessGroup.getName()), deleteDialogBox);
+					deleteDialogBox.setUserObject(businessGroup);
+				} else if(actionid.equals(TABLE_ACTION_LEAVE)) {
+					leaveDialogBox = activateYesNoDialog(ureq, null, translate("dialog.modal.bg.leave.text", businessGroup.getName()), leaveDialogBox);
+					leaveDialogBox.setUserObject(businessGroup);
+				} else if (actionid.equals(TABLE_ACTION_ACCESS)) {
+					//handleAccess(ureq);
+				}
+			}
+		} else if (source == deleteDialogBox) {
+			if (DialogBoxUIFactory.isOkEvent(event)) {
+				sendEMailOnDeleteDialogBox = activateYesNoDialog(ureq, null, translate("dialog.modal.bg.mail.text"), sendEMailOnDeleteDialogBox);
+				sendEMailOnDeleteDialogBox.setUserObject(deleteDialogBox.getUserObject());
+			}//else cancel was clicked or box closed
+		} else if(source == sendEMailOnDeleteDialogBox){
+			boolean withEmail = DialogBoxUIFactory.isOkEvent(event);
+			doGroupDelete(ureq, withEmail, (BusinessGroup)sendEMailOnDeleteDialogBox.getUserObject());
+		} else if (source == leaveDialogBox) {
+			if (event != Event.CANCELLED_EVENT && DialogBoxUIFactory.isYesEvent(event)) {
+				doGroupLeave(ureq, (BusinessGroup)leaveDialogBox.getUserObject());
+			}
+		}
+		super.event(ureq, source, event);
+	}
+	
+	/**
+	 * Removes user from the group as owner and participant. If
+	 * no other owner are found the user won't be removed from the owner group
+	 * 
+	 * @param ureq
+	 */
+	private void doGroupLeave(UserRequest ureq, BusinessGroup group) {
+		BGConfigFlags flags = BGConfigFlags.createGroupDefaultFlags();
+		// 1) remove as owner
+		if (securityManager.isIdentityInSecurityGroup(getIdentity(), group.getOwnerGroup())) {
+			List<Identity> ownerList = securityManager.getIdentitiesOfSecurityGroup(group.getOwnerGroup());
+			if (ownerList.size() > 1) {
+				businessGroupService.removeOwners(ureq.getIdentity(), Collections.singletonList(getIdentity()), group, flags);
+			} else {
+				// he is the last owner, but there must be at least one oner
+				// give him a warning, as long as he tries to leave, he gets
+				// this warning.
+				getWindowControl().setError(translate("msg.atleastone"));
+				return;
+			}
+		}
+		// if identity was also owner it must have successfully removed to end here.
+		// now remove the identity also as participant.
+		// 2) remove as participant
+		List<Identity> identities = Collections.singletonList(getIdentity());
+		businessGroupService.removeParticipants(ureq.getIdentity(), identities, group, flags);
+	}
+	
+	/**
+	 * Deletes the group. Checks if user is in owner group,
+	 * otherwhise does nothing
+	 * 
+	 * @param ureq
+	 * @param doSendMail specifies if notification mails should be sent to users of delted group
+	 */
+	private void doGroupDelete(UserRequest ureq, boolean doSendMail, BusinessGroup group) {
+		// 1) send notification mails to users
+		boolean ow = securityManager.isIdentityInSecurityGroup(getIdentity(), group.getOwnerGroup());
+		// check if user is in owner group (could fake link in table)
+		if (!admin && !ow) {
+			logWarn("User tried to delete a group but he was not owner of the group", null);
+			return;
+		}
+
+		if (doSendMail) {
+			String businessPath = getWindowControl().getBusinessControl().getAsString();
+			businessGroupService.deleteBusinessGroupWithMail(group, businessPath, getIdentity(), getLocale());
+		} else {
+			businessGroupService.deleteBusinessGroup(group);
+		}
+		// do Logging
+		ThreadLocalUserActivityLogger.log(GroupLoggingAction.GROUP_DELETED, getClass(), LoggingResourceable.wrap(group));
+		// 4) update Tables
+		showInfo("info.group.deleted");
+	}
+	
+	private void doSearch(SearchEvent event) {
+		List<BGTableItem> items = search(event);
+		groupListModel.setEntries(items);
+		groupListCtr.modelChanged();
+	}
+
+	private List<BGTableItem> search(SearchEvent event) {
+		Long id = event.getId();
+		String name = event.getName();
+		String description = event.getDescription();
+		String owner = event.getOwnerName();
+		
+		SearchBusinessGroupParams params = new SearchBusinessGroupParams();
+		params.setKey(id);
+		params.setName(StringHelper.containsNonWhitespace(name) ? name : null);
+		params.setDescription(StringHelper.containsNonWhitespace(description) ? description : null);
+		params.setOwner(StringHelper.containsNonWhitespace(owner) ? owner : null);
+		
+		Identity me = null;
+		if(event.isAttendee() || event.isOwner()) {
+			me = getIdentity();
+		}
+		List<BusinessGroup> groups = businessGroupService.findBusinessGroups(params, me, event.isOwner(), event.isAttendee(), null, 0, -1);
+		
+		List<Long> groupsWithMembership = businessGroupService.isIdentityInBusinessGroups(getIdentity(), groups);
+		Set<Long> memberships = new HashSet<Long>(groupsWithMembership);
+
+		List<Long> resourceKeys = new ArrayList<Long>();
+		for(BusinessGroup group:groups) {
+			resourceKeys.add(group.getResource().getKey());
+		}
+		List<BGRepositoryEntryRelation> resources = businessGroupService.findRelationToRepositoryEntries(groups, 0, -1);
+		List<OLATResourceAccess> resourcesWithAC = acFrontendManager.getAccessMethodForResources(resourceKeys, true, new Date());
+		
+		List<BGTableItem> items = new ArrayList<BGTableItem>();
+		for(BusinessGroup group:groups) {
+			Long oresKey = group.getResource().getKey();
+			List<PriceMethodBundle> accessMethods = null;
+			for(OLATResourceAccess access:resourcesWithAC) {
+				if(oresKey.equals(access.getResource().getKey())){
+					accessMethods = access.getMethods();
+					break;
+				}
+			}
+			
+			Boolean allowLeave =  memberships.contains(group.getKey()) ? Boolean.TRUE : null;
+			Boolean allowDelete = admin ? Boolean.TRUE : null;
+			boolean accessControl = (accessMethods != null);
+			boolean member = memberships.contains(group.getKey());
+			List<BGRepositoryEntryRelation> relations = new ArrayList<BGRepositoryEntryRelation>();
+			for(BGRepositoryEntryRelation resource:resources) {
+				if(group.getKey().equals(resource.getGroupKey())) {
+					relations.add(resource);
+					if(relations.size() >= 3) {
+						break;
+					}
+				}
+			}
+			BGTableItem tableItem = new BGTableItem(group, member, allowLeave, allowDelete, accessControl, accessMethods);
+			tableItem.setRelations(relations);
+			items.add(tableItem);
+		}
+		return items;
+	}
+}
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 c2aa075ae9a1e68c1ea44b425b1d99d7951a2366..eb98612664e3ca250f81943bff1d5e15fe3b7474 100644
--- a/src/main/java/org/olat/group/ui/main/BusinessGroupTableModelWithType.java
+++ b/src/main/java/org/olat/group/ui/main/BusinessGroupTableModelWithType.java
@@ -30,7 +30,6 @@ import java.util.List;
 
 import org.apache.commons.lang.StringEscapeUtils;
 import org.olat.core.gui.components.table.DefaultTableDataModel;
-import org.olat.core.gui.components.table.TableDataModel;
 import org.olat.core.gui.translator.Translator;
 import org.olat.core.util.Formatter;
 import org.olat.core.util.filter.FilterFactory;
@@ -39,7 +38,7 @@ import org.olat.group.BusinessGroup;
 /**
  * @author gnaegi
  */
-public class BusinessGroupTableModelWithType extends DefaultTableDataModel implements TableDataModel {
+public class BusinessGroupTableModelWithType extends DefaultTableDataModel<BGTableItem> {
 	private final int columnCount;
 	private Translator trans;
 
@@ -88,11 +87,13 @@ public class BusinessGroupTableModelWithType extends DefaultTableDataModel imple
 			case 6:
 				return new Boolean(wrapped.isAccessControl());
 			case 7:
-				if(wrapped.isMember()) return trans.translate("select");
-				return trans.translate("table.access");
+				if(wrapped.isAccessControl()) {
+					if(wrapped.isMember()) return trans.translate("select");
+					return trans.translate("table.access");
+				}
+				return null;
 			case 8:
 				return wrapped.getAccessTypes();
-				
 			default:
 				return "ERROR";
 		}
diff --git a/src/main/java/org/olat/group/ui/main/SearchEvent.java b/src/main/java/org/olat/group/ui/main/SearchEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..905bc602d971d104d86c67355a75d301b502a0e7
--- /dev/null
+++ b/src/main/java/org/olat/group/ui/main/SearchEvent.java
@@ -0,0 +1,82 @@
+package org.olat.group.ui.main;
+
+import org.olat.core.gui.control.Event;
+
+/**
+ * 
+ * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
+ */
+public class SearchEvent extends Event {
+
+	private static final long serialVersionUID = 6630250536374073143L;
+	
+	private Long id;
+	private String name;
+	private String description;
+	private String ownerName;
+	private boolean owner;
+	private boolean attendee;
+	private boolean waiting;
+	
+	public SearchEvent() {
+		super("search");
+	}
+
+	public Long getId() {
+		return id;
+	}
+
+	public void setId(Long id) {
+		this.id = id;
+	}
+
+	public String getName() {
+		return name;
+	}
+
+	public void setName(String name) {
+		this.name = name;
+	}
+
+	public String getDescription() {
+		return description;
+	}
+
+	public void setDescription(String description) {
+		this.description = description;
+	}
+
+	public String getOwnerName() {
+		return ownerName;
+	}
+
+	public void setOwnerName(String owner) {
+		this.ownerName = owner;
+	}
+
+	public boolean isOwner() {
+		return owner;
+	}
+
+	public void setOwner(boolean owner) {
+		this.owner = owner;
+	}
+
+	public boolean isAttendee() {
+		return attendee;
+	}
+
+	public void setAttendee(boolean attendee) {
+		this.attendee = attendee;
+	}
+
+	public boolean isWaiting() {
+		return waiting;
+	}
+
+	public void setWaiting(boolean waiting) {
+		this.waiting = waiting;
+	}
+	
+	
+}
diff --git a/src/main/java/org/olat/group/ui/main/_content/group_list.html b/src/main/java/org/olat/group/ui/main/_content/group_list.html
new file mode 100644
index 0000000000000000000000000000000000000000..8cefec8737fe767e476eb21b64c3bc5f7c262ebd
--- /dev/null
+++ b/src/main/java/org/olat/group/ui/main/_content/group_list.html
@@ -0,0 +1,6 @@
+<h4 class="b_with_small_icon_left b_group_icon">
+	$r.translate("index.header")
+</h4>
+$r.render("searchPanel")
+<p />
+$r.render("groupList")
diff --git a/src/main/java/org/olat/group/ui/main/_content/group_search.html b/src/main/java/org/olat/group/ui/main/_content/group_search.html
new file mode 100644
index 0000000000000000000000000000000000000000..970e9bd7ff1b36eb17a044ef12dd3e2d4c3f5a39
--- /dev/null
+++ b/src/main/java/org/olat/group/ui/main/_content/group_search.html
@@ -0,0 +1,13 @@
+<div class="b_clearfix">
+	<div class="b_c50l">
+		<div class="b_subcl">
+			$r.render("left_1")
+			$r.render("button_layout")
+		</div>
+	</div>
+	<div class="b_c50r">
+		<div class="b_subcr">	
+			$r.render("right_1")
+		</div>
+	</div>
+</div>
\ No newline at end of file
diff --git a/src/main/java/org/olat/group/ui/main/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/group/ui/main/_i18n/LocalStrings_de.properties
index cf8ffe603a37aa58fe847b0f2707c6c9f6b641e0..b4cc5dba783dec8ad1e3f535401374758d90b058 100644
--- a/src/main/java/org/olat/group/ui/main/_i18n/LocalStrings_de.properties
+++ b/src/main/java/org/olat/group/ui/main/_i18n/LocalStrings_de.properties
@@ -17,6 +17,8 @@ menu.index=Gruppen
 menu.index.alt=Arbeiten Sie mit Ihren Gruppen
 menu.learninggroups=Meine Lerngruppen
 menu.learninggroups.alt=Arbeiten Sie mit Ihren Lerngruppen
+menu.groups=Gruppen
+menu.groups.alt=Arbeiten Sie mit Ihen Gruppen
 menu.rightgroups=Meine Rechtegruppen
 menu.rightgroups.alt=Arbeiten Sie mit Ihren Rechtegruppen
 menu.opengroups=Ver\u00F6ffentlichte Gruppen
@@ -32,6 +34,10 @@ opengroups.search=Suchmaske
 search.header=Gruppe
 search.intro=In Gruppe suchen
 search.generic=Suchmaske
+search.attendee=Attendee
+search.owner=Owner
+search.waiting=Waiting
+
 cif.displayname=Name
 cif.description=Beschreibung
 cif.owner=Besitzer
diff --git a/src/main/java/org/olat/repository/RepositoryManager.java b/src/main/java/org/olat/repository/RepositoryManager.java
index f0d1ba57b1d50d721979cf36fd68bd3add8ba342..4550387b63977e87fb827f611d1401e8558a57a8 100644
--- a/src/main/java/org/olat/repository/RepositoryManager.java
+++ b/src/main/java/org/olat/repository/RepositoryManager.java
@@ -233,6 +233,18 @@ public class RepositoryManager extends BasicManager {
 		re.setParticipantGroup(participantGroup);
 	}
 	
+	public void createOwnerSecurityGroup(RepositoryEntry re) {
+		if(re.getOwnerGroup() != null) return;
+		
+		SecurityGroup ownerGroup = securityManager.createAndPersistSecurityGroup();
+		// member of this group may modify member's membership
+		securityManager.createAndPersistPolicy(ownerGroup, Constants.PERMISSION_ACCESS, ownerGroup);
+		// members of this group are always authors also
+		securityManager.createAndPersistPolicy(ownerGroup, Constants.PERMISSION_HASROLE, Constants.ORESOURCE_AUTHOR);
+		securityManager.addIdentityToSecurityGroup(securityManager.findIdentityByName("administrator"), ownerGroup);
+		re.setOwnerGroup(ownerGroup);
+	}
+	
 	/**
 	 * 
 	 * @param addedEntry
diff --git a/src/main/java/org/olat/upgrade/OLATUpgrade_8_2_0.java b/src/main/java/org/olat/upgrade/OLATUpgrade_8_2_0.java
index f0a45bb3561190df69d5b220e1a0fb3ab7e33106..123b082b0bef487d47646573a91a8409ddb7cd14 100644
--- a/src/main/java/org/olat/upgrade/OLATUpgrade_8_2_0.java
+++ b/src/main/java/org/olat/upgrade/OLATUpgrade_8_2_0.java
@@ -23,6 +23,7 @@ import java.util.Collections;
 import java.util.Iterator;
 import java.util.List;
 
+import org.olat.basesecurity.BaseSecurity;
 import org.olat.core.commons.persistence.DB;
 import org.olat.group.BusinessGroup;
 import org.olat.group.BusinessGroupImpl;
@@ -34,6 +35,7 @@ import org.olat.group.area.BGtoAreaRelationImpl;
 import org.olat.group.context.BGContext2Resource;
 import org.olat.group.model.BGResourceRelation;
 import org.olat.resource.OLATResource;
+import org.olat.resource.OLATResourceManager;
 import org.springframework.beans.factory.annotation.Autowired;
 
 /**
@@ -57,9 +59,13 @@ public class OLATUpgrade_8_2_0 extends OLATUpgrade {
 	@Autowired
 	private DB dbInstance;
 	@Autowired
+	private BaseSecurity securityManager;
+	@Autowired
 	private BGAreaManager areaManager;
 	@Autowired
 	private BusinessGroupService businessGroupService;
+	@Autowired
+	private OLATResourceManager resourceManager;
 
 	public OLATUpgrade_8_2_0() {
 		super();
@@ -146,6 +152,28 @@ public class OLATUpgrade_8_2_0 extends OLATUpgrade {
 		List<OLATResource> resources = findOLATResourcesForBusinessGroup(group);
 		List<OLATResource> currentList = businessGroupService.findResources(Collections.singletonList(group), 0, -1);
 		
+		boolean merge = false;
+		if(group.getResource() == null) {
+			OLATResource resource = resourceManager.findResourceable(group);
+			((BusinessGroupImpl)group).setResource(resource);
+			merge = true;
+		}
+		if(group.getOwnerGroup() == null) {
+			((BusinessGroupImpl)group).setOwnerGroup(securityManager.createAndPersistSecurityGroup());
+			merge = true;
+		}
+		if(group.getPartipiciantGroup() == null) {
+			((BusinessGroupImpl)group).setPartipiciantGroup(securityManager.createAndPersistSecurityGroup());
+			merge = true;
+		}
+		if(group.getWaitingGroup() == null) {
+			group.setWaitingGroup(securityManager.createAndPersistSecurityGroup());
+			merge = true;
+		}
+		if(merge) {
+			group = dbInstance.getCurrentEntityManager().merge(group);
+		}
+
 		int count = 0;
 		for	(OLATResource resource:resources) {
 			if(!currentList.contains(resource)) {
diff --git a/src/main/resources/database/mysql/alter_8_1_x_to_8_2_0.sql b/src/main/resources/database/mysql/alter_8_1_x_to_8_2_0.sql
index 33f5cd1567956ae0165636638232d93deaccfb06..228c77e3130f1d6ff7693a7a45caffb85bd9b8cb 100644
--- a/src/main/resources/database/mysql/alter_8_1_x_to_8_2_0.sql
+++ b/src/main/resources/database/mysql/alter_8_1_x_to_8_2_0.sql
@@ -1,3 +1,4 @@
+-- relation groups to resources
 create table if not exists o_gp_business_to_resource (
    g_id bigint not null,
    version mediumint unsigned not null,
@@ -6,14 +7,24 @@ create table if not exists o_gp_business_to_resource (
    fk_group bigint not null,
    primary key (g_id)
 );
-
 alter table o_gp_business_to_resource add constraint idx_bgp_to_rsrc_rsrc foreign key (fk_resource) references o_olatresource (resource_id);
 alter table o_gp_business_to_resource add constraint idx_bgp_to_rsrc_group foreign key (fk_group) references o_gp_business (group_id);
 
+-- groups
+alter table o_gp_business add column fk_resource bigint unique default null;
 
-
+-- area
+alter table o_gp_bgarea modify groupcontext_fk bigint;
 alter table o_gp_bgarea add column fk_resource bigint default null;
 alter table o_gp_bgarea add constraint idx_area_to_resource foreign key (fk_resource) references o_olatresource (resource_id);
 
-alter table o_gp_bgarea modify groupcontext_fk bigint;
-
+-- view
+create or replace view o_gp_business_to_repository_v as (
+	select 
+		grp.group_id as grp_id,
+		repoentry.repositoryentry_id as re_id,
+		repoentry.displayname as re_displayname
+	from o_gp_business as grp
+	inner join o_gp_business_to_resource as relation on (relation.fk_group = grp.group_id)
+	inner join o_repositoryentry as repoentry on (repoentry.fk_olatresource = relation.fk_resource)
+);
\ No newline at end of file
diff --git a/src/main/resources/database/mysql/setupDatabase.sql b/src/main/resources/database/mysql/setupDatabase.sql
index c740ffeab46fa79d7e6c3af54b69537d38d65751..8f5361f66a4438a7dc16fb5620ed4f53bea7e993 100644
--- a/src/main/resources/database/mysql/setupDatabase.sql
+++ b/src/main/resources/database/mysql/setupDatabase.sql
@@ -43,6 +43,7 @@ create table if not exists o_gp_business (
    waitinglist_enabled bit,
    autocloseranks_enabled bit,
    groupcontext_fk bigint,
+   fk_resource bigint unique,
    fk_ownergroup bigint unique,
    fk_partipiciantgroup bigint unique,
    fk_waitinggroup bigint unique,
@@ -1057,6 +1058,16 @@ create or replace view o_ep_notifications_comment_v as (
    left join o_ep_struct_el as page on (page.fk_struct_root_map_id = map.structure_id and page.structure_id = ucomment.ressubpath)
 );
 
+create or replace view o_gp_business_to_repository_v as (
+	select 
+		grp.group_id as grp_id,
+		repoentry.repositoryentry_id as re_id,
+		repoentry.displayname as re_displayname
+	from o_gp_business as grp
+	inner join o_gp_business_to_resource as relation on (relation.fk_group = grp.group_id)
+	inner join o_repositoryentry as repoentry on (repoentry.fk_olatresource = relation.fk_resource)
+);
+
 
 create index  ocl_asset_idx on oc_lock (asset);
 alter table oc_lock add index FK9E30F4B66115906D (identity_fk), add constraint FK9E30F4B66115906D foreign key (identity_fk) references o_bs_identity (id);
diff --git a/src/test/java/org/olat/group/test/BusinessGroupDAOTest.java b/src/test/java/org/olat/group/test/BusinessGroupDAOTest.java
index 325dcd580ac759d86d703ddbc49758f621cc94e2..3624b967a1670d54eed659894f797dcec0854801 100644
--- a/src/test/java/org/olat/group/test/BusinessGroupDAOTest.java
+++ b/src/test/java/org/olat/group/test/BusinessGroupDAOTest.java
@@ -90,6 +90,7 @@ public class BusinessGroupDAOTest extends OlatTestCase {
 		Assert.assertNotNull(group.getOwnerGroup());
 		Assert.assertNotNull(group.getPartipiciantGroup());
 		Assert.assertNotNull(group.getWaitingGroup());
+		Assert.assertNotNull(group.getResource());
 		Assert.assertEquals("gdao", group.getName());
 		Assert.assertEquals("gdao-desc", group.getDescription());
 		Assert.assertFalse(group.getWaitingListEnabled());
@@ -112,6 +113,7 @@ public class BusinessGroupDAOTest extends OlatTestCase {
 		Assert.assertNotNull(reloadedGroup.getOwnerGroup());
 		Assert.assertNotNull(reloadedGroup.getPartipiciantGroup());
 		Assert.assertNotNull(reloadedGroup.getWaitingGroup());
+		Assert.assertNotNull(group.getResource());
 		Assert.assertEquals("gdbo", reloadedGroup.getName());
 		Assert.assertEquals("gdbo-desc", reloadedGroup.getDescription());
 		Assert.assertFalse(reloadedGroup.getWaitingListEnabled());
@@ -671,5 +673,41 @@ public class BusinessGroupDAOTest extends OlatTestCase {
 		Assert.assertTrue(groups.contains(group3));
 	}
 	
+	
+	@Test
+	public void isIdentityInBusinessGroups() {
+		Identity id = JunitTestHelper.createAndPersistIdentityAsUser("is-in-grp-" + UUID.randomUUID().toString());
+		BusinessGroup group1 = businessGroupDao.createAndPersist(id, "is-in-grp-1", "is-in-grp-1-desc", 0, 5, true, false, true, false, false);
+		BusinessGroup group2 = businessGroupDao.createAndPersist(null, "is-in-grp-2", "is-in-grp-2-desc", 0, 5, true, false, true, false, false);
+		BusinessGroup group3 = businessGroupDao.createAndPersist(null, "is-in-grp-3", "is-in-grp-3-desc", 0, 5, true, false, true, false, false);
+		dbInstance.commitAndCloseSession();
+
+		securityManager.addIdentityToSecurityGroup(id, group2.getPartipiciantGroup());
+		securityManager.addIdentityToSecurityGroup(id, group3.getWaitingGroup());
+		dbInstance.commitAndCloseSession();
+		
+		List<BusinessGroup> groups = new ArrayList<BusinessGroup>();
+		groups.add(group1);
+		groups.add(group2);
+		groups.add(group3);
 
+		//check owner + attendee
+		List<Long> groupKeysA = businessGroupDao.isIdentityInBusinessGroups(id, true, true, groups);
+		Assert.assertNotNull(groupKeysA);
+		Assert.assertEquals(2, groupKeysA.size());
+		Assert.assertTrue(groupKeysA.contains(group1.getKey()));
+		Assert.assertTrue(groupKeysA.contains(group2.getKey()));
+		
+		//check owner 
+		List<Long> groupKeysB = businessGroupDao.isIdentityInBusinessGroups(id, true, false, groups);
+		Assert.assertNotNull(groupKeysB);
+		Assert.assertEquals(1, groupKeysB.size());
+		Assert.assertTrue(groupKeysB.contains(group1.getKey()));
+
+		//check attendee 
+		List<Long> groupKeysC = businessGroupDao.isIdentityInBusinessGroups(id, false, true, groups);
+		Assert.assertNotNull(groupKeysC);
+		Assert.assertEquals(1, groupKeysC.size());
+		Assert.assertTrue(groupKeysC.contains(group2.getKey()));
+	}
 }
diff --git a/src/test/java/org/olat/group/test/BusinessGroupRelationDAOTest.java b/src/test/java/org/olat/group/test/BusinessGroupRelationDAOTest.java
index fead4822a7ea3092c37d3f9ca5a85cc37b4f1031..bcdbf18c03c1e9655f434a8baa730848760e80d2 100644
--- a/src/test/java/org/olat/group/test/BusinessGroupRelationDAOTest.java
+++ b/src/test/java/org/olat/group/test/BusinessGroupRelationDAOTest.java
@@ -35,7 +35,9 @@ import org.olat.core.id.Identity;
 import org.olat.group.BusinessGroup;
 import org.olat.group.manager.BusinessGroupDAO;
 import org.olat.group.manager.BusinessGroupRelationDAO;
+import org.olat.group.model.BGRepositoryEntryRelation;
 import org.olat.group.model.SearchBusinessGroupParams;
+import org.olat.repository.RepositoryEntry;
 import org.olat.resource.OLATResource;
 import org.olat.test.JunitTestHelper;
 import org.olat.test.OlatTestCase;
@@ -76,6 +78,9 @@ public class BusinessGroupRelationDAOTest extends OlatTestCase {
 		Assert.assertNotNull(resources);
 		Assert.assertEquals(1, resources.size());
 		Assert.assertTrue(resources.contains(resource));
+		
+		int count = businessGroupRelationDao.countResources(group);
+		Assert.assertEquals(1, count);
 	}
 	
 	@Test
@@ -640,4 +645,39 @@ public class BusinessGroupRelationDAOTest extends OlatTestCase {
 		Assert.assertEquals(1, participant6.size());
 		Assert.assertTrue(participant6.contains(part4));
 	}
+	
+	@Test
+	public void findRelationToRepositoryEntries() {
+		//create 3 entries and 1 group
+		RepositoryEntry re1 = JunitTestHelper.createAndPersistRepositoryEntry();
+		RepositoryEntry re2 = JunitTestHelper.createAndPersistRepositoryEntry();
+		RepositoryEntry re3 = JunitTestHelper.createAndPersistRepositoryEntry();
+		BusinessGroup group = businessGroupDao.createAndPersist(null, "rel-repo", "rel-repo-desc", 0, 10, true, false, false, false, false);
+		dbInstance.commitAndCloseSession();
+		
+		businessGroupRelationDao.addRelationToResource(group, re1.getOlatResource());
+		businessGroupRelationDao.addRelationToResource(group, re2.getOlatResource());
+		businessGroupRelationDao.addRelationToResource(group, re3.getOlatResource());
+		dbInstance.commitAndCloseSession();
+		
+		//check with empty list of groups
+		List<BGRepositoryEntryRelation> emptyRelations = businessGroupRelationDao.findRelationToRepositoryEntries(Collections.<BusinessGroup>emptyList(), 0, -1); 
+		Assert.assertNotNull(emptyRelations);
+		Assert.assertEquals(0, emptyRelations.size());
+		
+		//check with the group
+		List<BGRepositoryEntryRelation> relations = businessGroupRelationDao.findRelationToRepositoryEntries(Collections.singletonList(group), 0, -1); 
+		Assert.assertNotNull(relations);
+		Assert.assertEquals(3, relations.size());
+		
+		int count = 0;
+		for(BGRepositoryEntryRelation relation:relations) {
+			if(relation.getRepositoryEntryKey().equals(re1.getKey())
+					|| relation.getRepositoryEntryKey().equals(re2.getKey())
+					|| relation.getRepositoryEntryKey().equals(re3.getKey())) {
+				count++;
+			}
+		}
+		Assert.assertEquals(3, count);
+	}
 }
diff --git a/src/test/java/org/olat/test/JunitTestHelper.java b/src/test/java/org/olat/test/JunitTestHelper.java
index eb19555cb71a768d0a1b98ec0ec3e83e72198692..cde524af4269d56466171bb558f700601d59e8c9 100644
--- a/src/test/java/org/olat/test/JunitTestHelper.java
+++ b/src/test/java/org/olat/test/JunitTestHelper.java
@@ -134,6 +134,24 @@ public class JunitTestHelper {
 		return identity;
 	}
 	
+	public static final RepositoryEntry createAndPersistRepositoryEntry() {
+		OLATResourceManager resourceManager = OLATResourceManager.getInstance();
+		OLATResourceable ores = OresHelper.createOLATResourceableInstance(UUID.randomUUID().toString(), 0l);
+		OLATResource r =  resourceManager.createOLATResourceInstance(ores);
+		resourceManager.saveOLATResource(r);
+		
+		RepositoryManager repositoryManager = RepositoryManager.getInstance();
+		RepositoryEntry re = repositoryManager.createRepositoryEntryInstance("Florian Gnägi");
+		re.setOlatResource(r);
+		re.setResourcename("Lernen mit OLAT");
+		re.setDisplayname(ores.getResourceableTypeName());
+		repositoryManager.createOwnerSecurityGroup(re);
+		repositoryManager.createTutorSecurityGroup(re);
+		repositoryManager.createParticipantSecurityGroup(re);
+		repositoryManager.saveRepositoryEntry(re);
+		return re;
+	}
+	
 	/**
 	 * Deploys/imports the "Demo Course".
 	 * @return the created RepositoryEntry