From 613bcaf36a93a658ad4c73decf2c3f96e638396e Mon Sep 17 00:00:00 2001
From: srosse <none@none>
Date: Fri, 9 May 2014 08:48:17 +0200
Subject: [PATCH] OO-990: authoring details and settings

---
 .../java/org/olat/core/util/PathUtils.java    |  38 ++
 .../course/nodes/AbstractFeedCourseNode.java  |  22 +-
 .../org/olat/course/nodes/CPCourseNode.java   |  14 +-
 .../olat/course/nodes/IQSELFCourseNode.java   |  12 +-
 .../olat/course/nodes/IQSURVCourseNode.java   |  17 +-
 .../olat/course/nodes/IQTESTCourseNode.java   |  14 +-
 .../course/nodes/PortfolioCourseNode.java     |   7 +-
 .../olat/course/nodes/ScormCourseNode.java    |  20 +-
 .../org/olat/course/nodes/WikiCourseNode.java |  12 +-
 .../course/nodes/wiki/WikiEditController.java |  36 +-
 .../olat/course/run/RunMainController.java    |   3 +-
 .../types/AnimationFileResource.java          |   7 +-
 .../fileresource/types/CourseResource.java    |  70 ----
 .../fileresource/types/DocFileResource.java   |   7 +-
 .../fileresource/types/FeedFileResource.java  |   7 +-
 .../olat/fileresource/types/FileResource.java |  31 +-
 .../fileresource/types/GlossaryResource.java  |   8 +-
 .../fileresource/types/ImageFileResource.java |   7 +-
 .../fileresource/types/ImsCPFileResource.java |   5 +-
 .../fileresource/types/MovieFileResource.java |   7 +-
 .../fileresource/types/PdfFileResource.java   |   7 +-
 .../types/PowerpointFileResource.java         |   7 +-
 .../types/ScormCPFileResource.java            |   5 +-
 .../types/SharedFolderFileResource.java       |   5 +-
 .../fileresource/types/SoundFileResource.java |   7 +-
 .../olat/fileresource/types/WikiResource.java |   5 +-
 .../fileresource/types/XlsFileResource.java   |   7 +-
 .../qti/fileresource/SurveyFileResource.java  |   5 +-
 .../qti/fileresource/TestFileResource.java    |   5 +-
 .../repository/RepositoryEntryAuthorView.java |   2 +
 .../RepositoryEntryImportExport.java          |  16 +-
 ...SearchAuthorRepositoryEntryViewParams.java |  32 +-
 .../repository/_spring/repositoryContext.xml  |   2 +-
 .../ReferencableEntriesSearchController.java  |   2 +-
 .../repository/handlers/CourseHandler.java    |  70 +++-
 .../handlers/RepositoryHandlerFactory.java    |  24 +-
 .../RepositoryEntryAuthorViewQueries.java     |  24 ++
 .../model/RepositoryEntryAuthorViewImpl.java  |   8 +-
 .../ui/author/AuthorListController.java       |  10 +-
 .../ui/author/AuthorSearchController.java     | 127 ++----
 .../author/AuthoringEditEntryController.java  |   2 +-
 .../AuthoringEntryDetailsController.java      | 391 ++++++++++++++++--
 .../author/CopyRepositoryEntryController.java |  13 +-
 .../ImportRepositoryEntryController.java      |   2 +-
 .../author/OverviewAuthoringController.java   |  12 +-
 .../repository/ui/author/SearchEvent.java     |  25 +-
 .../database/mysql/alter_9_4_0_to_10_0_0.sql  |   1 +
 .../database/mysql/setupDatabase.sql          |   1 +
 .../postgresql/alter_9_4_0_to_10_0_0.sql      |   1 +
 .../services/webdav/WebDAVExternalTest.java   |  19 +
 50 files changed, 740 insertions(+), 441 deletions(-)
 create mode 100644 src/main/java/org/olat/core/util/PathUtils.java
 delete mode 100644 src/main/java/org/olat/fileresource/types/CourseResource.java

diff --git a/src/main/java/org/olat/core/util/PathUtils.java b/src/main/java/org/olat/core/util/PathUtils.java
new file mode 100644
index 00000000000..eb7b67f08e8
--- /dev/null
+++ b/src/main/java/org/olat/core/util/PathUtils.java
@@ -0,0 +1,38 @@
+package org.olat.core.util;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.FileSystems;
+import java.nio.file.FileVisitor;
+import java.nio.file.Files;
+import java.nio.file.Path;
+
+/**
+ * 
+ * Initial date: 08.05.2014<br>
+ * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
+ *
+ */
+public class PathUtils {
+	
+	public static Path visit(File file, String filename, FileVisitor<Path> visitor) 
+	throws IOException {
+		if(!StringHelper.containsNonWhitespace(filename)) {
+			filename = file.getName();
+		}
+		
+		Path fPath = null;
+		if(file.isDirectory()) {
+			fPath = file.toPath();
+		} else if(filename != null && filename.toLowerCase().endsWith(".zip")) {
+			fPath = FileSystems.newFileSystem(file.toPath(), null).getPath("/");
+		} else {
+			fPath = file.toPath();
+		}
+		if(fPath != null) {
+		    Files.walkFileTree(fPath, visitor);
+		}
+		return fPath;
+	}
+
+}
diff --git a/src/main/java/org/olat/course/nodes/AbstractFeedCourseNode.java b/src/main/java/org/olat/course/nodes/AbstractFeedCourseNode.java
index d336c793cd6..ee15f1b6eb4 100644
--- a/src/main/java/org/olat/course/nodes/AbstractFeedCourseNode.java
+++ b/src/main/java/org/olat/course/nodes/AbstractFeedCourseNode.java
@@ -20,17 +20,11 @@
 package org.olat.course.nodes;
 
 import java.io.File;
-import java.util.Date;
 import java.util.Locale;
 
 import org.olat.core.gui.UserRequest;
 import org.olat.core.gui.control.WindowControl;
 import org.olat.core.id.Identity;
-import org.olat.core.id.OLATResourceable;
-import org.olat.core.util.Formatter;
-import org.olat.core.util.vfs.LocalFolderImpl;
-import org.olat.core.util.vfs.VFSContainer;
-import org.olat.core.util.vfs.VFSLeaf;
 import org.olat.course.ICourse;
 import org.olat.course.condition.Condition;
 import org.olat.course.condition.interpreter.ConditionInterpreter;
@@ -243,18 +237,20 @@ public abstract class AbstractFeedCourseNode extends GenericCourseNode {
 	}
 
 	public void importNode(RepositoryHandler handler, File importDirectory, Identity owner, Locale locale) {
-		File importSubdir = new File(importDirectory, getIdent());
-		RepositoryEntryImportExport rie = new RepositoryEntryImportExport(importSubdir);
-		RepositoryEntry re = handler.importResource(owner, rie.getDisplayName(), rie.getDescription(),
+		RepositoryEntryImportExport rie = new RepositoryEntryImportExport(importDirectory, getIdent());
+		if (rie.anyExportedPropertiesAvailable()) {
+			RepositoryEntry re = handler.importResource(owner, rie.getDisplayName(), rie.getDescription(),
 				locale, rie.importGetExportedFile(), null);
-		FeedNodeEditController.setReference(re, getModuleConfiguration());
+			FeedNodeEditController.setReference(re, getModuleConfiguration());
+		}
 	}
 
 	/**
 	 * @see org.olat.course.nodes.GenericCourseNode#archiveNodeData(java.util.Locale,
 	 *      org.olat.course.ICourse, java.io.File, java.lang.String)
-	 */
-	public void archiveNodeData(Locale locale, ICourse course, File exportDirectory, String charset, String type) {
+	 *//*
+	@Override
+	public boolean archiveNodeData(Locale locale, ICourse course, ArchiveOptions options, ZipOutputStream exportStream, String charset) {
 		VFSContainer exportContainer = new LocalFolderImpl(exportDirectory);
 		VFSContainer exportDir = (VFSContainer) exportContainer.resolve(type);
 		if (exportDir == null) {
@@ -273,5 +269,5 @@ public abstract class AbstractFeedCourseNode extends GenericCourseNode {
 			}
 			// FIXME:FG:6.3 Archive user comments as soon as implemented.			
 		}
-	}
+	}*/
 }
diff --git a/src/main/java/org/olat/course/nodes/CPCourseNode.java b/src/main/java/org/olat/course/nodes/CPCourseNode.java
index 3c71dc66b66..8b31557fd95 100644
--- a/src/main/java/org/olat/course/nodes/CPCourseNode.java
+++ b/src/main/java/org/olat/course/nodes/CPCourseNode.java
@@ -291,13 +291,13 @@ public class CPCourseNode extends AbstractAccessableCourseNode {
 
 	@Override
 	public void importNode(File importDirectory, ICourse course, Identity owner, Locale locale) {
-		RepositoryHandler handler = RepositoryHandlerFactory.getInstance().getRepositoryHandler(ImsCPFileResource.TYPE_NAME);
-		
-		File importSubdir = new File(importDirectory, getIdent());
-		RepositoryEntryImportExport rie = new RepositoryEntryImportExport(importSubdir);
-		RepositoryEntry re = handler.importResource(owner, rie.getDisplayName(), rie.getDescription(),
-				locale, rie.importGetExportedFile(), null);
-		CPEditController.setCPReference(re, getModuleConfiguration());
+		RepositoryEntryImportExport rie = new RepositoryEntryImportExport(importDirectory, getIdent());
+		if(rie.anyExportedPropertiesAvailable()) {
+			RepositoryHandler handler = RepositoryHandlerFactory.getInstance().getRepositoryHandler(ImsCPFileResource.TYPE_NAME);
+			RepositoryEntry re = handler.importResource(owner, rie.getDisplayName(), rie.getDescription(),
+					locale, rie.importGetExportedFile(), null);
+			CPEditController.setCPReference(re, getModuleConfiguration());
+		}
 	}
 
 	@Override
diff --git a/src/main/java/org/olat/course/nodes/IQSELFCourseNode.java b/src/main/java/org/olat/course/nodes/IQSELFCourseNode.java
index ced23c6c525..33f76df1fef 100644
--- a/src/main/java/org/olat/course/nodes/IQSELFCourseNode.java
+++ b/src/main/java/org/olat/course/nodes/IQSELFCourseNode.java
@@ -246,13 +246,13 @@ public class IQSELFCourseNode extends AbstractAccessableCourseNode implements Se
 
 	@Override
 	public void importNode(File importDirectory, ICourse course, Identity owner, Locale locale) {
-		RepositoryHandler handler = RepositoryHandlerFactory.getInstance().getRepositoryHandler(TestFileResource.TYPE_NAME);
-		
-		File importSubdir = new File(importDirectory, getIdent());
-		RepositoryEntryImportExport rie = new RepositoryEntryImportExport(importSubdir);
-		RepositoryEntry re = handler.importResource(owner, rie.getDisplayName(), rie.getDescription(),
+		RepositoryEntryImportExport rie = new RepositoryEntryImportExport(importDirectory, getIdent());
+		if(rie.anyExportedPropertiesAvailable()) {
+			RepositoryHandler handler = RepositoryHandlerFactory.getInstance().getRepositoryHandler(TestFileResource.TYPE_NAME);
+			RepositoryEntry re = handler.importResource(owner, rie.getDisplayName(), rie.getDescription(),
 				locale, rie.importGetExportedFile(), null);
-		IQEditController.setIQReference(re, getModuleConfiguration());
+			IQEditController.setIQReference(re, getModuleConfiguration());
+		}
 	}
 
 	@Override
diff --git a/src/main/java/org/olat/course/nodes/IQSURVCourseNode.java b/src/main/java/org/olat/course/nodes/IQSURVCourseNode.java
index 7e74a3f7704..eab9b1cb8e3 100644
--- a/src/main/java/org/olat/course/nodes/IQSURVCourseNode.java
+++ b/src/main/java/org/olat/course/nodes/IQSURVCourseNode.java
@@ -271,10 +271,7 @@ public class IQSURVCourseNode extends AbstractAccessableCourseNode implements QT
 		}
 	}
 
-	/**
-	 * @see org.olat.course.nodes.GenericCourseNode#exportNode(java.io.File,
-	 *      org.olat.course.ICourse)
-	 */
+	@Override
 	public void exportNode(File exportDirectory, ICourse course) {
 		String repositorySoftKey = (String) getModuleConfiguration().get(IQEditController.CONFIG_KEY_REPOSITORY_SOFTKEY);
 		if (repositorySoftKey == null) return; // nothing to export
@@ -293,13 +290,13 @@ public class IQSURVCourseNode extends AbstractAccessableCourseNode implements QT
 
 	@Override
 	public void importNode(File importDirectory, ICourse course, Identity owner, Locale locale) {
-		RepositoryHandler handler = RepositoryHandlerFactory.getInstance().getRepositoryHandler(SurveyFileResource.TYPE_NAME);
-		
-		File importSubdir = new File(importDirectory, getIdent());
-		RepositoryEntryImportExport rie = new RepositoryEntryImportExport(importSubdir);
-		RepositoryEntry re = handler.importResource(owner, rie.getDisplayName(), rie.getDescription(),
+		RepositoryEntryImportExport rie = new RepositoryEntryImportExport(importDirectory, getIdent());
+		if(rie.anyExportedPropertiesAvailable()) {
+			RepositoryHandler handler = RepositoryHandlerFactory.getInstance().getRepositoryHandler(SurveyFileResource.TYPE_NAME);
+			RepositoryEntry re = handler.importResource(owner, rie.getDisplayName(), rie.getDescription(),
 				locale, rie.importGetExportedFile(), null);
-		IQEditController.setIQReference(re, getModuleConfiguration());
+			IQEditController.setIQReference(re, getModuleConfiguration());
+		}
 	}
 
 	@Override
diff --git a/src/main/java/org/olat/course/nodes/IQTESTCourseNode.java b/src/main/java/org/olat/course/nodes/IQTESTCourseNode.java
index 88f580666f8..60f8f5dc122 100644
--- a/src/main/java/org/olat/course/nodes/IQTESTCourseNode.java
+++ b/src/main/java/org/olat/course/nodes/IQTESTCourseNode.java
@@ -68,7 +68,7 @@ import org.olat.ims.qti.QTIResultSet;
 import org.olat.ims.qti.export.QTIExportFormatter;
 import org.olat.ims.qti.export.QTIExportFormatterCSVType1;
 import org.olat.ims.qti.export.QTIExportManager;
-import org.olat.ims.qti.fileresource.SurveyFileResource;
+import org.olat.ims.qti.fileresource.TestFileResource;
 import org.olat.ims.qti.process.AssessmentInstance;
 import org.olat.ims.qti.statistics.QTIStatisticResourceResult;
 import org.olat.ims.qti.statistics.QTIStatisticSearchParams;
@@ -470,13 +470,13 @@ public class IQTESTCourseNode extends AbstractAccessableCourseNode implements As
 
 	@Override
 	public void importNode(File importDirectory, ICourse course, Identity owner, Locale locale) {
-		RepositoryHandler handler = RepositoryHandlerFactory.getInstance().getRepositoryHandler(SurveyFileResource.TYPE_NAME);
-		
-		File importSubdir = new File(importDirectory, getIdent());
-		RepositoryEntryImportExport rie = new RepositoryEntryImportExport(importSubdir);
-		RepositoryEntry re = handler.importResource(owner, rie.getDisplayName(), rie.getDescription(),
+		RepositoryEntryImportExport rie = new RepositoryEntryImportExport(importDirectory, getIdent());
+		if(rie.anyExportedPropertiesAvailable()) {
+			RepositoryHandler handler = RepositoryHandlerFactory.getInstance().getRepositoryHandler(TestFileResource.TYPE_NAME);
+			RepositoryEntry re = handler.importResource(owner, rie.getDisplayName(), rie.getDescription(),
 				locale, rie.importGetExportedFile(), null);
-		IQEditController.setIQReference(re, getModuleConfiguration());
+			IQEditController.setIQReference(re, getModuleConfiguration());
+		}
 	}
 
 	/**
diff --git a/src/main/java/org/olat/course/nodes/PortfolioCourseNode.java b/src/main/java/org/olat/course/nodes/PortfolioCourseNode.java
index ac11b59849f..9f6c478dc71 100644
--- a/src/main/java/org/olat/course/nodes/PortfolioCourseNode.java
+++ b/src/main/java/org/olat/course/nodes/PortfolioCourseNode.java
@@ -94,7 +94,7 @@ public class PortfolioCourseNode extends AbstractAccessableCourseNode implements
 		ModuleConfiguration config = getModuleConfiguration();
 		if (isNewNode) {
 			MSCourseNode.initDefaultConfig(config);
-	    config.setConfigurationVersion(CURRENT_CONFIG_VERSION);
+			config.setConfigurationVersion(CURRENT_CONFIG_VERSION);
 		} 
 		if (config.getConfigurationVersion() < 2) {
 			if(config.get(PortfolioCourseNodeConfiguration.REPO_SOFT_KEY) == null) {
@@ -105,7 +105,7 @@ public class PortfolioCourseNode extends AbstractAccessableCourseNode implements
 					config.set(PortfolioCourseNodeConfiguration.REPO_SOFT_KEY, re.getSoftkey());
 				}
 			}
-	    config.setConfigurationVersion(2);
+			config.setConfigurationVersion(2);
 		}
 	}
 	
@@ -421,8 +421,7 @@ public class PortfolioCourseNode extends AbstractAccessableCourseNode implements
 
 	@Override
 	public void importNode(File importDirectory, ICourse course, Identity owner, Locale locale) {
-		File importSubdir = new File(importDirectory, getIdent());
-		RepositoryEntryImportExport rie = new RepositoryEntryImportExport(importSubdir);
+		RepositoryEntryImportExport rie = new RepositoryEntryImportExport(importDirectory, getIdent());
 		if (rie.anyExportedPropertiesAvailable()) {
 			RepositoryHandler handler = RepositoryHandlerFactory.getInstance().getRepositoryHandler(EPTemplateMapResource.TYPE_NAME);
 			RepositoryEntry re = handler.importResource(owner, rie.getDisplayName(), rie.getDescription(),
diff --git a/src/main/java/org/olat/course/nodes/ScormCourseNode.java b/src/main/java/org/olat/course/nodes/ScormCourseNode.java
index 8c2e2b39f4b..c29715d6f7d 100644
--- a/src/main/java/org/olat/course/nodes/ScormCourseNode.java
+++ b/src/main/java/org/olat/course/nodes/ScormCourseNode.java
@@ -326,13 +326,13 @@ public class ScormCourseNode extends AbstractAccessableCourseNode implements Ass
 
 	@Override
 	public void importNode(File importDirectory, ICourse course, Identity owner, Locale locale) {
-		RepositoryHandler handler = RepositoryHandlerFactory.getInstance().getRepositoryHandler(ScormCPFileResource.TYPE_NAME);
-		
-		File importSubdir = new File(importDirectory, getIdent());
-		RepositoryEntryImportExport rie = new RepositoryEntryImportExport(importSubdir);
-		RepositoryEntry re = handler.importResource(owner, rie.getDisplayName(), rie.getDescription(),
+		RepositoryEntryImportExport rie = new RepositoryEntryImportExport(importDirectory, getIdent());
+		if(rie.anyExportedPropertiesAvailable()) {
+			RepositoryHandler handler = RepositoryHandlerFactory.getInstance().getRepositoryHandler(ScormCPFileResource.TYPE_NAME);
+			RepositoryEntry re = handler.importResource(owner, rie.getDisplayName(), rie.getDescription(),
 				locale, rie.importGetExportedFile(), null);
-		ScormEditController.setScormCPReference(re, getModuleConfiguration());
+			ScormEditController.setScormCPReference(re, getModuleConfiguration());
+		}
 	}
 
 	@Override
@@ -353,18 +353,14 @@ public class ScormCourseNode extends AbstractAccessableCourseNode implements Ass
 		return true;
 	}
 
-	/**
-	 * @see org.olat.course.nodes.CourseNode#createInstanceForCopy()
-	 */
+	@Override
 	public CourseNode createInstanceForCopy() {
 		CourseNode copyInstance = super.createInstanceForCopy();
 		CPEditController.removeCPReference(copyInstance.getModuleConfiguration());
 		return copyInstance;
 	}
 
-	/**
-	 * @see org.olat.course.nodes.AssessableCourseNode#getUserScoreEvaluation(org.olat.course.run.userview.UserCourseEnvironment)
-	 */
+	@Override
 	public ScoreEvaluation getUserScoreEvaluation(UserCourseEnvironment userCourseEnvironment) {
 		// read score from properties save score, passed and attempts information
 		AssessmentManager am = userCourseEnvironment.getCourseEnvironment().getAssessmentManager();
diff --git a/src/main/java/org/olat/course/nodes/WikiCourseNode.java b/src/main/java/org/olat/course/nodes/WikiCourseNode.java
index fbc71010327..64186e18bab 100644
--- a/src/main/java/org/olat/course/nodes/WikiCourseNode.java
+++ b/src/main/java/org/olat/course/nodes/WikiCourseNode.java
@@ -209,13 +209,13 @@ public class WikiCourseNode extends AbstractAccessableCourseNode {
 
 	@Override
 	public void importNode(File importDirectory, ICourse course, Identity owner, Locale locale) {
-		RepositoryHandler handler = RepositoryHandlerFactory.getInstance().getRepositoryHandler(WikiResource.TYPE_NAME);
-		
-		File importSubdir = new File(importDirectory, getIdent());
-		RepositoryEntryImportExport rie = new RepositoryEntryImportExport(importSubdir);
-		RepositoryEntry re = handler.importResource(owner, rie.getDisplayName(), rie.getDescription(),
+		RepositoryEntryImportExport rie = new RepositoryEntryImportExport(importDirectory, getIdent());
+		if(rie.anyExportedPropertiesAvailable()) {
+			RepositoryHandler handler = RepositoryHandlerFactory.getInstance().getRepositoryHandler(WikiResource.TYPE_NAME);
+			RepositoryEntry re = handler.importResource(owner, rie.getDisplayName(), rie.getDescription(),
 				locale, rie.importGetExportedFile(), null);
-		WikiEditController.setWikiRepoReference(re, getModuleConfiguration());
+			WikiEditController.setWikiRepoReference(re, getModuleConfiguration());
+		}
 	}
 
 	@Override
diff --git a/src/main/java/org/olat/course/nodes/wiki/WikiEditController.java b/src/main/java/org/olat/course/nodes/wiki/WikiEditController.java
index 85b3b04ebc4..4847a5ab2d5 100644
--- a/src/main/java/org/olat/course/nodes/wiki/WikiEditController.java
+++ b/src/main/java/org/olat/course/nodes/wiki/WikiEditController.java
@@ -25,11 +25,8 @@
 
 package org.olat.course.nodes.wiki;
 
-import java.util.List;
-
 import org.olat.core.commons.services.notifications.SubscriptionContext;
 import org.olat.core.gui.UserRequest;
-import org.olat.core.gui.Windows;
 import org.olat.core.gui.components.Component;
 import org.olat.core.gui.components.link.Link;
 import org.olat.core.gui.components.link.LinkFactory;
@@ -41,13 +38,8 @@ import org.olat.core.gui.control.ControllerEventListener;
 import org.olat.core.gui.control.Event;
 import org.olat.core.gui.control.WindowControl;
 import org.olat.core.gui.control.generic.closablewrapper.CloseableModalController;
-import org.olat.core.gui.control.generic.dtabs.DTab;
-import org.olat.core.gui.control.generic.dtabs.DTabs;
 import org.olat.core.gui.control.generic.tabbable.ActivateableTabbableDefaultController;
 import org.olat.core.id.Identity;
-import org.olat.core.id.OLATResourceable;
-import org.olat.core.id.context.BusinessControlFactory;
-import org.olat.core.id.context.ContextEntry;
 import org.olat.core.logging.AssertException;
 import org.olat.course.ICourse;
 import org.olat.course.assessment.AssessmentHelper;
@@ -68,8 +60,6 @@ import org.olat.repository.RepositoryEntry;
 import org.olat.repository.RepositoryManager;
 import org.olat.repository.controllers.ReferencableEntriesSearchController;
 import org.olat.repository.controllers.RepositoryDetailsController;
-import org.olat.repository.handlers.RepositoryHandler;
-import org.olat.repository.handlers.RepositoryHandlerFactory;
 
 /**
  * Description: <BR/>Edit controller for single page course nodes <P/> Initial
@@ -212,32 +202,8 @@ public class WikiEditController extends ActivateableTabbableDefaultController im
 				// do nothing
 				return;
 			}
-			RepositoryHandler typeToEdit = RepositoryHandlerFactory.getInstance().getRepositoryHandler(repositoryEntry);
-			// Open editor in new tab
-			OLATResourceable ores = repositoryEntry.getOlatResource();
-			DTabs dts = Windows.getWindows(ureq).getWindow(ureq).getDTabs();
-			DTab dt = dts.getDTab(ores);
-			if (dt == null) {
-				// does not yet exist -> create and add
-				//fxdiff BAKS-7 Resume function
-				dt = dts.createDTab(ores, repositoryEntry, repositoryEntry.getDisplayname());
-				if (dt == null){
-					//null means DTabs are full -> warning is shown
-					return;
-				}
-				//user activity logger is set by course factory
-				Controller editorController = typeToEdit.createLaunchController(repositoryEntry, ureq, dt.getWindowControl());
-				if(editorController == null){
-					//editor could not be created -> warning is shown
-					return;
-				}
-				dt.setController(editorController);
-				dts.addDTab(ureq, dt);
-			}
-			List<ContextEntry> entries = BusinessControlFactory.getInstance().createCEListFromResourceType(RepositoryDetailsController.ACTIVATE_EDITOR);
-			dts.activate(ureq, dt, entries);
+			RepositoryDetailsController.doEdit(ureq, repositoryEntry);
 		}
-
 	}
 
 	/**
diff --git a/src/main/java/org/olat/course/run/RunMainController.java b/src/main/java/org/olat/course/run/RunMainController.java
index 489d758554f..311c882206b 100644
--- a/src/main/java/org/olat/course/run/RunMainController.java
+++ b/src/main/java/org/olat/course/run/RunMainController.java
@@ -140,7 +140,6 @@ import org.olat.repository.RepositoryEntryStatus;
 import org.olat.repository.RepositoryManager;
 import org.olat.repository.RepositoryService;
 import org.olat.repository.controllers.EntryChangedEvent;
-import org.olat.repository.controllers.RepositoryDetailsController;
 import org.olat.repository.ui.list.RepositoryEntryDetailsController;
 import org.olat.repository.ui.list.RepositoryEntryRow;
 import org.olat.resource.OLATResource;
@@ -1385,7 +1384,7 @@ public class RunMainController extends MainLayoutBasicController implements Gene
 			} catch (OLATSecurityException e) {
 				//the wrong link to the wrong person
 			}
-		} else if("Editor".equalsIgnoreCase(type) || RepositoryDetailsController.ACTIVATE_EDITOR.equalsIgnoreCase(type)) {
+		} else if("Editor".equalsIgnoreCase(type) || "activateEditor".equalsIgnoreCase(type)) {
 			// Nothing to do if already in editor. Can happen when editor is
 			// triggered externally, e.g. from the details page while user has
 			// the editor already open
diff --git a/src/main/java/org/olat/fileresource/types/AnimationFileResource.java b/src/main/java/org/olat/fileresource/types/AnimationFileResource.java
index 82b0ba15b63..f7599b6bf1e 100644
--- a/src/main/java/org/olat/fileresource/types/AnimationFileResource.java
+++ b/src/main/java/org/olat/fileresource/types/AnimationFileResource.java
@@ -39,10 +39,9 @@ public class AnimationFileResource extends FileResource {
 	 */
 	public static final String TYPE_NAME = "FileResource.ANIM";
 
-	/**
-	 * Default constructor.
-	 */
-	public AnimationFileResource() { super.setTypeName(TYPE_NAME); }
+	public AnimationFileResource() {
+		super(TYPE_NAME);
+	}
 	
 	/**
 	 * @param f
diff --git a/src/main/java/org/olat/fileresource/types/CourseResource.java b/src/main/java/org/olat/fileresource/types/CourseResource.java
deleted file mode 100644
index 963f980874e..00000000000
--- a/src/main/java/org/olat/fileresource/types/CourseResource.java
+++ /dev/null
@@ -1,70 +0,0 @@
-package org.olat.fileresource.types;
-
-import java.io.File;
-import java.io.IOException;
-import java.nio.file.FileVisitResult;
-import java.nio.file.Path;
-import java.nio.file.SimpleFileVisitor;
-import java.nio.file.attribute.BasicFileAttributes;
-
-import org.olat.core.logging.OLog;
-import org.olat.core.logging.Tracing;
-import org.olat.repository.RepositoryEntryImportExport;
-import org.olat.repository.RepositoryEntryImportExport.RepositoryEntryImport;
-
-public class CourseResource extends FileResource {
-	
-	private static final OLog log = Tracing.createLoggerFor(CourseResource.class);
-	
-	public static final String TYPE_NAME = "CourseModule";
-	public static final String EDITOR_XML = "editortreemodel.xml";
-	
-	public CourseResource() {
-		setTypeName(TYPE_NAME);
-	}
-	
-	public static ResourceEvaluation evaluate(File file, String filename) {
-		ResourceEvaluation eval = new ResourceEvaluation();
-		try {
-			IndexFileFilter visitor = new IndexFileFilter();
-			Path fPath = visit(file, filename, visitor);
-			
-			if(visitor.isValid()) {
-				Path repoXml = fPath.resolve("export/repo.xml");
-				if(repoXml != null) {
-					eval.setValid(true);
-					
-					RepositoryEntryImport re = RepositoryEntryImportExport.getConfiguration(repoXml);
-					if(re != null) {
-						eval.setDisplayname(re.getDisplayname());
-						eval.setDescription(re.getDescription());
-					}
-				}
-			}
-			eval.setValid(visitor.isValid());
-		} catch (IOException e) {
-			log.error("", e);
-		}
-		return eval;
-	}
-	
-	private static class IndexFileFilter extends SimpleFileVisitor<Path> {
-		private boolean editorFile;
-
-		@Override
-		public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
-		throws IOException {
-
-			String filename = file.getFileName().toString();
-			if(EDITOR_XML.equals(filename)) {
-				editorFile = true;
-			}
-			return editorFile ? FileVisitResult.TERMINATE : FileVisitResult.CONTINUE;
-		}
-		
-		public boolean isValid() {
-			return editorFile;
-		}
-	}
-
-}
diff --git a/src/main/java/org/olat/fileresource/types/DocFileResource.java b/src/main/java/org/olat/fileresource/types/DocFileResource.java
index 8e974170835..9120b3cb462 100644
--- a/src/main/java/org/olat/fileresource/types/DocFileResource.java
+++ b/src/main/java/org/olat/fileresource/types/DocFileResource.java
@@ -39,10 +39,9 @@ public class DocFileResource extends FileResource {
 	 */
 	public static final String TYPE_NAME = "FileResource.DOC";
 
-	/**
-	 * Standard constructor.
-	 */
-	public DocFileResource() { super.setTypeName(TYPE_NAME); }
+	public DocFileResource() {
+		super(TYPE_NAME);
+	}
 	
 	/**
 	 * @param f
diff --git a/src/main/java/org/olat/fileresource/types/FeedFileResource.java b/src/main/java/org/olat/fileresource/types/FeedFileResource.java
index 22d751e1643..74234de258d 100644
--- a/src/main/java/org/olat/fileresource/types/FeedFileResource.java
+++ b/src/main/java/org/olat/fileresource/types/FeedFileResource.java
@@ -29,6 +29,7 @@ import java.util.List;
 
 import org.olat.core.logging.OLog;
 import org.olat.core.logging.Tracing;
+import org.olat.core.util.PathUtils;
 import org.olat.core.util.vfs.LocalFolderImpl;
 import org.olat.core.util.vfs.VFSContainer;
 import org.olat.core.util.vfs.VFSItem;
@@ -50,11 +51,11 @@ public abstract class FeedFileResource extends FileResource {
 	private static final OLog log = Tracing.createLoggerFor(FeedFileResource.class);
 
 	public FeedFileResource(String type) {
-		super.setTypeName(type);
+		super(type);
 	}
 
 	public FeedFileResource(File root, File resourceFolder, String type) {
-		super.setTypeName(type);
+		super(type);
 		// After unziping the uploaded folder, I would like to copy it to the
 		// appropriate location right away (and not on the next read). So, I put the
 		// code here. Note that this constructor is also called on copying a
@@ -84,7 +85,7 @@ public abstract class FeedFileResource extends FileResource {
 		ResourceEvaluation eval = new ResourceEvaluation();
 		try {
 			IndexFileFilter visitor = new IndexFileFilter();
-			Path fPath = visit(file, filename, visitor);
+			Path fPath = PathUtils.visit(file, filename, visitor);
 			
 			if(visitor.isValid()) {
 				Path feedXml = fPath.resolve(FeedManager.FEED_FILE_NAME);
diff --git a/src/main/java/org/olat/fileresource/types/FileResource.java b/src/main/java/org/olat/fileresource/types/FileResource.java
index 43f8cdf87e5..6b597238912 100644
--- a/src/main/java/org/olat/fileresource/types/FileResource.java
+++ b/src/main/java/org/olat/fileresource/types/FileResource.java
@@ -29,7 +29,6 @@ import java.io.File;
 import java.io.IOException;
 import java.nio.file.FileSystems;
 import java.nio.file.FileVisitResult;
-import java.nio.file.FileVisitor;
 import java.nio.file.Files;
 import java.nio.file.Path;
 import java.nio.file.PathMatcher;
@@ -57,7 +56,7 @@ public class FileResource implements OLATResourceable {
 	 * Generic file resource type identifier.
 	 */
 	public static final String GENERIC_TYPE_NAME = "FileResource.FILE";
-	private String typeName;
+	private final String typeName;
 	private Long typeId;
 	
 	public FileResource() {
@@ -70,14 +69,6 @@ public class FileResource implements OLATResourceable {
 		typeId = new Long(CodeHelper.getForeverUniqueID());
 	}
 
-	 /**
-	 * User by subtypes to set appropriate ResourceableTypeName
-	 * @param newTypeName
-	 */
-	protected void setTypeName(String newTypeName) {
-		typeName = newTypeName;
-	}
-
 	/**
 	 * Only used internally when switching subtypes.
 	 * @param newId
@@ -100,25 +91,7 @@ public class FileResource implements OLATResourceable {
 		return typeId;
 	}
 	
-	protected static Path visit(File file, String filename, FileVisitor<Path> visitor) 
-	throws IOException {
-		if(!StringHelper.containsNonWhitespace(filename)) {
-			filename = file.getName();
-		}
-		
-		Path fPath = null;
-		if(file.isDirectory()) {
-			fPath = file.toPath();
-		} else if(filename != null && filename.toLowerCase().endsWith(".zip")) {
-			fPath = FileSystems.newFileSystem(file.toPath(), null).getPath("/");
-		} else {
-			fPath = file.toPath();
-		}
-		if(fPath != null) {
-		    Files.walkFileTree(fPath, visitor);
-		}
-		return fPath;
-	}
+
 	
 	/**
 	 * This method open a new FileSystem for zip
diff --git a/src/main/java/org/olat/fileresource/types/GlossaryResource.java b/src/main/java/org/olat/fileresource/types/GlossaryResource.java
index 371105483fe..4af7d53aae9 100644
--- a/src/main/java/org/olat/fileresource/types/GlossaryResource.java
+++ b/src/main/java/org/olat/fileresource/types/GlossaryResource.java
@@ -35,6 +35,7 @@ import java.nio.file.attribute.BasicFileAttributes;
 
 import org.olat.core.logging.OLog;
 import org.olat.core.logging.Tracing;
+import org.olat.core.util.PathUtils;
 
 /**
  * Description:<br>
@@ -62,11 +63,8 @@ public class GlossaryResource extends FileResource {
 		}
 	};
 
-	/**
-	 * Constructor
-	 */
 	public GlossaryResource() {
-		super.setTypeName(TYPE_NAME);
+		super(TYPE_NAME);
 	}
 
 	/**
@@ -91,7 +89,7 @@ public class GlossaryResource extends FileResource {
 		ResourceEvaluation eval = new ResourceEvaluation();
 		try {
 			GlossaryFileFilter visitor = new GlossaryFileFilter();
-			visit(file, filename, visitor);
+			PathUtils.visit(file, filename, visitor);
 			if(visitor.isValid()) {
 				eval.setValid(true);
 			}
diff --git a/src/main/java/org/olat/fileresource/types/ImageFileResource.java b/src/main/java/org/olat/fileresource/types/ImageFileResource.java
index 7918e481529..6303beea540 100644
--- a/src/main/java/org/olat/fileresource/types/ImageFileResource.java
+++ b/src/main/java/org/olat/fileresource/types/ImageFileResource.java
@@ -39,10 +39,9 @@ public class ImageFileResource extends FileResource {
 	 */
 	public static final String TYPE_NAME = "FileResource.IMAGE";
 
-	/**
-	 * Standard constructor.
-	 */
-	public ImageFileResource() { super.setTypeName(TYPE_NAME); }
+	public ImageFileResource() {
+		super(TYPE_NAME);
+	}
 	
 	/**
 	 * @param f
diff --git a/src/main/java/org/olat/fileresource/types/ImsCPFileResource.java b/src/main/java/org/olat/fileresource/types/ImsCPFileResource.java
index 365a19eba42..46a6e79e1f5 100644
--- a/src/main/java/org/olat/fileresource/types/ImsCPFileResource.java
+++ b/src/main/java/org/olat/fileresource/types/ImsCPFileResource.java
@@ -41,6 +41,7 @@ import org.dom4j.Element;
 import org.dom4j.XPath;
 import org.olat.core.logging.OLog;
 import org.olat.core.logging.Tracing;
+import org.olat.core.util.PathUtils;
 import org.olat.ims.resources.IMSLoader;
 
 /**
@@ -59,7 +60,7 @@ public class ImsCPFileResource extends FileResource {
 	public static final String TYPE_NAME = "FileResource.IMSCP";
 
 	public ImsCPFileResource() {
-		super.setTypeName(TYPE_NAME);
+		super(TYPE_NAME);
 	}
 	
 	/**
@@ -83,7 +84,7 @@ public class ImsCPFileResource extends FileResource {
 		ResourceEvaluation eval = new ResourceEvaluation();
 		try {
 			ImsManifestFileFilter visitor = new ImsManifestFileFilter();
-			Path fPath = visit(file, filename, visitor);
+			Path fPath = PathUtils.visit(file, filename, visitor);
 			if(visitor.isValid()) {
 				Path manifestPath = fPath.resolve(IMS_MANIFEST);
 				Document doc = IMSLoader.loadIMSDocument(manifestPath);
diff --git a/src/main/java/org/olat/fileresource/types/MovieFileResource.java b/src/main/java/org/olat/fileresource/types/MovieFileResource.java
index b14775bf5d6..63096b31094 100644
--- a/src/main/java/org/olat/fileresource/types/MovieFileResource.java
+++ b/src/main/java/org/olat/fileresource/types/MovieFileResource.java
@@ -39,10 +39,9 @@ public class MovieFileResource extends FileResource {
 	 */
 	public static final String TYPE_NAME = "FileResource.MOVIE";
 
-	/**
-	 * Standard constructor.
-	 */
-	public MovieFileResource() { super.setTypeName(TYPE_NAME); }
+	public MovieFileResource() {
+		super(TYPE_NAME);
+	}
 	
 	/**
 	 * @param f
diff --git a/src/main/java/org/olat/fileresource/types/PdfFileResource.java b/src/main/java/org/olat/fileresource/types/PdfFileResource.java
index 5996e9d8602..0e95f74ef04 100644
--- a/src/main/java/org/olat/fileresource/types/PdfFileResource.java
+++ b/src/main/java/org/olat/fileresource/types/PdfFileResource.java
@@ -39,10 +39,9 @@ public class PdfFileResource extends FileResource {
 	 */
 	public static final String TYPE_NAME = "FileResource.PDF";
 
-	/**
-	 * Standard constructor.
-	 */
-	public PdfFileResource() { super.setTypeName(TYPE_NAME); }
+	public PdfFileResource() {
+		super(TYPE_NAME);
+	}
 	
 	/**
 	 * @param f
diff --git a/src/main/java/org/olat/fileresource/types/PowerpointFileResource.java b/src/main/java/org/olat/fileresource/types/PowerpointFileResource.java
index 20e7bd5af90..b54cac04bd5 100644
--- a/src/main/java/org/olat/fileresource/types/PowerpointFileResource.java
+++ b/src/main/java/org/olat/fileresource/types/PowerpointFileResource.java
@@ -39,10 +39,9 @@ public class PowerpointFileResource extends FileResource {
 	 */
 	public static final String TYPE_NAME = "FileResource.PPT";
 
-	/**
-	 * Standard constructor.
-	 */
-	public PowerpointFileResource() { super.setTypeName(TYPE_NAME); }
+	public PowerpointFileResource() {
+		super(TYPE_NAME);
+	}
 	
 	/**
 	 * @param f
diff --git a/src/main/java/org/olat/fileresource/types/ScormCPFileResource.java b/src/main/java/org/olat/fileresource/types/ScormCPFileResource.java
index d058af54668..fc9c3294fd6 100644
--- a/src/main/java/org/olat/fileresource/types/ScormCPFileResource.java
+++ b/src/main/java/org/olat/fileresource/types/ScormCPFileResource.java
@@ -45,6 +45,7 @@ import org.dom4j.Namespace;
 import org.dom4j.XPath;
 import org.olat.core.logging.OLog;
 import org.olat.core.logging.Tracing;
+import org.olat.core.util.PathUtils;
 import org.olat.ims.resources.IMSLoader;
 
 /**
@@ -64,7 +65,7 @@ public class ScormCPFileResource extends FileResource {
 
 
 	public ScormCPFileResource() {
-		super.setTypeName(TYPE_NAME);
+		super(TYPE_NAME);
 	}
 	
 	/**
@@ -83,7 +84,7 @@ public class ScormCPFileResource extends FileResource {
 		ResourceEvaluation eval = new ResourceEvaluation();
 		try {
 			ImsManifestFileFilter visitor = new ImsManifestFileFilter();
-			Path fPath = visit(file, filename, visitor);
+			Path fPath = PathUtils.visit(file, filename, visitor);
 			if(visitor.isValid()) {
 				Path manifestPath = fPath.resolve(IMS_MANIFEST);
 				Document doc = IMSLoader.loadIMSDocument(manifestPath);
diff --git a/src/main/java/org/olat/fileresource/types/SharedFolderFileResource.java b/src/main/java/org/olat/fileresource/types/SharedFolderFileResource.java
index a6d7fa3e0aa..fe438a29191 100644
--- a/src/main/java/org/olat/fileresource/types/SharedFolderFileResource.java
+++ b/src/main/java/org/olat/fileresource/types/SharedFolderFileResource.java
@@ -44,11 +44,8 @@ public class SharedFolderFileResource extends FileResource {
 	 */
 	public static final String RESOURCE_NAME = "-";
 
-	/**
-	 * Standard constructor.
-	 */
 	public SharedFolderFileResource() {
-		super.setTypeName(TYPE_NAME);
+		super(TYPE_NAME);
 	}
 
 	/**
diff --git a/src/main/java/org/olat/fileresource/types/SoundFileResource.java b/src/main/java/org/olat/fileresource/types/SoundFileResource.java
index ab599804e0c..81ba484ae04 100644
--- a/src/main/java/org/olat/fileresource/types/SoundFileResource.java
+++ b/src/main/java/org/olat/fileresource/types/SoundFileResource.java
@@ -39,10 +39,9 @@ public class SoundFileResource extends FileResource {
 	 */
 	public static final String TYPE_NAME = "FileResource.SOUND";
 
-	/**
-	 * Standard constructor.
-	 */
-	public SoundFileResource() { super.setTypeName(TYPE_NAME); }
+	public SoundFileResource() {
+		super(TYPE_NAME);
+	}
 	
 	/**
 	 * @param f
diff --git a/src/main/java/org/olat/fileresource/types/WikiResource.java b/src/main/java/org/olat/fileresource/types/WikiResource.java
index b5a0b3d72de..645c50bd120 100644
--- a/src/main/java/org/olat/fileresource/types/WikiResource.java
+++ b/src/main/java/org/olat/fileresource/types/WikiResource.java
@@ -34,6 +34,7 @@ import java.nio.file.attribute.BasicFileAttributes;
 
 import org.olat.core.logging.OLog;
 import org.olat.core.logging.Tracing;
+import org.olat.core.util.PathUtils;
 import org.olat.modules.wiki.WikiManager;
 import org.olat.modules.wiki.WikiPage;
 
@@ -53,14 +54,14 @@ public class WikiResource extends FileResource {
 	public static final String INDEX_PROPNAME = WikiManager.generatePageId(WikiPage.WIKI_INDEX_PAGE) + "." + WikiManager.WIKI_PROPERTIES_SUFFIX;
 
 	public WikiResource() {
-		super.setTypeName(TYPE_NAME);
+		super(TYPE_NAME);
 	}
 
 	public static ResourceEvaluation validate(File file, String filename) {
 		ResourceEvaluation eval = new ResourceEvaluation();
 		try {
 			IndexFileFilter visitor = new IndexFileFilter();
-			visit(file, filename, visitor);
+			PathUtils.visit(file, filename, visitor);
 			eval.setValid(visitor.isValid());
 		} catch (IOException e) {
 			log.error("", e);
diff --git a/src/main/java/org/olat/fileresource/types/XlsFileResource.java b/src/main/java/org/olat/fileresource/types/XlsFileResource.java
index a9497e72004..d2065a30bcf 100644
--- a/src/main/java/org/olat/fileresource/types/XlsFileResource.java
+++ b/src/main/java/org/olat/fileresource/types/XlsFileResource.java
@@ -39,10 +39,9 @@ public class XlsFileResource extends FileResource {
 	 */
 	public static final String TYPE_NAME = "FileResource.XLS";
 
-	/**
-	 * Standard constructor.
-	 */
-	public XlsFileResource() { super.setTypeName(TYPE_NAME); }
+	public XlsFileResource() {
+		super(TYPE_NAME);
+	}
 	
 	/**
 	 * @param f
diff --git a/src/main/java/org/olat/ims/qti/fileresource/SurveyFileResource.java b/src/main/java/org/olat/ims/qti/fileresource/SurveyFileResource.java
index 643ba661be9..143bf5098da 100644
--- a/src/main/java/org/olat/ims/qti/fileresource/SurveyFileResource.java
+++ b/src/main/java/org/olat/ims/qti/fileresource/SurveyFileResource.java
@@ -40,6 +40,7 @@ import org.dom4j.Attribute;
 import org.olat.core.CoreSpringFactory;
 import org.olat.core.logging.OLog;
 import org.olat.core.logging.Tracing;
+import org.olat.core.util.PathUtils;
 import org.olat.core.util.vfs.LocalFileImpl;
 import org.olat.core.util.vfs.LocalFolderImpl;
 import org.olat.core.util.vfs.VFSContainer;
@@ -67,7 +68,7 @@ public class SurveyFileResource extends FileResource {
 	public static final String TYPE_NAME = "FileResource.SURVEY";
 
 	public SurveyFileResource() {
-		super.setTypeName(TYPE_NAME);
+		super(TYPE_NAME);
 	}
 	
 	/**
@@ -91,7 +92,7 @@ public class SurveyFileResource extends FileResource {
 		ResourceEvaluation eval = new ResourceEvaluation();
 		try {
 			QTIFileFilter visitor = new QTIFileFilter();
-			Path fPath = visit(file, filename, visitor);
+			Path fPath = PathUtils.visit(file, filename, visitor);
 			if(visitor.isValid()) {
 				Path qtiPath = fPath.resolve(QTI_FILE);
 				Document doc = QTIHelper.getDocument(qtiPath);
diff --git a/src/main/java/org/olat/ims/qti/fileresource/TestFileResource.java b/src/main/java/org/olat/ims/qti/fileresource/TestFileResource.java
index 44b70a4f5e5..f4ab27f13fd 100644
--- a/src/main/java/org/olat/ims/qti/fileresource/TestFileResource.java
+++ b/src/main/java/org/olat/ims/qti/fileresource/TestFileResource.java
@@ -40,6 +40,7 @@ import org.dom4j.Element;
 import org.olat.core.CoreSpringFactory;
 import org.olat.core.logging.OLog;
 import org.olat.core.logging.Tracing;
+import org.olat.core.util.PathUtils;
 import org.olat.core.util.vfs.LocalFileImpl;
 import org.olat.core.util.vfs.LocalFolderImpl;
 import org.olat.core.util.vfs.VFSContainer;
@@ -66,7 +67,7 @@ public class TestFileResource extends FileResource {
 	public static final String TYPE_NAME = "FileResource.TEST";
 
 	public TestFileResource() {
-		super.setTypeName(TYPE_NAME);
+		super(TYPE_NAME);
 	}
 	
 	/**
@@ -91,7 +92,7 @@ public class TestFileResource extends FileResource {
 		ResourceEvaluation eval = new ResourceEvaluation();
 		try {
 			QTIFileFilter visitor = new QTIFileFilter();
-			Path fPath = visit(file, filename, visitor);
+			Path fPath = PathUtils.visit(file, filename, visitor);
 			if(visitor.isValid()) {
 				Path qtiPath = fPath.resolve(QTI_FILE);
 				Document doc = QTIHelper.getDocument(qtiPath);
diff --git a/src/main/java/org/olat/repository/RepositoryEntryAuthorView.java b/src/main/java/org/olat/repository/RepositoryEntryAuthorView.java
index 89e9f2d25f0..a7fe36a1c0c 100644
--- a/src/main/java/org/olat/repository/RepositoryEntryAuthorView.java
+++ b/src/main/java/org/olat/repository/RepositoryEntryAuthorView.java
@@ -35,6 +35,8 @@ public interface RepositoryEntryAuthorView extends OLATResourceable, RepositoryE
 	
 	public Date getCreationDate();
 	
+	public String getSoftkey();
+	
 	public String getExternalId();
 	
 	public String getExternalRef();
diff --git a/src/main/java/org/olat/repository/RepositoryEntryImportExport.java b/src/main/java/org/olat/repository/RepositoryEntryImportExport.java
index 598786d103b..cb0bc19f4ae 100644
--- a/src/main/java/org/olat/repository/RepositoryEntryImportExport.java
+++ b/src/main/java/org/olat/repository/RepositoryEntryImportExport.java
@@ -86,8 +86,12 @@ public class RepositoryEntryImportExport {
 	 * 
 	 * @param baseDirecotry
 	 */
-	public RepositoryEntryImportExport(File baseDirecotry) {
-		this.baseDirectory = baseDirecotry;
+	public RepositoryEntryImportExport(File baseDirectory) {
+		this.baseDirectory = baseDirectory;
+	}
+	
+	public RepositoryEntryImportExport(File baseDirectory, String subDir) {
+		this.baseDirectory = new File(baseDirectory, subDir);
 	}
 	
 	public boolean anyExportedPropertiesAvailable() {
@@ -160,8 +164,12 @@ public class RepositoryEntryImportExport {
 	private void loadConfiguration() {
 		try {
 			File inputFile = new File(baseDirectory, PROPERTIES_FILE);
-			XStream xstream = getXStream();
-			repositoryProperties = (RepositoryEntryImport)xstream.fromXML(inputFile);
+			if(inputFile.exists()) {
+				XStream xstream = getXStream();
+				repositoryProperties = (RepositoryEntryImport)xstream.fromXML(inputFile);
+			} else {
+				repositoryProperties = new RepositoryEntryImport();
+			}
 			propertiesLoaded = true;
 		} catch (Exception ce) {
 			throw new OLATRuntimeException("Error importing repository entry properties.", ce);
diff --git a/src/main/java/org/olat/repository/SearchAuthorRepositoryEntryViewParams.java b/src/main/java/org/olat/repository/SearchAuthorRepositoryEntryViewParams.java
index 72cee09e16f..59cd269a7c8 100644
--- a/src/main/java/org/olat/repository/SearchAuthorRepositoryEntryViewParams.java
+++ b/src/main/java/org/olat/repository/SearchAuthorRepositoryEntryViewParams.java
@@ -32,11 +32,15 @@ import org.olat.core.id.Roles;
  *
  */
 public class SearchAuthorRepositoryEntryViewParams {
-	private Identity identity;
-	private Roles roles;
+	private final Identity identity;
+	private final Roles roles;
 	
 	private Boolean marked;
 	
+	private String idAndRefs;
+	private String author;
+	private String displayname;
+	
 	private OrderBy orderBy;
 	private List<Filter> filters;
 	private List<String> resourceTypes;
@@ -47,6 +51,30 @@ public class SearchAuthorRepositoryEntryViewParams {
 		this.roles = roles;
 	}
 
+	public String getIdAndRefs() {
+		return idAndRefs;
+	}
+
+	public void setIdAndRefs(String idAndRefs) {
+		this.idAndRefs = idAndRefs;
+	}
+
+	public String getAuthor() {
+		return author;
+	}
+
+	public void setAuthor(String author) {
+		this.author = author;
+	}
+
+	public String getDisplayname() {
+		return displayname;
+	}
+
+	public void setDisplayname(String displayname) {
+		this.displayname = displayname;
+	}
+
 	public List<Long> getRepoEntryKeys() {
 		return repoEntryKeys;
 	}
diff --git a/src/main/java/org/olat/repository/_spring/repositoryContext.xml b/src/main/java/org/olat/repository/_spring/repositoryContext.xml
index d53f1f7a161..c288bbaf94b 100644
--- a/src/main/java/org/olat/repository/_spring/repositoryContext.xml
+++ b/src/main/java/org/olat/repository/_spring/repositoryContext.xml
@@ -8,7 +8,7 @@
   http://www.springframework.org/schema/context 
   http://www.springframework.org/schema/context/spring-context.xsd">
 
-	<context:component-scan base-package="org.olat.repository.manager" />
+	<context:component-scan base-package="org.olat.repository.manager,org.olat.repository.handlers" />
 
 	<bean id="repositoryModule" class="org.olat.repository.RepositoryModule" depends-on="userModule">
 		<property name="groupModule" ref="businessGroupModule"/>
diff --git a/src/main/java/org/olat/repository/controllers/ReferencableEntriesSearchController.java b/src/main/java/org/olat/repository/controllers/ReferencableEntriesSearchController.java
index 121234a0a9d..caab020a21b 100644
--- a/src/main/java/org/olat/repository/controllers/ReferencableEntriesSearchController.java
+++ b/src/main/java/org/olat/repository/controllers/ReferencableEntriesSearchController.java
@@ -338,7 +338,7 @@ public class ReferencableEntriesSearchController extends BasicController {
 					StringBuilder sb = new StringBuilder(translate("error.launch"));
 					sb.append(": No launcher for repository entry: ");
 					sb.append(repositoryEntry.getKey());
-					throw new OLATRuntimeException(RepositoryDetailsController.class, sb.toString(), null);
+					throw new OLATRuntimeException(ReferencableEntriesSearchController.class, sb.toString(), null);
 				}
 				// do skip the increment launch counter, this is only a preview!
 				removeAsListenerAndDispose(previewCtr);
diff --git a/src/main/java/org/olat/repository/handlers/CourseHandler.java b/src/main/java/org/olat/repository/handlers/CourseHandler.java
index 35118fa25ba..6ada2e2c49f 100644
--- a/src/main/java/org/olat/repository/handlers/CourseHandler.java
+++ b/src/main/java/org/olat/repository/handlers/CourseHandler.java
@@ -26,6 +26,11 @@
 package org.olat.repository.handlers;
 
 import java.io.File;
+import java.io.IOException;
+import java.nio.file.FileVisitResult;
+import java.nio.file.Path;
+import java.nio.file.SimpleFileVisitor;
+import java.nio.file.attribute.BasicFileAttributes;
 import java.util.Collections;
 import java.util.List;
 import java.util.Locale;
@@ -53,6 +58,7 @@ import org.olat.core.logging.Tracing;
 import org.olat.core.util.CodeHelper;
 import org.olat.core.util.FileUtils;
 import org.olat.core.util.Formatter;
+import org.olat.core.util.PathUtils;
 import org.olat.core.util.StringHelper;
 import org.olat.core.util.Util;
 import org.olat.core.util.WebappHelper;
@@ -85,7 +91,6 @@ import org.olat.course.groupsandrights.CourseGroupManager;
 import org.olat.course.groupsandrights.PersistingCourseGroupManager;
 import org.olat.course.nodes.CourseNode;
 import org.olat.course.tree.CourseEditorTreeNode;
-import org.olat.fileresource.types.CourseResource;
 import org.olat.fileresource.types.GlossaryResource;
 import org.olat.fileresource.types.ResourceEvaluation;
 import org.olat.fileresource.types.SharedFolderFileResource;
@@ -94,6 +99,7 @@ import org.olat.modules.glossary.GlossaryManager;
 import org.olat.modules.sharedfolder.SharedFolderManager;
 import org.olat.repository.RepositoryEntry;
 import org.olat.repository.RepositoryEntryImportExport;
+import org.olat.repository.RepositoryEntryImportExport.RepositoryEntryImport;
 import org.olat.repository.RepositoryEntryManagedFlag;
 import org.olat.repository.RepositoryManager;
 import org.olat.repository.RepositoryService;
@@ -121,17 +127,9 @@ import de.tuchemnitz.wizard.workflows.coursecreation.steps.CcStep00;
  * 
  */
 public class CourseHandler implements RepositoryHandler {
-	
-	private static final OLog log = Tracing.createLoggerFor(CourseHandler.class);
 
-	/**
-	 * Command to add (i.e. import) a course.
-	 */
-	public static final String PROCESS_IMPORT = "add";
-	/**
-	 * Command to create a new course.
-	 */
-	public static final String PROCESS_CREATENEW = "new";
+	public static final String EDITOR_XML = "editortreemodel.xml";
+	private static final OLog log = Tracing.createLoggerFor(CourseHandler.class);
 
 	private static final List<String> supportedTypes = Collections.singletonList(CourseModule.getCourseTypeName());
 	
@@ -182,7 +180,28 @@ public class CourseHandler implements RepositoryHandler {
 
 	@Override
 	public ResourceEvaluation acceptImport(File file, String filename) {
-		return CourseResource.evaluate(file, filename);
+		ResourceEvaluation eval = new ResourceEvaluation();
+		try {
+			IndexFileFilter visitor = new IndexFileFilter();
+			Path fPath = PathUtils.visit(file, filename, visitor);
+			
+			if(visitor.isValid()) {
+				Path repoXml = fPath.resolve("export/repo.xml");
+				if(repoXml != null) {
+					eval.setValid(true);
+					
+					RepositoryEntryImport re = RepositoryEntryImportExport.getConfiguration(repoXml);
+					if(re != null) {
+						eval.setDisplayname(re.getDisplayname());
+						eval.setDescription(re.getDescription());
+					}
+				}
+			}
+			eval.setValid(visitor.isValid());
+		} catch (IOException e) {
+			log.error("", e);
+		}
+		return eval;
 	}
 	
 	@Override
@@ -212,8 +231,12 @@ public class CourseHandler implements RepositoryHandler {
 		
 		//import references
 		importReferences((CourseEditorTreeNode)course.getEditorTreeModel().getRootNode(), course, initialAuthor);
-		importSharedFolder(course, initialAuthor);
-		importGlossary(course, initialAuthor);
+		if(course.getCourseConfig().hasCustomSharedFolder()) {
+			importSharedFolder(course, initialAuthor);
+		}
+		if(course.getCourseConfig().hasGlossary()) {
+			importGlossary(course, initialAuthor);
+		}
 
 		// create group management / import groups
 		cgm = course.getCourseEnvironment().getCourseGroupManager();
@@ -562,4 +585,23 @@ public class CourseHandler implements RepositoryHandler {
 	public WizardCloseResourceController createCloseResourceController(UserRequest ureq, WindowControl wControl, RepositoryEntry repositoryEntry) {
 		return new WizardCloseCourseController(ureq, wControl, repositoryEntry);
 	}
+	
+	private static class IndexFileFilter extends SimpleFileVisitor<Path> {
+		private boolean editorFile;
+
+		@Override
+		public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
+		throws IOException {
+
+			String filename = file.getFileName().toString();
+			if(EDITOR_XML.equals(filename)) {
+				editorFile = true;
+			}
+			return editorFile ? FileVisitResult.TERMINATE : FileVisitResult.CONTINUE;
+		}
+		
+		public boolean isValid() {
+			return editorFile;
+		}
+	}
 }
diff --git a/src/main/java/org/olat/repository/handlers/RepositoryHandlerFactory.java b/src/main/java/org/olat/repository/handlers/RepositoryHandlerFactory.java
index 102a98dfea3..95773cdb594 100644
--- a/src/main/java/org/olat/repository/handlers/RepositoryHandlerFactory.java
+++ b/src/main/java/org/olat/repository/handlers/RepositoryHandlerFactory.java
@@ -29,9 +29,11 @@ import java.util.HashMap;
 import java.util.Map;
 import java.util.Set;
 
+import org.olat.core.CoreSpringFactory;
 import org.olat.core.id.OLATResourceable;
 import org.olat.core.logging.AssertException;
 import org.olat.repository.RepositoryEntry;
+import org.springframework.stereotype.Service;
 
 /**
  * Initial Date:  Apr 6, 2004
@@ -41,21 +43,12 @@ import org.olat.repository.RepositoryEntry;
  * Comment:  
  * 
  */
+@Service
 public class RepositoryHandlerFactory {
 
-	private static RepositoryHandlerFactory INSTANCE;
 	private static Map<String, RepositoryHandler> handlerMap;
-	
-	/**
-	 * 
-	 */
-	private RepositoryHandlerFactory() {
-		// singleton
-	}
-
 	static {
-		INSTANCE = new RepositoryHandlerFactory();
-		handlerMap = new HashMap<String, RepositoryHandler>(10);
+		handlerMap = new HashMap<String, RepositoryHandler>(21);
 
 		registerHandler(new WebDocumentHandler());
 		registerHandler(new ImsCPHandler());
@@ -75,10 +68,9 @@ public class RepositoryHandlerFactory {
 		}
 	}
 	
-	/**
-	 * @return Singleton.
-	 */
-	public static RepositoryHandlerFactory getInstance() {	return INSTANCE; }
+	public static RepositoryHandlerFactory getInstance() {
+		return CoreSpringFactory.getImpl(RepositoryHandlerFactory.class);
+	}
 	
 	/**
 	 * Get the repository handler for this repository entry.
@@ -104,7 +96,7 @@ public class RepositoryHandlerFactory {
 	 * Get a set of types this factory supports.
 	 * @return Set of supported types.
 	 */
-	public static Set<String> getSupportedTypes() {
+	public Set<String> getSupportedTypes() {
 		return handlerMap.keySet();
 	}
 }
diff --git a/src/main/java/org/olat/repository/manager/RepositoryEntryAuthorViewQueries.java b/src/main/java/org/olat/repository/manager/RepositoryEntryAuthorViewQueries.java
index 7395895cc20..f4dcd533b4b 100644
--- a/src/main/java/org/olat/repository/manager/RepositoryEntryAuthorViewQueries.java
+++ b/src/main/java/org/olat/repository/manager/RepositoryEntryAuthorViewQueries.java
@@ -29,6 +29,7 @@ import org.olat.core.commons.persistence.DB;
 import org.olat.core.id.Identity;
 import org.olat.core.logging.OLog;
 import org.olat.core.logging.Tracing;
+import org.olat.core.util.StringHelper;
 import org.olat.repository.RepositoryEntryAuthorView;
 import org.olat.repository.SearchAuthorRepositoryEntryViewParams;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -106,6 +107,23 @@ public class RepositoryEntryAuthorViewQueries {
 		if(params.getMarked() != null) {
 			sb.append(" and v.markKey ").append(params.getMarked().booleanValue() ? " is not null " : " is null ");
 		}
+		Long id = null;
+		String refs = null;
+		if(StringHelper.containsNonWhitespace(params.getIdAndRefs())) {
+			refs = params.getIdAndRefs();
+			if(StringHelper.isLong(refs)) {
+				try {
+					id = Long.parseLong(refs);
+				} catch (NumberFormatException e) {
+					//
+				}
+			}
+			sb.append(" and (v.externalId=:ref or v.externalRef=:ref or v.softkey=:ref");
+			if(id != null) {
+				sb.append(" or v.key=:vKey)");
+			}
+			sb.append(")");	
+		}
 		
 		TypedQuery<T> dbQuery = dbInstance.getCurrentEntityManager()
 				.createQuery(sb.toString(), type);
@@ -118,6 +136,12 @@ public class RepositoryEntryAuthorViewQueries {
 		if(params.isLifecycleFilterDefined()) {
 			dbQuery.setParameter("now", new Date());
 		}
+		if(id != null) {
+			dbQuery.setParameter("vKey", id);
+		}
+		if(refs != null) {
+			dbQuery.setParameter("ref", refs);
+		}
 		dbQuery.setParameter("identityKey", identity.getKey());
 		return dbQuery;
 	}
diff --git a/src/main/java/org/olat/repository/model/RepositoryEntryAuthorViewImpl.java b/src/main/java/org/olat/repository/model/RepositoryEntryAuthorViewImpl.java
index 8704b350ad5..8d2ab0e543a 100644
--- a/src/main/java/org/olat/repository/model/RepositoryEntryAuthorViewImpl.java
+++ b/src/main/java/org/olat/repository/model/RepositoryEntryAuthorViewImpl.java
@@ -73,6 +73,8 @@ public class RepositoryEntryAuthorViewImpl implements RepositoryEntryAuthorView
 	@Column(name="re_authors", nullable=false, insertable=false, updatable=false)
 	private String authors;
 	
+	@Column(name="re_softkey", nullable=false, insertable=false, updatable=false)
+	private String softkey;
 	@Column(name="re_external_id", nullable=false, insertable=false, updatable=false)
 	private String externalId;
 	@Column(name="re_external_ref", nullable=false, insertable=false, updatable=false)
@@ -147,7 +149,11 @@ public class RepositoryEntryAuthorViewImpl implements RepositoryEntryAuthorView
 	public String getDescription() {
 		return description;
 	}
-	
+
+	public String getSoftkey() {
+		return softkey;
+	}
+
 	@Override
 	public String getExternalId() {
 		return externalId;
diff --git a/src/main/java/org/olat/repository/ui/author/AuthorListController.java b/src/main/java/org/olat/repository/ui/author/AuthorListController.java
index cb5c7154bc3..307828bb3f8 100644
--- a/src/main/java/org/olat/repository/ui/author/AuthorListController.java
+++ b/src/main/java/org/olat/repository/ui/author/AuthorListController.java
@@ -23,7 +23,6 @@ import java.util.Collections;
 import java.util.List;
 
 import org.olat.NewControllerFactory;
-import org.olat.core.CoreSpringFactory;
 import org.olat.core.commons.services.mark.Mark;
 import org.olat.core.commons.services.mark.MarkManager;
 import org.olat.core.gui.UserRequest;
@@ -56,6 +55,7 @@ import org.olat.core.util.resource.OresHelper;
 import org.olat.repository.RepositoryManager;
 import org.olat.repository.SearchAuthorRepositoryEntryViewParams;
 import org.olat.repository.ui.author.AuthoringEntryDataModel.Cols;
+import org.springframework.beans.factory.annotation.Autowired;
 
 /**
  * 
@@ -69,17 +69,18 @@ public class AuthorListController extends FormBasicController implements Activat
 	private AuthoringEntryDataModel model;
 	private AuthoringEntryDataSource dataSource;
 	private final SearchAuthorRepositoryEntryViewParams searchParams;
-	private final MarkManager markManager;
 	private final TooledStackedPanel stackPanel;
 
 	private AuthorSearchController searchCtrl;
 	private AuthoringEntryDetailsController detailsCtrl;
 	
+	@Autowired
+	private MarkManager markManager;
+	
 	public AuthorListController(UserRequest ureq, WindowControl wControl, TooledStackedPanel stackPanel,
 			SearchAuthorRepositoryEntryViewParams searchParams) {
 		super(ureq, wControl, "repoentry_table");
 		setTranslator(Util.createPackageTranslator(RepositoryManager.class, getLocale(), getTranslator()));
-		markManager = CoreSpringFactory.getImpl(MarkManager.class);
 
 		this.stackPanel = stackPanel;
 		this.searchParams = searchParams;
@@ -196,6 +197,9 @@ public class AuthorListController extends FormBasicController implements Activat
 			searchParams.setResourceTypes(null);
 		}
 
+		searchParams.setIdAndRefs(se.getId());
+		searchParams.setAuthor(se.getAuthor());
+		searchParams.setDisplayname(se.getDisplayname());
 		tableEl.reset();
 	}
 	
diff --git a/src/main/java/org/olat/repository/ui/author/AuthorSearchController.java b/src/main/java/org/olat/repository/ui/author/AuthorSearchController.java
index 55e9e404e60..b0d26f450a9 100644
--- a/src/main/java/org/olat/repository/ui/author/AuthorSearchController.java
+++ b/src/main/java/org/olat/repository/ui/author/AuthorSearchController.java
@@ -1,10 +1,27 @@
-
+/**
+ * <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.repository.ui.author;
 
 import java.util.ArrayList;
 import java.util.List;
 
-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;
@@ -19,29 +36,11 @@ import org.olat.core.gui.components.link.Link;
 import org.olat.core.gui.control.Controller;
 import org.olat.core.gui.control.Event;
 import org.olat.core.gui.control.WindowControl;
+import org.olat.core.util.StringHelper;
 import org.olat.core.util.Util;
-import org.olat.course.CourseModule;
-import org.olat.fileresource.types.AnimationFileResource;
-import org.olat.fileresource.types.BlogFileResource;
-import org.olat.fileresource.types.DocFileResource;
-import org.olat.fileresource.types.FileResource;
-import org.olat.fileresource.types.GlossaryResource;
-import org.olat.fileresource.types.ImageFileResource;
-import org.olat.fileresource.types.ImsCPFileResource;
-import org.olat.fileresource.types.MovieFileResource;
-import org.olat.fileresource.types.PdfFileResource;
-import org.olat.fileresource.types.PodcastFileResource;
-import org.olat.fileresource.types.PowerpointFileResource;
-import org.olat.fileresource.types.ScormCPFileResource;
-import org.olat.fileresource.types.SharedFolderFileResource;
-import org.olat.fileresource.types.SoundFileResource;
-import org.olat.fileresource.types.WikiResource;
-import org.olat.fileresource.types.XlsFileResource;
-import org.olat.ims.qti.fileresource.SurveyFileResource;
-import org.olat.ims.qti.fileresource.TestFileResource;
-import org.olat.portfolio.EPTemplateMapResource;
 import org.olat.repository.RepositoryManager;
-import org.olat.repository.RepositoryModule;
+import org.olat.repository.handlers.RepositoryHandlerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
 
 /**
  * 
@@ -55,20 +54,19 @@ public class AuthorSearchController extends FormBasicController{
 	private TextElement displayName;
 	private TextElement author;
 	private TextElement description;
-	private TextElement externalId;
-	private TextElement externalRef;
 	private SingleSelection types;
 	private FormLink searchButton;
 	
 	private String[] limitTypes;
 	private boolean isAdmin;
-	private final boolean managedEnabled;
+	
+	@Autowired
+	private RepositoryHandlerFactory repositoryHandlerFactory;
 
 	public AuthorSearchController(UserRequest ureq, WindowControl wControl, boolean isAdmin, Form form) {
 		super(ureq, wControl, LAYOUT_CUSTOM, "search", form);
 		setTranslator(Util.createPackageTranslator(RepositoryManager.class, getLocale(), getTranslator()));
 		this.isAdmin = isAdmin;
-		managedEnabled = CoreSpringFactory.getImpl(RepositoryModule.class).isManagedRepositoryEntries();
 		initForm(ureq);
 	}
 	
@@ -81,9 +79,6 @@ public class AuthorSearchController extends FormBasicController{
 		displayName = uifactory.addTextElement("cif_displayname", "cif.displayname", 255, "", leftContainer);
 		displayName.setElementCssClass("o_sel_repo_search_displayname");
 		displayName.setFocus(true);
-		
-		author = uifactory.addTextElement("cif_author", "cif.author", 255, "", formLayout);
-		author.setElementCssClass("o_sel_repo_search_author");
 
 		description = uifactory.addTextElement("cif_description", "cif.description", 255, "", leftContainer);
 		description.setElementCssClass("o_sel_repo_search_description");
@@ -92,24 +87,18 @@ public class AuthorSearchController extends FormBasicController{
 		String[] typeKeys = typeList.toArray(new String[typeList.size()]);
 		String[] typeValues = getTranslatedResources(typeList);
 		types = uifactory.addDropdownSingleselect("cif.type", "cif.type", leftContainer, typeKeys, typeValues, null);
-		
-		
+
 		FormLayoutContainer rightContainer = FormLayoutContainer.createDefaultFormLayout("right_1", getTranslator());
 		rightContainer.setRootForm(mainForm);
 		formLayout.add(rightContainer);
 		
+		author = uifactory.addTextElement("cif_author", "cif.author", 255, "", rightContainer);
+		author.setElementCssClass("o_sel_repo_search_author");
+		
 		id = uifactory.addTextElement("cif_id", "cif.id", 12, "", rightContainer);
 		id.setElementCssClass("o_sel_repo_search_id");
 		id.setVisible(isAdmin);
 		id.setRegexMatchCheck("\\d*", "search.id.format");
-		
-		externalId = uifactory.addTextElement("cif_extid", "cif.externalid", 128, "", rightContainer);
-		externalId.setElementCssClass("o_sel_repo_search_external_id");
-		externalId.setVisible(managedEnabled);
-
-		externalRef = uifactory.addTextElement("cif_extref", "cif.externalref", 128, "", rightContainer);
-		externalRef.setElementCssClass("o_sel_repo_search_external_ref");
-		externalRef.setVisible(managedEnabled);
 
 		FormLayoutContainer buttonLayout = FormLayoutContainer.createButtonLayout("button_layout", getTranslator());
 		formLayout.add(buttonLayout);
@@ -120,30 +109,12 @@ public class AuthorSearchController extends FormBasicController{
 	protected void doDispose() {
 		//
 	}
-
-	/**
-	 * @return Is ID field available?
-	 */
-	public boolean hasId() {
-		return (id != null && !id.isEmpty());
-	}
 	
 	/**
 	 * @return Return value of ID field.
 	 */
-	public Long getId() {
-		if (!hasId()) {
-			return null;
-		}
-		return new Long(id.getValue());
-	}
-	
-	public String getExternalId() {
-		return externalId.getValue();
-	}
-	
-	public String getExternalRef() {
-		return externalRef.getValue();
+	public String getId() {
+		return id.getValue();
 	}
 
 	/**
@@ -181,8 +152,7 @@ public class AuthorSearchController extends FormBasicController{
 	
 	@Override
 	protected boolean validateFormLogic(UserRequest ureq) {
-		if (displayName.isEmpty() && author.isEmpty() && description.isEmpty() && (id != null && id.isEmpty())
-				&& externalId.isEmpty() && externalRef.isEmpty())	{
+		if (displayName.isEmpty() && author.isEmpty() && description.isEmpty() && (id != null && id.isEmpty()))	{
 			showWarning("cif.error.allempty", null);
 			return false;
 		}
@@ -211,8 +181,6 @@ public class AuthorSearchController extends FormBasicController{
 		e.setId(getId());
 		e.setAuthor(getAuthor());
 		e.setDisplayname(getDisplayName());
-		e.setExternalId(getExternalId());
-		e.setExternalRef(getExternalRef());
 		e.setType(getRestrictedType());
 		fireEvent(ureq, e);
 	}
@@ -220,34 +188,21 @@ public class AuthorSearchController extends FormBasicController{
 	private String[] getTranslatedResources(List<String> resources) {
 		List<String> l = new ArrayList<String>();
 		for(String key: resources){
-			l.add(translate(key));
+			if(StringHelper.containsNonWhitespace(key)) {
+				l.add(translate(key));
+			} else {
+				l.add("");
+			}
 		}
 		return l.toArray(new String[0]);
 	}
 	
 	private List<String> getResources() {
 		List<String> resources = new ArrayList<String>();
-		resources.add(CourseModule.getCourseTypeName());
-		resources.add(ImsCPFileResource.TYPE_NAME);
-		resources.add(ScormCPFileResource.TYPE_NAME);
-		resources.add(WikiResource.TYPE_NAME);
-		resources.add(PodcastFileResource.TYPE_NAME);
-		resources.add(BlogFileResource.TYPE_NAME);
-		resources.add(TestFileResource.TYPE_NAME);
-		resources.add(SurveyFileResource.TYPE_NAME);
-		resources.add(EPTemplateMapResource.TYPE_NAME);
-		resources.add(SharedFolderFileResource.TYPE_NAME);
-		resources.add(GlossaryResource.TYPE_NAME);
-		resources.add(PdfFileResource.TYPE_NAME);
-		resources.add(XlsFileResource.TYPE_NAME);
-		resources.add(PowerpointFileResource.TYPE_NAME);
-		resources.add(DocFileResource.TYPE_NAME);
-		resources.add(AnimationFileResource.TYPE_NAME);
-		resources.add(ImageFileResource.TYPE_NAME);
-		resources.add(SoundFileResource.TYPE_NAME);
-		resources.add(MovieFileResource.TYPE_NAME);
-		resources.add(FileResource.GENERIC_TYPE_NAME);
+		resources.add("");
+		for(String type:repositoryHandlerFactory.getSupportedTypes()) {
+			resources.add(type);
+		}
 		return resources;
 	}
-
 }
\ No newline at end of file
diff --git a/src/main/java/org/olat/repository/ui/author/AuthoringEditEntryController.java b/src/main/java/org/olat/repository/ui/author/AuthoringEditEntryController.java
index db1aa1a3e52..93aeb3440ba 100644
--- a/src/main/java/org/olat/repository/ui/author/AuthoringEditEntryController.java
+++ b/src/main/java/org/olat/repository/ui/author/AuthoringEditEntryController.java
@@ -56,7 +56,7 @@ public class AuthoringEditEntryController extends BasicController {
 	private final RepositoryEditDescriptionController descriptionCtrl;
 	
 	private RepositoryEntry entry;
-	private final RepositoryService repositoryService;
+	private RepositoryService repositoryService;
 	
 	public AuthoringEditEntryController(UserRequest ureq, WindowControl wControl, TooledStackedPanel stackPanel,
 			AuthoringEntryRow row) {
diff --git a/src/main/java/org/olat/repository/ui/author/AuthoringEntryDetailsController.java b/src/main/java/org/olat/repository/ui/author/AuthoringEntryDetailsController.java
index e8cf676c8d3..94548d0ad2a 100644
--- a/src/main/java/org/olat/repository/ui/author/AuthoringEntryDetailsController.java
+++ b/src/main/java/org/olat/repository/ui/author/AuthoringEntryDetailsController.java
@@ -23,9 +23,10 @@ import java.util.ArrayList;
 import java.util.List;
 
 import org.olat.NewControllerFactory;
+import org.olat.basesecurity.GroupRoles;
 import org.olat.catalog.CatalogEntry;
 import org.olat.catalog.CatalogManager;
-import org.olat.core.CoreSpringFactory;
+import org.olat.catalog.ui.CatalogEntryAddController;
 import org.olat.core.commons.services.commentAndRating.CommentAndRatingDefaultSecurityCallback;
 import org.olat.core.commons.services.commentAndRating.CommentAndRatingSecurityCallback;
 import org.olat.core.commons.services.commentAndRating.ui.UserCommentsController;
@@ -47,30 +48,51 @@ import org.olat.core.gui.control.Controller;
 import org.olat.core.gui.control.Event;
 import org.olat.core.gui.control.WindowControl;
 import org.olat.core.gui.control.generic.closablewrapper.CloseableModalController;
+import org.olat.core.gui.control.generic.modal.DialogBoxController;
+import org.olat.core.gui.control.generic.modal.DialogBoxUIFactory;
+import org.olat.core.gui.media.MediaResource;
+import org.olat.core.id.Identity;
 import org.olat.core.id.OLATResourceable;
+import org.olat.core.id.Roles;
+import org.olat.core.logging.OLATSecurityException;
 import org.olat.core.util.Formatter;
 import org.olat.core.util.StringHelper;
 import org.olat.core.util.Util;
+import org.olat.core.util.coordinate.CoordinatorManager;
+import org.olat.core.util.coordinate.LockResult;
 import org.olat.core.util.filter.FilterFactory;
 import org.olat.core.util.resource.OresHelper;
 import org.olat.core.util.vfs.VFSContainer;
 import org.olat.core.util.vfs.VFSContainerMapper;
 import org.olat.core.util.vfs.VFSLeaf;
+import org.olat.course.CorruptedCourseException;
+import org.olat.course.CourseModule;
+import org.olat.course.run.RunMainController;
 import org.olat.group.BusinessGroup;
 import org.olat.group.BusinessGroupService;
 import org.olat.group.model.SearchBusinessGroupParams;
 import org.olat.repository.RepositoryEntry;
+import org.olat.repository.RepositoryEntryManagedFlag;
+import org.olat.repository.RepositoryManager;
+import org.olat.repository.RepositoryModule;
 import org.olat.repository.RepositoryService;
 import org.olat.repository.RepositoyUIFactory;
+import org.olat.repository.controllers.EntryChangedEvent;
+import org.olat.repository.controllers.RepositoryMembersController;
+import org.olat.repository.controllers.WizardCloseResourceController;
 import org.olat.repository.handlers.RepositoryHandler;
 import org.olat.repository.handlers.RepositoryHandlerFactory;
 import org.olat.repository.ui.PriceMethod;
+import org.olat.resource.OLATResource;
 import org.olat.resource.accesscontrol.ACService;
 import org.olat.resource.accesscontrol.AccessResult;
 import org.olat.resource.accesscontrol.model.AccessMethod;
 import org.olat.resource.accesscontrol.model.OfferAccess;
 import org.olat.resource.accesscontrol.model.Price;
+import org.olat.resource.accesscontrol.ui.OrdersAdminController;
 import org.olat.resource.accesscontrol.ui.PriceFormat;
+import org.olat.user.UserManager;
+import org.springframework.beans.factory.annotation.Autowired;
 
 /**
  * 
@@ -81,50 +103,173 @@ import org.olat.resource.accesscontrol.ui.PriceFormat;
 public class AuthoringEntryDetailsController extends FormBasicController {
 	
 	private FormLink markLink, startLink;
+	
 	private Link editLink;
+	private Link downloadLink, downloadCompatLink, bookmarkLink, catalogLink;
+	private Link launchLink, editSettingsLink, membersLink, copyLink, deleteLink, closeLink, orderLink;
 	
 	private CloseableModalController cmc;
+	private WizardCloseResourceController wc;
+	private OrdersAdminController ordersCtlr;
+	private Controller catalogAdddController;
 	private UserCommentsController commentsCtrl;
+	private DialogBoxController deleteDialogCtrl;
 	private AuthoringEditEntryController editCtrl;
+	private RepositoryMembersController membersEditController;
 	
 	private final TooledStackedPanel stackPanel;
 	
+	private boolean corrupted;
 	private final RepositoryEntry entry;
 	private final AuthoringEntryRow row;
 
-	private final ACService acService;
-	private final MarkManager markManager;
-	private final CatalogManager catalogManager;
-	private final RepositoryService repositoryService;
-	private final BusinessGroupService businessGroupService;
+	@Autowired
+	private ACService acService;
+	@Autowired
+	private MarkManager markManager;
+	@Autowired
+	private UserManager userManager;
+	@Autowired
+	private CatalogManager catalogManager;
+	@Autowired
+	private RepositoryManager repositoryManager;
+	@Autowired
+	private RepositoryModule repositoryModule;
+	@Autowired
+	private RepositoryService repositoryService;
+	@Autowired
+	private BusinessGroupService businessGroupService;
+	@Autowired
+	private RepositoryHandlerFactory repositoryHandlerFactory;
 	
 	private String baseUrl;
+	private final boolean isOwner;
+	private final boolean isAuthor;
+	private final boolean isOlatAdmin;
+	private final boolean isGuestOnly;
+	private LockResult lockResult;
 	
 	public AuthoringEntryDetailsController(UserRequest ureq, WindowControl wControl,
 			TooledStackedPanel stackPanel, AuthoringEntryRow row) {
 		super(ureq, wControl, "details");
-		
 		setTranslator(Util.createPackageTranslator(RepositoryService.class, getLocale(), getTranslator()));
 
-		acService = CoreSpringFactory.getImpl(ACService.class);
-		markManager = CoreSpringFactory.getImpl(MarkManager.class);
-		catalogManager = CoreSpringFactory.getImpl(CatalogManager.class);
-		repositoryService = CoreSpringFactory.getImpl(RepositoryService.class);
-		businessGroupService = CoreSpringFactory.getImpl(BusinessGroupService.class);
-		
 		this.stackPanel = stackPanel;
 		this.row = row;
 		entry = repositoryService.loadByKey(row.getKey());
 		
+		Identity identity = getIdentity();
+		Roles roles = ureq.getUserSession().getRoles();
+		isOlatAdmin = roles.isOLATAdmin();
+		boolean isInstitutionalResourceManager = !roles.isGuestOnly()
+					&& RepositoryManager.getInstance().isInstitutionalRessourceManagerFor(identity, roles, entry);
+		isOwner = isOlatAdmin || repositoryService.hasRole(ureq.getIdentity(), entry, GroupRoles.owner.name())
+					| isInstitutionalResourceManager;
+		isAuthor = isOlatAdmin || roles.isAuthor() | isInstitutionalResourceManager;
+		isGuestOnly = roles.isGuestOnly();
+
 		initForm(ureq);
 		
 		if(stackPanel != null) {
 			String displayName = row.getDisplayname();
 			stackPanel.pushController(displayName, this);
+			initToolbar(ureq);
+		}
+	}
+	
+	
+	private void initToolbar(UserRequest ureq) {
+		// init handler details
+		RepositoryHandler handler = repositoryHandlerFactory.getRepositoryHandler(entry);
+	
+		launchLink = LinkFactory.createToolLink("launch", translate("details.launch"), this, "o_sel_repo_launch");
+		launchLink.setEnabled(checkIsRepositoryEntryLaunchable(ureq) && !corrupted);
+		stackPanel.addTool(launchLink, false);
+
+		if (!isGuestOnly) {
+			boolean canDownload = entry.getCanDownload() && handler.supportsDownload(entry);
+			// disable download for courses if not author or owner
+			if (entry.getOlatResource().getResourceableTypeName().equals(CourseModule.getCourseTypeName()) && !(isOwner || isAuthor)) {
+				canDownload = false;
+			}
+			// always enable download for owners
+			if (isOwner && handler.supportsDownload(entry)) {
+				canDownload = true;
+			}
+
+			downloadLink = LinkFactory.createToolLink("download", translate("details.download"), this, "o_sel_repo_download");
+			downloadLink.setEnabled(canDownload && !corrupted);
+			downloadCompatLink = LinkFactory.createToolLink("downloadcompat", translate("details.download.compatible"), this, "o_sel_repo_download_backward");
+			downloadCompatLink.setEnabled(canDownload && !corrupted
+					&& "CourseModule".equals(entry.getOlatResource().getResourceableTypeName()));
+			
+			boolean marked = markManager.isMarked(entry, getIdentity(), null);
+			String css = marked ? Mark.MARK_CSS_LARGE : Mark.MARK_ADD_CSS_LARGE;
+			bookmarkLink = LinkFactory.createToolLink("downloadcompat", translate("details.bookmark"), this, css);
+			bookmarkLink.setEnabled(!corrupted);
+
+			stackPanel.addTool(downloadLink, false);
+			stackPanel.addTool(downloadCompatLink, false);
+			stackPanel.addTool(bookmarkLink, false);
+		}
+
+		if (isAuthor || isOwner) {
+			if (isOwner) {
+				editLink = LinkFactory.createToolLink("edit", translate("details.openeditor"), this, "o_sel_repo_edit_descritpion");
+				boolean editManaged = RepositoryEntryManagedFlag.isManaged(entry, RepositoryEntryManagedFlag.editcontent);
+				editLink.setEnabled(handler.supportsEdit(entry) && !corrupted && !editManaged);
+				stackPanel.addTool(editLink, false);
+				
+				editSettingsLink = LinkFactory.createToolLink("editdesc", translate("details.chprop"), this, "o_sel_repor_edit_properties");
+				editSettingsLink.setEnabled(!corrupted);
+				stackPanel.addTool(editLink, false);
+		
+				if(repositoryModule.isCatalogEnabled()) {
+					catalogLink = LinkFactory.createToolLink("cat", translate("details.catadd"), this, "o_sel_repo_add_to_catalog");
+					catalogLink.setEnabled(!corrupted && (entry.getAccess() >= RepositoryEntry.ACC_USERS || entry.isMembersOnly()));
+					stackPanel.addTool(catalogLink, false);
+				}
+
+				boolean closeManaged = RepositoryEntryManagedFlag.isManaged(entry, RepositoryEntryManagedFlag.close);
+				if ((OresHelper.isOfType(entry.getOlatResource(), CourseModule.class))
+						&& !closeManaged
+						&& (!RepositoryManager.getInstance().createRepositoryEntryStatus(entry.getStatusCode()).isClosed())) {
+					
+					closeLink = LinkFactory.createToolLink("close", translate("details.close.ressoure"), this, "o_sel_repo_close_resource");
+					closeLink.setEnabled(!corrupted);
+					stackPanel.addTool(closeLink, false);
+				}
+			}
+		
+			if(isAuthor) {	
+				copyLink = LinkFactory.createToolLink("close", translate("details.copy"), this, "o_sel_repo_copy");
+				boolean copyManaged = RepositoryEntryManagedFlag.isManaged(entry, RepositoryEntryManagedFlag.copy);
+				copyLink.setEnabled((isOwner || entry.getCanCopy()) && !corrupted && !copyManaged);
+				stackPanel.addTool(copyLink, false);
+			}
 			
-			editLink = LinkFactory.createToolLink("edit", "Edit", this);
-			stackPanel.addTool(editLink, false);
+			if (isOwner) {
+				deleteLink = LinkFactory.createToolLink("delete", translate("details.delete"), this, "o_sel_repo_delete");
+				boolean deleteManaged = RepositoryEntryManagedFlag.isManaged(entry, RepositoryEntryManagedFlag.delete);
+				deleteLink.setEnabled(!corrupted && !deleteManaged);
+				
+				membersLink = LinkFactory.createToolLink("close", translate("details.copy"), this, "o_sel_repo_members");
+				membersLink.setEnabled(!corrupted);
+				
+				orderLink = LinkFactory.createToolLink("order", translate("details.orders"), this, "o_sel_repo_booking");
+				boolean booking = acService.isResourceAccessControled(entry.getOlatResource(), null);
+				orderLink.setEnabled(!corrupted && booking);
+			}
+		}
+	}
+	
+	private boolean checkIsRepositoryEntryLaunchable(UserRequest ureq) {
+		RepositoryHandler type = repositoryHandlerFactory.getRepositoryHandler(entry);
+		if (repositoryManager.isAllowedToLaunch(ureq, entry) ||
+				(type.supportsLaunch(entry) && ureq.getUserSession().getRoles().isOLATAdmin())) {
+			return true;
 		}
+		return false;
 	}
 	
 	private void setText(String text, String key, FormLayoutContainer layoutCont) {
@@ -261,23 +406,91 @@ public class AuthoringEntryDetailsController extends FormBasicController {
 			
 		} else if(cmc == source) {
 			cleanUp();
+		} else if (source == wc) {
+			if (event == Event.CANCELLED_EVENT) {
+				cmc.deactivate();
+			} else if (event == Event.DONE_EVENT) {
+				cmc.deactivate();
+				updateView(ureq);
+				fireEvent(ureq, Event.CHANGED_EVENT);
+			}
+		} else if (source == editCtrl) {
+			if (event == Event.CHANGED_EVENT || event == Event.DONE_EVENT) {
+				// RepositoryEntry changed
+
+				updateView(ureq);
+			} else if (event == Event.CANCELLED_EVENT) {
+				
+			}
+			cleanUp();
+		} else if (source == deleteDialogCtrl){
+			if (DialogBoxUIFactory.isYesEvent(event)){
+				deleteRepositoryEntry(ureq, getWindowControl());
+			}	
+		} else if (source == catalogAdddController) {
+			// finish modal dialog and reload categories list controller
+			cmc.deactivate();
+			updateCategoriesTableC(ureq);
 		}
 		super.event(ureq, source, event);
 	}
+	
+	private void updateView(UserRequest ureq) {
+		
+	}
+	
+	private void updateCategoriesTableC(UserRequest ureq) {
+		
+	}
 
 	@Override
 	public void event(UserRequest ureq, Component source, Event event) {
-		if(editLink == source) {
+		if (downloadLink == source) { 
+			doDownload(ureq, false);
+		} else if (downloadCompatLink == source) {
+			doDownload(ureq, true);
+		} else if (launchLink == source) {
+			launch(ureq);
+		} else if (editLink == source) {
 			doEdit(ureq);
+		} else if (editSettingsLink == source) {
+			doEditSettings(ureq);
+		} else if (catalogLink == source) {
+			if(repositoryModule.isCatalogEnabled()) {
+				doAddCatalog(ureq);
+			}
+		} else if (bookmarkLink == source) {
+			String css = doMark() ? Mark.MARK_CSS_LARGE : Mark.MARK_ADD_CSS_LARGE;
+			bookmarkLink.setElementCssClass(css);
+		} else if (membersLink == source) { // membership
+			doOpenMembers(ureq);
+		} else if (orderLink == source) {
+			doOrders(ureq);
+		} else if (closeLink == source) {
+			doCloseResource(ureq);
+		} else if (deleteLink == source) { // delete
+			if (!isOwner) throw new OLATSecurityException("Trying to delete, but not allowed: user = " + ureq.getIdentity());
+			doDelete(ureq);
 		}
 		super.event(ureq, source, event);
 	}
 
 	private void cleanUp() {
+		removeAsListenerAndDispose(catalogAdddController);
+		removeAsListenerAndDispose(membersEditController);
+		removeAsListenerAndDispose(deleteDialogCtrl);
 		removeAsListenerAndDispose(commentsCtrl);
+		removeAsListenerAndDispose(ordersCtlr);
+		removeAsListenerAndDispose(editCtrl);
 		removeAsListenerAndDispose(cmc);
+		removeAsListenerAndDispose(wc);
+		catalogAdddController = null;
+		deleteDialogCtrl = null;
 		commentsCtrl = null;
+		ordersCtlr = null;
+		editCtrl = null;
 		cmc = null;
+		wc = null;
 	}
 
 	@Override
@@ -294,7 +507,7 @@ public class AuthoringEntryDetailsController extends FormBasicController {
 			} else if("comments".equals(cmd)) {
 				doOpenComments(ureq);
 			} else if("start".equals(cmd)) {
-				doStart(ureq);
+				launch(ureq);
 			} else if("group".equals(cmd)) {
 				Long groupKey = (Long)link.getUserObject();
 				doOpenGroup(ureq, groupKey);
@@ -302,19 +515,93 @@ public class AuthoringEntryDetailsController extends FormBasicController {
 		}
 		super.formInnerEvent(ureq, source, event);
 	}
+
+	private void doCloseResource(UserRequest ureq) {
+		RepositoryHandler repoHandler = RepositoryHandlerFactory.getInstance().getRepositoryHandler(entry);
+
+		removeAsListenerAndDispose(wc);
+		wc = repoHandler.createCloseResourceController(ureq, getWindowControl(), entry);
+		listenTo(wc);
+		
+		wc.startWorkflow();
+		
+		removeAsListenerAndDispose(cmc);
+		cmc = new CloseableModalController(getWindowControl(), translate("close"), wc.getInitialComponent());
+		listenTo(cmc);
+		
+		cmc.activate();
+	}
 	
-	public void doEdit(UserRequest ureq) {
-		removeAsListenerAndDispose(editCtrl);
+	private void doDelete(UserRequest ureq) {
+		//show how many users are currently using this resource
 
-		editCtrl = new AuthoringEditEntryController(ureq, getWindowControl(), stackPanel, row);
-		listenTo(editCtrl);
+		String dialogTitle = translate("del.header", entry.getDisplayname());
+		OLATResourceable courseRunOres = OresHelper.createOLATResourceableInstance(RunMainController.ORES_TYPE_COURSE_RUN, entry.getOlatResource().getResourceableId());
+		int cnt = CoordinatorManager.getInstance().getCoordinator().getEventBus().getListeningIdentityCntFor(courseRunOres);
+		
+		String dialogText = translate(corrupted ? "del.confirm.corrupted" : "del.confirm", String.valueOf(cnt));
+		deleteDialogCtrl = activateYesNoDialog(ureq, dialogTitle, dialogText, deleteDialogCtrl);
 	}
 	
-	private void doStart(UserRequest ureq) {
-		String businessPath = "[RepositoryEntry:" + entry.getKey() + "]";
+	private void doDownload(UserRequest ureq, boolean backwardsCompatible) {
+		RepositoryHandler typeToDownload = RepositoryHandlerFactory.getInstance().getRepositoryHandler(entry);
+		if (typeToDownload == null) {
+			StringBuilder sb = new StringBuilder(translate("error.download"));
+			sb.append(": No download handler for repository entry: ")
+			  .append(entry.getKey());
+			showError(sb.toString());
+			return;
+		}
+		OLATResource ores = entry.getOlatResource();
+		if (ores == null) {
+			showError("error.download");
+			return;
+		}
+		
+		boolean isAlreadyLocked = typeToDownload.isLocked(ores);
+		try {			
+		  lockResult = typeToDownload.acquireLock(ores, ureq.getIdentity());
+		  if(lockResult == null || (lockResult !=null && lockResult.isSuccess() && !isAlreadyLocked)) {
+		    MediaResource mr = typeToDownload.getAsMediaResource(ores, backwardsCompatible);
+		    if(mr!=null) {
+		      repositoryService.incrementDownloadCounter(entry);
+		      ureq.getDispatchResult().setResultingMediaResource(mr);
+		    } else {
+			    showError("error.export");
+			    fireEvent(ureq, Event.FAILED_EVENT);			
+		    }
+		  } else if(lockResult !=null && lockResult.isSuccess() && isAlreadyLocked) {
+		  	String fullName = userManager.getUserDisplayName(lockResult.getOwner());
+		  	showInfo("warning.course.alreadylocked.bySameUser", fullName);
+		  	lockResult = null; //invalid lock, it was already locked
+		  } else {
+		  	String fullName = userManager.getUserDisplayName(lockResult.getOwner());
+		  	showInfo("warning.course.alreadylocked", fullName);
+		  }
+		} finally {	
+			if((lockResult!=null && lockResult.isSuccess() && !isAlreadyLocked)) {
+			  typeToDownload.releaseLock(lockResult);		
+			  lockResult = null;
+			}
+		}
+	}
+	
+	private void doEdit(UserRequest ureq) {
+		String businessPath = "[RepositoryEntry:" + entry.getKey() + "][Editor:0]";
 		NewControllerFactory.getInstance().launch(businessPath, ureq, getWindowControl());
 	}
 	
+	/**
+	 * Open the editor for all repository entry metadata, access control...
+	 * @param ureq
+	 */
+	private void doEditSettings(UserRequest ureq) {
+		removeAsListenerAndDispose(editCtrl);
+
+		editCtrl = new AuthoringEditEntryController(ureq, getWindowControl(), stackPanel, row);
+		listenTo(editCtrl);
+	}
+	
 	private void doOpenCategory(UserRequest ureq, Long categoryKey) {
 		String businessPath = "[CatalogEntry:" + categoryKey + "]";
 		NewControllerFactory.getInstance().launch(businessPath, ureq, getWindowControl());
@@ -348,4 +635,62 @@ public class AuthoringEntryDetailsController extends FormBasicController {
 		listenTo(cmc);
 		cmc.activate();
 	}
+	
+	private void doOpenMembers(UserRequest ureq) {
+		if (!isOwner) throw new OLATSecurityException("Trying to access groupmanagement, but not allowed: user = " + getIdentity());
+		if(membersEditController != null) return;
+		
+		membersEditController = new RepositoryMembersController(ureq, getWindowControl(), entry);
+		listenTo(membersEditController);
+		CloseableModalController cmc = new CloseableModalController(getWindowControl(), translate("close"),
+				membersEditController.getInitialComponent(), true, translate("details.members"));
+		listenTo(cmc);
+		cmc.activate();
+	}
+	
+	private void doOrders(UserRequest ureq) {
+		if(ordersCtlr != null) return;
+
+		ordersCtlr = new OrdersAdminController(ureq, getWindowControl(), entry.getOlatResource());
+		listenTo(ordersCtlr);
+
+		removeAsListenerAndDispose(cmc);
+		CloseableModalController cmc = new CloseableModalController(getWindowControl(), translate("close"), ordersCtlr.getInitialComponent());
+		listenTo(cmc);
+		
+		cmc.activate();
+	}
+	
+	private void launch(UserRequest ureq) {
+		try {
+			String businessPath = "[RepositoryEntry:" + entry.getKey() + "]";
+			NewControllerFactory.getInstance().launch(businessPath, ureq, getWindowControl());
+		} catch (CorruptedCourseException e)  {
+			logError("", e);
+		}
+	}
+	
+	/**
+	 * Internal helper to initiate the add to catalog workflow
+	 * @param ureq
+	 */
+	private void doAddCatalog(UserRequest ureq) {
+		if(catalogAdddController != null) return;
+
+		catalogAdddController = new CatalogEntryAddController(ureq, getWindowControl(), entry, true, false);
+		listenTo(catalogAdddController);
+		cmc = new CloseableModalController(getWindowControl(), "close",
+				catalogAdddController.getInitialComponent(), true, translate("details.catadd"));
+		listenTo(cmc);
+		cmc.activate();
+	}
+	
+	private void deleteRepositoryEntry(UserRequest ureq, WindowControl wControl) {
+		if (RepositoryManager.getInstance().deleteRepositoryEntryWithAllData( ureq, wControl, entry) ) {
+			fireEvent(ureq, new EntryChangedEvent(entry, EntryChangedEvent.DELETED));
+			showInfo("info.entry.deleted");
+		} else {
+			showInfo("info.could.not.delete.entry");
+		}
+	}
 }
diff --git a/src/main/java/org/olat/repository/ui/author/CopyRepositoryEntryController.java b/src/main/java/org/olat/repository/ui/author/CopyRepositoryEntryController.java
index 45fc9613b19..4220e35da62 100644
--- a/src/main/java/org/olat/repository/ui/author/CopyRepositoryEntryController.java
+++ b/src/main/java/org/olat/repository/ui/author/CopyRepositoryEntryController.java
@@ -19,7 +19,6 @@
  */
 package org.olat.repository.ui.author;
 
-import org.olat.core.CoreSpringFactory;
 import org.olat.core.gui.UserRequest;
 import org.olat.core.gui.components.form.flexible.FormItemContainer;
 import org.olat.core.gui.components.form.flexible.elements.RichTextElement;
@@ -42,6 +41,7 @@ import org.olat.repository.handlers.RepositoryHandlerFactory;
 import org.olat.resource.OLATResource;
 import org.olat.resource.OLATResourceManager;
 import org.olat.util.logging.activity.LoggingResourceable;
+import org.springframework.beans.factory.annotation.Autowired;
 
 /**
  * 
@@ -57,17 +57,16 @@ public class CopyRepositoryEntryController extends FormBasicController {
 	private RepositoryEntry copyEntry;
 	private final RepositoryEntry sourceEntry;
 
-	private final RepositoryService repositoryService;
-	private final OLATResourceManager resourceManager;
+	@Autowired
+	private RepositoryService repositoryService;
+	@Autowired
+	private OLATResourceManager resourceManager;
 	
 	public CopyRepositoryEntryController(UserRequest ureq, WindowControl wControl, RepositoryEntry sourceEntry) {
 		super(ureq, wControl);
 		setTranslator(Util.createPackageTranslator(RepositoryManager.class, getLocale(), getTranslator()));
 		this.sourceEntry = sourceEntry;
-		
-		resourceManager = OLATResourceManager.getInstance();
-		repositoryService = CoreSpringFactory.getImpl(RepositoryService.class);
-		
+
 		initForm(ureq);
 	}
 
diff --git a/src/main/java/org/olat/repository/ui/author/ImportRepositoryEntryController.java b/src/main/java/org/olat/repository/ui/author/ImportRepositoryEntryController.java
index ce2322e72ce..17eaae11ecf 100644
--- a/src/main/java/org/olat/repository/ui/author/ImportRepositoryEntryController.java
+++ b/src/main/java/org/olat/repository/ui/author/ImportRepositoryEntryController.java
@@ -177,7 +177,7 @@ public class ImportRepositoryEntryController extends FormBasicController {
 		File uploadedFile = uploadFileEl.getUploadFile();
 		String uploadedFilename = uploadFileEl.getUploadFileName();
 		
-		for(String type:RepositoryHandlerFactory.getSupportedTypes()) {
+		for(String type:RepositoryHandlerFactory.getInstance().getSupportedTypes()) {
 			RepositoryHandler handler = RepositoryHandlerFactory.getInstance().getRepositoryHandler(type);
 			ResourceEvaluation eval = handler.acceptImport(uploadedFile, uploadedFilename);
 			if(eval != null && eval.isValid()) {
diff --git a/src/main/java/org/olat/repository/ui/author/OverviewAuthoringController.java b/src/main/java/org/olat/repository/ui/author/OverviewAuthoringController.java
index b3dd71bed69..1eb446860ba 100644
--- a/src/main/java/org/olat/repository/ui/author/OverviewAuthoringController.java
+++ b/src/main/java/org/olat/repository/ui/author/OverviewAuthoringController.java
@@ -55,6 +55,7 @@ import org.olat.repository.handlers.RepositoryHandler;
 import org.olat.repository.handlers.RepositoryHandlerFactory;
 import org.olat.user.UserManager;
 import org.olat.util.logging.activity.LoggingResourceable;
+import org.springframework.beans.factory.annotation.Autowired;
 
 /**
  * 
@@ -79,8 +80,11 @@ public class OverviewAuthoringController extends BasicController implements Acti
 	private Dropdown createDropdown;
 	private Link importLink;
 	
-	private final UserManager userManager;
-
+	@Autowired
+	private UserManager userManager;
+	@Autowired
+	private RepositoryHandlerFactory repositoryHandlerFactory;
+	
 	public OverviewAuthoringController(UserRequest ureq, WindowControl wControl) {
 		super(ureq, wControl);
 		setTranslator(Util.createPackageTranslator(RepositoryManager.class, getLocale(), getTranslator()));
@@ -95,11 +99,11 @@ public class OverviewAuthoringController extends BasicController implements Acti
 		importLink = LinkFactory.createLink("cmd.import.ressource", getTranslator(), this);
 		importLink.setDomReplacementWrapperRequired(false);
 		
-		Set<String> types = RepositoryHandlerFactory.getSupportedTypes();
+		Set<String> types = repositoryHandlerFactory.getSupportedTypes();
 
 		createDropdown = new Dropdown("cmd.create.ressource", "cmd.create.ressource", false, getTranslator());
 		for(String type:types) {
-			RepositoryHandler handler = RepositoryHandlerFactory.getInstance().getRepositoryHandler(type);
+			RepositoryHandler handler = repositoryHandlerFactory.getRepositoryHandler(type);
 			if(handler != null && handler.isCreate()) {
 				addCreateLink(handler, createDropdown);
 			}
diff --git a/src/main/java/org/olat/repository/ui/author/SearchEvent.java b/src/main/java/org/olat/repository/ui/author/SearchEvent.java
index 24341f6d28c..ad8a9818eb2 100644
--- a/src/main/java/org/olat/repository/ui/author/SearchEvent.java
+++ b/src/main/java/org/olat/repository/ui/author/SearchEvent.java
@@ -32,11 +32,9 @@ public class SearchEvent  extends Event implements StateEntry {
 
 	private static final long serialVersionUID = -1222660688926846838L;
 	
-	private Long id;
+	private String id;
 	private String displayname;
 	private String author;
-	private String externalId;
-	private String externalRef;
 	private String type;
 	
 	public SearchEvent() {
@@ -44,11 +42,11 @@ public class SearchEvent  extends Event implements StateEntry {
 	}
 
 	
-	public Long getId() {
+	public String getId() {
 		return id;
 	}
 
-	public void setId(Long id) {
+	public void setId(String id) {
 		this.id = id;
 	}
 
@@ -68,22 +66,6 @@ public class SearchEvent  extends Event implements StateEntry {
 		this.author = author;
 	}
 
-	public String getExternalId() {
-		return externalId;
-	}
-
-	public void setExternalId(String externalId) {
-		this.externalId = externalId;
-	}
-
-	public String getExternalRef() {
-		return externalRef;
-	}
-
-	public void setExternalRef(String externalRef) {
-		this.externalRef = externalRef;
-	}
-
 	public String getType() {
 		return type;
 	}
@@ -92,7 +74,6 @@ public class SearchEvent  extends Event implements StateEntry {
 		this.type = type;
 	}
 
-
 	@Override
 	public SearchEvent clone() {
 		SearchEvent clone = new SearchEvent();
diff --git a/src/main/resources/database/mysql/alter_9_4_0_to_10_0_0.sql b/src/main/resources/database/mysql/alter_9_4_0_to_10_0_0.sql
index c600566c3d9..9ed46f1f368 100644
--- a/src/main/resources/database/mysql/alter_9_4_0_to_10_0_0.sql
+++ b/src/main/resources/database/mysql/alter_9_4_0_to_10_0_0.sql
@@ -341,6 +341,7 @@ create view o_repositoryentry_author_v as (
       re.lastmodified as re_lastmodified,
       re.displayname as re_displayname,
       re.description as re_description,
+      re.softkey as re_softkey,
       re.external_id as re_external_id,
       re.external_ref as re_external_ref,
       re.initialauthor as re_author,
diff --git a/src/main/resources/database/mysql/setupDatabase.sql b/src/main/resources/database/mysql/setupDatabase.sql
index d759103287c..922c672b572 100644
--- a/src/main/resources/database/mysql/setupDatabase.sql
+++ b/src/main/resources/database/mysql/setupDatabase.sql
@@ -1506,6 +1506,7 @@ create view o_repositoryentry_author_v as (
       re.lastmodified as re_lastmodified,
       re.displayname as re_displayname,
       re.description as re_description,
+      re.softkey as re_softkey,
       re.external_id as re_external_id,
       re.external_ref as re_external_ref,
       re.initialauthor as re_author,
diff --git a/src/main/resources/database/postgresql/alter_9_4_0_to_10_0_0.sql b/src/main/resources/database/postgresql/alter_9_4_0_to_10_0_0.sql
index 8e41d9b40aa..9be9a3379db 100644
--- a/src/main/resources/database/postgresql/alter_9_4_0_to_10_0_0.sql
+++ b/src/main/resources/database/postgresql/alter_9_4_0_to_10_0_0.sql
@@ -347,6 +347,7 @@ create view o_repositoryentry_author_v as (
       re.lastmodified as re_lastmodified,
       re.displayname as re_displayname,
       re.description as re_description,
+      re.softkey as re_softkey,
       re.external_id as re_external_id,
       re.external_ref as re_external_ref,
       re.initialauthor as re_author,
diff --git a/src/test/java/org/olat/core/commons/services/webdav/WebDAVExternalTest.java b/src/test/java/org/olat/core/commons/services/webdav/WebDAVExternalTest.java
index 3d58e120ed8..31a028c22cc 100644
--- a/src/test/java/org/olat/core/commons/services/webdav/WebDAVExternalTest.java
+++ b/src/test/java/org/olat/core/commons/services/webdav/WebDAVExternalTest.java
@@ -1,3 +1,22 @@
+/**
+ * <a href="http://www.openolat.org">
+ * OpenOLAT - Online Learning and Training</a><br>
+ * <p>
+ * Licensed under the Apache License, Version 2.0 (the "License"); <br>
+ * you may not use this file except in compliance with the License.<br>
+ * You may obtain a copy of the License at the
+ * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a>
+ * <p>
+ * Unless required by applicable law or agreed to in writing,<br>
+ * software distributed under the License is distributed on an "AS IS" BASIS, <br>
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br>
+ * See the License for the specific language governing permissions and <br>
+ * limitations under the License.
+ * <p>
+ * Initial code contributed and copyrighted by<br>
+ * frentix GmbH, http://www.frentix.com
+ * <p>
+ */
 package org.olat.core.commons.services.webdav;
 
 import java.io.IOException;
-- 
GitLab