From 452237b4035f8312110a257ce27d6d327049f35a Mon Sep 17 00:00:00 2001
From: srosse <none@none>
Date: Mon, 27 Jan 2014 08:53:18 +0100
Subject: [PATCH] OO-952: move the "display members" configuration to the
 business group table, optimize the query for the roster (list of contacts)

---
 .../persistence/_spring/core_persistence.xml  |   6 +-
 .../java/org/olat/group/BusinessGroup.java    |  28 +++
 .../org/olat/group/BusinessGroupImpl.hbm.xml  |   7 +
 .../org/olat/group/BusinessGroupImpl.java     |  83 ++++++-
 .../org/olat/group/BusinessGroupService.java  |   8 +-
 .../olat/group/manager/BusinessGroupDAO.java  |  15 +-
 .../manager/BusinessGroupImportExport.java    |  40 ++--
 .../manager/BusinessGroupPropertyDAO.java     | 217 ------------------
 .../manager/BusinessGroupServiceImpl.java     |  58 +++--
 .../org/olat/group/manager/ContactDAO.java    |  51 ++--
 .../olat/group/model/ContactKeyOwnerView.java | 110 +++++++++
 .../model/ContactKeyParticipantView.java      | 110 +++++++++
 ...nerViewImpl.java => ContactOwnerView.java} |  12 +-
 ...wImpl.java => ContactParticipantView.java} |   8 +-
 .../org/olat/group/model/DisplayMembers.java  | 103 ---------
 .../ui/edit/BusinessGroupEditController.java  |   9 +-
 .../edit/BusinessGroupMembersController.java  |  22 +-
 .../ui/edit/DisplayMemberSwitchForm.java      |  54 +++--
 .../ui/homepage/GroupInfoMainController.java  |  10 +-
 .../GroupMembersDisplayController.java        |   9 +-
 .../run/BusinessGroupMainRunController.java   |  13 +-
 .../run/BusinessGroupSendToChooserForm.java   |  13 +-
 .../manager/InstantMessagingServiceImpl.java  |  12 +-
 .../olat/properties/PropertyConstants.java    |  43 ----
 .../group/LearningGroupWebService.java        |  33 +--
 .../org/olat/upgrade/OLATUpgrade_9_4_0.java   | 176 ++++++++++++++
 .../olat/upgrade/_spring/upgradeContext.xml   |   1 +
 .../database/mysql/alter_9_3_0_to_9_4_0.sql   |  60 +++++
 .../database/mysql/setupDatabase.sql          |  42 +++-
 .../database/oracle/alter_9_3_0_to_9_4_0.sql  |  59 +++++
 .../database/oracle/setupDatabase.sql         |  44 +++-
 .../postgresql/alter_9_3_0_to_9_4_0.sql       |  61 +++++
 .../database/postgresql/setupDatabase.sql     |  44 +++-
 .../olat/group/test/BusinessGroupDAOTest.java |  33 +--
 .../test/BusinessGroupImportExportTest.java   |  15 +-
 .../org/olat/group/test/ContactDAOTest.java   | 184 ++++++++++++++-
 .../InstantMessageServiceTest.java            |   5 +-
 .../modules/coach/CoachingManagerTest.java    |   5 +-
 .../java/org/olat/restapi/ContactsTest.java   |   9 +-
 .../org/olat/restapi/GroupFoldersTest.java    |   5 +-
 .../java/org/olat/restapi/GroupMgmtTest.java  |  12 +-
 41 files changed, 1204 insertions(+), 625 deletions(-)
 delete mode 100644 src/main/java/org/olat/group/manager/BusinessGroupPropertyDAO.java
 create mode 100644 src/main/java/org/olat/group/model/ContactKeyOwnerView.java
 create mode 100644 src/main/java/org/olat/group/model/ContactKeyParticipantView.java
 rename src/main/java/org/olat/group/model/{BusinessGroupOwnerViewImpl.java => ContactOwnerView.java} (91%)
 rename src/main/java/org/olat/group/model/{BusinessGroupParticipantViewImpl.java => ContactParticipantView.java} (93%)
 delete mode 100644 src/main/java/org/olat/group/model/DisplayMembers.java
 delete mode 100644 src/main/java/org/olat/properties/PropertyConstants.java
 create mode 100644 src/main/java/org/olat/upgrade/OLATUpgrade_9_4_0.java
 create mode 100644 src/main/resources/database/mysql/alter_9_3_0_to_9_4_0.sql
 create mode 100644 src/main/resources/database/oracle/alter_9_3_0_to_9_4_0.sql
 create mode 100644 src/main/resources/database/postgresql/alter_9_3_0_to_9_4_0.sql

diff --git a/src/main/java/org/olat/core/commons/persistence/_spring/core_persistence.xml b/src/main/java/org/olat/core/commons/persistence/_spring/core_persistence.xml
index 96a1911012c..1c43c1649e2 100644
--- a/src/main/java/org/olat/core/commons/persistence/_spring/core_persistence.xml
+++ b/src/main/java/org/olat/core/commons/persistence/_spring/core_persistence.xml
@@ -92,8 +92,10 @@
 		<class>org.olat.core.commons.services.taskexecutor.model.PersistentTask</class>
 		<class>org.olat.core.commons.services.taskexecutor.model.PersistentTaskModifier</class>
 		<class>org.olat.course.assessment.model.UserCourseInfosImpl</class>
-		<class>org.olat.group.model.BusinessGroupParticipantViewImpl</class>
-		<class>org.olat.group.model.BusinessGroupOwnerViewImpl</class>
+		<class>org.olat.group.model.ContactParticipantView</class>
+		<class>org.olat.group.model.ContactOwnerView</class>
+		<class>org.olat.group.model.ContactKeyParticipantView</class>
+		<class>org.olat.group.model.ContactKeyOwnerView</class>
 		<class>org.olat.group.model.BusinessGroupLazyImpl</class>
 		<class>org.olat.repository.model.RepositoryEntryLifecycle</class>
 		<class>org.olat.repository.model.ParticipantRepositoryEntryShort</class>
diff --git a/src/main/java/org/olat/group/BusinessGroup.java b/src/main/java/org/olat/group/BusinessGroup.java
index b904766bb1c..269d63ae0c5 100644
--- a/src/main/java/org/olat/group/BusinessGroup.java
+++ b/src/main/java/org/olat/group/BusinessGroup.java
@@ -140,6 +140,34 @@ public interface BusinessGroup extends BusinessGroupShort, Persistable, CreateIn
 	 * @return last usage of this group
 	 */
 	public Date getLastUsage();
+	
+	public boolean isOwnersVisibleIntern();
+
+	public void setOwnersVisibleIntern(boolean visible);
+
+	public boolean isParticipantsVisibleIntern();
+
+	public void setParticipantsVisibleIntern(boolean visible);
+
+	public boolean isWaitingListVisibleIntern();
+
+	public void setWaitingListVisibleIntern(boolean visible);
+
+	public boolean isOwnersVisiblePublic();
+
+	public void setOwnersVisiblePublic(boolean visible);
+
+	public boolean isParticipantsVisiblePublic();
+
+	public void setParticipantsVisiblePublic(boolean visible);
+
+	public boolean isWaitingListVisiblePublic();
+
+	public void setWaitingListVisiblePublic(boolean visible);
+
+	public boolean isDownloadMembersLists();
+
+	public void setDownloadMembersLists(boolean downloadMembersLists);
 
 	/**
 	 * @return the maximal number of participants
diff --git a/src/main/java/org/olat/group/BusinessGroupImpl.hbm.xml b/src/main/java/org/olat/group/BusinessGroupImpl.hbm.xml
index 73af71595cd..587d1d34615 100644
--- a/src/main/java/org/olat/group/BusinessGroupImpl.hbm.xml
+++ b/src/main/java/org/olat/group/BusinessGroupImpl.hbm.xml
@@ -33,6 +33,13 @@
 		<property name="externalId" column="external_id" unique="false" not-null="false" type="string"/>
 		<property name="managedFlagsString" column="managed_flags" unique="false" not-null="false" type="string"/>
 		
+		<property name="ownersVisibleIntern" column="ownersintern" unique="false" not-null="true" type="boolean"/>
+		<property name="ownersVisiblePublic" column="ownerspublic" unique="false" not-null="true" type="boolean"/>
+		<property name="participantsVisibleIntern" column="participantsintern" unique="false" not-null="true" type="boolean"/>
+		<property name="participantsVisiblePublic" column="participantspublic" unique="false" not-null="true" type="boolean"/>
+		<property name="waitingListVisibleIntern" column="waitingintern" unique="false" not-null="true" type="boolean"/>
+		<property name="waitingListVisiblePublic" column="waitingpublic" unique="false" not-null="true" type="boolean"/>
+		<property name="downloadMembersLists" column="downloadmembers" unique="false" not-null="true" type="boolean"/>
 			 		
 		<property name="name" type="string" column="groupname" unique="false" length="255" index="gp_name_idx"/>	
 		<property name="description" type="string" column="descr" length="16777210" not-null="false"/>
diff --git a/src/main/java/org/olat/group/BusinessGroupImpl.java b/src/main/java/org/olat/group/BusinessGroupImpl.java
index 2472ee31571..fbc353559d3 100644
--- a/src/main/java/org/olat/group/BusinessGroupImpl.java
+++ b/src/main/java/org/olat/group/BusinessGroupImpl.java
@@ -66,6 +66,13 @@ public class BusinessGroupImpl extends PersistentObject implements BusinessGroup
 	private Boolean waitingListEnabled;
 	private Boolean autoCloseRanksEnabled;
 	private Date lastModified;
+	private boolean ownersVisibleIntern;
+	private boolean participantsVisibleIntern;
+	private boolean waitingListVisibleIntern;
+	private boolean ownersVisiblePublic;
+	private boolean participantsVisiblePublic;
+	private boolean waitingListVisiblePublic;
+	private boolean downloadMembersLists;
 
 	private static final int TYPE_MAXLENGTH = 15;
 
@@ -167,7 +174,63 @@ public class BusinessGroupImpl extends PersistentObject implements BusinessGroup
 	 * @see org.olat.group.BusinessGroup#getName()
 	 */
 	public String getName() {
-		return this.name;
+		return name;
+	}
+
+	public boolean isOwnersVisibleIntern() {
+		return ownersVisibleIntern;
+	}
+
+	public void setOwnersVisibleIntern(boolean visible) {
+		this.ownersVisibleIntern = visible;
+	}
+
+	public boolean isParticipantsVisibleIntern() {
+		return participantsVisibleIntern;
+	}
+
+	public void setParticipantsVisibleIntern(boolean visible) {
+		this.participantsVisibleIntern = visible;
+	}
+
+	public boolean isWaitingListVisibleIntern() {
+		return waitingListVisibleIntern;
+	}
+
+	public void setWaitingListVisibleIntern(boolean visible) {
+		this.waitingListVisibleIntern = visible;
+	}
+
+	public boolean isOwnersVisiblePublic() {
+		return ownersVisiblePublic;
+	}
+
+	public void setOwnersVisiblePublic(boolean visible) {
+		this.ownersVisiblePublic = visible;
+	}
+
+	public boolean isParticipantsVisiblePublic() {
+		return participantsVisiblePublic;
+	}
+
+	public void setParticipantsVisiblePublic(boolean visible) {
+		this.participantsVisiblePublic = visible;
+	}
+
+	public boolean isWaitingListVisiblePublic() {
+		return waitingListVisiblePublic;
+	}
+
+	public void setWaitingListVisiblePublic(boolean visible) {
+		this.waitingListVisiblePublic = visible;
+	}
+
+	public boolean isDownloadMembersLists() {
+		return downloadMembersLists;
+	}
+
+	public void setDownloadMembersLists(boolean visible) {
+		this.downloadMembersLists = visible;
 	}
 
 	public OLATResource getResource() {
@@ -182,28 +245,28 @@ public class BusinessGroupImpl extends PersistentObject implements BusinessGroup
 	 * @see org.olat.group.BusinessGroup#getOwnerGroup()
 	 */
 	public SecurityGroup getOwnerGroup() {
-		return this.ownerGroup;
+		return ownerGroup;
 	}
 
 	/**
 	 * @see org.olat.group.BusinessGroup#getPartipiciantGroup()
 	 */
 	public SecurityGroup getPartipiciantGroup() {
-		return this.partipiciantGroup;
+		return partipiciantGroup;
 	}
 
 	/**
 	 * @see org.olat.group.BusinessGroup#getWaitingGroup()
 	 */
 	public SecurityGroup getWaitingGroup() {
-		return this.waitingGroup;
+		return waitingGroup;
 	}
 
 	/**
 	 * @return Returns the lastUsage.
 	 */
-	public java.util.Date getLastUsage() {
-		return this.lastUsage;
+	public Date getLastUsage() {
+		return lastUsage;
 	}
 
 	/**
@@ -211,15 +274,15 @@ public class BusinessGroupImpl extends PersistentObject implements BusinessGroup
 	 * 
 	 * @param lastUsageP
 	 */
-	public void setLastUsage(final java.util.Date lastUsageP) {
-		this.lastUsage = lastUsageP;
+	public void setLastUsage(Date lastUsage) {
+		this.lastUsage = lastUsage;
 	}
 
 	/**
 	 * @see org.olat.group.BusinessGroup#getType()
 	 */
 	public String getType() {
-		return this.type;// BusinessGroupImpl.class.getName();
+		return type;// BusinessGroupImpl.class.getName();
 	}
 
 	/**
@@ -252,7 +315,7 @@ public class BusinessGroupImpl extends PersistentObject implements BusinessGroup
 	 * @see org.olat.group.BusinessGroup#getGroupContext()
 	 */
 	public Long getGroupContextKey() {
-		return this.groupContextKey;
+		return groupContextKey;
 	}
 
 	/**
diff --git a/src/main/java/org/olat/group/BusinessGroupService.java b/src/main/java/org/olat/group/BusinessGroupService.java
index 1ebd023389f..05ef0f42d54 100644
--- a/src/main/java/org/olat/group/BusinessGroupService.java
+++ b/src/main/java/org/olat/group/BusinessGroupService.java
@@ -34,7 +34,6 @@ import org.olat.group.area.BGArea;
 import org.olat.group.model.BGRepositoryEntryRelation;
 import org.olat.group.model.BusinessGroupEnvironment;
 import org.olat.group.model.BusinessGroupMembershipChange;
-import org.olat.group.model.DisplayMembers;
 import org.olat.group.model.EnrollState;
 import org.olat.group.model.MembershipModification;
 import org.olat.group.model.SearchBusinessGroupParams;
@@ -113,9 +112,10 @@ public interface BusinessGroupService {
 	public BusinessGroup updateBusinessGroup(Identity ureqIdentity, BusinessGroup group, String name, String description,
 			Integer minParticipants, Integer maxParticipants, Boolean waitingList, Boolean autoCloseRanks);
 	
-	public DisplayMembers getDisplayMembers(BusinessGroup group);
-	
-	public void updateDisplayMembers(BusinessGroup group, DisplayMembers displayMembers);
+	public BusinessGroup updateDisplayMembers(BusinessGroup group,
+			boolean ownersIntern, boolean participantsIntern, boolean waitingListIntern,
+			boolean ownersPublis, boolean participantsPublic, boolean waitingListPublic,
+			boolean download);
 	
 	/**
 	 * Delete a business group from the persistence store
diff --git a/src/main/java/org/olat/group/manager/BusinessGroupDAO.java b/src/main/java/org/olat/group/manager/BusinessGroupDAO.java
index ce27fc36140..4be6e415d16 100644
--- a/src/main/java/org/olat/group/manager/BusinessGroupDAO.java
+++ b/src/main/java/org/olat/group/manager/BusinessGroupDAO.java
@@ -83,8 +83,6 @@ public class BusinessGroupDAO {
 	private BaseSecurity securityManager;
 	@Autowired
 	private OLATResourceManager olatResourceManager;
-	@Autowired
-	private BusinessGroupPropertyDAO businessGroupPropertyManager;
 	
 	public BusinessGroup createAndPersist(Identity creator, String name, String description,
 			Integer minParticipants, Integer maxParticipants, boolean waitingListEnabled, boolean autoCloseRanksEnabled,
@@ -119,6 +117,14 @@ public class BusinessGroupDAO {
 		if(StringHelper.containsNonWhitespace(managedFlags)) {
 			businessgroup.setManagedFlagsString(managedFlags);
 		}
+		businessgroup.setOwnersVisibleIntern(showOwners);
+		businessgroup.setParticipantsVisibleIntern(showParticipants);
+		businessgroup.setWaitingListVisibleIntern(showWaitingList);
+		// group members visibility
+		businessgroup.setOwnersVisiblePublic(false);
+		businessgroup.setParticipantsVisiblePublic(false);
+		businessgroup.setWaitingListVisiblePublic(false);
+		businessgroup.setDownloadMembersLists(false);
 		
 		businessgroup.setWaitingListEnabled(waitingListEnabled);
 		businessgroup.setAutoCloseRanksEnabled(autoCloseRanksEnabled);
@@ -139,7 +145,7 @@ public class BusinessGroupDAO {
 		businessgroup.setResource(businessgroupOlatResource);
 		em.merge(businessgroup);
 
-		//		securityManager.createAndPersistPolicy(ownerGroup, Constants.PERMISSION_ACCESS, businessgroup);
+		// securityManager.createAndPersistPolicy(ownerGroup, Constants.PERMISSION_ACCESS, businessgroup);
 		securityManager.createAndPersistPolicyWithResource(ownerGroup, Constants.PERMISSION_ACCESS, businessgroupOlatResource);
 		securityManager.createAndPersistPolicyWithResource(participantGroup, Constants.PERMISSION_READ, businessgroupOlatResource);
 		// membership: add identity
@@ -148,9 +154,6 @@ public class BusinessGroupDAO {
 		}
 
 		// per default all collaboration-tools are disabled
-
-		// group members visibility
-		businessGroupPropertyManager.createAndPersistDisplayMembers(businessgroup, showOwners, showParticipants, showWaitingList);
 		return businessgroup;
 	}
 	
diff --git a/src/main/java/org/olat/group/manager/BusinessGroupImportExport.java b/src/main/java/org/olat/group/manager/BusinessGroupImportExport.java
index d278d2d0273..fba7ec95f74 100644
--- a/src/main/java/org/olat/group/manager/BusinessGroupImportExport.java
+++ b/src/main/java/org/olat/group/manager/BusinessGroupImportExport.java
@@ -46,7 +46,6 @@ import org.olat.group.area.BGAreaManager;
 import org.olat.group.model.BGAreaReference;
 import org.olat.group.model.BusinessGroupEnvironment;
 import org.olat.group.model.BusinessGroupReference;
-import org.olat.properties.Property;
 import org.olat.repository.RepositoryEntry;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
@@ -70,8 +69,6 @@ public class BusinessGroupImportExport {
 	@Autowired
 	private BusinessGroupService businessGroupService;
 	@Autowired
-	private BusinessGroupPropertyDAO businessGroupPropertyManager;
-	@Autowired
 	private BusinessGroupModule groupModule;
 	
 	
@@ -173,10 +170,9 @@ public class BusinessGroupImportExport {
 			newGroup.areaRelations.add(areaRelation.getName());
 		}
 		// export properties
-		Property property = businessGroupPropertyManager.findProperty(group);
-		boolean showOwners = businessGroupPropertyManager.showOwners(property);
-		boolean showParticipants = businessGroupPropertyManager.showPartips(property);
-		boolean showWaitingList = businessGroupPropertyManager.showWaitingList(property);
+		boolean showOwners = group.isOwnersVisibleIntern();
+		boolean showParticipants = group.isParticipantsVisibleIntern();
+		boolean showWaitingList = group.isWaitingListVisibleIntern();
 
 		newGroup.showOwners = showOwners;
 		newGroup.showParticipants = showParticipants;
@@ -260,6 +256,20 @@ public class BusinessGroupImportExport {
 					enableAutoCloseRanks = group.autoCloseRanks.booleanValue();
 				}
 				
+				// get properties
+				boolean showOwners = true;
+				boolean showParticipants = true;
+				boolean showWaitingList = true;
+				if (group.showOwners != null) {
+					showOwners = group.showOwners;
+				}
+				if (group.showParticipants != null) {
+					showParticipants = group.showParticipants;
+				}
+				if (group.showWaitingList != null) {
+					showWaitingList = group.showWaitingList;
+				}
+				
 				BusinessGroup newGroup = businessGroupService.createBusinessGroup(null, groupName, groupDesc, groupMinParticipants, groupMaxParticipants, waitingList, enableAutoCloseRanks, re);
 				//map the group
 				env.getGroups().add(new BusinessGroupReference(newGroup, group.key, group.name));
@@ -302,21 +312,9 @@ public class BusinessGroupImportExport {
 					}
 				}
 
-				// get properties
-				boolean showOwners = true;
-				boolean showParticipants = true;
-				boolean showWaitingList = true;
-				if (group.showOwners != null) {
-					showOwners = group.showOwners;
-				}
-				if (group.showParticipants != null) {
-					showParticipants = group.showParticipants;
-				}
-				if (group.showWaitingList != null) {
-					showWaitingList = group.showWaitingList;
-				}
+				
 				boolean download = groupModule.isUserListDownloadDefaultAllowed();
-				businessGroupPropertyManager.updateDisplayMembers(newGroup, showOwners, showParticipants, showWaitingList, false, false, false, download);
+				newGroup = businessGroupService.updateDisplayMembers(newGroup, showOwners, showParticipants, showWaitingList, false, false, false, download);
 			
 				if(dbCount++ % 3 == 0) {
 					dbInstance.commitAndCloseSession();
diff --git a/src/main/java/org/olat/group/manager/BusinessGroupPropertyDAO.java b/src/main/java/org/olat/group/manager/BusinessGroupPropertyDAO.java
deleted file mode 100644
index 613ec05f3b0..00000000000
--- a/src/main/java/org/olat/group/manager/BusinessGroupPropertyDAO.java
+++ /dev/null
@@ -1,217 +0,0 @@
-/**
-* OLAT - Online Learning and Training<br>
-* http://www.olat.org
-* <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
-* <p>
-* http://www.apache.org/licenses/LICENSE-2.0
-* <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>
-* Copyright (c) since 2004 at Multimedia- & E-Learning Services (MELS),<br>
-* University of Zurich, Switzerland.
-* <hr>
-* <a href="http://www.openolat.org">
-* OpenOLAT - Online Learning and Training</a><br>
-* This file has been modified by the OpenOLAT community. Changes are licensed
-* under the Apache 2.0 license as the original file.
-*/
-
-package org.olat.group.manager;
-
-import org.olat.core.util.StringHelper;
-import org.olat.group.BusinessGroup;
-import org.olat.group.BusinessGroupModule;
-import org.olat.properties.Property;
-import org.olat.properties.PropertyConstants;
-import org.olat.properties.PropertyManager;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Service;
-
-/**
- * Description:<BR>
- * Handles the displayMembers property assigned to BusinessGroups. It uses the
- * float column in the property table, and stores there a bitfield.<br>
- * The DisplayMembers Property is used to switch on - off exposing the owner
- * members, partipiciant members respectively, to the partipiciants of a
- * BusinessGroup.
- * <p>
- * Initial Date: Sep 22, 2004
- * 
- * @author patrick
- */
-@Service("businessGroupPropertyManager")
-public class BusinessGroupPropertyDAO {
-	private static final String PROP_NAME = "displayMembers";
-	private static final int showOwnersVal      = 1;// 0x..0001
-	private static final int showPartipsVal     = 2;// 0x..0010
-	private static final int showWaitingListVal = 4;// 0x..0100
-
-	@Autowired
-	private PropertyManager propertyManager;
-	@Autowired
-	private BusinessGroupModule groupModule;
-
-	/**
-	 * Creates and persists a new Property for the Display Members configuration
-	 * according to the supplied booleans.
-	 * 
-	 * @param showOwners
-	 * @param showPartips
-	 * @return The generated property
-	 */
-	public Property createAndPersistDisplayMembers(BusinessGroup group, boolean showOwners, boolean showPartips, boolean showWaitingList) {
-		long showXXX = 0;
-		if (showOwners) showXXX += showOwnersVal;
-		if (showPartips) showXXX += showPartipsVal;
-		if (showWaitingList) showXXX += showWaitingListVal;
-		
-		Property prop = propertyManager.createPropertyInstance(null, group, group, PropertyConstants.OLATRESOURCE_CONFIGURATION, PROP_NAME, null, new Long(showXXX), null, null);
-		propertyManager.saveProperty(prop);
-		return prop;
-	}
-
-	/**
-	 * updates an existing property, if it is not existing, i.e. called before the
-	 * property was created and persisted, a null pointer exception occurs.
-	 * 
-	 * @param showOwners
-	 * @param showPartips
-	 */
-	public void updateDisplayMembers(BusinessGroup group, boolean showOwners, boolean showPartips, boolean showWaitingList,
-			boolean ownrsPublic, boolean partipsPublic, boolean waitingListPublic, boolean downloadLists) {
-		long showXXX = 0;
-		if (showOwners) showXXX += showOwnersVal;
-		if (showPartips) showXXX += showPartipsVal;
-		if (showWaitingList) showXXX += showWaitingListVal;
-		
-		long publicXXX = 0;
-		if (ownrsPublic) publicXXX += showOwnersVal;
-		if (partipsPublic) publicXXX += showPartipsVal;
-		if (waitingListPublic) publicXXX += showWaitingListVal;
-		
-		float download = downloadLists ? 1.0f : 0.0f;
-		
-		Property property = findProperty(group);
-		property.setLongValue(new Long(showXXX));
-		property.setStringValue(Long.toString(publicXXX));
-		property.setFloatValue(new Float(download));
-		propertyManager.updateProperty(property);
-	}
-
-	/**
-	 * delete the display members property
-	 */
-	public void deleteDisplayMembers(BusinessGroup group) {
-		Property property = findProperty(group);
-		propertyManager.deleteProperty(property);
-	}
-
-	/**
-	 * true if Members can see the Owners, false otherwise. If the property is not
-	 * existing, i.e. called before the property was created and persisted, a null
-	 * pointer exception occurs.
-	 * 
-	 * @return true if group owners are configured to be displayed
-	 */
-	public boolean showOwners(Property prop) {
-		return ((getDisplayMembersValue(prop) & showOwnersVal) == showOwnersVal);
-	}
-
-	/**
-	 * true if Members can see the Participants, false otherwise. If the property
-	 * is not existing, i.e. called before the property was created and persisted,
-	 * a null pointer exception occurs.
-	 * 
-	 * @return true if group participants are configured to be displayed
-	 */
-	public boolean showPartips(Property prop) {
-		return ((getDisplayMembersValue(prop) & showPartipsVal) == showPartipsVal);
-	}
-
-	/**
-	 * true if Members can see the Waiting, false otherwise. If the property
-	 * is not existing, i.e. called before the property was created and persisted,
-	 * a null pointer exception occurs.
-	 * 
-	 * @return true if group participants are configured to be displayed
-	 */
-	public boolean showWaitingList(Property prop) {
-		return ((getDisplayMembersValue(prop) & showWaitingListVal) == showWaitingListVal);
-	}
-	
-	public boolean isOwnersPublic(Property prop) {
-		return ((getPublicMembersValue(prop) & showOwnersVal) == showOwnersVal);
-	}
-
-	public boolean isPartipsPublic(Property prop) {
-		return ((getPublicMembersValue(prop) & showPartipsVal) == showPartipsVal);
-	}
-
-	public boolean isWaitingListPublic(Property prop) {
-		return ((getPublicMembersValue(prop) & showWaitingListVal) == showWaitingListVal);
-	}
-	
-	public boolean isDownloadLists(Property prop) {
-		Float val = prop.getFloatValue();
-		if(val == null) {
-			return groupModule.isUserListDownloadDefaultAllowed();//default
-		}
-		return 0.5f < val.floatValue();	
-	}
-
-	private int getDisplayMembersValue(Property prop) {
-		int showXXX = prop.getLongValue().intValue();
-		return showXXX;
-	}
-	
-	private long getPublicMembersValue(Property prop) {
-		String publicXXX = prop.getStringValue();
-		if(StringHelper.isLong(publicXXX)) {
-			return Long.parseLong(publicXXX);
-		}
-		return 0;
-	}
-
-	/**
-	 * @return The group property. Either red from database or newly created.
-	 */
-	public Property findProperty(BusinessGroup group) {
-		Property prop = propertyManager.findProperty(null, group, group, PropertyConstants.OLATRESOURCE_CONFIGURATION, PROP_NAME);
-		// prop != null, otherwise the init of this businessGroup was incomplete
-		// or the caller uses the function in the wrong way
-		//
-		// BugFix 986, http://bugzilla.olat.org/show_bug.cgi?id=986
-		// above statement is still true, but as old groups are existing, which
-		// return prop==null in this case, we decided to handle it as if both groups
-		// are to show. This reproduces behaviour of OLAT before the code was added.
-		// Furthermore if the property wass not existing one will be created.
-		if (prop == null) {
-			prop = createAndPersistDisplayMembers(group, true, true, true);
-		}
-		return prop;
-	}
-
-	/**
-	 * @param sourceGroup The group from which the configuration should be copied
-	 */
-	public void copyConfigurationFromGroup(BusinessGroup sourceGroup, BusinessGroup targetGroup) {
-		Property sourceGPM = findProperty(sourceGroup);
-		boolean showOwners = showOwners(sourceGPM);
-		boolean showPartips = showPartips(sourceGPM);
-		boolean showWaitingList = showWaitingList(sourceGPM);
-		boolean ownersPublic = isOwnersPublic(sourceGPM);
-		boolean partipsPublic = isPartipsPublic(sourceGPM);
-		boolean waitingListPublic = isWaitingListPublic(sourceGPM);
-		boolean downloadLists = isDownloadLists(sourceGPM);
-		updateDisplayMembers(targetGroup, showOwners, showPartips, showWaitingList,
-				ownersPublic, partipsPublic, waitingListPublic,
-				downloadLists);
-	}
-}
\ No newline at end of file
diff --git a/src/main/java/org/olat/group/manager/BusinessGroupServiceImpl.java b/src/main/java/org/olat/group/manager/BusinessGroupServiceImpl.java
index a24ae44455b..ce1a932a54a 100644
--- a/src/main/java/org/olat/group/manager/BusinessGroupServiceImpl.java
+++ b/src/main/java/org/olat/group/manager/BusinessGroupServiceImpl.java
@@ -89,7 +89,6 @@ import org.olat.group.model.BusinessGroupMembershipChange;
 import org.olat.group.model.BusinessGroupMembershipImpl;
 import org.olat.group.model.BusinessGroupMembershipViewImpl;
 import org.olat.group.model.BusinessGroupMembershipsChanges;
-import org.olat.group.model.DisplayMembers;
 import org.olat.group.model.EnrollState;
 import org.olat.group.model.IdentityGroupKey;
 import org.olat.group.model.MembershipModification;
@@ -98,7 +97,6 @@ import org.olat.group.right.BGRightManager;
 import org.olat.group.right.BGRightsRole;
 import org.olat.group.ui.BGMailHelper;
 import org.olat.group.ui.edit.BusinessGroupModifiedEvent;
-import org.olat.properties.Property;
 import org.olat.repository.RepositoryEntry;
 import org.olat.repository.RepositoryEntryShort;
 import org.olat.repository.RepositoryManager;
@@ -143,8 +141,6 @@ public class BusinessGroupServiceImpl implements BusinessGroupService, UserDataD
 	@Autowired
 	private BusinessGroupArchiver businessGroupArchiver;
 	@Autowired
-	private BusinessGroupPropertyDAO businessGroupPropertyManager;
-	@Autowired
 	private UserDeletionManager userDeletionManager;
 	@Autowired
 	private NotificationsManager notificationsManager;
@@ -289,30 +285,25 @@ public class BusinessGroupServiceImpl implements BusinessGroupService, UserDataD
 	}
 
 	@Override
-	public DisplayMembers getDisplayMembers(BusinessGroup group) {
-		Property props = businessGroupPropertyManager.findProperty(group);
-		DisplayMembers displayMembers = new DisplayMembers();
-		displayMembers.setShowOwners(businessGroupPropertyManager.showOwners(props));
-		displayMembers.setShowParticipants(businessGroupPropertyManager.showPartips(props));
-		displayMembers.setShowWaitingList(businessGroupPropertyManager.showWaitingList(props));
-		displayMembers.setOwnersPublic(businessGroupPropertyManager.isOwnersPublic(props));
-		displayMembers.setParticipantsPublic(businessGroupPropertyManager.isPartipsPublic(props));
-		displayMembers.setWaitingListPublic(businessGroupPropertyManager.isWaitingListPublic(props));
-		displayMembers.setDownloadLists(businessGroupPropertyManager.isDownloadLists(props));
-		return displayMembers;
-	}
-
-	@Override
-	public void updateDisplayMembers(BusinessGroup group, DisplayMembers displayMembers) {
-		boolean showOwners = displayMembers.isShowOwners();
-		boolean showPartips = displayMembers.isShowParticipants();
-		boolean showWaitingList = displayMembers.isShowWaitingList();
-		boolean ownersPublic = displayMembers.isOwnersPublic();
-		boolean partipsPublic = displayMembers.isParticipantsPublic();
-		boolean waitingListPublic = displayMembers.isWaitingListPublic();
-		boolean downloadLists = displayMembers.isDownloadLists();
-		businessGroupPropertyManager.updateDisplayMembers(group, showOwners, showPartips, showWaitingList,
-				ownersPublic, partipsPublic, waitingListPublic, downloadLists);
+	public BusinessGroup updateDisplayMembers(BusinessGroup group,
+			boolean ownersIntern, boolean participantsIntern, boolean waitingListIntern,
+			boolean ownersPublic, boolean participantsPublic, boolean waitingListPublic,
+			boolean download) {
+		
+		BusinessGroup reloadedBusinessGroup = businessGroupDAO.loadForUpdate(group.getKey());
+		BusinessGroup mergedGroup = null;
+		if(reloadedBusinessGroup != null) {
+			reloadedBusinessGroup.setOwnersVisibleIntern(ownersIntern);
+			reloadedBusinessGroup.setOwnersVisiblePublic(ownersPublic);
+			reloadedBusinessGroup.setParticipantsVisibleIntern(participantsIntern);
+			reloadedBusinessGroup.setParticipantsVisiblePublic(participantsPublic);
+			reloadedBusinessGroup.setWaitingListVisibleIntern(waitingListIntern);
+			reloadedBusinessGroup.setWaitingListVisiblePublic(waitingListPublic);
+			reloadedBusinessGroup.setDownloadMembersLists(download);
+			mergedGroup = businessGroupDAO.merge(reloadedBusinessGroup);
+		}
+		dbInstance.commit();
+		return mergedGroup;
 	}
 
 	@Override
@@ -399,7 +390,13 @@ public class BusinessGroupServiceImpl implements BusinessGroupService, UserDataD
 		}
 		// 3. copy member visibility
 		if (copyMemberVisibility) {
-			businessGroupPropertyManager.copyConfigurationFromGroup(sourceBusinessGroup, newGroup);
+			newGroup.setOwnersVisibleIntern(sourceBusinessGroup.isOwnersVisibleIntern());
+			newGroup.setOwnersVisiblePublic(sourceBusinessGroup.isOwnersVisiblePublic());
+			newGroup.setParticipantsVisibleIntern(sourceBusinessGroup.isParticipantsVisibleIntern());
+			newGroup.setParticipantsVisiblePublic(sourceBusinessGroup.isParticipantsVisiblePublic());
+			newGroup.setWaitingListVisibleIntern(sourceBusinessGroup.isWaitingListVisibleIntern());
+			newGroup.setWaitingListVisiblePublic(sourceBusinessGroup.isWaitingListVisiblePublic());
+			newGroup.setDownloadMembersLists(sourceBusinessGroup.isDownloadMembersLists());
 		}
 		// 4. copy areas
 		if (copyAreas) {
@@ -746,9 +743,6 @@ public class BusinessGroupServiceImpl implements BusinessGroupService, UserDataD
 			// 1) Delete all group properties
 			CollaborationTools ct = CollaborationToolsFactory.getInstance().getOrCreateCollaborationTools(group);
 			ct.deleteTools(group);// deletes everything concerning properties&collabTools
-			
-			// 1.b)delete display member property
-			businessGroupPropertyManager.deleteDisplayMembers(group);
 			// 1.c)delete user in security groups
 			//removeFromRepositoryEntrySecurityGroup(group);
 			// 2) Delete the group areas
diff --git a/src/main/java/org/olat/group/manager/ContactDAO.java b/src/main/java/org/olat/group/manager/ContactDAO.java
index e2855c08921..6fa951cba52 100644
--- a/src/main/java/org/olat/group/manager/ContactDAO.java
+++ b/src/main/java/org/olat/group/manager/ContactDAO.java
@@ -30,9 +30,10 @@ import org.olat.basesecurity.SecurityGroupMembershipImpl;
 import org.olat.core.commons.persistence.DB;
 import org.olat.core.id.Identity;
 import org.olat.group.BusinessGroupImpl;
-import org.olat.group.model.BusinessGroupOwnerViewImpl;
-import org.olat.group.model.BusinessGroupParticipantViewImpl;
-import org.olat.properties.Property;
+import org.olat.group.model.ContactOwnerView;
+import org.olat.group.model.ContactParticipantView;
+import org.olat.group.model.ContactKeyOwnerView;
+import org.olat.group.model.ContactKeyParticipantView;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
@@ -50,10 +51,9 @@ public class ContactDAO {
 	@Autowired
 	private DB dbInstance;
 	
-	
 	public Collection<Long> getDistinctGroupOwnersParticipants(Identity me) {
-		List<Long> owners = getMembersForCount(me, BusinessGroupOwnerViewImpl.class);
-		List<Long> participants = getMembersForCount(me, BusinessGroupParticipantViewImpl.class);
+		List<Long> owners = getMembersForCount(me, ContactKeyOwnerView.class);
+		List<Long> participants = getMembersForCount(me, ContactKeyParticipantView.class);
 		Set<Long> contacts = new HashSet<Long>(participants);
 		contacts.addAll(owners);
 		return contacts;
@@ -62,10 +62,12 @@ public class ContactDAO {
 	private List<Long> getMembersForCount(Identity me, Class<?> cl) {
 		StringBuilder sb = new StringBuilder();
 		sb.append("select memv.identityKey from ").append(cl.getName()).append(" memv ")
-		  .append(" where memv.ownerSecGroupKey in (")
-		  .append("   select ownerSgmi.securityGroup from ").append(SecurityGroupMembershipImpl.class.getName()).append(" as ownerSgmi where ownerSgmi.identity.key=:identKey")
-		  .append(" ) or memv.participantSecGroupKey in (")
-		  .append("   select partSgmi.securityGroup from ").append(SecurityGroupMembershipImpl.class.getName()).append(" as partSgmi where partSgmi.identity.key=:identKey")
+		  .append(" where exists (")
+		  .append("   select ownerSgmi from ").append(SecurityGroupMembershipImpl.class.getName()).append(" as ownerSgmi")
+		  .append("     where ownerSgmi.securityGroup=memv.ownerSecGroupKey and ownerSgmi.identity.key=:identKey")
+		  .append(" ) or exists (")
+		  .append("   select partSgmi from ").append(SecurityGroupMembershipImpl.class.getName()).append(" as partSgmi")
+		  .append("     where memv.participantSecGroupKey=partSgmi.securityGroup and partSgmi.identity.key=:identKey")
 		  .append(" )");
 		
 		return dbInstance.getCurrentEntityManager().createQuery(sb.toString(), Long.class)
@@ -73,21 +75,23 @@ public class ContactDAO {
 				.getResultList();
 	}
 
-	public List<BusinessGroupOwnerViewImpl> getGroupOwners(Identity me) {
-		return getMembers(me, BusinessGroupOwnerViewImpl.class);
+	public List<ContactOwnerView> getGroupOwners(Identity me) {
+		return getMembers(me, ContactOwnerView.class);
 	}
 	
-	public List<BusinessGroupParticipantViewImpl> getParticipants(Identity me) {
-		return getMembers(me, BusinessGroupParticipantViewImpl.class);
+	public List<ContactParticipantView> getParticipants(Identity me) {
+		return getMembers(me, ContactParticipantView.class);
 	}
 	
 	private <U> List<U> getMembers(Identity me, Class<U> cl) {
 		StringBuilder sb = new StringBuilder();
 		sb.append("select memv from ").append(cl.getName()).append(" memv ")
-		  .append(" where memv.ownerSecGroupKey in (")
-		  .append("   select ownerSgmi.securityGroup from ").append(SecurityGroupMembershipImpl.class.getName()).append(" as ownerSgmi where ownerSgmi.identity.key=:identKey")
-		  .append(" ) or memv.participantSecGroupKey in (")
-		  .append("   select partSgmi.securityGroup from ").append(SecurityGroupMembershipImpl.class.getName()).append(" as partSgmi where partSgmi.identity.key=:identKey")
+		  .append(" where exists (")
+		  .append("   select ownerSgmi from ").append(SecurityGroupMembershipImpl.class.getName()).append(" as ownerSgmi")
+		  .append("     where memv.ownerSecGroupKey=ownerSgmi.securityGroup and ownerSgmi.identity.key=:identKey")
+		  .append(" ) or exists (")
+		  .append("   select partSgmi from ").append(SecurityGroupMembershipImpl.class.getName()).append(" as partSgmi")
+		  .append("     where memv.participantSecGroupKey=partSgmi.securityGroup and partSgmi.identity.key=:identKey")
 		  .append(" )");
 		
 		return dbInstance.getCurrentEntityManager().createQuery(sb.toString(), cl)
@@ -126,19 +130,19 @@ public class ContactDAO {
 		     .append(" inner join sgmi.securityGroup as secGroup ")
 		     .append(" where ")
 		     .append("  secGroup in (")
-		     .append("    select bg1.ownerGroup from ").append(BusinessGroupImpl.class.getName()).append(" as bg1,").append(Property.class.getName()).append(" as prop where prop.grp=bg1 and prop.name='displayMembers' and prop.longValue in (1,3,5,7)")
+		     .append("    select bg1.ownerGroup from ").append(BusinessGroupImpl.class.getName()).append(" as bg1 where bg1.ownersVisibleIntern=true")
 		     .append("      and bg1.ownerGroup in (select ownerSgmi.securityGroup from ").append(SecurityGroupMembershipImpl.class.getName()).append(" as ownerSgmi where ownerSgmi.identity.key=:identKey)")
 		     .append("  ) or")
 		     .append("  secGroup in (")
-		     .append("    select bg3.ownerGroup from ").append(BusinessGroupImpl.class.getName()).append(" as bg3,").append(Property.class.getName()).append(" as prop where prop.grp=bg3 and prop.name='displayMembers' and prop.longValue in (1,3,5,7)")
+		     .append("    select bg3.ownerGroup from ").append(BusinessGroupImpl.class.getName()).append(" as bg3 where bg3.ownersVisibleIntern=true")
 		     .append("      and bg3.partipiciantGroup in (select partSgmi.securityGroup from ").append(SecurityGroupMembershipImpl.class.getName()).append(" as partSgmi where partSgmi.identity.key=:identKey)")
 		     .append("  ) or")
 		     .append("  secGroup in (")
-		     .append("    select bg2.partipiciantGroup from ").append(BusinessGroupImpl.class.getName()).append(" as bg2,").append(Property.class.getName()).append(" as prop where prop.grp=bg2 and prop.name='displayMembers' and prop.longValue in (2,3,6,7)")
+		     .append("    select bg2.partipiciantGroup from ").append(BusinessGroupImpl.class.getName()).append(" as bg2 where bg2.participantsVisibleIntern=true")
 		     .append("      and bg2.partipiciantGroup in (select partSgmi.securityGroup from ").append(SecurityGroupMembershipImpl.class.getName()).append(" as partSgmi where partSgmi.identity.key=:identKey)")
 		     .append("  ) or")
 		     .append("  secGroup in (")
-		     .append("    select bg4.partipiciantGroup from ").append(BusinessGroupImpl.class.getName()).append(" as bg4,").append(Property.class.getName()).append(" as prop where prop.grp=bg4 and prop.name='displayMembers' and prop.longValue in (2,3,6,7)")
+		     .append("    select bg4.partipiciantGroup from ").append(BusinessGroupImpl.class.getName()).append(" as bg4 where bg4.participantsVisibleIntern=true")
 		     .append("      and bg4.ownerGroup in (select ownerSgmi.securityGroup from ").append(SecurityGroupMembershipImpl.class.getName()).append(" as ownerSgmi where ownerSgmi.identity.key=:identKey)")
 		     .append("  )");
 		if(Identity.class.equals(resultClass)) {
@@ -149,7 +153,4 @@ public class ContactDAO {
 		db.setParameter("identKey", identity.getKey());
 		return db;
 	}
-
-
-
 }
diff --git a/src/main/java/org/olat/group/model/ContactKeyOwnerView.java b/src/main/java/org/olat/group/model/ContactKeyOwnerView.java
new file mode 100644
index 00000000000..3a7b23755b8
--- /dev/null
+++ b/src/main/java/org/olat/group/model/ContactKeyOwnerView.java
@@ -0,0 +1,110 @@
+/**
+ * <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 javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+import javax.persistence.Table;
+
+import org.hibernate.annotations.GenericGenerator;
+import org.olat.core.id.Persistable;
+
+/**
+ * The view list all visible owners
+ * Initial date: 24.1.2014<br>
+ * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
+ *
+ */
+@Entity
+@Table(name="o_gp_contactkey_owner_v")
+public class ContactKeyOwnerView implements Persistable {
+
+	private static final long serialVersionUID = 5125563005863650603L;
+
+	@Id
+	@GeneratedValue(generator = "system-uuid")
+	@GenericGenerator(name = "system-uuid", strategy = "hilo")
+	@Column(name="membership_id", nullable=false, unique=true, insertable=true, updatable=false)
+	private Long key;
+
+	@Column(name="bg_owner_member_id", nullable=false, insertable=true, updatable=false)
+	private Long identityKey;
+	@Column(name="bg_owner_sec_id", nullable=false, insertable=true, updatable=false)
+	private Long ownerSecGroupKey;
+	@Column(name="bg_part_sec_id", nullable=false, insertable=true, updatable=false)
+	private Long participantSecGroupKey;
+
+	@Override
+	public Long getKey() {
+		return key;
+	}
+	
+	public void setKey(Long key) {
+		this.key = key;
+	}
+
+	public Long getIdentityKey() {
+		return identityKey;
+	}
+
+	public void setIdentityKey(Long identityKey) {
+		this.identityKey = identityKey;
+	}
+
+	public Long getOwnerSecGroupKey() {
+		return ownerSecGroupKey;
+	}
+
+	public void setOwnerSecGroupKey(Long ownerSecGroupKey) {
+		this.ownerSecGroupKey = ownerSecGroupKey;
+	}
+
+	public Long getParticipantSecGroupKey() {
+		return participantSecGroupKey;
+	}
+
+	public void setParticipantSecGroupKey(Long participantSecGroupKey) {
+		this.participantSecGroupKey = participantSecGroupKey;
+	}
+
+	@Override
+	public int hashCode() {
+		return key == null ? 925867 : key.hashCode();
+	}
+
+	@Override
+	public boolean equals(Object obj) {
+		if(this == obj) {
+			return true;
+		}
+		if(obj instanceof ContactKeyOwnerView) {
+			ContactKeyOwnerView msg = (ContactKeyOwnerView)obj;
+			return key != null && key.equals(msg.key);
+		}
+		return false;
+	}
+
+	@Override
+	public boolean equalsByPersistableKey(Persistable persistable) {
+		return equals(persistable);
+	}
+}
diff --git a/src/main/java/org/olat/group/model/ContactKeyParticipantView.java b/src/main/java/org/olat/group/model/ContactKeyParticipantView.java
new file mode 100644
index 00000000000..8a8c70a2409
--- /dev/null
+++ b/src/main/java/org/olat/group/model/ContactKeyParticipantView.java
@@ -0,0 +1,110 @@
+/**
+ * <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 javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+import javax.persistence.Table;
+
+import org.hibernate.annotations.GenericGenerator;
+import org.olat.core.id.Persistable;
+
+/**
+ * The view list all visible owners
+ * Initial date: 24.1.2014<br>
+ * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
+ *
+ */
+@Entity
+@Table(name="o_gp_contactkey_participant_v")
+public class ContactKeyParticipantView implements Persistable {
+
+	private static final long serialVersionUID = 5125563005863650603L;
+
+	@Id
+	@GeneratedValue(generator = "system-uuid")
+	@GenericGenerator(name = "system-uuid", strategy = "hilo")
+	@Column(name="membership_id", nullable=false, unique=true, insertable=true, updatable=false)
+	private Long key;
+	@Column(name="bg_part_member_id", nullable=false, insertable=true, updatable=false)
+	private Long identityKey;
+	@Column(name="bg_owner_sec_id", nullable=false, insertable=true, updatable=false)
+	private Long ownerSecGroupKey;
+	@Column(name="bg_part_sec_id", nullable=false, insertable=true, updatable=false)
+	private Long participantSecGroupKey;
+
+
+	@Override
+	public Long getKey() {
+		return key;
+	}
+	
+	public void setKey(Long key) {
+		this.key = key;
+	}
+
+	public Long getIdentityKey() {
+		return identityKey;
+	}
+
+	public void setIdentityKey(Long identityKey) {
+		this.identityKey = identityKey;
+	}
+
+	public Long getOwnerSecGroupKey() {
+		return ownerSecGroupKey;
+	}
+
+	public void setOwnerSecGroupKey(Long ownerSecGroupKey) {
+		this.ownerSecGroupKey = ownerSecGroupKey;
+	}
+
+	public Long getParticipantSecGroupKey() {
+		return participantSecGroupKey;
+	}
+
+	public void setParticipantSecGroupKey(Long participantSecGroupKey) {
+		this.participantSecGroupKey = participantSecGroupKey;
+	}
+
+	@Override
+	public int hashCode() {
+		return key == null ? 925867 : key.hashCode();
+	}
+
+	@Override
+	public boolean equals(Object obj) {
+		if(this == obj) {
+			return true;
+		}
+		if(obj instanceof ContactKeyParticipantView) {
+			ContactKeyParticipantView msg = (ContactKeyParticipantView)obj;
+			return key != null && key.equals(msg.key);
+		}
+		return false;
+	}
+
+	@Override
+	public boolean equalsByPersistableKey(Persistable persistable) {
+		return equals(persistable);
+	}
+}
\ No newline at end of file
diff --git a/src/main/java/org/olat/group/model/BusinessGroupOwnerViewImpl.java b/src/main/java/org/olat/group/model/ContactOwnerView.java
similarity index 91%
rename from src/main/java/org/olat/group/model/BusinessGroupOwnerViewImpl.java
rename to src/main/java/org/olat/group/model/ContactOwnerView.java
index 40c7328bd21..66ab7f8fd31 100644
--- a/src/main/java/org/olat/group/model/BusinessGroupOwnerViewImpl.java
+++ b/src/main/java/org/olat/group/model/ContactOwnerView.java
@@ -36,14 +36,14 @@ import org.olat.group.BusinessGroupMemberView;
  *
  */
 @Entity
-@Table(name="o_gp_visible_owner_v")
-public class BusinessGroupOwnerViewImpl implements BusinessGroupMemberView, Persistable {
+@Table(name="o_gp_contact_owner_v")
+public class ContactOwnerView implements BusinessGroupMemberView, Persistable {
 
 	private static final long serialVersionUID = 5125563005863650603L;
 
 	@Id
-  @GeneratedValue(generator = "system-uuid")
-  @GenericGenerator(name = "system-uuid", strategy = "hilo")
+	@GeneratedValue(generator = "system-uuid")
+	@GenericGenerator(name = "system-uuid", strategy = "hilo")
 	@Column(name="membership_id", nullable=false, unique=true, insertable=true, updatable=false)
 	private Long key;
 	
@@ -127,8 +127,8 @@ public class BusinessGroupOwnerViewImpl implements BusinessGroupMemberView, Pers
 		if(this == obj) {
 			return true;
 		}
-		if(obj instanceof BusinessGroupOwnerViewImpl) {
-			BusinessGroupOwnerViewImpl msg = (BusinessGroupOwnerViewImpl)obj;
+		if(obj instanceof ContactOwnerView) {
+			ContactOwnerView msg = (ContactOwnerView)obj;
 			return key != null && key.equals(msg.key);
 		}
 		return false;
diff --git a/src/main/java/org/olat/group/model/BusinessGroupParticipantViewImpl.java b/src/main/java/org/olat/group/model/ContactParticipantView.java
similarity index 93%
rename from src/main/java/org/olat/group/model/BusinessGroupParticipantViewImpl.java
rename to src/main/java/org/olat/group/model/ContactParticipantView.java
index 257f2e5db0b..45d7aecc462 100644
--- a/src/main/java/org/olat/group/model/BusinessGroupParticipantViewImpl.java
+++ b/src/main/java/org/olat/group/model/ContactParticipantView.java
@@ -36,8 +36,8 @@ import org.olat.group.BusinessGroupMemberView;
  *
  */
 @Entity
-@Table(name="o_gp_visible_participant_v")
-public class BusinessGroupParticipantViewImpl implements BusinessGroupMemberView, Persistable {
+@Table(name="o_gp_contact_participant_v")
+public class ContactParticipantView implements BusinessGroupMemberView, Persistable {
 
 	private static final long serialVersionUID = 5125563005863650603L;
 
@@ -128,8 +128,8 @@ public class BusinessGroupParticipantViewImpl implements BusinessGroupMemberView
 		if(this == obj) {
 			return true;
 		}
-		if(obj instanceof BusinessGroupParticipantViewImpl) {
-			BusinessGroupParticipantViewImpl msg = (BusinessGroupParticipantViewImpl)obj;
+		if(obj instanceof ContactParticipantView) {
+			ContactParticipantView msg = (ContactParticipantView)obj;
 			return key != null && key.equals(msg.key);
 		}
 		return false;
diff --git a/src/main/java/org/olat/group/model/DisplayMembers.java b/src/main/java/org/olat/group/model/DisplayMembers.java
deleted file mode 100644
index 03c0fe6a789..00000000000
--- a/src/main/java/org/olat/group/model/DisplayMembers.java
+++ /dev/null
@@ -1,103 +0,0 @@
-/**
- * <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;
-
-/**
- * 
- * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
- */
-public class DisplayMembers {
-	
-	private boolean showOwners;
-	private boolean showParticipants;
-	private boolean showWaitingList;
-	
-	private boolean ownersPublic;
-	private boolean participantsPublic;
-	private boolean waitingListPublic;
-	
-	private boolean downloadLists;
-	
-	public DisplayMembers() {
-		//
-	}
-	
-	public DisplayMembers(boolean showOwners, boolean showParticipants, boolean showWaitingList) {
-		this.showOwners = showOwners;
-		this.showParticipants = showParticipants;
-		this.showWaitingList = showWaitingList;
-	}
-	
-	public boolean isShowOwners() {
-		return showOwners;
-	}
-	
-	public void setShowOwners(boolean showOwners) {
-		this.showOwners = showOwners;
-	}
-	
-	public boolean isShowParticipants() {
-		return showParticipants;
-	}
-	
-	public void setShowParticipants(boolean showParticipants) {
-		this.showParticipants = showParticipants;
-	}
-	
-	public boolean isShowWaitingList() {
-		return showWaitingList;
-	}
-	
-	public void setShowWaitingList(boolean showWaitingList) {
-		this.showWaitingList = showWaitingList;
-	}
-
-	public boolean isOwnersPublic() {
-		return ownersPublic;
-	}
-
-	public void setOwnersPublic(boolean ownersPublic) {
-		this.ownersPublic = ownersPublic;
-	}
-
-	public boolean isParticipantsPublic() {
-		return participantsPublic;
-	}
-
-	public void setParticipantsPublic(boolean participantsPublic) {
-		this.participantsPublic = participantsPublic;
-	}
-
-	public boolean isWaitingListPublic() {
-		return waitingListPublic;
-	}
-
-	public void setWaitingListPublic(boolean waitingListPublic) {
-		this.waitingListPublic = waitingListPublic;
-	}
-
-	public boolean isDownloadLists() {
-		return downloadLists;
-	}
-
-	public void setDownloadLists(boolean downloadLists) {
-		this.downloadLists = downloadLists;
-	}
-}
diff --git a/src/main/java/org/olat/group/ui/edit/BusinessGroupEditController.java b/src/main/java/org/olat/group/ui/edit/BusinessGroupEditController.java
index 208c829e036..7a6a5df9e16 100644
--- a/src/main/java/org/olat/group/ui/edit/BusinessGroupEditController.java
+++ b/src/main/java/org/olat/group/ui/edit/BusinessGroupEditController.java
@@ -290,8 +290,13 @@ public class BusinessGroupEditController extends BasicController implements Cont
 				// do logging
 				ThreadLocalUserActivityLogger.log(GroupLoggingAction.GROUP_CONFIGURATION_CHANGED, getClass());
 			}
-		} 
-		else if (source == tabAccessCtrl) {
+		} else if (source == membersController) {
+			if (event == Event.DONE_EVENT || event == Event.CHANGED_EVENT) {
+				//reload the business group
+				currBusinessGroup = membersController.getGroup();
+				fireEvent(ureq, event);
+			}
+		} else if (source == tabAccessCtrl) {
 			setAllTabs(ureq);
 			fireEvent(ureq, event);
 		} else if (source == resourceController) {
diff --git a/src/main/java/org/olat/group/ui/edit/BusinessGroupMembersController.java b/src/main/java/org/olat/group/ui/edit/BusinessGroupMembersController.java
index cdd3071527f..8fa9afb958a 100644
--- a/src/main/java/org/olat/group/ui/edit/BusinessGroupMembersController.java
+++ b/src/main/java/org/olat/group/ui/edit/BusinessGroupMembersController.java
@@ -47,7 +47,6 @@ import org.olat.group.BusinessGroupManagedFlag;
 import org.olat.group.BusinessGroupService;
 import org.olat.group.GroupLoggingAction;
 import org.olat.group.model.BusinessGroupMembershipChange;
-import org.olat.group.model.DisplayMembers;
 import org.olat.group.ui.main.MemberPermissionChangeEvent;
 import org.olat.group.ui.main.SearchMembersParams;
 
@@ -80,14 +79,13 @@ public class BusinessGroupMembersController extends BasicController {
 
 		// Member Display Form, allows to enable/disable that others partips see
 		// partips and/or owners
-		DisplayMembers displayMembers = businessGroupService.getDisplayMembers(businessGroup);
 		// configure the form with checkboxes for owners and/or partips according
 		// the booleans
 		dmsForm = new DisplayMemberSwitchForm(ureq, getWindowControl(), true, true, hasWaitingList);
 		dmsForm.setEnabled(!BusinessGroupManagedFlag.isManaged(businessGroup, BusinessGroupManagedFlag.display));
 		listenTo(dmsForm);
 		// set if the checkboxes are checked or not.
-		dmsForm.setDisplayMembers(displayMembers);
+		dmsForm.setDisplayMembers(businessGroup);
 		mainVC.put("displayMembers", dmsForm.getInitialComponent());
 		
 		boolean managed = BusinessGroupManagedFlag.isManaged(businessGroup, BusinessGroupManagedFlag.membersmanagement);
@@ -109,6 +107,10 @@ public class BusinessGroupMembersController extends BasicController {
 		mainVC.put("importMembers", importMemberLink);
 	}
 	
+	public BusinessGroup getGroup() {
+		return businessGroup;
+	}
+	
 	@Override
 	protected void doDispose() {
 		//
@@ -140,11 +142,23 @@ public class BusinessGroupMembersController extends BasicController {
 	protected void event(UserRequest ureq, Controller source, Event event) {
 		if (source == dmsForm) {
 			if(event == Event.CHANGED_EVENT) {
-				businessGroupService.updateDisplayMembers(businessGroup, dmsForm.getDisplayMembers());
+				boolean ownersIntern = dmsForm.isDisplayOwnersIntern();
+				boolean participantsIntern = dmsForm.isDisplayParticipantsIntern();
+				boolean waitingIntern = dmsForm.isDisplayWaitingListIntern();
+				boolean ownersPublic = dmsForm.isDisplayOwnersPublic();
+				boolean participantsPublic = dmsForm.isDisplayParticipantsPublic();
+				boolean waitingPublic = dmsForm.isDisplayWaitingListPublic();
+				boolean download = dmsForm.isDownloadList();
+				
+				businessGroup = businessGroupService.updateDisplayMembers(businessGroup,
+						ownersIntern, participantsIntern, waitingIntern,
+						ownersPublic, participantsPublic, waitingPublic,
+						download);
 				// notify current active users of this business group
 				BusinessGroupModifiedEvent.fireModifiedGroupEvents(BusinessGroupModifiedEvent.CONFIGURATION_MODIFIED_EVENT, businessGroup, null);
 				// do loggin
 				ThreadLocalUserActivityLogger.log(GroupLoggingAction.GROUP_CONFIGURATION_CHANGED, getClass());
+				fireEvent(ureq, event);
 			}
 		} else if(source == importMembersWizard) {
 			if(event == Event.CANCELLED_EVENT || event == Event.DONE_EVENT || event == Event.CHANGED_EVENT) {
diff --git a/src/main/java/org/olat/group/ui/edit/DisplayMemberSwitchForm.java b/src/main/java/org/olat/group/ui/edit/DisplayMemberSwitchForm.java
index e2a210e8539..7347c4d1f29 100644
--- a/src/main/java/org/olat/group/ui/edit/DisplayMemberSwitchForm.java
+++ b/src/main/java/org/olat/group/ui/edit/DisplayMemberSwitchForm.java
@@ -34,7 +34,7 @@ import org.olat.core.gui.components.form.flexible.impl.FormEvent;
 import org.olat.core.gui.control.Controller;
 import org.olat.core.gui.control.Event;
 import org.olat.core.gui.control.WindowControl;
-import org.olat.group.model.DisplayMembers;
+import org.olat.group.BusinessGroup;
 
 
 
@@ -70,26 +70,42 @@ public class DisplayMemberSwitchForm extends FormBasicController {
 		initForm(ureq);
 	}
 	
-	public DisplayMembers getDisplayMembers() {
-		DisplayMembers displayMembers = new DisplayMembers();
-		displayMembers.setShowOwners(showOwners.isSelected(0));
-		displayMembers.setShowParticipants(showPartips.isSelected(0));
-		displayMembers.setShowWaitingList(showWaitingList.isVisible() && showWaitingList.isEnabled() && showWaitingList.isSelected(0));
-		displayMembers.setOwnersPublic(openOwners.isSelected(0));
-		displayMembers.setParticipantsPublic(openPartips.isSelected(0));
-		displayMembers.setWaitingListPublic(openWaitingList.isVisible() && openWaitingList.isEnabled() && openWaitingList.isSelected(0));
-		displayMembers.setDownloadLists(downloadList.isSelected(0));
-		return displayMembers;
+	public boolean isDisplayOwnersIntern() {
+		return showOwners.isSelected(0);
 	}
 	
-	public void setDisplayMembers(DisplayMembers displayMembers) {
-		showOwners.select("show_owners", displayMembers.isShowOwners());
-		showPartips.select("show_participants", displayMembers.isShowParticipants());
-		showWaitingList.select("show_waiting_list", displayMembers.isShowWaitingList());
-		openOwners.select("open_owners", displayMembers.isOwnersPublic());
-		openPartips.select("open_participants", displayMembers.isParticipantsPublic());
-		openWaitingList.select("open_waiting_list", displayMembers.isWaitingListPublic());
-		downloadList.select("download_list", displayMembers.isDownloadLists());
+	public boolean isDisplayParticipantsIntern() {
+		return showPartips.isSelected(0);
+	}
+	
+	public boolean isDisplayWaitingListIntern() {
+		return showWaitingList.isVisible() && showWaitingList.isEnabled() && showWaitingList.isSelected(0);
+	}
+	
+	public boolean isDisplayOwnersPublic() {
+		return openOwners.isSelected(0);
+	}
+	
+	public boolean isDisplayParticipantsPublic() {
+		return openPartips.isSelected(0);
+	}
+	
+	public boolean isDisplayWaitingListPublic() {
+		return openWaitingList.isVisible() && openWaitingList.isEnabled() && openWaitingList.isSelected(0);
+	}
+	
+	public boolean isDownloadList() {
+		return downloadList.isSelected(0);
+	}
+	
+	public void setDisplayMembers(BusinessGroup group) {
+		showOwners.select("show_owners", group.isOwnersVisibleIntern());
+		showPartips.select("show_participants", group.isParticipantsVisibleIntern());
+		showWaitingList.select("show_waiting_list", group.isWaitingListVisibleIntern());
+		openOwners.select("open_owners", group.isOwnersVisiblePublic());
+		openPartips.select("open_participants", group.isParticipantsVisiblePublic());
+		openWaitingList.select("open_waiting_list", group.isWaitingListVisiblePublic());
+		downloadList.select("download_list", group.isDownloadMembersLists());
 	}
 	
 	public void setWaitingListReadOnly(boolean b) {
diff --git a/src/main/java/org/olat/group/ui/homepage/GroupInfoMainController.java b/src/main/java/org/olat/group/ui/homepage/GroupInfoMainController.java
index a11123a8e16..99b50346dfe 100644
--- a/src/main/java/org/olat/group/ui/homepage/GroupInfoMainController.java
+++ b/src/main/java/org/olat/group/ui/homepage/GroupInfoMainController.java
@@ -45,8 +45,6 @@ import org.olat.core.util.resource.OresHelper;
 import org.olat.core.util.tree.TreeHelper;
 import org.olat.group.BusinessGroup;
 import org.olat.group.BusinessGroupModule;
-import org.olat.group.BusinessGroupService;
-import org.olat.group.model.DisplayMembers;
 
 /**
  * 
@@ -66,7 +64,6 @@ public class GroupInfoMainController extends MainLayoutBasicController implement
 	
 	/** The business group we're dealing with */
 	private BusinessGroup businessGroup;
-	private DisplayMembers members;
 	
 	/** The navigation tree */
 	private MenuTree menuTree;
@@ -76,15 +73,12 @@ public class GroupInfoMainController extends MainLayoutBasicController implement
 	private GroupContactController groupContactController;
 	
 	private final BusinessGroupModule module;
-	private final BusinessGroupService businessGroupService;
 	
 	public GroupInfoMainController(UserRequest ureq, WindowControl wControl, BusinessGroup businessGroup) {
 		// Initialize
 		super(ureq, wControl);
 		this.businessGroup = businessGroup;
 		module = CoreSpringFactory.getImpl(BusinessGroupModule.class);
-		businessGroupService = CoreSpringFactory.getImpl(BusinessGroupService.class);
-		members = businessGroupService.getDisplayMembers(businessGroup);
 
 		menuTree = new MenuTree("menuTree");
 		menuTree.setRootVisible(false);
@@ -176,7 +170,7 @@ public class GroupInfoMainController extends MainLayoutBasicController implement
 		if(groupMembersDisplayController == null) {
 			OLATResourceable ores = OresHelper.createOLATResourceableInstance("Members", 0l);
 			WindowControl bwControl = BusinessControlFactory.getInstance().createBusinessWindowControl(ores, null, getWindowControl());
-			groupMembersDisplayController = new GroupMembersDisplayController(ureq, bwControl, businessGroup, members);
+			groupMembersDisplayController = new GroupMembersDisplayController(ureq, bwControl, businessGroup);
 			listenTo(groupMembersDisplayController);
 		}
 		
@@ -214,7 +208,7 @@ public class GroupInfoMainController extends MainLayoutBasicController implement
 		rootNode.addChild(childNode);
 		rootNode.setDelegate(childNode);
 		
-		if(members.isOwnersPublic() || members.isParticipantsPublic() || members.isWaitingListPublic()) {
+		if(businessGroup.isOwnersVisiblePublic() || businessGroup.isParticipantsVisiblePublic() || businessGroup.isWaitingListVisiblePublic()) {
 			childNode = new GenericTreeNode();
 			childNode.setTitle(translate("main.menu.members"));
 			childNode.setUserObject(COMMAND_MENU_GROUPMEMBERS);
diff --git a/src/main/java/org/olat/group/ui/homepage/GroupMembersDisplayController.java b/src/main/java/org/olat/group/ui/homepage/GroupMembersDisplayController.java
index dab84cbf98e..78a8d5b29de 100644
--- a/src/main/java/org/olat/group/ui/homepage/GroupMembersDisplayController.java
+++ b/src/main/java/org/olat/group/ui/homepage/GroupMembersDisplayController.java
@@ -27,7 +27,6 @@ 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.group.BusinessGroup;
-import org.olat.group.model.DisplayMembers;
 
 /**
  * 
@@ -40,22 +39,22 @@ public class GroupMembersDisplayController extends BasicController {
 
 	private final VelocityContainer content;
 
-	public GroupMembersDisplayController(UserRequest ureq, WindowControl wControl, BusinessGroup businessGroup, DisplayMembers members) {
+	public GroupMembersDisplayController(UserRequest ureq, WindowControl wControl, BusinessGroup businessGroup) {
 		super(ureq, wControl);
 		// display owners and participants
 		content = createVelocityContainer("groupmembersdisplay");
 
-		if(members.isOwnersPublic()) {
+		if(businessGroup.isOwnersVisiblePublic()) {
 			GroupController groupOwnersController = new GroupController(ureq, wControl, false, true, false, false, false, false, businessGroup.getOwnerGroup());
 			content.put("owners", groupOwnersController.getInitialComponent());
 			listenTo(groupOwnersController);
 		}
-		if(members.isParticipantsPublic()) {
+		if(businessGroup.isParticipantsVisiblePublic()) {
 			GroupController groupParticipantsController = new GroupController(ureq, wControl, false, true, false, false, false, false, businessGroup.getPartipiciantGroup());
 			content.put("participants", groupParticipantsController.getInitialComponent());
 			listenTo(groupParticipantsController);
 		}
-		if(members.isWaitingListPublic()) {
+		if(businessGroup.isWaitingListVisiblePublic()) {
 			GroupController groupWaitingListController = new GroupController(ureq, wControl, false, true, false, false, false, false, businessGroup.getWaitingGroup());
 			content.put("waitingList", groupWaitingListController.getInitialComponent());
 			listenTo(groupWaitingListController);
diff --git a/src/main/java/org/olat/group/ui/run/BusinessGroupMainRunController.java b/src/main/java/org/olat/group/ui/run/BusinessGroupMainRunController.java
index 470620e799d..2a998ee9893 100644
--- a/src/main/java/org/olat/group/ui/run/BusinessGroupMainRunController.java
+++ b/src/main/java/org/olat/group/ui/run/BusinessGroupMainRunController.java
@@ -82,7 +82,6 @@ import org.olat.group.BusinessGroup;
 import org.olat.group.BusinessGroupMembership;
 import org.olat.group.BusinessGroupService;
 import org.olat.group.GroupLoggingAction;
-import org.olat.group.model.DisplayMembers;
 import org.olat.group.ui.BGControllerFactory;
 import org.olat.group.ui.edit.BusinessGroupEditController;
 import org.olat.group.ui.edit.BusinessGroupModifiedEvent;
@@ -737,9 +736,8 @@ public class BusinessGroupMainRunController extends MainLayoutBasicController im
 	private void doShowMembers(UserRequest ureq) {
 		VelocityContainer membersVc = createVelocityContainer("ownersandmembers");
 		// 1. show owners if configured with Owners
-		DisplayMembers displayMembers = businessGroupService.getDisplayMembers(businessGroup);
-		boolean downloadAllowed = displayMembers.isDownloadLists();
-		if (displayMembers.isShowOwners()) {
+		boolean downloadAllowed = businessGroup.isDownloadMembersLists();
+		if (businessGroup.isOwnersVisibleIntern()) {
 			removeAsListenerAndDispose(gownersC);
 			gownersC = new GroupController(ureq, getWindowControl(), false, true, true, false, downloadAllowed, false, businessGroup.getOwnerGroup());
 			listenTo(gownersC);
@@ -749,7 +747,7 @@ public class BusinessGroupMainRunController extends MainLayoutBasicController im
 			membersVc.contextPut("showOwnerGroups", Boolean.FALSE);
 		}
 		// 2. show participants if configured with Participants
-		if (displayMembers.isShowParticipants()) {
+		if (businessGroup.isParticipantsVisibleIntern()) {
 			removeAsListenerAndDispose(gparticipantsC);
 			gparticipantsC = new GroupController(ureq, getWindowControl(), false, true, false, false, downloadAllowed, false, businessGroup.getPartipiciantGroup());
 			listenTo(gparticipantsC);
@@ -761,7 +759,7 @@ public class BusinessGroupMainRunController extends MainLayoutBasicController im
 		}
 		// 3. show waiting-list if configured 
 		membersVc.contextPut("hasWaitingList", new Boolean(businessGroup.getWaitingListEnabled()) );
-		if (displayMembers.isShowWaitingList()) {
+		if (businessGroup.isWaitingListVisibleIntern()) {
 			removeAsListenerAndDispose(waitingListController);
 			waitingListController = new GroupController(ureq, getWindowControl(), false, true, false, false, downloadAllowed, false, businessGroup.getWaitingGroup());
 			listenTo(waitingListController);
@@ -1027,8 +1025,7 @@ public class BusinessGroupMainRunController extends MainLayoutBasicController im
 			nodeResources = gtnChild;
 		}
 
-		DisplayMembers displayMembers = businessGroupService.getDisplayMembers(businessGroup);
-		if (displayMembers.isShowOwners() || displayMembers.isShowParticipants()) {
+		if (businessGroup.isOwnersVisibleIntern() || businessGroup.isParticipantsVisibleIntern()) {
 			// either owners or participants, or both are visible
 			// otherwise the node is not visible
 			gtnChild = new GenericTreeNode();
diff --git a/src/main/java/org/olat/group/ui/run/BusinessGroupSendToChooserForm.java b/src/main/java/org/olat/group/ui/run/BusinessGroupSendToChooserForm.java
index ca37f2c3e5c..eb090a2b17f 100644
--- a/src/main/java/org/olat/group/ui/run/BusinessGroupSendToChooserForm.java
+++ b/src/main/java/org/olat/group/ui/run/BusinessGroupSendToChooserForm.java
@@ -32,7 +32,6 @@ import java.util.Set;
 
 import org.olat.basesecurity.BaseSecurityManager;
 import org.olat.basesecurity.SecurityGroup;
-import org.olat.core.CoreSpringFactory;
 import org.olat.core.gui.UserRequest;
 import org.olat.core.gui.components.form.flexible.FormItem;
 import org.olat.core.gui.components.form.flexible.FormItemContainer;
@@ -48,19 +47,13 @@ import org.olat.core.id.Identity;
 import org.olat.core.id.User;
 import org.olat.core.util.ArrayHelper;
 import org.olat.group.BusinessGroup;
-import org.olat.group.BusinessGroupService;
-import org.olat.group.model.DisplayMembers;
 import org.olat.user.UserManager;
 import org.olat.user.propertyhandlers.UserPropertyHandler;
 
 /**
- * Description: <BR>
- * TODO: Class Description for BusinessGroupSendToChooserForm
- * <P>
  * 
  * @author patrick
  */
-
 public class BusinessGroupSendToChooserForm extends FormBasicController {
 
 	private BusinessGroup businessGroup;
@@ -108,10 +101,8 @@ public class BusinessGroupSendToChooserForm extends FormBasicController {
 		this.isAdmin = isAdmin;
 		
 		// check 'members can see owners' and 'members can see participants' 
-		BusinessGroupService businessGroupService = CoreSpringFactory.getImpl(BusinessGroupService.class);
-		DisplayMembers displayMembers = businessGroupService.getDisplayMembers(businessGroup);
-		showChooseOwners  = displayMembers.isShowOwners();
-		showChoosePartips = displayMembers.isShowParticipants();
+		showChooseOwners  = businessGroup.isOwnersVisibleIntern();
+		showChoosePartips = businessGroup.isParticipantsVisibleIntern();
 		showWaitingList = isAdmin && businessGroup.getWaitingListEnabled().booleanValue();
 		
 		if (isMultiSelectionOwnerKeys())  {
diff --git a/src/main/java/org/olat/instantMessaging/manager/InstantMessagingServiceImpl.java b/src/main/java/org/olat/instantMessaging/manager/InstantMessagingServiceImpl.java
index 3be8b576b74..70c9305b52b 100644
--- a/src/main/java/org/olat/instantMessaging/manager/InstantMessagingServiceImpl.java
+++ b/src/main/java/org/olat/instantMessaging/manager/InstantMessagingServiceImpl.java
@@ -44,8 +44,8 @@ import org.olat.group.BusinessGroup;
 import org.olat.group.BusinessGroupMemberView;
 import org.olat.group.DeletableGroupData;
 import org.olat.group.manager.ContactDAO;
-import org.olat.group.model.BusinessGroupOwnerViewImpl;
-import org.olat.group.model.BusinessGroupParticipantViewImpl;
+import org.olat.group.model.ContactOwnerView;
+import org.olat.group.model.ContactParticipantView;
 import org.olat.instantMessaging.ImPreferences;
 import org.olat.instantMessaging.InstantMessage;
 import org.olat.instantMessaging.InstantMessageNotification;
@@ -268,14 +268,14 @@ public class InstantMessagingServiceImpl extends BasicManager implements Instant
 		List<BuddyGroup> groups = new ArrayList<BuddyGroup>(25);
 		Map<Long,BuddyGroup> groupMap = new HashMap<Long,BuddyGroup>();
 		Map<Long, String> identityKeyToStatus = new HashMap<Long, String>();
-		List<BusinessGroupOwnerViewImpl> ownerList = contactDao.getGroupOwners(me);
+		List<ContactOwnerView> ownerList = contactDao.getGroupOwners(me);
 		collectMembersStatus(ownerList, identityKeyToStatus);
-		List<BusinessGroupParticipantViewImpl> participantList = contactDao.getParticipants(me);
+		List<ContactParticipantView> participantList = contactDao.getParticipants(me);
 		collectMembersStatus(participantList, identityKeyToStatus);
-		for(BusinessGroupOwnerViewImpl owner:ownerList) {
+		for(ContactOwnerView owner:ownerList) {
 			addBuddyToGroupList(owner, me, groupMap, groups, identityKeyToStatus, true, offlineUsers);
 		}
-		for(BusinessGroupParticipantViewImpl participant:participantList) {
+		for(ContactParticipantView participant:participantList) {
 			addBuddyToGroupList(participant, me, groupMap, groups, identityKeyToStatus, false, offlineUsers);
 		}
 		
diff --git a/src/main/java/org/olat/properties/PropertyConstants.java b/src/main/java/org/olat/properties/PropertyConstants.java
deleted file mode 100644
index 3af3b0230d5..00000000000
--- a/src/main/java/org/olat/properties/PropertyConstants.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/**
-* OLAT - Online Learning and Training<br>
-* http://www.olat.org
-* <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
-* <p>
-* http://www.apache.org/licenses/LICENSE-2.0
-* <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>
-* Copyright (c) since 2004 at Multimedia- & E-Learning Services (MELS),<br>
-* University of Zurich, Switzerland.
-* <hr>
-* <a href="http://www.openolat.org">
-* OpenOLAT - Online Learning and Training</a><br>
-* This file has been modified by the OpenOLAT community. Changes are licensed
-* under the Apache 2.0 license as the original file.
-*/
-
-package org.olat.properties;
-
-/**
- *  Description:<br>
- *  Constants used in the Properties Table.
- *
- * @author Felix Jost
- */
-public class PropertyConstants {
-    /**
-     * Resource is visited by a certain user.
-     */
-	public static final String OLATRESOURCE_VISITED = "rvst";
-    /**
-     * loosly coupled configuration attributes for a resource
-     */
-    public static final String OLATRESOURCE_CONFIGURATION = "config";
-}
diff --git a/src/main/java/org/olat/restapi/group/LearningGroupWebService.java b/src/main/java/org/olat/restapi/group/LearningGroupWebService.java
index bfc8abbbc8f..565b8b6365a 100644
--- a/src/main/java/org/olat/restapi/group/LearningGroupWebService.java
+++ b/src/main/java/org/olat/restapi/group/LearningGroupWebService.java
@@ -65,7 +65,6 @@ import org.olat.core.util.vfs.restapi.VFSWebservice;
 import org.olat.group.BusinessGroup;
 import org.olat.group.BusinessGroupAddResponse;
 import org.olat.group.BusinessGroupService;
-import org.olat.group.model.DisplayMembers;
 import org.olat.group.model.SearchBusinessGroupParams;
 import org.olat.modules.fo.Forum;
 import org.olat.modules.fo.restapi.ForumWebService;
@@ -282,7 +281,7 @@ public class LearningGroupWebService {
 		}
 		
 		final BusinessGroupService bgs = CoreSpringFactory.getImpl(BusinessGroupService.class);
-		final BusinessGroup bg = bgs.loadBusinessGroup(groupKey);
+		BusinessGroup bg = bgs.loadBusinessGroup(groupKey);
 		if(bg == null) {
 			return Response.serverError().status(Status.NOT_FOUND).build();
 		}
@@ -304,26 +303,34 @@ public class LearningGroupWebService {
 			tools.setToolEnabled(tool, enable);
 		}
 		
-		DisplayMembers displayMembers = bgs.getDisplayMembers(bg);
+		boolean ownersIntern = bg.isOwnersVisibleIntern();
 		if(group.getOwnersVisible() != null) {
-			displayMembers.setShowOwners(group.getOwnersVisible().booleanValue());
+			ownersIntern = group.getOwnersVisible().booleanValue();
 		}
+		boolean participantsIntern = bg.isParticipantsVisibleIntern();
 		if(group.getParticipantsVisible() != null) {
-			displayMembers.setShowParticipants(group.getParticipantsVisible().booleanValue());
+			participantsIntern = group.getParticipantsVisible().booleanValue();
 		}
+		boolean waitingListIntern = bg.isWaitingListVisibleIntern();
 		if(group.getWaitingListVisible() != null) {
-			displayMembers.setShowWaitingList(group.getWaitingListVisible().booleanValue());
+			waitingListIntern = group.getWaitingListVisible().booleanValue();
 		}
+		boolean ownersPublic = bg.isOwnersVisiblePublic();
 		if(group.getOwnersPublic() != null) {
-			displayMembers.setOwnersPublic(group.getOwnersPublic().booleanValue());
+			ownersPublic = group.getOwnersPublic().booleanValue();
 		}
+		boolean participantsPublic = bg.isParticipantsVisiblePublic();
 		if(group.getParticipantsPublic() != null) {
-			displayMembers.setParticipantsPublic(group.getParticipantsPublic().booleanValue());
+			participantsPublic = group.getParticipantsPublic().booleanValue();
 		}
+		boolean waitingListPublic = bg.isWaitingListVisiblePublic();
 		if(group.getWaitingListPublic() != null) {
-			displayMembers.setWaitingListPublic(group.getWaitingListPublic().booleanValue());
+			waitingListPublic = group.getWaitingListPublic().booleanValue();
 		}
-		bgs.updateDisplayMembers(bg, displayMembers);
+		bg = bgs.updateDisplayMembers(bg,
+				ownersIntern, participantsIntern, waitingListIntern,
+				ownersPublic, participantsPublic, waitingListPublic,
+				bg.isDownloadMembersLists());
 		return Response.ok().build();
 	}
 	
@@ -502,8 +509,7 @@ public class LearningGroupWebService {
 			if(!bgs.isIdentityInBusinessGroup(identity, bg)) {
 				return Response.serverError().status(Status.UNAUTHORIZED).build();
 			}
-			DisplayMembers displayMembers = bgs.getDisplayMembers(bg);
-			if(!displayMembers.isShowOwners()) {
+			if(!bg.isOwnersVisibleIntern()) {
 				return Response.serverError().status(Status.UNAUTHORIZED).build();
 			}
 		}
@@ -537,8 +543,7 @@ public class LearningGroupWebService {
 			if(!bgs.isIdentityInBusinessGroup(identity, bg)) {
 				return Response.serverError().status(Status.UNAUTHORIZED).build();
 			}
-			DisplayMembers displayMembers = bgs.getDisplayMembers(bg);
-			if(!displayMembers.isShowParticipants()) {
+			if(!bg.isParticipantsVisibleIntern()) {
 				return Response.serverError().status(Status.UNAUTHORIZED).build();
 			}
 		}
diff --git a/src/main/java/org/olat/upgrade/OLATUpgrade_9_4_0.java b/src/main/java/org/olat/upgrade/OLATUpgrade_9_4_0.java
new file mode 100644
index 00000000000..0f3eb5615fe
--- /dev/null
+++ b/src/main/java/org/olat/upgrade/OLATUpgrade_9_4_0.java
@@ -0,0 +1,176 @@
+/**
+ * <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.upgrade;
+
+import java.util.List;
+
+import org.olat.core.commons.persistence.DB;
+import org.olat.core.util.mail.MailManager;
+import org.olat.group.BusinessGroup;
+import org.olat.group.BusinessGroupImpl;
+import org.olat.properties.Property;
+import org.olat.properties.PropertyManager;
+import org.springframework.beans.factory.annotation.Autowired;
+
+/**
+ * 
+ * Initial date: 23.01.2014<br>
+ * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
+ *
+ */
+public class OLATUpgrade_9_4_0 extends OLATUpgrade {
+	
+	private static final int BATCH_SIZE = 50;
+	private static final String TASK_DISPLAY_MEMBERS = "Upgrade display members";
+	private static final String VERSION = "OLAT_9.4.0";
+	
+	private static final String PROP_NAME = "displayMembers";
+	private static final String OLATRESOURCE_CONFIGURATION = "config";
+	
+	@Autowired
+	private DB dbInstance;
+	@Autowired
+	private MailManager mailManager;
+	@Autowired
+	private PropertyManager propertyManager;
+	
+	public OLATUpgrade_9_4_0() {
+		super();
+	}
+
+	@Override
+	public String getVersion() {
+		return VERSION;
+	}
+	
+	@Override
+	public boolean doPreSystemInitUpgrade(UpgradeManager upgradeManager) {
+		return false;
+	}
+
+	@Override
+	public boolean doPostSystemInitUpgrade(UpgradeManager upgradeManager) {
+		UpgradeHistoryData uhd = upgradeManager.getUpgradesHistory(VERSION);
+		if (uhd == null) {
+			// has never been called, initialize
+			uhd = new UpgradeHistoryData();
+		} else if (uhd.isInstallationComplete()) {
+			return false;
+		}
+		
+		boolean allOk = upgradeDisplayMembers(upgradeManager, uhd);
+		
+		uhd.setInstallationComplete(allOk);
+		upgradeManager.setUpgradesHistory(uhd, VERSION);
+		if(allOk) {
+			log.audit("Finished OLATUpgrade_9_4_0 successfully!");
+		} else {
+			log.audit("OLATUpgrade_9_4_0 not finished, try to restart OpenOLAT!");
+		}
+		return allOk;
+	}
+	
+	private static final int showOwnersVal      = 1;// 0x..0001
+	private static final int showPartipsVal     = 2;// 0x..0010
+	private static final int showWaitingListVal = 4;// 0x..0100
+	
+	private boolean upgradeDisplayMembers(UpgradeManager upgradeManager, UpgradeHistoryData uhd) {
+		if (!uhd.getBooleanDataValue(TASK_DISPLAY_MEMBERS)) {
+			int counter = 0;
+			List<BusinessGroupImpl> groups;
+			do {
+				groups = findGroups(counter, BATCH_SIZE);
+				for(BusinessGroupImpl group:groups) {
+					Property prop = findProperty(group);
+					if(prop != null) {
+						boolean changed = false;
+						
+						Long internValue = prop.getLongValue();
+						if(internValue != null && internValue.longValue() > 0) {
+							long value = internValue.longValue();
+							boolean owners = (value & showOwnersVal) == showOwnersVal;
+							boolean participants = (value & showPartipsVal) == showPartipsVal;
+							boolean waiting = (value & showWaitingListVal) == showWaitingListVal;
+							group.setOwnersVisibleIntern(owners);
+							group.setParticipantsVisibleIntern(participants);
+							group.setWaitingListVisibleIntern(waiting);
+							changed = true;
+						}
+						
+						String publicValue = prop.getStringValue();
+						if(publicValue != null && publicValue.length() > 0
+								&& Character.isDigit(publicValue.toCharArray()[0])) {
+							try {
+								int value = Integer.parseInt(publicValue);
+								boolean owners = (value & showOwnersVal) == showOwnersVal;
+								boolean participants = (value & showPartipsVal) == showPartipsVal;
+								boolean waiting = (value & showWaitingListVal) == showWaitingListVal;
+								group.setOwnersVisiblePublic(owners);
+								group.setParticipantsVisiblePublic(participants);
+								group.setWaitingListVisiblePublic(waiting);
+							} catch (NumberFormatException e) {
+								log.error("", e);
+							}
+							changed = true;
+						}
+						
+						Float downloadValue = prop.getFloatValue();
+						if(downloadValue != null && downloadValue != 0.0f) {
+							float value = downloadValue.floatValue();
+							//paranoid check
+							if(value > 0.9 && value < 1.1) {
+								group.setDownloadMembersLists(true);
+								changed = true;
+							} else if(value < -0.9 && value > -1.1) {
+								group.setDownloadMembersLists(true);
+								changed = true;
+							}
+						}
+						
+						if(changed) {
+							prop.setCategory("configMoved");
+							dbInstance.getCurrentEntityManager().merge(group);
+						}
+					}
+				}
+				counter += groups.size();
+				log.audit("Business groups processed: " + groups.size());
+				dbInstance.commitAndCloseSession();
+			} while(groups.size() == BATCH_SIZE);
+			uhd.setBooleanDataValue(TASK_DISPLAY_MEMBERS, false);
+			upgradeManager.setUpgradesHistory(uhd, VERSION);
+		}
+		return true;
+	}
+	
+	private List<BusinessGroupImpl> findGroups(int firstResult, int maxResults) {
+		StringBuilder sb = new StringBuilder();	
+		sb.append("select grp from ").append(BusinessGroupImpl.class.getName()).append(" grp order by key");
+		return dbInstance.getCurrentEntityManager().createQuery(sb.toString(), BusinessGroupImpl.class)
+				.setFirstResult(firstResult)
+				.setMaxResults(maxResults)
+				.getResultList();
+	}
+	
+	public Property findProperty(BusinessGroup group) {
+		Property prop = propertyManager.findProperty(null, group, group, OLATRESOURCE_CONFIGURATION, PROP_NAME);
+		return prop;
+	}
+}
diff --git a/src/main/java/org/olat/upgrade/_spring/upgradeContext.xml b/src/main/java/org/olat/upgrade/_spring/upgradeContext.xml
index a7337547593..837f7b674d9 100644
--- a/src/main/java/org/olat/upgrade/_spring/upgradeContext.xml
+++ b/src/main/java/org/olat/upgrade/_spring/upgradeContext.xml
@@ -39,6 +39,7 @@
 				<bean id="upgrade_8_4_0" class="org.olat.upgrade.OLATUpgrade_8_4_0"/>
 				<bean id="upgrade_8_4_5" class="org.olat.upgrade.OLATUpgrade_8_4_5"/>
 				<bean id="upgrade_9_0_0" class="org.olat.upgrade.OLATUpgrade_9_0_0"/>
+				<bean id="upgrade_9_4_0" class="org.olat.upgrade.OLATUpgrade_9_4_0"/>
 			</list>
 		</property>
 	</bean>
diff --git a/src/main/resources/database/mysql/alter_9_3_0_to_9_4_0.sql b/src/main/resources/database/mysql/alter_9_3_0_to_9_4_0.sql
new file mode 100644
index 00000000000..a193432dd01
--- /dev/null
+++ b/src/main/resources/database/mysql/alter_9_3_0_to_9_4_0.sql
@@ -0,0 +1,60 @@
+alter table o_gp_business add column ownersintern bit not null default 0;
+alter table o_gp_business add column participantsintern bit not null default 0;
+alter table o_gp_business add column waitingintern bit not null default 0;
+alter table o_gp_business add column ownerspublic bit not null default 0;
+alter table o_gp_business add column participantspublic bit not null default 0;
+alter table o_gp_business add column waitingpublic bit not null default 0;
+alter table o_gp_business add column downloadmembers bit not null default 0;
+
+create or replace view o_gp_contact_participant_v as
+   select
+      bg_part_member.id as membership_id,
+      bgroup.group_id as bg_id,
+      bgroup.groupname as bg_name,
+      bgroup.fk_partipiciantgroup as bg_part_sec_id,
+      bgroup.fk_ownergroup as bg_owner_sec_id,
+      bg_part_member.identity_id as bg_part_member_id,
+      ident.name as bg_part_member_name 
+   from o_gp_business as bgroup
+   inner join o_bs_membership as bg_part_member on (bg_part_member.secgroup_id = bgroup.fk_partipiciantgroup)
+   inner join o_bs_identity as ident on (bg_part_member.identity_id = ident.id)
+   where bgroup.participantsintern=1
+;
+   
+create or replace view o_gp_contact_owner_v as
+   select
+      bg_owner_member.id as membership_id,
+      bgroup.group_id as bg_id,
+      bgroup.groupname as bg_name,
+      bgroup.fk_partipiciantgroup as bg_part_sec_id,
+      bgroup.fk_ownergroup as bg_owner_sec_id,
+      bg_owner_member.identity_id as bg_owner_member_id,
+      ident.name as bg_owner_member_name
+   from o_gp_business as bgroup
+   inner join o_bs_membership as bg_owner_member on (bg_owner_member.secgroup_id = bgroup.fk_ownergroup)
+   inner join o_bs_identity as ident on (bg_owner_member.identity_id = ident.id)
+   where bgroup.ownersintern=1
+;
+
+create or replace view o_gp_contactkey_participant_v as
+   select
+      bg_part_member.id as membership_id,
+      bgroup.fk_partipiciantgroup as bg_part_sec_id,
+      bgroup.fk_ownergroup as bg_owner_sec_id,
+      bg_part_member.identity_id as bg_part_member_id
+   from o_gp_business as bgroup
+   inner join o_bs_membership as bg_part_member on (bg_part_member.secgroup_id = bgroup.fk_partipiciantgroup)
+   where bgroup.participantsintern=1
+;
+   
+create or replace view o_gp_contactkey_owner_v as
+   select
+      bg_owner_member.id as membership_id,
+      bgroup.fk_partipiciantgroup as bg_part_sec_id,
+      bgroup.fk_ownergroup as bg_owner_sec_id,
+      bg_owner_member.identity_id as bg_owner_member_id
+   from o_gp_business as bgroup
+   inner join o_bs_membership as bg_owner_member on (bg_owner_member.secgroup_id = bgroup.fk_ownergroup)
+   where bgroup.ownersintern=1
+;
+
diff --git a/src/main/resources/database/mysql/setupDatabase.sql b/src/main/resources/database/mysql/setupDatabase.sql
index 61f7c21c407..66ddae3947d 100644
--- a/src/main/resources/database/mysql/setupDatabase.sql
+++ b/src/main/resources/database/mysql/setupDatabase.sql
@@ -44,6 +44,13 @@ create table if not exists o_gp_business (
    maxparticipants integer,
    waitinglist_enabled bit,
    autocloseranks_enabled bit,
+   ownersintern bit not null default 0,
+   participantsintern bit not null default 0,
+   waitingintern bit not null default 0,
+   ownerspublic bit not null default 0,
+   participantspublic bit not null default 0,
+   waitingpublic bit not null default 0,
+   downloadmembers bit not null default 0,
    groupcontext_fk bigint,
    fk_resource bigint unique,
    fk_ownergroup bigint unique,
@@ -1504,7 +1511,8 @@ select
   where re1.repositoryentry_id is not null or re2.repositoryentry_id is not null
 ;
 
-create or replace view o_gp_visible_participant_v as (
+-- contacts
+create or replace view o_gp_contact_participant_v as
    select
       bg_part_member.id as membership_id,
       bgroup.group_id as bg_id,
@@ -1514,12 +1522,12 @@ create or replace view o_gp_visible_participant_v as (
       bg_part_member.identity_id as bg_part_member_id,
       ident.name as bg_part_member_name 
    from o_gp_business as bgroup
-   inner join o_property as bconfig on (bconfig.grp = bgroup.group_id and bconfig.name = 'displayMembers' and bconfig.category = 'config' and bconfig.longValue in (2,3,6,7))
    inner join o_bs_membership as bg_part_member on (bg_part_member.secgroup_id = bgroup.fk_partipiciantgroup)
    inner join o_bs_identity as ident on (bg_part_member.identity_id = ident.id)
- );
+   where bgroup.participantsintern=1
+;
    
-create or replace view o_gp_visible_owner_v as ( 
+create or replace view o_gp_contact_owner_v as
    select
       bg_owner_member.id as membership_id,
       bgroup.group_id as bg_id,
@@ -1529,10 +1537,32 @@ create or replace view o_gp_visible_owner_v as (
       bg_owner_member.identity_id as bg_owner_member_id,
       ident.name as bg_owner_member_name
    from o_gp_business as bgroup
-   inner join o_property as bconfig on (bconfig.grp = bgroup.group_id and bconfig.name = 'displayMembers' and bconfig.category = 'config' and bconfig.longValue in (1,3,5,7))
    inner join o_bs_membership as bg_owner_member on (bg_owner_member.secgroup_id = bgroup.fk_ownergroup)
    inner join o_bs_identity as ident on (bg_owner_member.identity_id = ident.id)
-);
+   where bgroup.ownersintern=1
+;
+
+create or replace view o_gp_contactkey_participant_v as
+   select
+      bg_part_member.id as membership_id,
+      bgroup.fk_partipiciantgroup as bg_part_sec_id,
+      bgroup.fk_ownergroup as bg_owner_sec_id,
+      bg_part_member.identity_id as bg_part_member_id
+   from o_gp_business as bgroup
+   inner join o_bs_membership as bg_part_member on (bg_part_member.secgroup_id = bgroup.fk_partipiciantgroup)
+   where bgroup.participantsintern=1
+;
+   
+create or replace view o_gp_contactkey_owner_v as
+   select
+      bg_owner_member.id as membership_id,
+      bgroup.fk_partipiciantgroup as bg_part_sec_id,
+      bgroup.fk_ownergroup as bg_owner_sec_id,
+      bg_owner_member.identity_id as bg_owner_member_id
+   from o_gp_business as bgroup
+   inner join o_bs_membership as bg_owner_member on (bg_owner_member.secgroup_id = bgroup.fk_ownergroup)
+   where bgroup.ownersintern=1
+;
 
 -- coaching
 create or replace view o_as_eff_statement_groups_v as (
diff --git a/src/main/resources/database/oracle/alter_9_3_0_to_9_4_0.sql b/src/main/resources/database/oracle/alter_9_3_0_to_9_4_0.sql
new file mode 100644
index 00000000000..d000fbe602d
--- /dev/null
+++ b/src/main/resources/database/oracle/alter_9_3_0_to_9_4_0.sql
@@ -0,0 +1,59 @@
+alter table o_gp_business add (ownersintern number default 0 not null);
+alter table o_gp_business add (participantsintern number default 0 not null);
+alter table o_gp_business add (waitingintern number default 0 not null);
+alter table o_gp_business add (ownerspublic number default 0 not null);
+alter table o_gp_business add (participantspublic number default 0 not null);
+alter table o_gp_business add (waitingpublic number default 0 not null);
+alter table o_gp_business add (downloadmembers number default 0 not null);
+
+create view o_gp_contact_participant_v as
+   select
+      bg_part_member.id as membership_id,
+      bgroup.group_id as bg_id,
+      bgroup.groupname as bg_name,
+      bgroup.fk_partipiciantgroup as bg_part_sec_id,
+      bgroup.fk_ownergroup as bg_owner_sec_id,
+      bg_part_member.identity_id as bg_part_member_id,
+      ident.name as bg_part_member_name 
+   from o_gp_business bgroup
+   inner join o_bs_membership bg_part_member on (bg_part_member.secgroup_id = bgroup.fk_partipiciantgroup)
+   inner join o_bs_identity ident on (bg_part_member.identity_id = ident.id)
+   where bgroup.participantsintern=1
+;
+
+create view o_gp_contact_owner_v as
+   select
+      bg_owner_member.id as membership_id,
+      bgroup.group_id as bg_id,
+      bgroup.groupname as bg_name,
+      bgroup.fk_partipiciantgroup as bg_part_sec_id,
+      bgroup.fk_ownergroup as bg_owner_sec_id,
+      bg_owner_member.identity_id as bg_owner_member_id,
+      ident.name as bg_owner_member_name
+   from o_gp_business bgroup
+   inner join o_bs_membership bg_owner_member on (bg_owner_member.secgroup_id = bgroup.fk_ownergroup)
+   inner join o_bs_identity ident on (bg_owner_member.identity_id = ident.id)
+   where bgroup.ownersintern=1
+;
+
+create view o_gp_contactkey_participant_v as
+   select
+      bg_part_member.id as membership_id,
+      bgroup.fk_partipiciantgroup as bg_part_sec_id,
+      bgroup.fk_ownergroup as bg_owner_sec_id,
+      bg_part_member.identity_id as bg_part_member_id
+   from o_gp_business bgroup
+   inner join o_bs_membership bg_part_member on (bg_part_member.secgroup_id = bgroup.fk_partipiciantgroup)
+   where bgroup.participantsintern=1
+;
+  
+create view o_gp_contactkey_owner_v as
+   select
+      bg_owner_member.id as membership_id,
+      bgroup.fk_partipiciantgroup as bg_part_sec_id,
+      bgroup.fk_ownergroup as bg_owner_sec_id,
+      bg_owner_member.identity_id as bg_owner_member_id
+   from o_gp_business bgroup
+   inner join o_bs_membership bg_owner_member on (bg_owner_member.secgroup_id = bgroup.fk_ownergroup)
+   where bgroup.ownersintern=1
+;
diff --git a/src/main/resources/database/oracle/setupDatabase.sql b/src/main/resources/database/oracle/setupDatabase.sql
index 3cef28c714a..b0b205342ba 100644
--- a/src/main/resources/database/oracle/setupDatabase.sql
+++ b/src/main/resources/database/oracle/setupDatabase.sql
@@ -51,6 +51,13 @@ CREATE TABLE o_gp_business (
   maxparticipants number(11),
   waitinglist_enabled number,
   autocloseranks_enabled number,
+  ownersintern number default 0 not null,
+  participantsintern number default 0 not null,
+  waitingintern number default 0 not null,
+  ownerspublic number default 0 not null,
+  participantspublic number default 0 not null,
+  waitingpublic number default 0 not null,
+  downloadmembers number default 0 not null,
   groupcontext_fk number(20),
   fk_resource number(20),
   fk_ownergroup number(20),
@@ -1568,7 +1575,8 @@ create or replace view o_gp_business_v  as (
    from o_gp_business gp
 );
 
-create view o_gp_visible_participant_v as (
+-- contacts
+create view o_gp_contact_participant_v as
    select
       bg_part_member.id as membership_id,
       bgroup.group_id as bg_id,
@@ -1578,12 +1586,12 @@ create view o_gp_visible_participant_v as (
       bg_part_member.identity_id as bg_part_member_id,
       ident.name as bg_part_member_name 
    from o_gp_business bgroup
-   inner join o_property bconfig on (bconfig.grp = bgroup.group_id and bconfig.name = 'displayMembers' and bconfig.category = 'config' and bconfig.longValue in (2,3,6,7))
    inner join o_bs_membership bg_part_member on (bg_part_member.secgroup_id = bgroup.fk_partipiciantgroup)
    inner join o_bs_identity ident on (bg_part_member.identity_id = ident.id)
- );
-   
-create view o_gp_visible_owner_v as ( 
+   where bgroup.participantsintern=1
+;
+
+create view o_gp_contact_owner_v as
    select
       bg_owner_member.id as membership_id,
       bgroup.group_id as bg_id,
@@ -1593,10 +1601,32 @@ create view o_gp_visible_owner_v as (
       bg_owner_member.identity_id as bg_owner_member_id,
       ident.name as bg_owner_member_name
    from o_gp_business bgroup
-   inner join o_property bconfig on (bconfig.grp = bgroup.group_id and bconfig.name = 'displayMembers' and bconfig.category = 'config' and bconfig.longValue in (1,3,5,7))
    inner join o_bs_membership bg_owner_member on (bg_owner_member.secgroup_id = bgroup.fk_ownergroup)
    inner join o_bs_identity ident on (bg_owner_member.identity_id = ident.id)
-);
+   where bgroup.ownersintern=1
+;
+
+create view o_gp_contactkey_participant_v as
+   select
+      bg_part_member.id as membership_id,
+      bgroup.fk_partipiciantgroup as bg_part_sec_id,
+      bgroup.fk_ownergroup as bg_owner_sec_id,
+      bg_part_member.identity_id as bg_part_member_id
+   from o_gp_business bgroup
+   inner join o_bs_membership bg_part_member on (bg_part_member.secgroup_id = bgroup.fk_partipiciantgroup)
+   where bgroup.participantsintern=1
+;
+  
+create view o_gp_contactkey_owner_v as
+   select
+      bg_owner_member.id as membership_id,
+      bgroup.fk_partipiciantgroup as bg_part_sec_id,
+      bgroup.fk_ownergroup as bg_owner_sec_id,
+      bg_owner_member.identity_id as bg_owner_member_id
+   from o_gp_business bgroup
+   inner join o_bs_membership bg_owner_member on (bg_owner_member.secgroup_id = bgroup.fk_ownergroup)
+   where bgroup.ownersintern=1
+;
 
 create or replace view o_im_roster_entry_v as (
    select
diff --git a/src/main/resources/database/postgresql/alter_9_3_0_to_9_4_0.sql b/src/main/resources/database/postgresql/alter_9_3_0_to_9_4_0.sql
new file mode 100644
index 00000000000..c07faa6a724
--- /dev/null
+++ b/src/main/resources/database/postgresql/alter_9_3_0_to_9_4_0.sql
@@ -0,0 +1,61 @@
+alter table o_gp_business add column ownersintern bool not null default false;
+alter table o_gp_business add column participantsintern bool not null default false;
+alter table o_gp_business add column waitingintern bool not null default false;
+alter table o_gp_business add column ownerspublic bool not null default false;
+alter table o_gp_business add column participantspublic bool not null default false;
+alter table o_gp_business add column waitingpublic bool not null default false;
+alter table o_gp_business add column downloadmembers bool not null default false;
+
+drop view o_gp_visible_participant_v;
+create view o_gp_contact_participant_v as
+   select
+      bg_part_member.id as membership_id,
+      bgroup.group_id as bg_id,
+      bgroup.groupname as bg_name,
+      bgroup.fk_partipiciantgroup as bg_part_sec_id,
+      bgroup.fk_ownergroup as bg_owner_sec_id,
+      bg_part_member.identity_id as bg_part_member_id,
+      ident.name as bg_part_member_name 
+   from o_gp_business as bgroup
+   inner join o_bs_membership as bg_part_member on (bg_part_member.secgroup_id = bgroup.fk_partipiciantgroup)
+   inner join o_bs_identity as ident on (bg_part_member.identity_id = ident.id)
+   where bgroup.participantsintern=true
+;
+  
+drop view o_gp_visible_owner_v;
+create view o_gp_contact_owner_v as
+   select
+      bg_owner_member.id as membership_id,
+      bgroup.group_id as bg_id,
+      bgroup.groupname as bg_name,
+      bgroup.fk_partipiciantgroup as bg_part_sec_id,
+      bgroup.fk_ownergroup as bg_owner_sec_id,
+      bg_owner_member.identity_id as bg_owner_member_id,
+      ident.name as bg_owner_member_name
+   from o_gp_business as bgroup
+   inner join o_bs_membership as bg_owner_member on (bg_owner_member.secgroup_id = bgroup.fk_ownergroup)
+   inner join o_bs_identity as ident on (bg_owner_member.identity_id = ident.id)
+   where bgroup.ownersintern=true
+;
+
+create view o_gp_contactkey_participant_v as
+   select
+      bg_part_member.id as membership_id,
+      bgroup.fk_partipiciantgroup as bg_part_sec_id,
+      bgroup.fk_ownergroup as bg_owner_sec_id,
+      bg_part_member.identity_id as bg_part_member_id
+   from o_gp_business as bgroup
+   inner join o_bs_membership as bg_part_member on (bg_part_member.secgroup_id = bgroup.fk_partipiciantgroup)
+   where bgroup.participantsintern=true
+;
+  
+create view o_gp_contactkey_owner_v as
+   select
+      bg_owner_member.id as membership_id,
+      bgroup.fk_partipiciantgroup as bg_part_sec_id,
+      bgroup.fk_ownergroup as bg_owner_sec_id,
+      bg_owner_member.identity_id as bg_owner_member_id
+   from o_gp_business as bgroup
+   inner join o_bs_membership as bg_owner_member on (bg_owner_member.secgroup_id = bgroup.fk_ownergroup)
+   where bgroup.ownersintern=true
+;
diff --git a/src/main/resources/database/postgresql/setupDatabase.sql b/src/main/resources/database/postgresql/setupDatabase.sql
index 8b65c7919f2..5cc776d7e44 100644
--- a/src/main/resources/database/postgresql/setupDatabase.sql
+++ b/src/main/resources/database/postgresql/setupDatabase.sql
@@ -42,6 +42,13 @@ create table o_gp_business (
    maxparticipants int4,
    waitinglist_enabled bool,
    autocloseranks_enabled bool,
+   ownersintern bool not null default false,
+   participantsintern bool not null default false,
+   waitingintern bool not null default false,
+   ownerspublic bool not null default false,
+   participantspublic bool not null default false,
+   waitingpublic bool not null default false,
+   downloadmembers bool not null default false,
    groupcontext_fk int8,
    fk_resource int8 unique,
    fk_ownergroup int8 unique,
@@ -1501,7 +1508,7 @@ union select
    inner join o_bs_membership bg_member on (bg_member.secgroup_id = bgroup.fk_ownergroup)
 ;
 
-create view o_gp_visible_participant_v as (
+create view o_gp_contact_participant_v as
    select
       bg_part_member.id as membership_id,
       bgroup.group_id as bg_id,
@@ -1511,12 +1518,13 @@ create view o_gp_visible_participant_v as (
       bg_part_member.identity_id as bg_part_member_id,
       ident.name as bg_part_member_name 
    from o_gp_business as bgroup
-   inner join o_property as bconfig on (bconfig.grp = bgroup.group_id and bconfig.name = 'displayMembers' and bconfig.category = 'config' and bconfig.longValue in (2,3,6,7))
    inner join o_bs_membership as bg_part_member on (bg_part_member.secgroup_id = bgroup.fk_partipiciantgroup)
    inner join o_bs_identity as ident on (bg_part_member.identity_id = ident.id)
- );
-   
-create view o_gp_visible_owner_v as ( 
+   where bgroup.participantsintern=true
+;
+  
+-- contacts
+create view o_gp_contact_owner_v as
    select
       bg_owner_member.id as membership_id,
       bgroup.group_id as bg_id,
@@ -1526,10 +1534,32 @@ create view o_gp_visible_owner_v as (
       bg_owner_member.identity_id as bg_owner_member_id,
       ident.name as bg_owner_member_name
    from o_gp_business as bgroup
-   inner join o_property as bconfig on (bconfig.grp = bgroup.group_id and bconfig.name = 'displayMembers' and bconfig.category = 'config' and bconfig.longValue in (1,3,5,7))
    inner join o_bs_membership as bg_owner_member on (bg_owner_member.secgroup_id = bgroup.fk_ownergroup)
    inner join o_bs_identity as ident on (bg_owner_member.identity_id = ident.id)
-);
+   where bgroup.ownersintern=true
+;
+
+create view o_gp_contactkey_participant_v as
+   select
+      bg_part_member.id as membership_id,
+      bgroup.fk_partipiciantgroup as bg_part_sec_id,
+      bgroup.fk_ownergroup as bg_owner_sec_id,
+      bg_part_member.identity_id as bg_part_member_id
+   from o_gp_business as bgroup
+   inner join o_bs_membership as bg_part_member on (bg_part_member.secgroup_id = bgroup.fk_partipiciantgroup)
+   where bgroup.participantsintern=true
+;
+  
+create view o_gp_contactkey_owner_v as
+   select
+      bg_owner_member.id as membership_id,
+      bgroup.fk_partipiciantgroup as bg_part_sec_id,
+      bgroup.fk_ownergroup as bg_owner_sec_id,
+      bg_owner_member.identity_id as bg_owner_member_id
+   from o_gp_business as bgroup
+   inner join o_bs_membership as bg_owner_member on (bg_owner_member.secgroup_id = bgroup.fk_ownergroup)
+   where bgroup.ownersintern=true
+;
 
 -- coaching
 create or replace view o_as_eff_statement_groups_v as (
diff --git a/src/test/java/org/olat/group/test/BusinessGroupDAOTest.java b/src/test/java/org/olat/group/test/BusinessGroupDAOTest.java
index c9cd6ff63ff..4d489104e1f 100644
--- a/src/test/java/org/olat/group/test/BusinessGroupDAOTest.java
+++ b/src/test/java/org/olat/group/test/BusinessGroupDAOTest.java
@@ -38,8 +38,6 @@ import org.olat.core.commons.persistence.DB;
 import org.olat.core.commons.persistence.PersistenceHelper;
 import org.olat.core.commons.services.mark.MarkManager;
 import org.olat.core.id.Identity;
-import org.olat.core.logging.OLog;
-import org.olat.core.logging.Tracing;
 import org.olat.group.BusinessGroup;
 import org.olat.group.BusinessGroupLazy;
 import org.olat.group.BusinessGroupMembership;
@@ -47,11 +45,9 @@ import org.olat.group.BusinessGroupOrder;
 import org.olat.group.BusinessGroupShort;
 import org.olat.group.BusinessGroupView;
 import org.olat.group.manager.BusinessGroupDAO;
-import org.olat.group.manager.BusinessGroupPropertyDAO;
 import org.olat.group.manager.BusinessGroupRelationDAO;
 import org.olat.group.model.BusinessGroupMembershipViewImpl;
 import org.olat.group.model.SearchBusinessGroupParams;
-import org.olat.properties.Property;
 import org.olat.repository.RepositoryEntry;
 import org.olat.resource.accesscontrol.ACService;
 import org.olat.resource.accesscontrol.model.Offer;
@@ -65,8 +61,6 @@ import org.springframework.beans.factory.annotation.Autowired;
  */
 public class BusinessGroupDAOTest extends OlatTestCase {
 	
-	private OLog log = Tracing.createLoggerFor(BusinessGroupDAOTest.class);
-	
 	@Autowired
 	private BusinessGroupDAO businessGroupDao;
 	@Autowired
@@ -76,8 +70,6 @@ public class BusinessGroupDAOTest extends OlatTestCase {
 	@Autowired
 	private BaseSecurity securityManager;
 	@Autowired
-	private BusinessGroupPropertyDAO businessGroupPropertyManager;
-	@Autowired
 	private ACService acService;
 	@Autowired
 	private MarkManager markManager;
@@ -425,20 +417,17 @@ public class BusinessGroupDAOTest extends OlatTestCase {
 		dbInstance.commitAndCloseSession();
 		
 		//check the value
-		Property prop1 = businessGroupPropertyManager.findProperty(group1);
-		Assert.assertTrue(businessGroupPropertyManager.showOwners(prop1));
-		Assert.assertTrue(businessGroupPropertyManager.showPartips(prop1));
-		Assert.assertFalse(businessGroupPropertyManager.showWaitingList(prop1));
-		
-		Property prop2 = businessGroupPropertyManager.findProperty(group2);
-		Assert.assertFalse(businessGroupPropertyManager.showOwners(prop2));
-		Assert.assertTrue(businessGroupPropertyManager.showPartips(prop2));
-		Assert.assertFalse(businessGroupPropertyManager.showWaitingList(prop2));
-		
-		Property prop3 = businessGroupPropertyManager.findProperty(group3);
-		Assert.assertFalse(businessGroupPropertyManager.showOwners(prop3));
-		Assert.assertFalse(businessGroupPropertyManager.showPartips(prop3));
-		Assert.assertTrue(businessGroupPropertyManager.showWaitingList(prop3));
+		Assert.assertTrue(group1.isOwnersVisibleIntern());
+		Assert.assertTrue(group1.isParticipantsVisibleIntern());
+		Assert.assertFalse(group1.isWaitingListVisibleIntern());
+		
+		Assert.assertFalse(group2.isOwnersVisibleIntern());
+		Assert.assertTrue(group2.isParticipantsVisibleIntern());
+		Assert.assertFalse(group2.isWaitingListVisibleIntern());
+		
+		Assert.assertFalse(group3.isOwnersVisibleIntern());
+		Assert.assertFalse(group3.isParticipantsVisibleIntern());
+		Assert.assertTrue(group3.isWaitingListVisibleIntern());
 	}
 	
 	@Test
diff --git a/src/test/java/org/olat/group/test/BusinessGroupImportExportTest.java b/src/test/java/org/olat/group/test/BusinessGroupImportExportTest.java
index ecdedad82b4..3560e771397 100644
--- a/src/test/java/org/olat/group/test/BusinessGroupImportExportTest.java
+++ b/src/test/java/org/olat/group/test/BusinessGroupImportExportTest.java
@@ -34,7 +34,6 @@ import org.olat.group.BusinessGroup;
 import org.olat.group.BusinessGroupService;
 import org.olat.group.area.BGArea;
 import org.olat.group.area.BGAreaManager;
-import org.olat.group.model.DisplayMembers;
 import org.olat.group.model.SearchBusinessGroupParams;
 import org.olat.repository.RepositoryEntry;
 import org.olat.test.JunitTestHelper;
@@ -89,10 +88,9 @@ public class BusinessGroupImportExportTest extends OlatTestCase {
 		Assert.assertFalse(group1.getAutoCloseRanksEnabled().booleanValue());
 		Assert.assertFalse(group1.getWaitingListEnabled().booleanValue());
 		//check display members settings
-		DisplayMembers displayMembersGroup1 = businessGroupService.getDisplayMembers(group1);
-		Assert.assertTrue(displayMembersGroup1.isShowOwners());
-		Assert.assertTrue(displayMembersGroup1.isShowParticipants());
-		Assert.assertFalse(displayMembersGroup1.isShowWaitingList());
+		Assert.assertTrue(group1.isOwnersVisibleIntern());
+		Assert.assertTrue(group1.isParticipantsVisibleIntern());
+		Assert.assertFalse(group1.isWaitingListVisibleIntern());
 		//check collaboration tools
 		CollaborationTools toolGroup1 = CollaborationToolsFactory.getInstance().getCollaborationToolsIfExists(group1);
 		Assert.assertNotNull(toolGroup1);
@@ -118,10 +116,9 @@ public class BusinessGroupImportExportTest extends OlatTestCase {
 		Assert.assertTrue(group3.getWaitingListEnabled().booleanValue());
 		Assert.assertEquals(new Integer(25), group3.getMaxParticipants());
 		//check display members settings
-		DisplayMembers displayMembersGroup3 = businessGroupService.getDisplayMembers(group3);
-		Assert.assertTrue(displayMembersGroup3.isShowOwners());
-		Assert.assertTrue(displayMembersGroup3.isShowParticipants());
-		Assert.assertTrue(displayMembersGroup3.isShowWaitingList());
+		Assert.assertTrue(group3.isOwnersVisibleIntern());
+		Assert.assertTrue(group3.isParticipantsVisibleIntern());
+		Assert.assertTrue(group3.isWaitingListVisibleIntern());
 		//check collaboration tools
 		CollaborationTools toolGroup3 = CollaborationToolsFactory.getInstance().getCollaborationToolsIfExists(group3);
 		Assert.assertNotNull(toolGroup3);
diff --git a/src/test/java/org/olat/group/test/ContactDAOTest.java b/src/test/java/org/olat/group/test/ContactDAOTest.java
index c75eeb7b332..4034e877864 100644
--- a/src/test/java/org/olat/group/test/ContactDAOTest.java
+++ b/src/test/java/org/olat/group/test/ContactDAOTest.java
@@ -19,6 +19,7 @@
  */
 package org.olat.group.test;
 
+import java.util.Collection;
 import java.util.List;
 import java.util.UUID;
 
@@ -30,8 +31,9 @@ import org.olat.core.commons.persistence.DB;
 import org.olat.core.id.Identity;
 import org.olat.group.BusinessGroup;
 import org.olat.group.manager.BusinessGroupDAO;
-import org.olat.group.manager.BusinessGroupPropertyDAO;
 import org.olat.group.manager.ContactDAO;
+import org.olat.group.model.ContactOwnerView;
+import org.olat.group.model.ContactParticipantView;
 import org.olat.test.JunitTestHelper;
 import org.olat.test.OlatTestCase;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -50,8 +52,6 @@ public class ContactDAOTest extends OlatTestCase {
 	private DB dbInstance;
 	@Autowired
 	private BaseSecurity securityManager;
-	@Autowired
-	private BusinessGroupPropertyDAO businessGroupPropertyManager;
 
 	@Test
 	public void testContacts() {
@@ -183,4 +183,182 @@ public class ContactDAOTest extends OlatTestCase {
 		List<Identity> contactList5 = contactDao.findContacts(id5, 0, -1);
 		Assert.assertEquals(0, contactList5.size());
 	}
+	
+	@Test
+	public void testDistinctGroupOwnersParticipants() {
+		//5 identities
+		Identity id1 = JunitTestHelper.createAndPersistIdentityAsUser("edao-1-" + UUID.randomUUID().toString());
+		Identity id2 = JunitTestHelper.createAndPersistIdentityAsUser("edao-2-" + UUID.randomUUID().toString());
+		Identity id3 = JunitTestHelper.createAndPersistIdentityAsUser("edao-3-" + UUID.randomUUID().toString());
+		Identity id4 = JunitTestHelper.createAndPersistIdentityAsUser("edao-4-" + UUID.randomUUID().toString());
+		Identity id5 = JunitTestHelper.createAndPersistIdentityAsUser("edao-5-" + UUID.randomUUID().toString());
+		//create 3 groups
+		BusinessGroup group1 = businessGroupDao.createAndPersist(null, "geoo", "gdoo-desc", 0, 5, true, false, true, false, false);
+		BusinessGroup group2 = businessGroupDao.createAndPersist(null, "gepo", "gdpo-desc", 0, 5, true, false, false, true, false);
+		BusinessGroup group3 = businessGroupDao.createAndPersist(null, "geqo", "gdqo-desc", 0, 5, true, false, false, false, false);
+		dbInstance.commitAndCloseSession();
+		
+		//id1 -> group 1 and 2
+		securityManager.addIdentityToSecurityGroup(id1, group1.getOwnerGroup());		//visible
+		securityManager.addIdentityToSecurityGroup(id1, group2.getPartipiciantGroup());	//visible
+		//id2 -> group 1 and 2
+		securityManager.addIdentityToSecurityGroup(id2, group1.getPartipiciantGroup()); //not
+		securityManager.addIdentityToSecurityGroup(id2, group2.getOwnerGroup());        //not
+		//id3 -> group 1 and 3
+		securityManager.addIdentityToSecurityGroup(id3, group2.getOwnerGroup());        //not
+		securityManager.addIdentityToSecurityGroup(id3, group3.getPartipiciantGroup()); //not
+		//id4 -> group 2
+		securityManager.addIdentityToSecurityGroup(id4, group2.getOwnerGroup());        //not
+		securityManager.addIdentityToSecurityGroup(id4, group3.getOwnerGroup());        //not
+		//id5 -> group 3
+		securityManager.addIdentityToSecurityGroup(id5, group3.getOwnerGroup());        //not
+		dbInstance.commitAndCloseSession();	
+		
+		//check identity1 : no contact
+		Collection<Long> contacts1 = contactDao.getDistinctGroupOwnersParticipants(id1);
+		Assert.assertNotNull(contacts1);
+		Assert.assertEquals(1, contacts1.size());
+		Assert.assertTrue(contacts1.contains(id1.getKey()));
+		
+		//check identity2 : contact to id1 and id3
+		Collection<Long> contacts2 = contactDao.getDistinctGroupOwnersParticipants(id2);
+		Assert.assertNotNull(contacts2);
+		Assert.assertEquals(1, contacts2.size());
+		Assert.assertTrue(contacts2.contains(id1.getKey()));
+		
+		//check identity3 : contact to id1 and id2
+		Collection<Long> contacts3 = contactDao.getDistinctGroupOwnersParticipants(id3);
+		Assert.assertNotNull(contacts3);
+		Assert.assertEquals(1, contacts3.size());
+		Assert.assertTrue(contacts3.contains(id1.getKey()));
+		
+		//check identity4 : contact to id1
+		Collection<Long> contacts4 = contactDao.getDistinctGroupOwnersParticipants(id4);
+		Assert.assertNotNull(contacts4);
+		Assert.assertEquals(1, contacts4.size());
+		Assert.assertTrue(contacts4.contains(id1.getKey()));
+		
+		//check identity5 : contact to id2
+		Collection<Long> contacts5 = contactDao.getDistinctGroupOwnersParticipants(id5);
+		Assert.assertNotNull(contacts5);
+		Assert.assertEquals(0, contacts5.size());
+	}
+	
+	@Test
+	public void testGroupOwners() {
+		//5 identities
+		Identity id1 = JunitTestHelper.createAndPersistIdentityAsUser("fdao-1-" + UUID.randomUUID().toString());
+		Identity id2 = JunitTestHelper.createAndPersistIdentityAsUser("fdao-2-" + UUID.randomUUID().toString());
+		Identity id3 = JunitTestHelper.createAndPersistIdentityAsUser("fdao-3-" + UUID.randomUUID().toString());
+		Identity id4 = JunitTestHelper.createAndPersistIdentityAsUser("fdao-4-" + UUID.randomUUID().toString());
+		Identity id5 = JunitTestHelper.createAndPersistIdentityAsUser("fdao-5-" + UUID.randomUUID().toString());
+		//create 3 groups
+		BusinessGroup group1 = businessGroupDao.createAndPersist(null, "gfoo", "gfoo-desc", 0, 5, true, false, true, false, false);
+		BusinessGroup group2 = businessGroupDao.createAndPersist(null, "gfpo", "gfpo-desc", 0, 5, true, false, false, true, false);
+		BusinessGroup group3 = businessGroupDao.createAndPersist(null, "gfqo", "gfqo-desc", 0, 5, true, false, false, false, false);
+		dbInstance.commitAndCloseSession();
+		
+		//id1 -> group 1 and 2
+		securityManager.addIdentityToSecurityGroup(id1, group1.getOwnerGroup());		//visible
+		securityManager.addIdentityToSecurityGroup(id1, group2.getPartipiciantGroup());	//visible
+		//id2 -> group 1 and 2
+		securityManager.addIdentityToSecurityGroup(id2, group1.getPartipiciantGroup()); //not
+		securityManager.addIdentityToSecurityGroup(id2, group2.getOwnerGroup());        //not
+		//id3 -> group 1 and 3
+		securityManager.addIdentityToSecurityGroup(id3, group2.getOwnerGroup());        //not
+		securityManager.addIdentityToSecurityGroup(id3, group3.getPartipiciantGroup()); //not
+		//id4 -> group 2
+		securityManager.addIdentityToSecurityGroup(id4, group2.getOwnerGroup());        //not
+		securityManager.addIdentityToSecurityGroup(id4, group3.getOwnerGroup());        //not
+		//id5 -> group 3
+		securityManager.addIdentityToSecurityGroup(id5, group3.getOwnerGroup());        //not
+		dbInstance.commitAndCloseSession();	
+		
+		//check identity1 : no contact
+		Collection<ContactOwnerView> contacts1 = contactDao.getGroupOwners(id1);
+		Assert.assertNotNull(contacts1);
+		Assert.assertEquals(1, contacts1.size());
+		Assert.assertTrue(contacts1.iterator().next().getIdentityKey().equals(id1.getKey()));
+		
+		//check identity2 : contact to id1 and id3
+		Collection<ContactOwnerView> contacts2 = contactDao.getGroupOwners(id2);
+		Assert.assertNotNull(contacts2);
+		Assert.assertEquals(1, contacts2.size());
+		Assert.assertTrue(contacts2.iterator().next().getIdentityKey().equals(id1.getKey()));
+		
+		//check identity3 : contact to id1 and id2
+		Collection<ContactOwnerView> contacts3 = contactDao.getGroupOwners(id3);
+		Assert.assertNotNull(contacts3);
+		Assert.assertEquals(0, contacts3.size());
+		
+		//check identity4 : contact to id1
+		Collection<ContactOwnerView> contacts4 = contactDao.getGroupOwners(id4);
+		Assert.assertNotNull(contacts4);
+		Assert.assertEquals(0, contacts4.size());
+		
+		//check identity5 : contact to id2
+		Collection<ContactOwnerView> contacts5 = contactDao.getGroupOwners(id5);
+		Assert.assertNotNull(contacts5);
+		Assert.assertEquals(0, contacts5.size());
+	}
+	
+	@Test
+	public void testGroupParticipants() {
+		//5 identities
+		Identity id1 = JunitTestHelper.createAndPersistIdentityAsUser("fdao-1-" + UUID.randomUUID().toString());
+		Identity id2 = JunitTestHelper.createAndPersistIdentityAsUser("fdao-2-" + UUID.randomUUID().toString());
+		Identity id3 = JunitTestHelper.createAndPersistIdentityAsUser("fdao-3-" + UUID.randomUUID().toString());
+		Identity id4 = JunitTestHelper.createAndPersistIdentityAsUser("fdao-4-" + UUID.randomUUID().toString());
+		Identity id5 = JunitTestHelper.createAndPersistIdentityAsUser("fdao-5-" + UUID.randomUUID().toString());
+		//create 3 groups
+		BusinessGroup group1 = businessGroupDao.createAndPersist(null, "gfoo", "gfoo-desc", 0, 5, true, false, true, false, false);
+		BusinessGroup group2 = businessGroupDao.createAndPersist(null, "gfpo", "gfpo-desc", 0, 5, true, false, false, true, false);
+		BusinessGroup group3 = businessGroupDao.createAndPersist(null, "gfqo", "gfqo-desc", 0, 5, true, false, false, false, false);
+		dbInstance.commitAndCloseSession();
+		
+		//id1 -> group 1 and 2
+		securityManager.addIdentityToSecurityGroup(id1, group1.getOwnerGroup());		//visible
+		securityManager.addIdentityToSecurityGroup(id1, group2.getPartipiciantGroup());	//visible
+		//id2 -> group 1 and 2
+		securityManager.addIdentityToSecurityGroup(id2, group1.getPartipiciantGroup()); //not
+		securityManager.addIdentityToSecurityGroup(id2, group2.getOwnerGroup());        //not
+		//id3 -> group 1 and 3
+		securityManager.addIdentityToSecurityGroup(id3, group2.getOwnerGroup());        //not
+		securityManager.addIdentityToSecurityGroup(id3, group3.getPartipiciantGroup()); //not
+		//id4 -> group 2
+		securityManager.addIdentityToSecurityGroup(id4, group2.getOwnerGroup());        //not
+		securityManager.addIdentityToSecurityGroup(id4, group3.getOwnerGroup());        //not
+		//id5 -> group 3
+		securityManager.addIdentityToSecurityGroup(id5, group3.getOwnerGroup());        //not
+		dbInstance.commitAndCloseSession();	
+		
+		//check identity1 : no contact
+		Collection<ContactParticipantView> contacts1 = contactDao.getParticipants(id1);
+		Assert.assertNotNull(contacts1);
+		Assert.assertEquals(1, contacts1.size());
+		Assert.assertTrue(contacts1.iterator().next().getIdentityKey().equals(id1.getKey()));
+		
+		//check identity2 : contact to id1 and id3
+		Collection<ContactParticipantView> contacts2 = contactDao.getParticipants(id2);
+		Assert.assertNotNull(contacts2);
+		Assert.assertEquals(1, contacts2.size());
+		Assert.assertTrue(contacts2.iterator().next().getIdentityKey().equals(id1.getKey()));
+		
+		//check identity3 : contact to id1 and id2
+		Collection<ContactParticipantView> contacts3 = contactDao.getParticipants(id3);
+		Assert.assertNotNull(contacts3);
+		Assert.assertEquals(1, contacts3.size());
+		Assert.assertTrue(contacts3.iterator().next().getIdentityKey().equals(id1.getKey()));
+		
+		//check identity4 : contact to id1
+		Collection<ContactParticipantView> contacts4 = contactDao.getParticipants(id4);
+		Assert.assertNotNull(contacts4);
+		Assert.assertEquals(1, contacts4.size());
+		Assert.assertTrue(contacts4.iterator().next().getIdentityKey().equals(id1.getKey()));
+		
+		//check identity5 : contact to id2
+		Collection<ContactParticipantView> contacts5 = contactDao.getParticipants(id5);
+		Assert.assertNotNull(contacts5);
+		Assert.assertEquals(0, contacts5.size());
+	}
 }
diff --git a/src/test/java/org/olat/instantMessaging/InstantMessageServiceTest.java b/src/test/java/org/olat/instantMessaging/InstantMessageServiceTest.java
index 425bd220767..7b6cb8b07b1 100644
--- a/src/test/java/org/olat/instantMessaging/InstantMessageServiceTest.java
+++ b/src/test/java/org/olat/instantMessaging/InstantMessageServiceTest.java
@@ -34,7 +34,6 @@ import org.olat.core.util.event.GenericEventListener;
 import org.olat.core.util.resource.OresHelper;
 import org.olat.group.BusinessGroup;
 import org.olat.group.BusinessGroupService;
-import org.olat.group.model.DisplayMembers;
 import org.olat.instantMessaging.manager.InstantMessageDAO;
 import org.olat.instantMessaging.manager.InstantMessagePreferencesDAO;
 import org.olat.instantMessaging.manager.RosterDAO;
@@ -130,7 +129,7 @@ public class InstantMessageServiceTest extends OlatTestCase {
 		securityManager.addIdentityToSecurityGroup(chatter1, group.getOwnerGroup());
 		securityManager.addIdentityToSecurityGroup(chatter2, group.getPartipiciantGroup());
 		dbInstance.commit();
-		businessGroupService.updateDisplayMembers(group, new DisplayMembers(false, false, false));
+		businessGroupService.updateDisplayMembers(group, false, false, false, false, false, false, false);
 		dbInstance.commitAndCloseSession();
 		
 		//check the buddies
@@ -152,7 +151,7 @@ public class InstantMessageServiceTest extends OlatTestCase {
 		securityManager.addIdentityToSecurityGroup(chatter1, group.getOwnerGroup());
 		securityManager.addIdentityToSecurityGroup(chatter2, group.getPartipiciantGroup());
 		dbInstance.commit();
-		businessGroupService.updateDisplayMembers(group, new DisplayMembers(true, true, false));
+		businessGroupService.updateDisplayMembers(group, true, true, false, false, false, false, false);
 		dbInstance.commitAndCloseSession();
 		
 		//check the buddies
diff --git a/src/test/java/org/olat/modules/coach/CoachingManagerTest.java b/src/test/java/org/olat/modules/coach/CoachingManagerTest.java
index e172ca7681e..36beb83fe1a 100644
--- a/src/test/java/org/olat/modules/coach/CoachingManagerTest.java
+++ b/src/test/java/org/olat/modules/coach/CoachingManagerTest.java
@@ -40,7 +40,6 @@ import org.olat.core.id.Identity;
 import org.olat.course.ICourse;
 import org.olat.group.BusinessGroup;
 import org.olat.group.BusinessGroupService;
-import org.olat.group.model.DisplayMembers;
 import org.olat.modules.coach.manager.CoachingService;
 import org.olat.modules.coach.model.CourseStatEntry;
 import org.olat.modules.coach.model.EfficiencyStatementEntry;
@@ -171,8 +170,8 @@ public class CoachingManagerTest extends OlatTestCase {
 	    BusinessGroup g2 =  businessGroupService.createBusinessGroup(author, "coach-g2", null, new Integer(0), new Integer(10), false, false, re);
 	    
 	    //permission to see owners and participants
-	    businessGroupService.updateDisplayMembers(g1, new DisplayMembers(false, false, false));
-	    businessGroupService.updateDisplayMembers(g2, new DisplayMembers(true, true, false));
+	    businessGroupService.updateDisplayMembers(g1, false, false, false, false, false, false, false);
+	    businessGroupService.updateDisplayMembers(g2, true, true, false, false, false, false, false);
 	    
 	    // coach
 	    addCoachToGroupCourse(coach10, g1, re);
diff --git a/src/test/java/org/olat/restapi/ContactsTest.java b/src/test/java/org/olat/restapi/ContactsTest.java
index 21c07877421..f5efcf91696 100644
--- a/src/test/java/org/olat/restapi/ContactsTest.java
+++ b/src/test/java/org/olat/restapi/ContactsTest.java
@@ -45,7 +45,6 @@ import org.olat.core.id.OLATResourceable;
 import org.olat.core.util.resource.OresHelper;
 import org.olat.group.BusinessGroup;
 import org.olat.group.BusinessGroupService;
-import org.olat.group.model.DisplayMembers;
 import org.olat.repository.RepositoryEntry;
 import org.olat.repository.RepositoryManager;
 import org.olat.resource.OLATResource;
@@ -122,8 +121,8 @@ public class ContactsTest extends OlatJerseyTestCase {
     g2 = businessGroupService.createBusinessGroup(null, "rest-g2", null, 0, 10, false, false, c1);
     
     //permission to see owners and participants
-    businessGroupService.updateDisplayMembers(g1, new DisplayMembers(false, false, false));
-    businessGroupService.updateDisplayMembers(g2, new DisplayMembers(true, true, false));
+    businessGroupService.updateDisplayMembers(g1, false, false, false, false, false, false, false);
+    businessGroupService.updateDisplayMembers(g2, true, true, false, false, false, false, false);
     
     // members g1
     secm.addIdentityToSecurityGroup(owner1, g1.getOwnerGroup());
@@ -140,9 +139,9 @@ public class ContactsTest extends OlatJerseyTestCase {
 		RepositoryEntry c2 =  JunitTestHelper.createAndPersistRepositoryEntry();
     // groups
     g3 = businessGroupService.createBusinessGroup(null, "rest-g3", null, -1, -1, false, false, c2);
-    businessGroupService.updateDisplayMembers(g3, new DisplayMembers(false, true, false));
+    businessGroupService.updateDisplayMembers(g3, false, true, false, false, false, false, false);
     g4 = businessGroupService.createBusinessGroup(null, "rest-g4", null, -1, -1, false, false, c2);
-    businessGroupService.updateDisplayMembers(g4, new DisplayMembers(false, true, false));
+    businessGroupService.updateDisplayMembers(g4, false, true, false, false, false, false, false);
     // members -> default participants are visible
     secm.addIdentityToSecurityGroup(owner1, g3.getPartipiciantGroup());
     secm.addIdentityToSecurityGroup(part3, g3.getPartipiciantGroup());
diff --git a/src/test/java/org/olat/restapi/GroupFoldersTest.java b/src/test/java/org/olat/restapi/GroupFoldersTest.java
index 223ae5694c5..b752a934581 100644
--- a/src/test/java/org/olat/restapi/GroupFoldersTest.java
+++ b/src/test/java/org/olat/restapi/GroupFoldersTest.java
@@ -68,7 +68,6 @@ import org.olat.core.util.vfs.VFSContainer;
 import org.olat.core.util.vfs.VFSLeaf;
 import org.olat.group.BusinessGroup;
 import org.olat.group.BusinessGroupService;
-import org.olat.group.model.DisplayMembers;
 import org.olat.repository.RepositoryEntry;
 import org.olat.repository.RepositoryManager;
 import org.olat.resource.OLATResource;
@@ -154,8 +153,8 @@ public class GroupFoldersTest extends OlatJerseyTestCase {
 	    g2 = businessGroupService.createBusinessGroup(null, "rest-g2", null, 0, 10, false, false, c1);
 	    
 	    //permission to see owners and participants
-	    businessGroupService.updateDisplayMembers(g1, new DisplayMembers(false, false, false));
-	    businessGroupService.updateDisplayMembers(g2, new DisplayMembers(true, true, false));
+	    businessGroupService.updateDisplayMembers(g1, false, false, false, false, false, false, false);
+	    businessGroupService.updateDisplayMembers(g2, true, true, false, false, false, false, false);
 	    
 	    // members g1
 	    secm.addIdentityToSecurityGroup(owner1, g1.getOwnerGroup());
diff --git a/src/test/java/org/olat/restapi/GroupMgmtTest.java b/src/test/java/org/olat/restapi/GroupMgmtTest.java
index 6bb98378e8e..9a29bba6462 100644
--- a/src/test/java/org/olat/restapi/GroupMgmtTest.java
+++ b/src/test/java/org/olat/restapi/GroupMgmtTest.java
@@ -68,7 +68,6 @@ import org.olat.core.logging.Tracing;
 import org.olat.core.util.resource.OresHelper;
 import org.olat.group.BusinessGroup;
 import org.olat.group.BusinessGroupService;
-import org.olat.group.model.DisplayMembers;
 import org.olat.modules.fo.Forum;
 import org.olat.modules.fo.ForumManager;
 import org.olat.modules.fo.Message;
@@ -168,8 +167,8 @@ public class GroupMgmtTest extends OlatJerseyTestCase {
     g2 = businessGroupService.createBusinessGroup(null, "rest-g2", null, 0, 10, false, false, c1);
     
     //permission to see owners and participants
-    businessGroupService.updateDisplayMembers(g1, new DisplayMembers(false, false, false));
-    businessGroupService.updateDisplayMembers(g2, new DisplayMembers(true, true, false));
+    businessGroupService.updateDisplayMembers(g1, false, false, false, false, false, false, false);
+    businessGroupService.updateDisplayMembers(g2, true, true, false, false, false, false, false);
     
     // members g1
     secm.addIdentityToSecurityGroup(owner1, g1.getOwnerGroup());
@@ -492,10 +491,9 @@ public class GroupMgmtTest extends OlatJerseyTestCase {
 		assertFalse(tools.isToolEnabled(CollaborationTools.TOOL_PORTFOLIO));
 		assertFalse(tools.isToolEnabled(CollaborationTools.TOOL_WIKI));
 		//check display members
-		DisplayMembers displayMembers = businessGroupService.getDisplayMembers(bg);
-		assertTrue(displayMembers.isShowOwners());
-		assertFalse(displayMembers.isShowParticipants());
-		assertFalse(displayMembers.isShowWaitingList());
+		assertTrue(bg.isOwnersVisibleIntern());
+		assertFalse(bg.isParticipantsVisibleIntern());
+		assertFalse(bg.isWaitingListVisibleIntern());
 	}
 	
 	@Test
-- 
GitLab