From fd6f4370bd4ac4cd4c2be0ac826f2ab0d412a969 Mon Sep 17 00:00:00 2001
From: fkiefer <none@none>
Date: Fri, 13 Jan 2017 14:01:59 +0100
Subject: [PATCH] OO-2365 GUI Changes, Webdav behaviour, wording

---
 .../olat/course/MergedCourseContainer.java    |  16 +-
 .../groupsandrights/CourseGroupManager.java   |   2 +-
 .../nodes/pf/manager/CountingCallback.java    | 123 +++++++++++
 .../nodes/pf/manager/FileSystemExport.java    |  13 +-
 .../course/nodes/pf/manager/PFManager.java    | 198 ++++++++++--------
 .../nodes/pf/manager/PFNotifications.java     |   2 +-
 .../pf/manager/PFNotificationsHandler.java    |   2 +-
 .../nodes/pf/manager/ReadWriteCallback.java   |   4 +-
 .../course/nodes/pf/ui/PFCoachController.java |   4 +-
 .../nodes/pf/ui/PFEditFormController.java     |  24 ++-
 .../nodes/pf/ui/PFParticipantController.java  |   3 +-
 .../nodes/pf/ui/PFPeekviewController.java     |   3 +-
 .../pf/ui/_i18n/LocalStrings_de.properties    |   3 +
 .../pf/ui/_i18n/LocalStrings_en.properties    |   3 +
 .../pf/ui/_i18n/LocalStrings_fr.properties    |   5 +-
 .../nodes/pf/manager/PFManagerTest.java       |   6 +-
 16 files changed, 300 insertions(+), 111 deletions(-)
 create mode 100644 src/main/java/org/olat/course/nodes/pf/manager/CountingCallback.java

diff --git a/src/main/java/org/olat/course/MergedCourseContainer.java b/src/main/java/org/olat/course/MergedCourseContainer.java
index 5167de38893..a52893c4cec 100644
--- a/src/main/java/org/olat/course/MergedCourseContainer.java
+++ b/src/main/java/org/olat/course/MergedCourseContainer.java
@@ -226,7 +226,8 @@ public class MergedCourseContainer extends MergeSource {
 					folderName = getBCFolderName(nodesContainer, pfNode, folderName);
 					MergeSource courseNodeContainer = new MergeSource(nodesContainer, folderName);					
 					UserCourseEnvironment userCourseEnv = new UserCourseEnvironmentImpl(identityEnv, course.getCourseEnvironment());
-					VFSContainer rootFolder = pfManager.provideCoachOrParticipantContainer(pfNode, userCourseEnv, identityEnv.getIdentity());
+					VFSContainer rootFolder = pfManager.provideCoachOrParticipantContainer(pfNode, userCourseEnv,
+							identityEnv.getIdentity(), courseReadOnly);
 					VFSContainer nodeContentContainer = new NamedContainerImpl(folderName, rootFolder);
 					courseNodeContainer.addContainersChildren(nodeContentContainer, true);
 		
@@ -284,7 +285,18 @@ public class MergedCourseContainer extends MergeSource {
  					addFolderBuildingBlocks(course, courseNodeContainer, child);
  				}
 			} else if (child instanceof PFCourseNode) {
-				//FIXME check if something is to be done here
+				final PFCourseNode pfNode = (PFCourseNode) child;					
+				// add folder not to merge source. Use name and node id to have unique name
+				PFManager pfManager = CoreSpringFactory.getImpl(PFManager.class);
+				folderName = getBCFolderName(nodesContainer, pfNode, folderName);
+				MergeSource courseNodeContainer = new MergeSource(nodesContainer, folderName);					
+				VFSContainer rootFolder = pfManager.provideAdminContainer(pfNode, course.getCourseEnvironment());
+				VFSContainer nodeContentContainer = new NamedContainerImpl(folderName, rootFolder);
+				courseNodeContainer.addContainersChildren(nodeContentContainer, true);
+	
+				addFolderBuildingBlocks(course, courseNodeContainer, child);
+				// Do recursion for all children
+				nodesContainer.addContainer(courseNodeContainer);
 			} else {
 				// For non-folder course nodes, add merge source (no files to show) ...
 				MergeSource courseNodeContainer = new MergeSource(null, folderName);
diff --git a/src/main/java/org/olat/course/groupsandrights/CourseGroupManager.java b/src/main/java/org/olat/course/groupsandrights/CourseGroupManager.java
index a79465bb2f6..ef5ab2196ca 100644
--- a/src/main/java/org/olat/course/groupsandrights/CourseGroupManager.java
+++ b/src/main/java/org/olat/course/groupsandrights/CourseGroupManager.java
@@ -108,7 +108,7 @@ public interface CourseGroupManager {
 	public boolean isIdentityInLearningArea(Identity identity, Long areaKey);
 
 	/**
-	 * Checks if user is coach in any of the courses learning groups
+	 * Checks if user is coach in the course (of the repository entry or of a business group)
 	 * 
 	 * @param identity
 	 * @return true if user is coach
diff --git a/src/main/java/org/olat/course/nodes/pf/manager/CountingCallback.java b/src/main/java/org/olat/course/nodes/pf/manager/CountingCallback.java
new file mode 100644
index 00000000000..4800bcc0637
--- /dev/null
+++ b/src/main/java/org/olat/course/nodes/pf/manager/CountingCallback.java
@@ -0,0 +1,123 @@
+/**
+ * <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.course.nodes.pf.manager;
+
+import java.util.List;
+
+import org.olat.core.commons.modules.bc.components.FolderComponent;
+import org.olat.core.commons.services.notifications.SubscriptionContext;
+import org.olat.core.util.vfs.Quota;
+import org.olat.core.util.vfs.VFSContainer;
+import org.olat.core.util.vfs.VFSItem;
+import org.olat.core.util.vfs.callbacks.VFSSecurityCallback;
+import org.olat.core.util.vfs.filters.VFSItemExcludePrefixFilter;
+import org.olat.core.util.vfs.filters.VFSItemFilter;
+/**
+*
+* @author Fabian Kiefer, fabian.kiefer@frentix.com, http://www.frentix.com
+*
+*/
+public class CountingCallback implements VFSSecurityCallback {
+	
+	private static final VFSItemFilter attachmentExcludeFilter = new VFSItemExcludePrefixFilter(FolderComponent.ATTACHMENT_EXCLUDE_PREFIXES);
+
+	private SubscriptionContext subsContext;
+	private VFSContainer dropbox;
+	private int limit;
+	private boolean alterFile;
+
+	public CountingCallback(SubscriptionContext subsContext, VFSContainer dropbox, int limit, boolean alterFile) {
+		super();
+		this.subsContext = subsContext;
+		this.dropbox = dropbox;
+		this.limit = limit;
+		this.alterFile = alterFile;
+	}
+	
+	private int countFiles(VFSContainer vfsContainer) {
+		int counter = 0;
+		if (vfsContainer.exists()) {
+			List<VFSItem> children = vfsContainer.getItems(attachmentExcludeFilter);
+			for (VFSItem vfsItem : children) {
+				if (vfsItem instanceof VFSContainer){
+					counter += countFiles((VFSContainer)vfsItem);
+				} else {
+					counter++;										
+				}
+			}
+		}
+		return counter;
+	}
+	
+	private boolean limitReached () {
+		return countFiles(dropbox) <= limit;
+	}
+
+	@Override
+	public boolean canRead() {
+		return true;
+	}
+
+	@Override
+	public boolean canWrite() {
+		return limitReached();
+	}
+
+	@Override
+	public boolean canCreateFolder() {
+		return limitReached();
+	}
+
+	@Override
+	public boolean canDelete() {
+		return alterFile;
+	}
+
+	@Override
+	public boolean canList() {
+		return true;
+	}
+
+	@Override
+	public boolean canCopy() {
+		return limitReached();
+	}
+
+	@Override
+	public boolean canDeleteRevisionsPermanently() {
+		return false;
+	}
+
+	@Override
+	public Quota getQuota() {
+		return null;
+	}
+
+	@Override
+	public void setQuota(Quota quota) {
+		
+	}
+
+	@Override
+	public SubscriptionContext getSubscriptionContext() {
+		return subsContext;
+	}
+
+}
diff --git a/src/main/java/org/olat/course/nodes/pf/manager/FileSystemExport.java b/src/main/java/org/olat/course/nodes/pf/manager/FileSystemExport.java
index 950f3139e51..f440cabb989 100644
--- a/src/main/java/org/olat/course/nodes/pf/manager/FileSystemExport.java
+++ b/src/main/java/org/olat/course/nodes/pf/manager/FileSystemExport.java
@@ -29,6 +29,7 @@ import java.nio.file.SimpleFileVisitor;
 import java.nio.file.attribute.BasicFileAttributes;
 import java.util.HashSet;
 import java.util.List;
+import java.util.Locale;
 import java.util.Set;
 import java.util.zip.ZipEntry;
 import java.util.zip.ZipOutputStream;
@@ -37,10 +38,13 @@ import javax.servlet.http.HttpServletResponse;
 
 import org.olat.core.CoreSpringFactory;
 import org.olat.core.gui.media.MediaResource;
+import org.olat.core.gui.translator.Translator;
 import org.olat.core.id.Identity;
 import org.olat.core.logging.OLog;
 import org.olat.core.logging.Tracing;
+import org.olat.core.util.Util;
 import org.olat.course.nodes.PFCourseNode;
+import org.olat.course.nodes.pf.ui.PFRunController;
 import org.olat.course.run.environment.CourseEnvironment;
 import org.olat.user.UserManager;
 /**
@@ -56,12 +60,15 @@ public class FileSystemExport implements MediaResource {
 	private List<Identity> identities;
 	private PFCourseNode pfNode;
 	private CourseEnvironment courseEnv;
+	private Translator translator;
 
-	public FileSystemExport(List<Identity> identities, PFCourseNode pfNode, CourseEnvironment courseEnv) {
+	public FileSystemExport(List<Identity> identities, PFCourseNode pfNode, CourseEnvironment courseEnv, Locale locale) {
 		super();
 		this.identities = identities;
 		this.pfNode = pfNode;
 		this.courseEnv = courseEnv;
+		this.translator = Util.createPackageTranslator(PFRunController.class, locale);
+
 	}
 
 	@Override
@@ -94,10 +101,10 @@ public class FileSystemExport implements MediaResource {
 		try (ZipOutputStream zout = new ZipOutputStream(hres.getOutputStream())) {
 			zout.setLevel(9);
 			
-			String pfolder = "participantfolder/";
+			String pfolder = translator.translate("participant.folder") + "/";
 			
 			Path relPath = Paths.get(courseEnv.getCourseBaseContainer().getBasefile().getAbsolutePath(),
-					pfolder, pfNode.getIdent()); 
+					PFManager.FILENAME_PARTICIPANTFOLDER, pfNode.getIdent()); 
 						
 			fsToZip(zout, relPath, pfolder);
 			
diff --git a/src/main/java/org/olat/course/nodes/pf/manager/PFManager.java b/src/main/java/org/olat/course/nodes/pf/manager/PFManager.java
index 29f2a712925..14b6b489a46 100644
--- a/src/main/java/org/olat/course/nodes/pf/manager/PFManager.java
+++ b/src/main/java/org/olat/course/nodes/pf/manager/PFManager.java
@@ -30,15 +30,14 @@ import java.nio.file.attribute.BasicFileAttributes;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Date;
-import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Locale;
-import java.util.Map;
 import java.util.Set;
 import java.util.stream.Collectors;
 
 import org.olat.basesecurity.GroupRoles;
+import org.olat.core.commons.modules.bc.components.FolderComponent;
 import org.olat.core.commons.modules.bc.vfs.OlatRootFolderImpl;
 import org.olat.core.commons.services.notifications.SubscriptionContext;
 import org.olat.core.gui.UserRequest;
@@ -47,9 +46,9 @@ import org.olat.core.gui.translator.Translator;
 import org.olat.core.id.Identity;
 import org.olat.core.logging.OLog;
 import org.olat.core.logging.Tracing;
-import org.olat.core.util.FileUtils;
 import org.olat.core.util.Util;
 import org.olat.core.util.i18n.I18nManager;
+import org.olat.core.util.i18n.I18nModule;
 import org.olat.core.util.vfs.NamedContainerImpl;
 import org.olat.core.util.vfs.VFSContainer;
 import org.olat.core.util.vfs.VFSItem;
@@ -57,8 +56,9 @@ import org.olat.core.util.vfs.VFSLeaf;
 import org.olat.core.util.vfs.VFSManager;
 import org.olat.core.util.vfs.VirtualContainer;
 import org.olat.core.util.vfs.callbacks.VFSSecurityCallback;
+import org.olat.core.util.vfs.filters.VFSItemExcludePrefixFilter;
+import org.olat.core.util.vfs.filters.VFSItemFilter;
 import org.olat.course.CourseModule;
-import org.olat.course.groupsandrights.CourseGroupManager;
 import org.olat.course.nodes.PFCourseNode;
 import org.olat.course.nodes.pf.ui.DropBoxRow;
 import org.olat.course.nodes.pf.ui.PFRunController;
@@ -66,6 +66,10 @@ import org.olat.course.run.environment.CourseEnvironment;
 import org.olat.course.run.userview.UserCourseEnvironment;
 import org.olat.group.BusinessGroup;
 import org.olat.group.BusinessGroupService;
+import org.olat.repository.RepositoryEntry;
+import org.olat.repository.RepositoryEntryRelationType;
+import org.olat.repository.RepositoryService;
+import org.olat.repository.manager.RepositoryEntryRelationDAO;
 import org.olat.user.UserManager;
 import org.olat.user.UserPropertiesRow;
 import org.olat.user.propertyhandlers.UserPropertyHandler;
@@ -83,7 +87,8 @@ import org.springframework.stereotype.Service;
 public class PFManager {
 	
 	private static final OLog log = Tracing.createLoggerFor(PFManager.class);
-	
+	private static final VFSItemFilter attachmentExcludeFilter = new VFSItemExcludePrefixFilter(FolderComponent.ATTACHMENT_EXCLUDE_PREFIXES);
+
 	public static final String FILENAME_PARTICIPANTFOLDER = "participantfolder";
 	public static final String FILENAME_RETURNBOX = "returnbox";
 	public static final String FILENAME_DROPBOX = "dropbox";
@@ -91,6 +96,10 @@ public class PFManager {
 	@Autowired
 	private	BusinessGroupService groupService;
 	@Autowired
+	private RepositoryService repositoryService;
+	@Autowired
+	private RepositoryEntryRelationDAO repositoryEntryRelationDao;
+	@Autowired
 	private UserManager userManager;
 	
 	/**
@@ -132,16 +141,12 @@ public class PFManager {
 	private int countFiles(VFSContainer vfsContainer) {
 		int counter = 0;
 		if (vfsContainer.exists()) {
-			List<VFSItem> children = vfsContainer.getItems();
+			List<VFSItem> children = vfsContainer.getItems(attachmentExcludeFilter);
 			for (VFSItem vfsItem : children) {
 				if (vfsItem instanceof VFSContainer){
 					counter += countFiles((VFSContainer)vfsItem);
 				} else {
-					String filename = vfsItem.getName();
-					String suffix = FileUtils.getFileSuffix(filename);
-					if (!filename.startsWith(".") && !"zip".equals(suffix)){
-						counter++;					
-					}					
+					counter++;										
 				}
 			}
 		}
@@ -251,7 +256,7 @@ public class PFManager {
 	 * @param courseEnv 
 	 */
 	public MediaResource exportMediaResource (UserRequest ureq, List<Identity> identities, PFCourseNode pfNode, CourseEnvironment courseEnv) {
-		MediaResource resource = new FileSystemExport (identities, pfNode, courseEnv);
+		MediaResource resource = new FileSystemExport (identities, pfNode, courseEnv, ureq.getLocale());
 		ureq.getDispatchResult().setResultingMediaResource(resource);
 		return resource;
 	}
@@ -263,7 +268,7 @@ public class PFManager {
 	 * @param dropbox
 	 * @return the VFSSecurityCallback
 	 */
-	private VFSSecurityCallback calculateCallback (CourseEnvironment courseEnv, PFCourseNode pfNode, VFSContainer dropbox) {
+	private VFSSecurityCallback calculateCallback (CourseEnvironment courseEnv, PFCourseNode pfNode, VFSContainer dropbox, boolean webdav) {
 		VFSSecurityCallback callback;
 		SubscriptionContext folderSubContext = CourseModule.createSubscriptionContext(courseEnv, pfNode);
 		int count = countFiles(dropbox);
@@ -272,6 +277,8 @@ public class PFManager {
 		boolean alterFile = pfNode.hasAlterFileConfigured();
 		if (timeFrame || limitCount && !alterFile){
 			callback = new ReadOnlyCallback(folderSubContext);
+		} else if (webdav) {
+			callback= new CountingCallback(folderSubContext, dropbox, pfNode.getLimitCount(), alterFile);
 		} else if (limitCount && alterFile) {
 			callback = new ReadDeleteCallback(folderSubContext);
 		} else if (!limitCount && !alterFile) {
@@ -291,12 +298,13 @@ public class PFManager {
 	 * @param identity 
 	 * @return the VFSContainer
 	 */
-	public VFSContainer provideCoachOrParticipantContainer (PFCourseNode pfNode, UserCourseEnvironment userCourseEnv, Identity identity) {	
+	public VFSContainer provideCoachOrParticipantContainer (PFCourseNode pfNode, UserCourseEnvironment userCourseEnv,
+			Identity identity, boolean courseReadOnly) {	
 		VFSContainer vfsContainer = null;
 		if (userCourseEnv.isCoach() || userCourseEnv.isAdmin()) {
-			vfsContainer = provideCoachContainer(pfNode, userCourseEnv.getCourseEnvironment(), identity);
+			vfsContainer = provideCoachContainer(pfNode, userCourseEnv.getCourseEnvironment(), identity, userCourseEnv.isAdmin());
 		} else if (userCourseEnv.isParticipant()) {
-			vfsContainer = provideParticipantContainer(pfNode, userCourseEnv, identity);
+			vfsContainer = provideParticipantContainer(pfNode, userCourseEnv.getCourseEnvironment(), identity, courseReadOnly);
 		}
 		return vfsContainer;
 	}
@@ -309,11 +317,10 @@ public class PFManager {
 	 * @param identity
 	 * @return the VFS container
 	 */
-	private VFSContainer provideParticipantContainer (PFCourseNode pfNode, UserCourseEnvironment userCourseEnv, Identity identity) {
+	private VFSContainer provideParticipantContainer (PFCourseNode pfNode, CourseEnvironment courseEnv,
+			Identity identity, boolean courseReadOnly) {
 		Locale locale = I18nManager.getInstance().getLocaleOrDefault(identity.getUser().getPreferences().getLanguage());
 		Translator translator = Util.createPackageTranslator(PFRunController.class, locale);
-		CourseEnvironment courseEnv = userCourseEnv.getCourseEnvironment();
-		boolean readOnly = userCourseEnv.isCourseReadOnly();
 		SubscriptionContext subsContext = CourseModule.createSubscriptionContext(courseEnv, pfNode);
 		String path = courseEnv.getCourseBaseContainer().getRelPath() + "/" + FILENAME_PARTICIPANTFOLDER;
 		VFSContainer courseElementBaseContainer = new OlatRootFolderImpl(path, null);
@@ -323,11 +330,11 @@ public class PFManager {
 		if (pfNode.hasParticipantBoxConfigured()){
 			VFSContainer dropContainer = new NamedContainerImpl(translator.translate("drop.box"),
 					VFSManager.resolveOrCreateContainerFromPath(userBaseContainer, FILENAME_DROPBOX));
-			if (readOnly) {
+			if (courseReadOnly) {
 				dropContainer.setLocalSecurityCallback(new ReadOnlyCallback(subsContext));
 			} else {
 				VFSContainer dropbox = resolveOrCreateDropFolder(courseEnv, pfNode, identity);
-				VFSSecurityCallback callback = calculateCallback(courseEnv, pfNode, dropbox);
+				VFSSecurityCallback callback = calculateCallback(courseEnv, pfNode, dropbox, true);
 				dropContainer.setLocalSecurityCallback(callback);
 			}
 			namedCourseFolder.addItem(dropContainer);
@@ -349,26 +356,28 @@ public class PFManager {
 	 * @param identity
 	 * @return the VFSContainer
 	 */
-	private VFSContainer provideCoachContainer (PFCourseNode pfNode, CourseEnvironment courseEnv, Identity identity) {
+	private VFSContainer provideCoachContainer (PFCourseNode pfNode, CourseEnvironment courseEnv, Identity identity, boolean admin) {
 		Locale locale = I18nManager.getInstance().getLocaleOrDefault(identity.getUser().getPreferences().getLanguage());
 		Translator translator = Util.createPackageTranslator(PFRunController.class, locale);
 		SubscriptionContext nodefolderSubContext = CourseModule.createSubscriptionContext(courseEnv, pfNode);
-		List<Identity> participants =  getParticipants(identity, courseEnv); 
+		List<Identity> participants =  getParticipants(identity, courseEnv, admin); 
 		String path = courseEnv.getCourseBaseContainer().getRelPath() + "/" + FILENAME_PARTICIPANTFOLDER;
 		VFSContainer courseElementBaseContainer = new OlatRootFolderImpl(path, null);
-		VirtualContainer namedCourseFolder = new VirtualContainer(identity.getName());
+		VirtualContainer namedCourseFolder = new VirtualContainer(translator.translate("participant.folder"));
 		for (Identity participant : participants) {
 			Path relPath = Paths.get(pfNode.getIdent(), getIdFolderName(participant));
 			VFSContainer userBaseContainer = VFSManager.resolveOrCreateContainerFromPath(courseElementBaseContainer, relPath.toString());
-			VirtualContainer participantFolder = new VirtualContainer(participant.getName());
+			String participantfoldername = userManager.getUserDisplayName(participant);
+			VirtualContainer participantFolder = new VirtualContainer(participantfoldername);
 			namedCourseFolder.addItem(participantFolder);
 			
 			if (pfNode.hasParticipantBoxConfigured()){
 				VFSContainer dropContainer = new NamedContainerImpl(translator.translate("drop.box"),
 						VFSManager.resolveOrCreateContainerFromPath(userBaseContainer, FILENAME_DROPBOX));
+				//if coach is also participant, can user his/her webdav folder with participant rights
 				if (identity.equals(participant)){
 					VFSContainer dropbox = resolveOrCreateDropFolder(courseEnv, pfNode, identity);
-					VFSSecurityCallback callback = calculateCallback(courseEnv, pfNode, dropbox);
+					VFSSecurityCallback callback = calculateCallback(courseEnv, pfNode, dropbox, true);
 					dropContainer.setLocalSecurityCallback(callback);
 				} else {
 					dropContainer.setLocalSecurityCallback(new ReadOnlyCallback(nodefolderSubContext));
@@ -387,6 +396,47 @@ public class PFManager {
 		return namedCourseFolder;
 	}
 	
+	/**
+	 * Provide admin view for webdav, contains all participants of the course.
+	 *
+	 * @param pfNode the pf node
+	 * @param courseEnv the course env
+	 * @return the VFS container
+	 */
+	public VFSContainer provideAdminContainer (PFCourseNode pfNode, CourseEnvironment courseEnv) {
+		Translator translator = Util.createPackageTranslator(PFRunController.class, I18nModule.getDefaultLocale());
+		SubscriptionContext nodefolderSubContext = CourseModule.createSubscriptionContext(courseEnv, pfNode);
+		RepositoryEntry re = courseEnv.getCourseGroupManager().getCourseEntry();
+		List<Identity> participants =  repositoryEntryRelationDao.getMembers(re, 
+				RepositoryEntryRelationType.both, GroupRoles.participant.name());		
+		String path = courseEnv.getCourseBaseContainer().getRelPath() + "/" + FILENAME_PARTICIPANTFOLDER;
+		VFSContainer courseElementBaseContainer = new OlatRootFolderImpl(path, null);
+		VirtualContainer namedCourseFolder = new VirtualContainer(translator.translate("participant.folder"));
+		for (Identity participant : participants) {
+			Path relPath = Paths.get(pfNode.getIdent(), getIdFolderName(participant));
+			VFSContainer userBaseContainer = VFSManager.resolveOrCreateContainerFromPath(courseElementBaseContainer, relPath.toString());
+			String participantfoldername = userManager.getUserDisplayName(participant);
+			VirtualContainer participantFolder = new VirtualContainer(participantfoldername);
+			namedCourseFolder.addItem(participantFolder);
+			
+			if (pfNode.hasParticipantBoxConfigured()) {
+				VFSContainer dropContainer = new NamedContainerImpl(translator.translate("drop.box"),
+						VFSManager.resolveOrCreateContainerFromPath(userBaseContainer, FILENAME_DROPBOX));
+				dropContainer.setLocalSecurityCallback(new ReadWriteDeleteCallback(nodefolderSubContext));
+				participantFolder.addItem(dropContainer);
+			}
+			
+			if (pfNode.hasCoachBoxConfigured()){
+				VFSContainer returnContainer = new NamedContainerImpl(translator.translate("return.box"),
+						VFSManager.resolveOrCreateContainerFromPath(userBaseContainer, FILENAME_RETURNBOX));
+				returnContainer.setLocalSecurityCallback(new ReadWriteDeleteCallback(nodefolderSubContext));
+				participantFolder.addItem(returnContainer);
+			}
+		}		
+		return namedCourseFolder;
+	}
+	
+
 	
 	/**
 	 * Provide participant folder in GUI.
@@ -398,11 +448,9 @@ public class PFManager {
 	 * @param isCoach 
 	 * @return the VFS container
 	 */
-	public VFSContainer provideParticipantFolder (PFCourseNode pfNode, PFView pfView,
+	public VFSContainer provideParticipantFolder (PFCourseNode pfNode, PFView pfView, Translator translator,
 			CourseEnvironment courseEnv, Identity identity, boolean isCoach, boolean readOnly) {
-		Locale locale = I18nManager.getInstance().getLocaleOrDefault(identity.getUser().getPreferences().getLanguage());
 		SubscriptionContext nodefolderSubContext = CourseModule.createSubscriptionContext(courseEnv, pfNode);
-		Translator translator = Util.createPackageTranslator(PFRunController.class, locale);
 		
 		String path = courseEnv.getCourseBaseContainer().getRelPath() + "/" + FILENAME_PARTICIPANTFOLDER;
 		VFSContainer courseElementBaseContainer = new OlatRootFolderImpl(path, null);
@@ -442,7 +490,7 @@ public class PFManager {
 				returnContainer.setLocalSecurityCallback(new ReadWriteDeleteCallback(nodefolderSubContext));
 			} else {
 				VFSContainer dropbox = resolveOrCreateDropFolder(courseEnv, pfNode, identity);
-				VFSSecurityCallback callback = calculateCallback(courseEnv, pfNode, dropbox);
+				VFSSecurityCallback callback = calculateCallback(courseEnv, pfNode, dropbox, false);
 				dropContainer.setLocalSecurityCallback(callback);
 				returnContainer.setLocalSecurityCallback(new ReadOnlyCallback(nodefolderSubContext));
 			}
@@ -474,29 +522,29 @@ public class PFManager {
 	 * @param pfNode 
 	 * @param locale 
 	 * @param courseEnv
+	 * @param admin
 	 * @return the participants
 	 */
-	public List<Identity> getParticipants (Identity id, CourseEnvironment courseEnv) {
-		CourseGroupManager groupManager = courseEnv.getCourseGroupManager();
-		Set<Identity> identitiesSet = new HashSet<>();
-		// iterate course members
-		if (groupManager.isIdentityCourseAdministrator(id) || groupManager.isIdentityCourseAdministrator(id)) {
-			List<Identity> identities = groupManager.getParticipants();
-			for (Identity identity : identities) {
-				identitiesSet.add(identity);
+	public List<Identity> getParticipants(Identity id, CourseEnvironment courseEnv, boolean admin) {
+		Set<Identity> identitySet = new HashSet<>();
+		RepositoryEntry re = courseEnv.getCourseGroupManager().getCourseEntry();
+		if(admin) {
+			return repositoryEntryRelationDao.getMembers(re, RepositoryEntryRelationType.both, GroupRoles.participant.name());
+		} else {
+			if(repositoryService.hasRole(id, re, GroupRoles.coach.name())) {
+				List<Identity> identities = repositoryService.getMembers(re, GroupRoles.participant.name());
+				identitySet.addAll(identities);
 			}
-		}
-		//iterate group members
-		List<BusinessGroup> bgroups = groupManager.getOwnedBusinessGroups(id);
-		if (bgroups != null) {
-			for (BusinessGroup bgroup : bgroups) {
-				List<Identity> identities = groupService.getMembers(bgroup, GroupRoles.participant.toString());
-				for (Identity identity : identities) {
-					identitiesSet.add(identity);
+			
+			List<BusinessGroup> bgroups = courseEnv.getCourseGroupManager().getOwnedBusinessGroups(id);
+			if (bgroups != null) {
+				for (BusinessGroup bgroup : bgroups) {
+					List<Identity> identities = groupService.getMembers(bgroup, GroupRoles.participant.name());
+					identitySet.addAll(identities);
 				}
 			}
 		}
-		List<Identity> participants = identitiesSet.stream().collect(Collectors.toList());
+		List<Identity> participants = identitySet.stream().collect(Collectors.toList());
 		return participants;
 	}
 	
@@ -508,48 +556,32 @@ public class PFManager {
 	 * @param userPropertyHandlers 
 	 * @param locale 
 	 * @param courseEnv
+	 * @param admin
 	 * @return the participants
 	 */
 	public List<DropBoxRow> getParticipants (Identity id, PFCourseNode pfNode, List<UserPropertyHandler> userPropertyHandlers, 
-			Locale locale, CourseEnvironment courseEnv) {
-		Map<Identity, DropBoxRow> participantsMap = new HashMap<>();
-		CourseGroupManager groupManager = courseEnv.getCourseGroupManager();
-		// iterate course members
-		if (groupManager.isIdentityCourseAdministrator(id) || groupManager.isIdentityCourseAdministrator(id)) {
-			List<Identity> identities = groupManager.getParticipants();
-			for (Identity identity : identities) {
-				VFSContainer dropbox = resolveOrCreateDropFolder(courseEnv, pfNode, identity);
-				int filecount = countFiles(dropbox);
-				VFSContainer returnbox = resolveOrCreateReturnFolder(courseEnv, pfNode, identity);
-				int filecountR = countFiles(returnbox);
-				Date lastModified = getLastUpdated(courseEnv, pfNode, identity, FILENAME_DROPBOX);
-				Date lastModifiedR = getLastUpdated(courseEnv, pfNode, identity, FILENAME_RETURNBOX);
-				UserPropertiesRow urow = new UserPropertiesRow(identity, userPropertyHandlers, locale);
-				participantsMap.put(identity, new DropBoxRow(urow, "status",
-						filecount, filecountR, pfNode.getLimitCount(), lastModified, lastModifiedR));		
+			Locale locale, CourseEnvironment courseEnv, boolean admin) {
 
+		List<Identity> identityList = getParticipants(id, courseEnv, admin);
+
+		Set<Identity> duplicates = new HashSet<>();
+		List<DropBoxRow> participants = new ArrayList<>(identityList.size());
+		for (Identity identity : identityList) {
+			if(duplicates.contains(identity)) {
+				continue;
 			}
+			duplicates.add(identity);
+
+			VFSContainer dropbox = resolveOrCreateDropFolder(courseEnv, pfNode, identity);
+			int filecount = countFiles(dropbox);
+			VFSContainer returnbox = resolveOrCreateReturnFolder(courseEnv, pfNode, identity);
+			int filecountR = countFiles(returnbox);
+			Date lastModified = getLastUpdated(courseEnv, pfNode, identity, FILENAME_DROPBOX);
+			Date lastModifiedR = getLastUpdated(courseEnv, pfNode, identity, FILENAME_RETURNBOX);
+			UserPropertiesRow urow = new UserPropertiesRow(identity, userPropertyHandlers, locale);
+			participants.add(new DropBoxRow(urow, "status",
+					filecount, filecountR, pfNode.getLimitCount(), lastModified, lastModifiedR));
 		}
-		//iterate group members
-		List<BusinessGroup> bgroups = groupManager.getOwnedBusinessGroups(id);
-		if (bgroups != null) {
-			for (BusinessGroup bgroup : bgroups) {
-				List<Identity> identities = groupService.getMembers(bgroup, GroupRoles.participant.toString());
-				for (Identity identity : identities) {
-					VFSContainer dropbox = resolveOrCreateDropFolder(courseEnv, pfNode, identity);
-					int filecount = countFiles(dropbox);
-					VFSContainer returnbox = resolveOrCreateReturnFolder(courseEnv, pfNode, identity);
-					int filecountR = countFiles(returnbox);
-					Date lastModified = getLastUpdated(courseEnv, pfNode, identity, FILENAME_DROPBOX);
-					Date lastModifiedR = getLastUpdated(courseEnv, pfNode, identity, FILENAME_RETURNBOX);
-					UserPropertiesRow urow = new UserPropertiesRow(identity, userPropertyHandlers, locale);
-					participantsMap.put(identity, new DropBoxRow(urow, "status",
-							filecount, filecountR, pfNode.getLimitCount(), lastModified, lastModifiedR));
-				
-				}
-			}
-		}
-		List<DropBoxRow> participants = new ArrayList<>(participantsMap.values());
 		return participants;		
 	}
 	
diff --git a/src/main/java/org/olat/course/nodes/pf/manager/PFNotifications.java b/src/main/java/org/olat/course/nodes/pf/manager/PFNotifications.java
index 99d30c3238f..761b131c0f1 100644
--- a/src/main/java/org/olat/course/nodes/pf/manager/PFNotifications.java
+++ b/src/main/java/org/olat/course/nodes/pf/manager/PFNotifications.java
@@ -94,7 +94,7 @@ public class PFNotifications {
 			this.displayname = entry.getDisplayname();
 			
 			if (groupManager.isIdentityCourseCoach(identity) || groupManager.isIdentityCourseAdministrator(identity)) {
-				List<Identity> participants = pfManager.getParticipants(identity, courseEnv);
+				List<Identity> participants = pfManager.getParticipants(identity, courseEnv, groupManager.isIdentityCourseAdministrator(identity));
 
 				for (Identity participant : participants) {					
 					gatherItems(participant, p, courseEnv, node);
diff --git a/src/main/java/org/olat/course/nodes/pf/manager/PFNotificationsHandler.java b/src/main/java/org/olat/course/nodes/pf/manager/PFNotificationsHandler.java
index a2db4064d27..a13852ea4ad 100644
--- a/src/main/java/org/olat/course/nodes/pf/manager/PFNotificationsHandler.java
+++ b/src/main/java/org/olat/course/nodes/pf/manager/PFNotificationsHandler.java
@@ -57,7 +57,7 @@ import org.springframework.stereotype.Service;
 public class PFNotificationsHandler implements NotificationsHandler {
 
 	private static final OLog log = Tracing.createLoggerFor(PFNotificationsHandler.class);
-	protected static final String CSS_CLASS_ICON = "o_gta_icon";
+	protected static final String CSS_CLASS_ICON = "o_pf_icon";
 
 	@Autowired
 	private NotificationsManager notificationsManager;
diff --git a/src/main/java/org/olat/course/nodes/pf/manager/ReadWriteCallback.java b/src/main/java/org/olat/course/nodes/pf/manager/ReadWriteCallback.java
index c06c9a82606..e5eed49f686 100644
--- a/src/main/java/org/olat/course/nodes/pf/manager/ReadWriteCallback.java
+++ b/src/main/java/org/olat/course/nodes/pf/manager/ReadWriteCallback.java
@@ -48,7 +48,7 @@ public class ReadWriteCallback implements VFSSecurityCallback {
 
 	@Override
 	public boolean canCreateFolder() {
-		return false;
+		return true;
 	}
 
 	@Override
@@ -63,7 +63,7 @@ public class ReadWriteCallback implements VFSSecurityCallback {
 
 	@Override
 	public boolean canCopy() {
-		return false;
+		return true;
 	}
 
 	@Override
diff --git a/src/main/java/org/olat/course/nodes/pf/ui/PFCoachController.java b/src/main/java/org/olat/course/nodes/pf/ui/PFCoachController.java
index a70979b8d12..cc6d3842f94 100644
--- a/src/main/java/org/olat/course/nodes/pf/ui/PFCoachController.java
+++ b/src/main/java/org/olat/course/nodes/pf/ui/PFCoachController.java
@@ -272,8 +272,8 @@ public class PFCoachController extends FormBasicController implements Controller
 		dropboxTable.setSelectAllEnable(true);
 		dropboxTable.setExportEnabled(true);
 		dropboxTable.setAndLoadPersistedPreferences(ureq, this.getClass().getName() + "_" + pfView.name());
-
-		tableModel.setObjects(pfManager.getParticipants(identity, pfNode, userPropertyHandlers, getLocale(), courseEnv));
+		
+		tableModel.setObjects(pfManager.getParticipants(identity, pfNode, userPropertyHandlers, getLocale(), courseEnv, userCourseEnv.isAdmin()));
 
 		
 		FormLayoutContainer buttonGroupLayout = FormLayoutContainer.createButtonLayout("buttons", getTranslator());
diff --git a/src/main/java/org/olat/course/nodes/pf/ui/PFEditFormController.java b/src/main/java/org/olat/course/nodes/pf/ui/PFEditFormController.java
index c953678293d..6b4df7c3bc3 100644
--- a/src/main/java/org/olat/course/nodes/pf/ui/PFEditFormController.java
+++ b/src/main/java/org/olat/course/nodes/pf/ui/PFEditFormController.java
@@ -67,19 +67,11 @@ public class PFEditFormController extends FormBasicController {
 		alterFiles = uifactory.addCheckboxesHorizontal("alter.file", "blank.label", formLayout, new String[]{"xx"}, alterfile);
 		alterFiles.addActionListener(FormEvent.ONCLICK);
 		
-		String[] limitcount = new String[]{ translate("limit.count") };
-		limitFileCount = uifactory.addCheckboxesHorizontal("limit.count", "blank.label", formLayout, new String[]{"xx"}, limitcount);
-		limitFileCount.addActionListener(FormEvent.ONCLICK);
-		limitFileCount.showLabel(Boolean.FALSE);
-		fileCount = uifactory.addIntegerElement("file.count", 3, formLayout);
-		fileCount.showLabel(Boolean.FALSE);
-
 		String[] timeframe = new String[]{ translate("time.frame") };
 		timeFrame = uifactory.addCheckboxesHorizontal("time.frame", "blank.label", formLayout, new String[]{"xx"}, timeframe);
 		timeFrame.addActionListener(FormEvent.ONCLICK);
 		timeFrame.showLabel(Boolean.FALSE);
-	
-		
+			
 		dateStart = new JSDateChooser("dateStart", getLocale());
 		dateStart.setLabel("date.start", null);
 		dateStart.setDateChooserTimeEnabled(true);
@@ -94,6 +86,14 @@ public class PFEditFormController extends FormBasicController {
 		dateEnd.setMandatory(true);
 		formLayout.add(dateEnd);
 		
+		String[] limitcount = new String[]{ translate("limit.count") };
+		limitFileCount = uifactory.addCheckboxesHorizontal("limit.count", "blank.label", formLayout, new String[]{"xx"}, limitcount);
+		limitFileCount.addActionListener(FormEvent.ONCLICK);
+		limitFileCount.showLabel(Boolean.FALSE);
+		fileCount = uifactory.addIntegerElement("file.count", 3, formLayout);
+		fileCount.showLabel(Boolean.FALSE);
+		fileCount.setHelpTextKey("limit.count.coach.info", null);
+
 		spacerEl = uifactory.addSpacerElement("spacer1", formLayout, false);
 		
 		teacherDropBox = uifactory.addCheckboxesHorizontal("coach.drop", formLayout, new String[]{"xx"}, new String[]{null});
@@ -137,7 +137,9 @@ public class PFEditFormController extends FormBasicController {
 			activateSettings();
 		} else if (source == limitFileCount) {
 			activateFileCount();
-			showInfo("limit.count.coach.info");
+			if (limitFileCount.isSelected(0)) {
+				showInfo("limit.count.coach.info");
+			}
 		} else if (source == timeFrame) {
 			activateTimeFrame();
 		}
@@ -199,6 +201,8 @@ public class PFEditFormController extends FormBasicController {
 	protected void formOK(UserRequest ureq) {
 		if (!checkTimeFrameValid()) {
 			dateEnd.setErrorKey("timeframe.error", null);
+		} else if (1 > fileCount.getIntValue()) {
+			fileCount.setErrorKey("filecount.error", null);
 		} else if (!(studentDropBox.isSelected(0) || teacherDropBox.isSelected(0))) {
 			showError("folderselection.error");
 		} else {
diff --git a/src/main/java/org/olat/course/nodes/pf/ui/PFParticipantController.java b/src/main/java/org/olat/course/nodes/pf/ui/PFParticipantController.java
index 37235020045..1606e1562c8 100644
--- a/src/main/java/org/olat/course/nodes/pf/ui/PFParticipantController.java
+++ b/src/main/java/org/olat/course/nodes/pf/ui/PFParticipantController.java
@@ -79,7 +79,8 @@ public class PFParticipantController extends BasicController {
 		//CourseFreeze
 		readOnly = readOnly ? true : userCourseEnv.isCourseReadOnly();
 		
-		VFSContainer frc = pfManager.provideParticipantFolder(pfNode, pfView, courseEnv, identity, isCoach, readOnly);
+		VFSContainer frc = pfManager.provideParticipantFolder(pfNode, pfView, getTranslator(),courseEnv,
+				identity, isCoach, readOnly);
 		folderRunController = new FolderRunController(frc, false, false, false, false, ureq, wControl, null, null, null);
 		folderRunController.disableSubscriptionController();
 		listenTo(folderRunController);
diff --git a/src/main/java/org/olat/course/nodes/pf/ui/PFPeekviewController.java b/src/main/java/org/olat/course/nodes/pf/ui/PFPeekviewController.java
index 3f19fb01faa..a546bf56a00 100644
--- a/src/main/java/org/olat/course/nodes/pf/ui/PFPeekviewController.java
+++ b/src/main/java/org/olat/course/nodes/pf/ui/PFPeekviewController.java
@@ -22,6 +22,7 @@ package org.olat.course.nodes.pf.ui;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Comparator;
+import java.util.Date;
 import java.util.List;
 
 import org.olat.core.CoreSpringFactory;
@@ -86,7 +87,7 @@ public class PFPeekviewController extends BasicController implements Controller
 			// Add link to jump to course node
 			if (leaf instanceof LocalFileImpl) {
 				DownloadComponent dlComp = new DownloadComponent("nodeLinkDL_"+(i+1), leaf, forceDownload,
-						leaf.getName(), translate("preview.downloadfile"),
+						leaf.getName() + " " + new Date(leaf.getLastModified()), translate("peekview.downloadfile"),
 						CSSHelper.createFiletypeIconCssClassFor(leaf.getName()));
 				dlComp.setElementCssClass("o_gotoNode");
 				peekviewVC.put("nodeLinkDL_"+(i+1),dlComp);
diff --git a/src/main/java/org/olat/course/nodes/pf/ui/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/course/nodes/pf/ui/_i18n/LocalStrings_de.properties
index eba24c12dd5..187b3dff5b6 100644
--- a/src/main/java/org/olat/course/nodes/pf/ui/_i18n/LocalStrings_de.properties
+++ b/src/main/java/org/olat/course/nodes/pf/ui/_i18n/LocalStrings_de.properties
@@ -1,3 +1,4 @@
+participant.folder=Teilnehmer Ordner
 participant.drop=Teilnehmer Abgabeordner aktivieren
 coach.drop=Betreuer R\u00FCckgabeordner aktivieren
 drop.box=Teilnehmer Abgabeordner
@@ -40,9 +41,11 @@ notifications.entry.by=von
 notifications.header=Teilnehmer des Kurses "{0}" haben neue Dokumente eingestellt.
 timeframe.error=Bitte \u00FCberpr\u00FCfen Sie ob das limitierende Zeitfenster korrekt ist. 
 folderselection.error=Bitte aktivieren Sie mindestens einen der beiden Ordner.
+filecount.error=Bitte erlauben Sie mindestens einen Hochladevorgang.
 condition.accessibility.title=Zugang
 upload.success=Es wurden Dokumente eingestellt
 peekview.allItemsLink=Alle Dokumente
+peekview.downloadfile=Dokument herunterladen
 preview.drop=Teilnehmer Abgabeordner aktiviert
 preview.return=Betreuer R\u00FCckgabeordner aktiviert
 preview.limit=Dokumentenlimite aktiviert
diff --git a/src/main/java/org/olat/course/nodes/pf/ui/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/course/nodes/pf/ui/_i18n/LocalStrings_en.properties
index eb3fabeafd1..0557e658c03 100644
--- a/src/main/java/org/olat/course/nodes/pf/ui/_i18n/LocalStrings_en.properties
+++ b/src/main/java/org/olat/course/nodes/pf/ui/_i18n/LocalStrings_en.properties
@@ -1,3 +1,4 @@
+participant.folder=Participant folder
 participant.drop=Enable Participant Drop Box
 coach.drop=Enable Coach Return Box
 drop.box=Participant Drop Box
@@ -40,9 +41,11 @@ notifications.entry.by=by
 notifications.header=Participants of of the course "{0}" uploaded new files.
 timeframe.error=Please check if your time interval is valid!
 folderselection.error=Please enable at least one folder.
+filecount.error=Please allow at least one upload.
 condition.accessibility.title=Access Control
 upload.success=Files have been uploaded
 peekview.allItemsLink=All documents
+peekview.downloadfile=Download file
 preview.drop=Participant Dropbox enabled
 preview.return=Coach Returnbox enabled
 preview.limit=Filelimit active
diff --git a/src/main/java/org/olat/course/nodes/pf/ui/_i18n/LocalStrings_fr.properties b/src/main/java/org/olat/course/nodes/pf/ui/_i18n/LocalStrings_fr.properties
index 6ee0809afb6..52298a9c5ca 100644
--- a/src/main/java/org/olat/course/nodes/pf/ui/_i18n/LocalStrings_fr.properties
+++ b/src/main/java/org/olat/course/nodes/pf/ui/_i18n/LocalStrings_fr.properties
@@ -1,4 +1,5 @@
-#Thu Jan 12 18:48:48 CET 2017
+#Wed Jan 11 22:04:13 CET 2017
+participant.folder=Dossier de participant
 alter.file=Autoriser l'effacement et la r\u00E9\u00E9criture des documents
 blank.label=
 coach.drop=Activ\u00E9 le dossier du coach
@@ -26,6 +27,7 @@ pane.tab.accessibility=Acc\u00E8s
 pane.tab.configuration=Configuration des dossiers
 participant.drop=Activer bo\u00EEte de d\u00E9p\u00F4t
 peekview.allItemsLink=Tous les documents
+peekview.downloadfile=T\u00E9tl\u00E9tcharger un fichier
 preview.drop=Bo\u00EEte de d\u00E9p\u00F4t activ\u00E9e
 preview.header=Configuration du dossier pour l'utilisateur simul\u00E9
 preview.info=Un exemple se trouve ci-dessous\:
@@ -47,6 +49,7 @@ table.no.selection=Vous n'avez pas s\u00E9lectionn\u00E9 d'utilisateur.
 textfield.upload=T\u00E9l\u00E9charger un fichier
 time.frame=Limiter la p\u00E9riode de t\u00E9l\u00E9chargement
 timeframe.error=V\u00E9rifier que l'intervalle de temps sont correct.
+filecount.error=Veuillez autoriser au moins un t\u00E9l\u00E9chargement.
 upload.link=T\u00E9l\u00E9charger en masse
 upload.success=Des fichiers ont \u00E9t\u00E9 t\u00E9l\u00E9charg\u00E9s
 valid.date=Entrez s'il vous pla\u00EEt une date valide.
diff --git a/src/test/java/org/olat/course/nodes/pf/manager/PFManagerTest.java b/src/test/java/org/olat/course/nodes/pf/manager/PFManagerTest.java
index e95170aacd9..a9fa64fd5fc 100644
--- a/src/test/java/org/olat/course/nodes/pf/manager/PFManagerTest.java
+++ b/src/test/java/org/olat/course/nodes/pf/manager/PFManagerTest.java
@@ -83,7 +83,7 @@ public class PFManagerTest extends OlatTestCase {
 
 		Identity check3 = JunitTestHelper.createAndPersistIdentityAsRndUser("check-3");
 		repositoryEntryRelationDao.addRole(check3, entry, GroupRoles.participant.name());
-		VFSContainer vfsContainer = pfManager.provideCoachOrParticipantContainer(pfNode, userCourseEnv, check3);
+		VFSContainer vfsContainer = pfManager.provideCoachOrParticipantContainer(pfNode, userCourseEnv, check3, false);
 		Assert.assertNotNull(vfsContainer);
 		Assert.assertTrue(vfsContainer.exists());
 	}
@@ -107,7 +107,7 @@ public class PFManagerTest extends OlatTestCase {
 		
 		Identity check4 = JunitTestHelper.createAndPersistIdentityAsRndUser("check-4");
 		repositoryEntryRelationDao.addRole(check4, entry, GroupRoles.coach.name());
-		VFSContainer vfsContainer = pfManager.provideCoachOrParticipantContainer(pfNode, userCourseEnv, check4);
+		VFSContainer vfsContainer = pfManager.provideCoachOrParticipantContainer(pfNode, userCourseEnv, check4, false);
 		Assert.assertNotNull(vfsContainer);
 	}
 	
@@ -203,7 +203,7 @@ public class PFManagerTest extends OlatTestCase {
 		dbInstance.commitAndCloseSession();
 		
 		
-		List<Identity> ids = pfManager.getParticipants(initialAuthor, courseEnv);
+		List<Identity> ids = pfManager.getParticipants(initialAuthor, courseEnv, true);
 		//check
 		Assert.assertEquals(ids.size(), 5);
 		Assert.assertFalse(ids.contains(initialAuthor));
-- 
GitLab