diff --git a/src/main/java/de/bps/onyx/plugin/course/nodes/iq/IQEditForm.java b/src/main/java/de/bps/onyx/plugin/course/nodes/iq/IQEditForm.java
index c365fa4f6d2023863ada43ad097943154d30f7ce..ed3aac5a5df2309e842ac454820a407def02d19c 100644
--- a/src/main/java/de/bps/onyx/plugin/course/nodes/iq/IQEditForm.java
+++ b/src/main/java/de/bps/onyx/plugin/course/nodes/iq/IQEditForm.java
@@ -174,6 +174,22 @@ public class IQEditForm extends FormBasicController {
 
 	@Override
 	protected void formOK(UserRequest ureq) {
+		modConfig.set(IQEditController.CONFIG_KEY_TEMPLATE, getTemplate());
+		if (!isSurvey) {
+			modConfig.set(IQEditController.CONFIG_KEY_ATTEMPTS, getAttempts());
+			modConfig.set(IQEditController.CONFIG_KEY_CUTVALUE, getCutValue());
+		}
+		modConfig.set(IQEditController.CONFIG_KEY_DATE_DEPENDENT_RESULTS, new Boolean(isShowResultsDateDependent()));
+		modConfig.set(IQEditController.CONFIG_KEY_RESULTS_START_DATE, getShowResultsStartDate());
+		modConfig.set(IQEditController.CONFIG_KEY_RESULTS_END_DATE, getShowResultsEndDate());
+		modConfig.set(IQEditController.CONFIG_KEY_RESULT_ON_HOME_PAGE, isShowResultsOnHomePage());
+		//<OLATCE-982>
+		modConfig.set(IQEditController.CONFIG_KEY_ALLOW_SHOW_SOLUTION, allowShowSolution());
+		//</OLATCE-982>
+		//<OLATCE-2009>
+		modConfig.set(IQEditController.CONFIG_KEY_ALLOW_SUSPENSION_ALLOWED, allowSuspension());
+		//</OLATCE-2009>
+		
 		fireEvent(ureq, Event.DONE_EVENT);
 	}
 
diff --git a/src/main/java/org/olat/course/CourseXStreamAliases.java b/src/main/java/org/olat/course/CourseXStreamAliases.java
index 125f657f226de150fb540cde0c4fa2887c1a1f63..f5d712bc4dd6ae165ca05028b5d02fdfca04583a 100644
--- a/src/main/java/org/olat/course/CourseXStreamAliases.java
+++ b/src/main/java/org/olat/course/CourseXStreamAliases.java
@@ -97,6 +97,7 @@ public class CourseXStreamAliases {
 		//start read configuration (mostly for compatibility with OLAT 7.3 and greater)
 		readXstream.alias("CourseConfig", CourseConfig.class);
 		readXstream.alias("com.frentix.olat.course.nodes.ViteroCourseNode", ViteroCourseNode.class);
+		readXstream.alias("org.olat.course.nodes.QTI21AssessmentCourseNode", IQTESTCourseNode.class);
 		readXstream.alias("CourseEditorTreeModel", CourseEditorTreeModel.class);
 		readXstream.alias("CourseEditorTreeNode", CourseEditorTreeNode.class);
 		readXstream.alias("Structure", Structure.class);
diff --git a/src/main/java/org/olat/course/nodes/IQSELFCourseNode.java b/src/main/java/org/olat/course/nodes/IQSELFCourseNode.java
index 3095ee1d26e66ec1b91b707f1aecbc7b5781b32a..8715ce585dc1c2fb685509c365c6885c9350dd8e 100644
--- a/src/main/java/org/olat/course/nodes/IQSELFCourseNode.java
+++ b/src/main/java/org/olat/course/nodes/IQSELFCourseNode.java
@@ -47,9 +47,9 @@ import org.olat.course.assessment.AssessmentManager;
 import org.olat.course.editor.CourseEditorEnv;
 import org.olat.course.editor.NodeEditController;
 import org.olat.course.editor.StatusDescription;
+import org.olat.course.nodes.iq.CourseIQSecurityCallback;
 import org.olat.course.nodes.iq.IQEditController;
 import org.olat.course.nodes.iq.IQRunController;
-import org.olat.course.nodes.iq.IQUIFactory;
 import org.olat.course.run.navigation.NodeRunConstructionResult;
 import org.olat.course.run.scoring.ScoreEvaluation;
 import org.olat.course.run.userview.NodeEvaluation;
@@ -63,6 +63,7 @@ import org.olat.ims.qti.fileresource.TestFileResource;
 import org.olat.ims.qti.process.AssessmentInstance;
 import org.olat.modules.ModuleConfiguration;
 import org.olat.modules.iq.IQManager;
+import org.olat.modules.iq.IQSecurityCallback;
 import org.olat.repository.RepositoryEntry;
 import org.olat.repository.RepositoryEntryImportExport;
 import org.olat.repository.RepositoryManager;
@@ -70,6 +71,7 @@ import org.olat.repository.handlers.RepositoryHandler;
 import org.olat.repository.handlers.RepositoryHandlerFactory;
 
 import de.bps.onyx.plugin.OnyxModule;
+import de.bps.onyx.plugin.run.OnyxRunController;
 
 /**
  * Initial Date: Feb 9, 2004
@@ -97,10 +99,8 @@ public class IQSELFCourseNode extends AbstractAccessableCourseNode implements Se
 	 */
 	@Override
 	public TabbableController createEditController(UserRequest ureq, WindowControl wControl, BreadcrumbPanel stackPanel, ICourse course, UserCourseEnvironment euce) {
-		
-		TabbableController childTabCntrllr = IQUIFactory.createIQSelftestEditController(ureq, wControl, stackPanel, course, this, course.getCourseEnvironment().getCourseGroupManager(), euce);
+		TabbableController childTabCntrllr = new IQEditController(ureq, wControl, stackPanel, course, this, euce);
 		CourseNode chosenNode = course.getEditorTreeModel().getCourseNode(euce.getCourseEditorEnv().getCurrentCourseNodeId());
-		
 		return new NodeEditController(ureq, wControl, course.getEditorTreeModel(), course, chosenNode, euce, childTabCntrllr);
 	}
 
@@ -114,9 +114,18 @@ public class IQSELFCourseNode extends AbstractAccessableCourseNode implements Se
 	public NodeRunConstructionResult createNodeRunConstructionResult(UserRequest ureq, WindowControl wControl,
 			UserCourseEnvironment userCourseEnv, NodeEvaluation ne, String nodecmd) {
 		
-		Controller runController = IQUIFactory.createIQSelftestRunController(ureq, wControl, userCourseEnv, this);
-		Controller ctrl = TitledWrapperHelper.getWrapper(ureq, wControl, runController, this, "o_iqself_icon");
+		Controller runController;
+		ModuleConfiguration config = getModuleConfiguration();
+		AssessmentManager am = userCourseEnv.getCourseEnvironment().getAssessmentManager();
+		boolean onyx = IQEditController.CONFIG_VALUE_QTI2.equals(config.get(IQEditController.CONFIG_KEY_TYPE_QTI));
+		if (onyx) {
+			runController = new OnyxRunController(userCourseEnv, config, ureq, wControl, this);
+		} else {
+			IQSecurityCallback sec = new CourseIQSecurityCallback(this, am, ureq.getIdentity());
+			runController = new IQRunController(userCourseEnv, getModuleConfiguration(), sec, ureq, wControl, this);
+		}
 		
+		Controller ctrl = TitledWrapperHelper.getWrapper(ureq, wControl, runController, this, "o_iqself_icon");
 		return new NodeRunConstructionResult(ctrl);
 	}
 
diff --git a/src/main/java/org/olat/course/nodes/IQSURVCourseNode.java b/src/main/java/org/olat/course/nodes/IQSURVCourseNode.java
index c920f3623d8faa898efa05774b8f0dbf598a1e86..1c7440b54d59c1be50a25e05d46807ca7dec9d82 100644
--- a/src/main/java/org/olat/course/nodes/IQSURVCourseNode.java
+++ b/src/main/java/org/olat/course/nodes/IQSURVCourseNode.java
@@ -37,22 +37,26 @@ import org.olat.core.gui.components.stack.BreadcrumbPanel;
 import org.olat.core.gui.components.stack.TooledStackedPanel;
 import org.olat.core.gui.control.Controller;
 import org.olat.core.gui.control.WindowControl;
+import org.olat.core.gui.control.generic.messages.MessageUIFactory;
 import org.olat.core.gui.control.generic.tabbable.TabbableController;
 import org.olat.core.gui.translator.PackageTranslator;
+import org.olat.core.gui.translator.Translator;
 import org.olat.core.id.Identity;
 import org.olat.core.id.OLATResourceable;
+import org.olat.core.id.Roles;
 import org.olat.core.logging.OLog;
 import org.olat.core.logging.Tracing;
 import org.olat.core.util.Util;
+import org.olat.core.util.coordinate.CoordinatorManager;
 import org.olat.core.util.resource.OresHelper;
 import org.olat.course.ICourse;
 import org.olat.course.assessment.AssessmentManager;
 import org.olat.course.editor.CourseEditorEnv;
 import org.olat.course.editor.NodeEditController;
 import org.olat.course.editor.StatusDescription;
+import org.olat.course.nodes.iq.CourseIQSecurityCallback;
 import org.olat.course.nodes.iq.IQEditController;
 import org.olat.course.nodes.iq.IQRunController;
-import org.olat.course.nodes.iq.IQUIFactory;
 import org.olat.course.properties.CoursePropertyManager;
 import org.olat.course.run.environment.CourseEnvironment;
 import org.olat.course.run.navigation.NodeRunConstructionResult;
@@ -71,12 +75,15 @@ import org.olat.ims.qti.statistics.QTIStatisticSearchParams;
 import org.olat.ims.qti.statistics.QTIType;
 import org.olat.ims.qti.statistics.ui.QTI12StatisticsToolController;
 import org.olat.modules.ModuleConfiguration;
+import org.olat.modules.iq.IQSecurityCallback;
 import org.olat.repository.RepositoryEntry;
 import org.olat.repository.RepositoryEntryImportExport;
 import org.olat.repository.RepositoryManager;
 import org.olat.repository.handlers.RepositoryHandler;
 import org.olat.repository.handlers.RepositoryHandlerFactory;
 
+import de.bps.onyx.plugin.run.OnyxRunController;
+
 /**
  * Initial Date: Feb 9, 2004
  * @author Mike Stock Comment:
@@ -105,7 +112,7 @@ public class IQSURVCourseNode extends AbstractAccessableCourseNode implements QT
 	 */
 	@Override
 	public TabbableController createEditController(UserRequest ureq, WindowControl wControl, BreadcrumbPanel stackPanel, ICourse course, UserCourseEnvironment euce) {
-		TabbableController childTabCntrllr = IQUIFactory.createIQSurveyEditController(ureq, wControl, stackPanel, course, this, course.getCourseEnvironment().getCourseGroupManager(), euce);
+		TabbableController childTabCntrllr = new IQEditController(ureq, wControl, stackPanel, course, this, euce);
 		CourseNode chosenNode = course.getEditorTreeModel().getCourseNode(euce.getCourseEditorEnv().getCurrentCourseNodeId());
 		return new NodeEditController(ureq, wControl, course.getEditorTreeModel(), course, chosenNode, euce, childTabCntrllr);
 	}
@@ -119,7 +126,39 @@ public class IQSURVCourseNode extends AbstractAccessableCourseNode implements QT
 	@Override
 	public NodeRunConstructionResult createNodeRunConstructionResult(UserRequest ureq, WindowControl wControl,
 			UserCourseEnvironment userCourseEnv, NodeEvaluation ne, String nodecmd) {
-		Controller controller = IQUIFactory.createIQSurveyRunController(ureq, wControl, userCourseEnv, this);
+
+		Controller controller;
+		// Do not allow guests to start questionnaires
+		Roles roles = ureq.getUserSession().getRoles();
+		if (roles.isGuestOnly()) {
+			Translator trans = Util.createPackageTranslator(IQSURVCourseNode.class, ureq.getLocale());
+			String title = trans.translate("guestnoaccess.title");
+			String message = trans.translate("guestnoaccess.message");
+			controller = MessageUIFactory.createInfoMessage(ureq, wControl, title, message);
+		} else {
+			ModuleConfiguration config = getModuleConfiguration();
+			boolean onyx = IQEditController.CONFIG_VALUE_QTI2.equals(config.get(IQEditController.CONFIG_KEY_TYPE_QTI));
+			if (onyx) {
+				controller = new OnyxRunController(userCourseEnv, config, ureq, wControl, this);
+			} else {
+				RepositoryEntry repositoryEntry = getReferencedRepositoryEntry();
+				OLATResourceable ores = repositoryEntry.getOlatResource();
+				Long resId = ores.getResourceableId();
+				SurveyFileResource fr = new SurveyFileResource();
+				fr.overrideResourceableId(resId);
+				if(!CoordinatorManager.getInstance().getCoordinator().getLocker().isLocked(fr, null)) {
+					AssessmentManager am = userCourseEnv.getCourseEnvironment().getAssessmentManager();
+					IQSecurityCallback sec = new CourseIQSecurityCallback(this, am, ureq.getIdentity());
+					controller = new IQRunController(userCourseEnv, getModuleConfiguration(), sec, ureq, wControl, this);
+				} else {
+					Translator trans = Util.createPackageTranslator(IQSURVCourseNode.class, ureq.getLocale());
+					String title = trans.translate("editor.lock.title");
+					String message = trans.translate("editor.lock.message");
+					controller = MessageUIFactory.createInfoMessage(ureq, wControl, title, message);
+				}
+			}
+		}
+		
 		Controller ctrl = TitledWrapperHelper.getWrapper(ureq, wControl, controller, this, "o_iqsurv_icon");
 		return new NodeRunConstructionResult(ctrl);
 	}
diff --git a/src/main/java/org/olat/course/nodes/IQTESTCourseNode.java b/src/main/java/org/olat/course/nodes/IQTESTCourseNode.java
index 0422a92067085903be62790591e8635b02882087..032f477c6656d48189b602def898055312368a1a 100644
--- a/src/main/java/org/olat/course/nodes/IQTESTCourseNode.java
+++ b/src/main/java/org/olat/course/nodes/IQTESTCourseNode.java
@@ -37,15 +37,18 @@ import org.olat.core.gui.components.stack.BreadcrumbPanel;
 import org.olat.core.gui.components.stack.TooledStackedPanel;
 import org.olat.core.gui.control.Controller;
 import org.olat.core.gui.control.WindowControl;
+import org.olat.core.gui.control.generic.messages.MessageUIFactory;
 import org.olat.core.gui.control.generic.tabbable.TabbableController;
 import org.olat.core.gui.translator.Translator;
 import org.olat.core.id.Identity;
 import org.olat.core.id.OLATResourceable;
+import org.olat.core.id.Roles;
 import org.olat.core.logging.DBRuntimeException;
 import org.olat.core.logging.KnownIssueException;
 import org.olat.core.logging.OLog;
 import org.olat.core.logging.Tracing;
 import org.olat.core.util.Util;
+import org.olat.core.util.coordinate.CoordinatorManager;
 import org.olat.core.util.resource.OresHelper;
 import org.olat.course.ICourse;
 import org.olat.course.assessment.AssessmentManager;
@@ -53,9 +56,12 @@ import org.olat.course.auditing.UserNodeAuditManager;
 import org.olat.course.editor.CourseEditorEnv;
 import org.olat.course.editor.NodeEditController;
 import org.olat.course.editor.StatusDescription;
+import org.olat.course.nodes.iq.CourseIQSecurityCallback;
 import org.olat.course.nodes.iq.IQEditController;
+import org.olat.course.nodes.iq.IQPreviewController;
 import org.olat.course.nodes.iq.IQRunController;
-import org.olat.course.nodes.iq.IQUIFactory;
+import org.olat.course.nodes.iq.QTI21AssessmentDetailsController;
+import org.olat.course.nodes.iq.QTI21AssessmentRunController;
 import org.olat.course.properties.CoursePropertyManager;
 import org.olat.course.run.environment.CourseEnvironment;
 import org.olat.course.run.navigation.NodeRunConstructionResult;
@@ -64,6 +70,7 @@ import org.olat.course.run.userview.NodeEvaluation;
 import org.olat.course.run.userview.UserCourseEnvironment;
 import org.olat.course.statistic.StatisticResourceOption;
 import org.olat.course.statistic.StatisticResourceResult;
+import org.olat.fileresource.types.ImsQTI21Resource;
 import org.olat.ims.qti.QTI12ResultDetailsController;
 import org.olat.ims.qti.QTIResultManager;
 import org.olat.ims.qti.QTIResultSet;
@@ -77,15 +84,18 @@ import org.olat.ims.qti.statistics.QTIStatisticSearchParams;
 import org.olat.ims.qti.statistics.QTIType;
 import org.olat.ims.qti.statistics.ui.QTI12StatisticsToolController;
 import org.olat.modules.ModuleConfiguration;
+import org.olat.modules.iq.IQSecurityCallback;
 import org.olat.repository.RepositoryEntry;
 import org.olat.repository.RepositoryEntryImportExport;
 import org.olat.repository.RepositoryManager;
 import org.olat.repository.handlers.RepositoryHandler;
 import org.olat.repository.handlers.RepositoryHandlerFactory;
+import org.olat.resource.OLATResource;
 
 import de.bps.ims.qti.QTIResultDetailsController;
 import de.bps.onyx.plugin.OnyxExportManager;
 import de.bps.onyx.plugin.OnyxModule;
+import de.bps.onyx.plugin.run.OnyxRunController;
 
 /**
  * Initial Date: Feb 9, 2004
@@ -111,22 +121,51 @@ public class IQTESTCourseNode extends AbstractAccessableCourseNode implements As
 	@Override
 	public TabbableController createEditController(UserRequest ureq, WindowControl wControl, BreadcrumbPanel stackPanel, ICourse course, UserCourseEnvironment euce) {
 		updateModuleConfigDefaults(false);
-		TabbableController childTabCntrllr = IQUIFactory.createIQTestEditController(ureq, wControl, stackPanel, course, this, course.getCourseEnvironment().getCourseGroupManager(), euce); 
+		TabbableController childTabCntrllr = new IQEditController(ureq, wControl, stackPanel, course, this, euce);
 		CourseNode chosenNode = course.getEditorTreeModel().getCourseNode(euce.getCourseEditorEnv().getCurrentCourseNodeId());
 		return new NodeEditController(ureq, wControl, course.getEditorTreeModel(), course, chosenNode, euce, childTabCntrllr);
 	}
 
-	/**
-	 * @see org.olat.course.nodes.CourseNode#createNodeRunConstructionResult(org.olat.core.gui.UserRequest,
-	 *      org.olat.core.gui.control.WindowControl,
-	 *      org.olat.course.run.userview.UserCourseEnvironment,
-	 *      org.olat.course.run.userview.NodeEvaluation)
-	 */
 	@Override
 	public NodeRunConstructionResult createNodeRunConstructionResult(UserRequest ureq, WindowControl wControl,
 			UserCourseEnvironment userCourseEnv, NodeEvaluation ne, String nodecmd) {
 		updateModuleConfigDefaults(false);		
-		Controller controller = IQUIFactory.createIQTestRunController(ureq, wControl, userCourseEnv, this);
+		
+		Controller controller;
+		// Do not allow guests to start tests
+		Roles roles = ureq.getUserSession().getRoles();
+		Translator trans = Util.createPackageTranslator(IQTESTCourseNode.class, ureq.getLocale());
+		if (roles.isGuestOnly()) {
+			String title = trans.translate("guestnoaccess.title");
+			String message = trans.translate("guestnoaccess.message");
+			controller = MessageUIFactory.createInfoMessage(ureq, wControl, title, message);
+		} else {
+			ModuleConfiguration config = getModuleConfiguration();
+			boolean onyx = IQEditController.CONFIG_VALUE_QTI2.equals(config.get(IQEditController.CONFIG_KEY_TYPE_QTI));
+			if (onyx) {
+				controller = new OnyxRunController(userCourseEnv, config, ureq, wControl, this);
+			} else {
+				RepositoryEntry repositoryEntry = getReferencedRepositoryEntry();
+				OLATResource ores = repositoryEntry.getOlatResource();
+				if(ImsQTI21Resource.TYPE_NAME.equals(ores.getResourceableTypeName())) {
+					//QTI 2.1
+					controller = new QTI21AssessmentRunController(ureq, wControl, userCourseEnv, this);
+				} else {
+					//QTI 1.2
+					TestFileResource fr = new TestFileResource();
+					fr.overrideResourceableId(ores.getResourceableId());
+					if(!CoordinatorManager.getInstance().getCoordinator().getLocker().isLocked(fr, null)) {
+						AssessmentManager am = userCourseEnv.getCourseEnvironment().getAssessmentManager();
+						IQSecurityCallback sec = new CourseIQSecurityCallback(this, am, ureq.getIdentity());
+						controller = new IQRunController(userCourseEnv, getModuleConfiguration(), sec, ureq, wControl, this);
+					} else {
+						String title = trans.translate("editor.lock.title");
+						String message = trans.translate("editor.lock.message");
+						controller = MessageUIFactory.createInfoMessage(ureq, wControl, title, message);
+					}
+				}
+			}
+		}
 		Controller ctrl = TitledWrapperHelper.getWrapper(ureq, wControl, controller, this, "o_iqtest_icon");
 		return new NodeRunConstructionResult(ctrl);
 	}
@@ -139,7 +178,15 @@ public class IQTESTCourseNode extends AbstractAccessableCourseNode implements As
 	 */
 	@Override
 	public Controller createPreviewController(UserRequest ureq, WindowControl wControl, UserCourseEnvironment userCourseEnv, NodeEvaluation ne) {
-		return IQUIFactory.createIQTestPreviewController(ureq, wControl, userCourseEnv, this);
+		Controller controller;
+		ModuleConfiguration config = getModuleConfiguration();
+		boolean onyx = IQEditController.CONFIG_VALUE_QTI2.equals(config.get(IQEditController.CONFIG_KEY_TYPE_QTI));
+		if (onyx) {
+			controller = new OnyxRunController(ureq, wControl, this);
+		} else {
+			controller = new IQPreviewController(ureq, wControl, userCourseEnv, this);
+		}
+		return controller;
 	}
 
 	@Override
@@ -159,9 +206,7 @@ public class IQTESTCourseNode extends AbstractAccessableCourseNode implements As
 		OLATResourceable courseOres = OresHelper.createOLATResourceableInstance("CourseModule", courseId);
 		QTIStatisticSearchParams searchParams = new QTIStatisticSearchParams(courseOres.getResourceableId(), getIdent());
 		searchParams.setLimitToGroups(options.getParticipantsGroups());
-
-		QTIStatisticResourceResult result = new QTIStatisticResourceResult(courseOres, this, searchParams);
-		return result;
+		return new QTIStatisticResourceResult(courseOres, this, searchParams);
 	}
 	
 	@Override
@@ -174,7 +219,7 @@ public class IQTESTCourseNode extends AbstractAccessableCourseNode implements As
 		if(types.length == 0 || (types.length == 1 && types[0] == null)) return true;
 		
 		for(QTIType type:types) {
-			if(QTIType.test.equals(type) || QTIType.onyx.equals(type)) {
+			if(QTIType.test.equals(type) || QTIType.onyx.equals(type) || QTIType.qtiworks.equals(type)) {
 				return true;
 			}
 		}
@@ -557,15 +602,22 @@ public class IQTESTCourseNode extends AbstractAccessableCourseNode implements As
 	 */
 	@Override
 	public Controller getDetailsEditController(UserRequest ureq, WindowControl wControl, BreadcrumbPanel stackPanel, UserCourseEnvironment userCourseEnvironment) {
+		Controller detailsCtrl = null;
 		RepositoryEntry ref = getReferencedRepositoryEntry();
-		Long courseResourceableId = userCourseEnvironment.getCourseEnvironment().getCourseResourceableId();
-		Identity assessedIdentity = userCourseEnvironment.getIdentityEnvironment().getIdentity();
-		boolean onyx = OnyxModule.isOnyxTest(ref.getOlatResource());
-		if(onyx) {
-			return new QTIResultDetailsController(courseResourceableId, getIdent(), assessedIdentity, ref, AssessmentInstance.QMD_ENTRY_TYPE_ASSESS, ureq, wControl);
-		} else {
-			return new QTI12ResultDetailsController(ureq, wControl, courseResourceableId, getIdent(), assessedIdentity, ref, AssessmentInstance.QMD_ENTRY_TYPE_ASSESS);
+		if(ref != null) {
+			OLATResource resource = ref.getOlatResource();
+			Long courseResourceableId = userCourseEnvironment.getCourseEnvironment().getCourseResourceableId();
+			Identity assessedIdentity = userCourseEnvironment.getIdentityEnvironment().getIdentity();
+			
+			if(ImsQTI21Resource.TYPE_NAME.equals(resource.getResourceableTypeName())) {
+				detailsCtrl = new QTI21AssessmentDetailsController(ureq, wControl, userCourseEnvironment, this);
+			} else if(OnyxModule.isOnyxTest(ref.getOlatResource())) {
+				detailsCtrl =  new QTIResultDetailsController(courseResourceableId, getIdent(), assessedIdentity, ref, AssessmentInstance.QMD_ENTRY_TYPE_ASSESS, ureq, wControl);
+			} else {
+				detailsCtrl = new QTI12ResultDetailsController(ureq, wControl, courseResourceableId, getIdent(), assessedIdentity, ref, AssessmentInstance.QMD_ENTRY_TYPE_ASSESS);
+			}	
 		}
+		return detailsCtrl;
 	}
 
 	/**
diff --git a/src/main/java/org/olat/course/nodes/QTI21AssessmentCourseNode.java b/src/main/java/org/olat/course/nodes/QTI21AssessmentCourseNode.java
deleted file mode 100644
index ff6881d575a555b2e7ec30cbeece92919a36eb11..0000000000000000000000000000000000000000
--- a/src/main/java/org/olat/course/nodes/QTI21AssessmentCourseNode.java
+++ /dev/null
@@ -1,371 +0,0 @@
-/**
- * <a href="http://www.openolat.org">
- * OpenOLAT - Online Learning and Training</a><br>
- * <p>
- * Licensed under the Apache License, Version 2.0 (the "License"); <br>
- * you may not use this file except in compliance with the License.<br>
- * You may obtain a copy of the License at the
- * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a>
- * <p>
- * Unless required by applicable law or agreed to in writing,<br>
- * software distributed under the License is distributed on an "AS IS" BASIS, <br>
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br>
- * See the License for the specific language governing permissions and <br>
- * limitations under the License.
- * <p>
- * Initial code contributed and copyrighted by<br>
- * frentix GmbH, http://www.frentix.com
- * <p>
- */
-package org.olat.course.nodes;
-
-import java.io.File;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Locale;
-import java.util.zip.ZipOutputStream;
-
-import org.olat.core.CoreSpringFactory;
-import org.olat.core.gui.UserRequest;
-import org.olat.core.gui.components.stack.BreadcrumbPanel;
-import org.olat.core.gui.control.Controller;
-import org.olat.core.gui.control.WindowControl;
-import org.olat.core.gui.control.generic.messages.MessageUIFactory;
-import org.olat.core.gui.control.generic.tabbable.TabbableController;
-import org.olat.core.gui.translator.Translator;
-import org.olat.core.id.Identity;
-import org.olat.core.id.Roles;
-import org.olat.core.logging.OLATRuntimeException;
-import org.olat.core.util.StringHelper;
-import org.olat.core.util.Util;
-import org.olat.course.ICourse;
-import org.olat.course.assessment.AssessmentManager;
-import org.olat.course.auditing.UserNodeAuditManager;
-import org.olat.course.editor.CourseEditorEnv;
-import org.olat.course.editor.NodeEditController;
-import org.olat.course.editor.StatusDescription;
-import org.olat.course.nodes.qti21.QTI21AssessmentDetailsController;
-import org.olat.course.nodes.qti21.QTI21AssessmentRunController;
-import org.olat.course.nodes.qti21.QTI21EditController;
-import org.olat.course.run.navigation.NodeRunConstructionResult;
-import org.olat.course.run.scoring.ScoreEvaluation;
-import org.olat.course.run.userview.NodeEvaluation;
-import org.olat.course.run.userview.UserCourseEnvironment;
-import org.olat.modules.ModuleConfiguration;
-import org.olat.repository.RepositoryEntry;
-import org.olat.repository.RepositoryManager;
-
-/**
- * 
- * Initial date: 19.05.2015<br>
- * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
- *
- */
-public class QTI21AssessmentCourseNode extends AbstractAccessableCourseNode implements AssessableCourseNode {
-
-	private static final long serialVersionUID = -3619170190576867622L;
-	private final static String PACKAGE_QTI21 = Util.getPackageName(QTI21EditController.class);
-	
-	public static final String CONFIG_KEY_REPOSITORY_SOFTKEY = "repoSoftkey";
-	public static final String CONFIG_KEY_ENABLESCOREINFO = "enableScoreInfo";
-	public static final String CONFIG_KEY_BLOCK_AFTER_SUCCESS = "blockAfterSuccess";
-	public final static String CONFIG_FULLWINDOW = "fullwindow";
-	
-	public static final String CONFIG_KEY_MINSCORE = "minscore";
-	public static final String CONFIG_KEY_MAXSCORE = "maxscore";
-	public static final String CONFIG_KEY_CUTVALUE = "cutvalue";
-	public static final String CONFIG_KEY_ATTEMPTS = "attempts";
-	
-	
-	public static final String TYPE = "qti21assessment";
-	private static final int CURRENT_CONFIG_VERSION = 1;
-
-	public QTI21AssessmentCourseNode() {
-		super(TYPE);
-		updateModuleConfigDefaults(true);
-	}
-	
-	@Override
-	public boolean needsReferenceToARepositoryEntry() {
-		return true;
-	}
-	
-	@Override
-	public RepositoryEntry getReferencedRepositoryEntry() {
-		String repoSoftkey = getModuleConfiguration().getStringValue(CONFIG_KEY_REPOSITORY_SOFTKEY);
-		if (repoSoftkey == null) {
-			return null;
-		}
-		return CoreSpringFactory.getImpl(RepositoryManager.class)
-				.lookupRepositoryEntryBySoftkey(repoSoftkey, false);
-	}
-	
-	@Override
-	public void updateModuleConfigDefaults(boolean isNewNode) {
-		ModuleConfiguration config = getModuleConfiguration();
-		if(isNewNode) {
-			//setup default configuration:
-			//layout
-			config.set(QTI21AssessmentCourseNode.CONFIG_FULLWINDOW, Boolean.TRUE);
-			
-			//configure grading
-			config.set(MSCourseNode.CONFIG_KEY_HAS_SCORE_FIELD, Boolean.FALSE);
-			config.set(MSCourseNode.CONFIG_KEY_SCORE_MIN, new Float(0));
-			config.set(MSCourseNode.CONFIG_KEY_SCORE_MAX, new Float(0));
-			config.set(MSCourseNode.CONFIG_KEY_HAS_PASSED_FIELD, Boolean.TRUE);
-			
-			config.setConfigurationVersion(CURRENT_CONFIG_VERSION);
-		} else {
-			config.setConfigurationVersion(CURRENT_CONFIG_VERSION);
-		}
-	}
-
-	@Override
-	public StatusDescription isConfigValid() {
-		if (oneClickStatusCache != null && oneClickStatusCache.length > 0) {
-			return oneClickStatusCache[0];
-		}
-		
-		List<StatusDescription> statusDescs = validateInternalConfiguration(null);
-		if(statusDescs.isEmpty()) {
-			statusDescs.add(StatusDescription.NOERROR);
-		}
-		oneClickStatusCache = StatusDescriptionHelper.sort(statusDescs);
-		return oneClickStatusCache[0];
-	}
-	
-	@Override
-	public StatusDescription[] isConfigValid(CourseEditorEnv cev) {
-		oneClickStatusCache = null;//delete the cache
-		
-		List<StatusDescription> sds = isConfigValidWithTranslator(cev, PACKAGE_QTI21, getConditionExpressions());
-		if(oneClickStatusCache != null && oneClickStatusCache.length > 0) {
-			//isConfigValidWithTranslator add first
-			sds.remove(oneClickStatusCache[0]);
-		}
-		sds.addAll(validateInternalConfiguration(cev));
-		oneClickStatusCache = StatusDescriptionHelper.sort(sds);
-		return oneClickStatusCache;
-	}
-	
-	private List<StatusDescription> validateInternalConfiguration(CourseEditorEnv cev) {
-		List<StatusDescription> sdList = new ArrayList<>(5);
-
-		ModuleConfiguration config = getModuleConfiguration();
-		
-		String repoEntrySoftKey = config.getStringValue(CONFIG_KEY_REPOSITORY_SOFTKEY);
-		if(!StringHelper.containsNonWhitespace(repoEntrySoftKey)) {
-			addStatusErrorDescription("error.missing.score.config", QTI21EditController.PANE_TAB_CONFIG_RE, sdList);
-		}
-		
-		return sdList;
-	}
-	
-	private void addStatusErrorDescription(String key, String pane, List<StatusDescription> status) {
-		String[] params = new String[] { getShortTitle() };
-		StatusDescription sd = new StatusDescription(StatusDescription.ERROR, key, key, params, PACKAGE_QTI21);
-		sd.setDescriptionForUnit(getIdent());
-		sd.setActivateableViewIdentifier(pane);
-		status.add(sd);
-	}
-	
-	@Override
-	public void exportNode(File fExportDirectory, ICourse course) {
-		super.exportNode(fExportDirectory, course);
-	}
-	
-	@Override
-	public void importNode(File importDirectory, ICourse course, Identity owner, Locale locale, boolean withReferences) {
-		super.importNode(importDirectory, course, owner, locale, withReferences);
-	}
-
-	@Override
-	public CourseNode createInstanceForCopy(boolean isNewTitle, ICourse course) {
-		return super.createInstanceForCopy(isNewTitle, course);
-	}
-	
-	@Override
-	public boolean archiveNodeData(Locale locale, ICourse course, ArchiveOptions options, ZipOutputStream exportStream, String charset) {
-		return super.archiveNodeData(locale, course, options, exportStream, charset);
-	}
-
-	@Override
-	public void cleanupOnDelete(ICourse course) {
-		super.cleanupOnDelete(course);
-	}
-	
-	@Override
-	public boolean hasStatusConfigured() {
-		return false;
-	}
-
-	@Override
-	public Float getMaxScoreConfiguration() {
-		if (!hasScoreConfigured()) {
-			throw new OLATRuntimeException(QTI21AssessmentCourseNode.class, "getMaxScore not defined when hasScore set to false", null);
-		}
-		return getModuleConfiguration().getFloatEntry(MSCourseNode.CONFIG_KEY_SCORE_MAX);
-	}
-
-	@Override
-	public Float getMinScoreConfiguration() {
-		return getModuleConfiguration().getFloatEntry(MSCourseNode.CONFIG_KEY_SCORE_MIN);
-	}
-
-	@Override
-	public Float getCutValueConfiguration() {
-		return getModuleConfiguration().getFloatEntry(MSCourseNode.CONFIG_KEY_PASSED_CUT_VALUE);
-	}
-
-	@Override
-	public boolean hasScoreConfigured() {
-		return true;
-	}
-
-	@Override
-	public boolean hasPassedConfigured() {
-		return true;
-	}
-
-	@Override
-	public boolean hasCommentConfigured() {
-		return true;
-	}
-
-	@Override
-	public boolean hasAttemptsConfigured() {
-		return true;
-	}
-
-	@Override
-	public boolean hasDetails() {
-		return true;
-	}
-
-	@Override
-	public boolean isEditableConfigured() {
-		return true;
-	}
-	
-	@Override
-	public TabbableController createEditController(UserRequest ureq, WindowControl wControl, BreadcrumbPanel stackPanel,
-			ICourse course, UserCourseEnvironment euce) {
-		QTI21EditController editCtrl = new QTI21EditController(ureq, wControl, stackPanel, this, course, euce);
-		CourseNode chosenNode = course.getEditorTreeModel().getCourseNode(euce.getCourseEditorEnv().getCurrentCourseNodeId());
-		return new NodeEditController(ureq, wControl, course.getEditorTreeModel(), course, chosenNode, euce, editCtrl);
-	}
-	
-	@Override
-	public NodeRunConstructionResult createNodeRunConstructionResult(UserRequest ureq, WindowControl wControl,
-			UserCourseEnvironment userCourseEnv, NodeEvaluation ne, String nodecmd) {
-		updateModuleConfigDefaults(false);
-		Controller controller;
-		// Do not allow guests to start tests
-		Roles roles = ureq.getUserSession().getRoles();
-		Translator trans = Util.createPackageTranslator(QTI21AssessmentCourseNode.class, ureq.getLocale());
-		if (roles.isGuestOnly()) {
-			String title = trans.translate("guestnoaccess.title");
-			String message = trans.translate("guestnoaccess.message");
-			controller = MessageUIFactory.createInfoMessage(ureq, wControl, title, message);
-		} else {
-			controller = new QTI21AssessmentRunController(ureq, wControl, userCourseEnv, this);
-		}
-		Controller ctrl = TitledWrapperHelper.getWrapper(ureq, wControl, controller, this, "o_qtiassessment_icon");
-		return new NodeRunConstructionResult(ctrl);
-	}
-	
-	@Override
-	public String getDetailsListViewHeaderKey() {
-		return "table.header.details.qti21test";
-	}
-
-	@Override
-	public String getDetailsListView(UserCourseEnvironment userCourseEnvironment) {
-		return "";
-	}
-	
-	@Override
-	public Controller getDetailsEditController(UserRequest ureq, WindowControl wControl,
-			BreadcrumbPanel stackPanel, UserCourseEnvironment userCourseEnvironment) {
-		return new QTI21AssessmentDetailsController(ureq, wControl, userCourseEnvironment, this);
-	}
-
-	@Override
-	public ScoreEvaluation getUserScoreEvaluation(UserCourseEnvironment userCourseEnv) {
-		// read score from properties save score, passed and attempts information
-		AssessmentManager am = userCourseEnv.getCourseEnvironment().getAssessmentManager();
-		Identity mySelf = userCourseEnv.getIdentityEnvironment().getIdentity();
-		Boolean passed = am.getNodePassed(this, mySelf);
-		Float score = am.getNodeScore(this, mySelf);		
-		Long assessmentID = am.getAssessmentID(this, mySelf);	
-		Boolean fullyAssessed = am.getNodeFullyAssessed(this, mySelf);	
-		return new ScoreEvaluation(score, passed, fullyAssessed, assessmentID);
-	}
-
-	@Override
-	public String getUserUserComment(UserCourseEnvironment userCourseEnv) {
-		AssessmentManager am = userCourseEnv.getCourseEnvironment().getAssessmentManager();
-		return am.getNodeComment(this, userCourseEnv.getIdentityEnvironment().getIdentity());
-	}
-
-	@Override
-	public String getUserCoachComment(UserCourseEnvironment userCourseEnv) {
-		AssessmentManager am = userCourseEnv.getCourseEnvironment().getAssessmentManager();
-		return am.getNodeCoachComment(this, userCourseEnv.getIdentityEnvironment().getIdentity());
-	}
-
-	@Override
-	public String getUserLog(UserCourseEnvironment userCourseEnv) {
-		UserNodeAuditManager am = userCourseEnv.getCourseEnvironment().getAuditManager();
-		return am.getUserNodeLog(this, userCourseEnv.getIdentityEnvironment().getIdentity());
-	}
-
-	@Override
-	public Integer getUserAttempts(UserCourseEnvironment userCourseEnv) {
-		AssessmentManager am = userCourseEnv.getCourseEnvironment().getAssessmentManager();
-		Identity assessedIdentity = userCourseEnv.getIdentityEnvironment().getIdentity();
-		return am.getNodeAttempts(this, assessedIdentity);
-	}
-
-	@Override
-	public void updateUserScoreEvaluation(ScoreEvaluation scoreEvaluation, UserCourseEnvironment userCourseEnv,
-			Identity coachingIdentity, boolean incrementAttempts) {
-		AssessmentManager am = userCourseEnv.getCourseEnvironment().getAssessmentManager();
-		Identity assessedIdentity = userCourseEnv.getIdentityEnvironment().getIdentity();
-		am.saveScoreEvaluation(this, coachingIdentity, assessedIdentity, new ScoreEvaluation(scoreEvaluation.getScore(), scoreEvaluation.getPassed()), userCourseEnv, incrementAttempts);
-	}
-
-	@Override
-	public void updateUserUserComment(String userComment, UserCourseEnvironment userCourseEnv, Identity coachingIdentity) {
-		AssessmentManager am = userCourseEnv.getCourseEnvironment().getAssessmentManager();
-		Identity assessedIdentity = userCourseEnv.getIdentityEnvironment().getIdentity();
-		if (userComment != null) {
-			am.saveNodeComment(this, coachingIdentity, assessedIdentity, userComment);
-		}
-	}
-
-	@Override
-	public void incrementUserAttempts(UserCourseEnvironment userCourseEnv) {
-		AssessmentManager am = userCourseEnv.getCourseEnvironment().getAssessmentManager();
-		Identity assessedIdentity = userCourseEnv.getIdentityEnvironment().getIdentity();
-		am.incrementNodeAttempts(this, assessedIdentity, userCourseEnv);
-	}
-
-	@Override
-	public void updateUserAttempts(Integer userAttempts, UserCourseEnvironment userCourseEnv, Identity coachingIdentity) {
-		if (userAttempts != null) {
-			AssessmentManager am = userCourseEnv.getCourseEnvironment().getAssessmentManager();
-			Identity assessedIdentity = userCourseEnv.getIdentityEnvironment().getIdentity();
-			am.saveNodeAttempts(this, coachingIdentity, assessedIdentity, userAttempts);
-		}
-	}
-
-	@Override
-	public void updateUserCoachComment(String coachComment, UserCourseEnvironment userCourseEnv) {
-		AssessmentManager am = userCourseEnv.getCourseEnvironment().getAssessmentManager();
-		Identity assessedIdentity = userCourseEnv.getIdentityEnvironment().getIdentity();
-		if (coachComment != null) {
-			am.saveNodeCoachComment(this, assessedIdentity, coachComment);
-		}
-	}
-}
\ No newline at end of file
diff --git a/src/main/java/org/olat/course/nodes/_spring/buildingblockContext.xml b/src/main/java/org/olat/course/nodes/_spring/buildingblockContext.xml
index 34290197de561b2f024a65fa967e938cb1c07bea..c60b1cccb5877a091a40ff8cdc29e2ac634da60a 100644
--- a/src/main/java/org/olat/course/nodes/_spring/buildingblockContext.xml
+++ b/src/main/java/org/olat/course/nodes/_spring/buildingblockContext.xml
@@ -126,8 +126,4 @@
 		<property name="order" value="210" />
 	</bean>
 	
-	<bean id="qti21test" class="org.olat.course.nodes.qti21.QTI21AssessmentCourseNodeConfiguration" scope="prototype" >
-		<property name="order" value="210" />
-	</bean>
-	
 </beans>
\ No newline at end of file
diff --git a/src/main/java/org/olat/course/nodes/iq/IQ12EditForm.java b/src/main/java/org/olat/course/nodes/iq/IQ12EditForm.java
index 31c3d82aa1c6df62b514eb57479fc6b6fd5d16fd..ebdc371f2d05bcc3a3ee6be89b2211ece674e48c 100644
--- a/src/main/java/org/olat/course/nodes/iq/IQ12EditForm.java
+++ b/src/main/java/org/olat/course/nodes/iq/IQ12EditForm.java
@@ -120,7 +120,6 @@ public class IQ12EditForm extends FormBasicController {
 	}
 	
 	protected boolean validateFormLogic (UserRequest ureq) {
-
 		startDateElement.clearError();
 		endDateElement.clearError();
 		
@@ -153,6 +152,42 @@ public class IQ12EditForm extends FormBasicController {
 	
 	@Override
 	protected void formOK(UserRequest ureq) {
+		modConfig.set(IQEditController.CONFIG_KEY_DISPLAYMENU, new Boolean(isDisplayMenu()));
+		modConfig.set(IQEditController.CONFIG_FULLWINDOW, new Boolean(isFullWindow()));
+		
+		if (isDisplayMenu()) {
+			modConfig.set(IQEditController.CONFIG_KEY_RENDERMENUOPTION, isMenuRenderSectionsOnly());
+			modConfig.set(IQEditController.CONFIG_KEY_ENABLEMENU, new Boolean(isEnableMenu()));
+		} else {
+			// set default values when menu is not displayed
+			modConfig.set(IQEditController.CONFIG_KEY_RENDERMENUOPTION, Boolean.FALSE);
+			modConfig.set(IQEditController.CONFIG_KEY_ENABLEMENU, Boolean.FALSE); 
+		}
+		
+		modConfig.set(IQEditController.CONFIG_KEY_QUESTIONPROGRESS, new Boolean(isDisplayQuestionProgress()));
+		modConfig.set(IQEditController.CONFIG_KEY_SEQUENCE, getSequence());
+		modConfig.set(IQEditController.CONFIG_KEY_ENABLECANCEL, new Boolean(isEnableCancel()));
+		modConfig.set(IQEditController.CONFIG_KEY_ENABLESUSPEND, new Boolean(isEnableSuspend()));
+		modConfig.set(IQEditController.CONFIG_KEY_QUESTIONTITLE, new Boolean(isDisplayQuestionTitle()));
+		modConfig.set(IQEditController.CONFIG_KEY_AUTOENUM_CHOICES, new Boolean(isAutoEnumChoices()));
+		modConfig.set(IQEditController.CONFIG_KEY_MEMO, new Boolean(isProvideMemoField()));
+		// Only tests and selftests have summaries and score progress
+		if (!isSurvey) {
+			modConfig.set(IQEditController.CONFIG_KEY_SUMMARY, getSummary());
+			modConfig.set(IQEditController.CONFIG_KEY_SCOREPROGRESS, new Boolean(isDisplayScoreProgress()));
+			modConfig.set(IQEditController.CONFIG_KEY_ENABLESCOREINFO, new Boolean(isEnableScoreInfo()));
+			modConfig.set(IQEditController.CONFIG_KEY_DATE_DEPENDENT_RESULTS, new Boolean(isShowResultsDateDependent()));
+			modConfig.set(IQEditController.CONFIG_KEY_RESULTS_START_DATE, getShowResultsStartDate());
+			modConfig.set(IQEditController.CONFIG_KEY_RESULTS_END_DATE, getShowResultsEndDate());
+			modConfig.set(IQEditController.CONFIG_KEY_RESULT_ON_FINISH, isShowResultsAfterFinishTest());
+			modConfig.set(IQEditController.CONFIG_KEY_RESULT_ON_HOME_PAGE, isShowResultsOnHomePage());
+		}
+		// Only tests have a limitation on number of attempts
+		if (isAssessment) {
+			modConfig.set(IQEditController.CONFIG_KEY_ATTEMPTS, getAttempts());
+			modConfig.set(IQEditController.CONFIG_KEY_BLOCK_AFTER_SUCCESS, new Boolean(isBlockAfterSuccess()));
+		}
+		
 		fireEvent(ureq, Event.DONE_EVENT);
 	}
 
@@ -428,65 +463,72 @@ public class IQ12EditForm extends FormBasicController {
 		flc.setDirty(true);
 	}
 	
+	private boolean isDisplayMenu() {
+		return displayMenu.isSelected(0);
+	}
 	
 	/**
 	 * @return true: menu is enabled
 	 */
-	boolean isEnableMenu() { return enableMenu.isSelected(0); }
-	/**
-	 * @return true: menu should be displayed
-	 */
-	boolean isDisplayMenu() { return displayMenu.isSelected(0); }
+	private boolean isEnableMenu() {
+		return enableMenu.isSelected(0);
+	}
+
 	/**
 	 * @return true: menu should be displayed
 	 */
-	boolean isFullWindow() { return fullWindowEl.isSelected(0); }
+	private boolean isFullWindow() {
+		return fullWindowEl.isSelected(0);
+	}
 	
 	/**
 	 * @return true: score progress is enabled
 	 */
-	boolean isDisplayScoreProgress() { return displayScoreProgress.isSelected(0); }
+	private boolean isDisplayScoreProgress() {
+		return displayScoreProgress.isSelected(0);
+	}
+	
 	/**
 	 * @return true: score progress is enabled
 	 */
-	boolean isDisplayQuestionProgress() { return displayQuestionProgress.isSelected(0); }
+	private boolean isDisplayQuestionProgress() { return displayQuestionProgress.isSelected(0); }
 	/**
 	 * @return true: question title is enabled
 	 */
-	boolean isDisplayQuestionTitle() { return displayQuestionTitle.isSelected(0); }
+	private boolean isDisplayQuestionTitle() { return displayQuestionTitle.isSelected(0); }
 	/**
 	 * @return true: automatic enumeration of choice options enabled 
 	 */
-	boolean isAutoEnumChoices() { return autoEnumerateChoices.isSelected(0); }
+	private boolean isAutoEnumChoices() { return autoEnumerateChoices.isSelected(0); }
 	/**
 	 * @return true: provide memo field
 	 */
-	boolean isProvideMemoField() { return provideMemoField.isSelected(0); }
+	private boolean isProvideMemoField() { return provideMemoField.isSelected(0); }
 	/**
 	 * @return sequence configuration: section or item
 	 */
-	String getSequence() { return sequence.getSelectedKey(); }
+	private String getSequence() { return sequence.getSelectedKey(); }
 	/**
 	 * @return true: cancel is enabled
 	 */
-	boolean isEnableCancel() { return enableCancel.isSelected(0); }
+	private boolean isEnableCancel() { return enableCancel.isSelected(0); }
 	/**
 	 * @return true: suspend is enabled
 	 */
-	boolean isEnableSuspend() { return enableSuspend.isSelected(0); }
+	private boolean isEnableSuspend() { return enableSuspend.isSelected(0); }
 	/**
 	 * @return summary type: compact or detailed
 	 */
-	String getSummary() { return summary.getSelectedKey();}
+	private String getSummary() { return summary.getSelectedKey();}
 	/**
 	 * @return number of max attempts
 	 */
-	Integer getAttempts() { 
+	private Integer getAttempts() { 
 		Integer a =  attempts.getIntValue();
 		return a == 0 ? null : attempts.getIntValue();
 	}
 	
-	boolean isBlockAfterSuccess() {
+	private boolean isBlockAfterSuccess() {
 		return blockAfterSuccess.isSelected(0);
 	}
 	
@@ -494,41 +536,41 @@ public class IQ12EditForm extends FormBasicController {
 	 * 
 	 * @return true if only section title should be rendered
 	 */
-	Boolean isMenuRenderSectionsOnly() {	return Boolean.valueOf(menuRenderOptions.getSelectedKey());}
+	private Boolean isMenuRenderSectionsOnly() {	return Boolean.valueOf(menuRenderOptions.getSelectedKey());}
 	/**
 	 * @return true: score-info on start-page is enabled
 	 */
-	boolean isEnableScoreInfo() { return scoreInfo.isSelected(0); }	
+	private boolean isEnableScoreInfo() { return scoreInfo.isSelected(0); }	
 	
 	/**
 	 * 
 	 * @return true is the results are shown date dependent
 	 */
-	boolean isShowResultsDateDependent() { return showResultsDateDependentButton.isSelected(0); }
+	private boolean isShowResultsDateDependent() { return showResultsDateDependentButton.isSelected(0); }
 	
 	/**
 	 * 
 	 * @return Returns the start date for the result visibility.
 	 */
-	Date getShowResultsStartDate() { return startDateElement.getDate(); }
+	private Date getShowResultsStartDate() { return startDateElement.getDate(); }
 	
 	/**
 	 * 
 	 * @return Returns the end date for the result visibility.
 	 */
-	Date getShowResultsEndDate() { return endDateElement.getDate(); }
+	private Date getShowResultsEndDate() { return endDateElement.getDate(); }
 	
 	/**
 	 * 
 	 * @return Returns true if the results are shown after test finished.
 	 */
-	boolean isShowResultsAfterFinishTest() { return showResultsAfterFinishTest.isSelected(0); }
+	private boolean isShowResultsAfterFinishTest() { return showResultsAfterFinishTest.isSelected(0); }
 	
 	/**
 	 * 
 	 * @return Returns true if the results are shown on the test home page.
 	 */
-	boolean isShowResultsOnHomePage() { return showResultsOnHomePage.isSelected(0); }
+	private boolean isShowResultsOnHomePage() { return showResultsOnHomePage.isSelected(0); }
 	
 	
 	@Override
diff --git a/src/main/java/org/olat/course/nodes/iq/IQConfigurationController.java b/src/main/java/org/olat/course/nodes/iq/IQConfigurationController.java
new file mode 100644
index 0000000000000000000000000000000000000000..637664f2c14859ea37b56fc49d9ef7f172642107
--- /dev/null
+++ b/src/main/java/org/olat/course/nodes/iq/IQConfigurationController.java
@@ -0,0 +1,669 @@
+/**
+ * <a href="http://www.openolat.org">
+ * OpenOLAT - Online Learning and Training</a><br>
+ * <p>
+ * Licensed under the Apache License, Version 2.0 (the "License"); <br>
+ * you may not use this file except in compliance with the License.<br>
+ * You may obtain a copy of the License at the
+ * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a>
+ * <p>
+ * Unless required by applicable law or agreed to in writing,<br>
+ * software distributed under the License is distributed on an "AS IS" BASIS, <br>
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br>
+ * See the License for the specific language governing permissions and <br>
+ * limitations under the License.
+ * <p>
+ * Initial code contributed and copyrighted by<br>
+ * frentix GmbH, http://www.frentix.com
+ * <p>
+ */
+package org.olat.course.nodes.iq;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.dom4j.Attribute;
+import org.dom4j.Document;
+import org.dom4j.Element;
+import org.olat.basesecurity.BaseSecurity;
+import org.olat.basesecurity.Constants;
+import org.olat.commons.file.filechooser.FileChooseCreateEditController;
+import org.olat.commons.file.filechooser.LinkChooseCreateEditController;
+import org.olat.core.CoreSpringFactory;
+import org.olat.core.commons.fullWebApp.LayoutMain3ColsController;
+import org.olat.core.gui.UserRequest;
+import org.olat.core.gui.components.Component;
+import org.olat.core.gui.components.link.Link;
+import org.olat.core.gui.components.link.LinkFactory;
+import org.olat.core.gui.components.stack.BreadcrumbPanel;
+import org.olat.core.gui.components.velocity.VelocityContainer;
+import org.olat.core.gui.control.Controller;
+import org.olat.core.gui.control.Event;
+import org.olat.core.gui.control.WindowControl;
+import org.olat.core.gui.control.controller.BasicController;
+import org.olat.core.gui.control.generic.closablewrapper.CloseableModalController;
+import org.olat.core.id.Identity;
+import org.olat.core.id.Roles;
+import org.olat.core.logging.AssertException;
+import org.olat.core.util.StringHelper;
+import org.olat.core.util.coordinate.CoordinatorManager;
+import org.olat.core.util.coordinate.LockResult;
+import org.olat.core.util.vfs.LocalFileImpl;
+import org.olat.core.util.vfs.LocalFolderImpl;
+import org.olat.core.util.vfs.VFSConstants;
+import org.olat.core.util.vfs.VFSContainer;
+import org.olat.core.util.vfs.VFSItem;
+import org.olat.core.util.vfs.VFSStatus;
+import org.olat.course.ICourse;
+import org.olat.course.editor.NodeEditController;
+import org.olat.course.nodes.AbstractAccessableCourseNode;
+import org.olat.course.nodes.CourseNodeFactory;
+import org.olat.course.nodes.IQSELFCourseNode;
+import org.olat.course.nodes.IQSURVCourseNode;
+import org.olat.course.run.userview.UserCourseEnvironment;
+import org.olat.course.tree.CourseInternalLinkTreeModel;
+import org.olat.fileresource.FileResourceManager;
+import org.olat.fileresource.types.ImsQTI21Resource;
+import org.olat.ims.qti.QTIResult;
+import org.olat.ims.qti.QTIResultManager;
+import org.olat.ims.qti.editor.QTIEditorPackage;
+import org.olat.ims.qti.editor.QTIEditorPackageImpl;
+import org.olat.ims.qti.editor.beecom.objects.Assessment;
+import org.olat.ims.qti.editor.beecom.objects.Item;
+import org.olat.ims.qti.editor.beecom.objects.Section;
+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.process.QTIHelper;
+import org.olat.modules.ModuleConfiguration;
+import org.olat.modules.iq.IQManager;
+import org.olat.modules.iq.IQPreviewSecurityCallback;
+import org.olat.repository.RepositoryEntry;
+import org.olat.repository.RepositoryManager;
+import org.olat.repository.controllers.ReferencableEntriesSearchController;
+import org.olat.resource.OLATResource;
+import org.olat.user.UserManager;
+import org.springframework.beans.factory.annotation.Autowired;
+
+import de.bps.onyx.plugin.OnyxModule;
+import de.bps.onyx.plugin.course.nodes.iq.IQEditForm;
+import de.bps.webservices.clients.onyxreporter.OnyxReporterConnector;
+import de.bps.webservices.clients.onyxreporter.OnyxReporterException;
+
+/**
+ * 
+ * Initial date: 26.06.2015<br>
+ * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
+ *
+ */
+public class IQConfigurationController extends BasicController {
+
+	private static final String VC_CHOSENTEST = "chosentest";
+
+	private VelocityContainer myContent;
+	private final BreadcrumbPanel stackPanel;
+	
+	private Link previewLink, chooseTestButton, changeTestButton, editTestButton;
+
+	private Controller previewLayoutCtr;
+	private CloseableModalController cmc;
+	private IQEditReplaceWizard replaceWizard;
+	private FileChooseCreateEditController fccecontr;
+	private ReferencableEntriesSearchController searchController;
+	
+	private IQEditForm modOnyxConfigForm;
+	private IQ12EditForm mod12ConfigForm;
+	private QTI21EditForm mod21ConfigForm;
+	
+	private String type;
+	private ICourse course;
+	private List<Identity> learners;
+	private Boolean allowRelativeLinks;
+	private ModuleConfiguration moduleConfiguration;
+	private AbstractAccessableCourseNode courseNode;
+
+	@Autowired
+	private IQManager iqManager;
+	@Autowired
+	private BaseSecurity securityManager;
+	@Autowired
+	private RepositoryManager repositoryManager;
+
+	/**
+	 * 
+	 * @param ureq
+	 * @param wControl
+	 * @param stackPanel
+	 * @param course
+	 * @param courseNode
+	 * @param euce
+	 * @param type
+	 */
+	public IQConfigurationController(UserRequest ureq, WindowControl wControl, BreadcrumbPanel stackPanel, ICourse course,
+			AbstractAccessableCourseNode courseNode, UserCourseEnvironment euce, String type) {
+		super(ureq, wControl);
+		this.stackPanel = stackPanel;
+		this.moduleConfiguration = courseNode.getModuleConfiguration();
+		//o_clusterOk by guido: save to hold reference to course inside editor
+		this.course = course;
+		this.courseNode = courseNode;
+		this.type = type;
+		
+		
+		myContent = createVelocityContainer("edit");		
+		chooseTestButton = LinkFactory.createButtonSmall("command.chooseRepFile", myContent, this);
+		chooseTestButton.setElementCssClass("o_sel_test_choose_repofile");
+		changeTestButton = LinkFactory.createButtonSmall("command.changeRepFile", myContent, this);
+		changeTestButton.setElementCssClass("o_sel_test_change_repofile");
+
+		// fetch repository entry
+		RepositoryEntry re = null;
+		String displayName = "";
+		String repoSoftkey = (String)moduleConfiguration.get(IQEditController.CONFIG_KEY_REPOSITORY_SOFTKEY);
+		if (repoSoftkey != null) {
+			re = getIQReference(moduleConfiguration, false);
+			displayName = StringHelper.escapeHtml(re.getDisplayname());
+		}
+		 
+		myContent.contextPut(VC_CHOSENTEST, re == null ? translate("no.file.chosen") : displayName);
+		if (re != null) {
+			myContent.contextPut("dontRenderRepositoryButton", new Boolean(true));
+			// Put values to velocity container
+
+			boolean isOnyx = OnyxModule.isOnyxTest(re.getOlatResource());
+			if(isOnyx) {
+				setOnyxVariables(re);
+			} else {
+				if (isEditable(ureq.getIdentity(), ureq.getUserSession().getRoles(), re)) {
+					editTestButton = LinkFactory.createButtonSmall("command.editRepFile", myContent, this);
+				}
+				myContent.contextPut("showOutcomes", Boolean.FALSE);
+				myContent.contextPut(IQEditController.CONFIG_KEY_MINSCORE, moduleConfiguration.get(IQEditController.CONFIG_KEY_MINSCORE));
+				myContent.contextPut(IQEditController.CONFIG_KEY_MAXSCORE, moduleConfiguration.get(IQEditController.CONFIG_KEY_MAXSCORE));
+				myContent.contextPut(IQEditController.CONFIG_KEY_CUTVALUE, moduleConfiguration.get(IQEditController.CONFIG_KEY_CUTVALUE));
+			}
+
+			previewLink = LinkFactory.createCustomLink("command.preview", "command.preview", displayName, Link.NONTRANSLATED, myContent, this);
+			previewLink.setIconLeftCSS("o_icon o_icon-fw o_icon_preview");
+			if(isOnyx) {
+				previewLink.setEnabled(false);
+			} else {
+				previewLink.setCustomEnabledLinkCSS("o_preview");
+				previewLink.setTitle(translate("command.preview"));
+			}
+		}
+
+		String disclaimer = (String) moduleConfiguration.get(IQEditController.CONFIG_KEY_DISCLAIMER);
+		String legend = translate("fieldset.chosecreateeditfile");
+	
+		allowRelativeLinks = moduleConfiguration.getBooleanEntry(IQEditController.CONFIG_KEY_ALLOW_RELATIVE_LINKS);
+		if(allowRelativeLinks == null) {
+			allowRelativeLinks=Boolean.FALSE;
+		}
+		fccecontr = new LinkChooseCreateEditController(ureq, wControl, disclaimer, allowRelativeLinks, course.getCourseFolderContainer(),
+				type, legend, new CourseInternalLinkTreeModel(course.getEditorTreeModel()));		
+		listenTo(fccecontr);
+		
+		Component fcContent = fccecontr.getInitialComponent();
+		myContent.put("filechoosecreateedit", fcContent);
+		myContent.contextPut("type", type);
+		
+		putInitialPanel(myContent);	
+		updateEditController(ureq);
+		
+		switch(type) {
+			case AssessmentInstance.QMD_ENTRY_TYPE_ASSESS:
+				myContent.contextPut("repEntryTitle", translate("choosenfile.test"));
+				break;
+			case AssessmentInstance.QMD_ENTRY_TYPE_SELF:
+				myContent.contextPut("repEntryTitle", translate("choosenfile.self"));
+				break;
+			case AssessmentInstance.QMD_ENTRY_TYPE_SURVEY:
+				myContent.contextPut("repEntryTitle", translate("choosenfile.surv"));
+				chooseTestButton.setCustomDisplayText(translate("command.createSurvey"));
+				break;
+		}
+	}
+	
+	private void updateEditController(UserRequest ureq) {
+		removeAsListenerAndDispose(mod12ConfigForm);
+		removeAsListenerAndDispose(mod21ConfigForm);
+		removeAsListenerAndDispose(modOnyxConfigForm);
+		
+		RepositoryEntry re = getIQReference(moduleConfiguration, false);
+		if(re == null) {
+			mod12ConfigForm = new IQ12EditForm(ureq, getWindowControl(), moduleConfiguration);
+			listenTo(mod12ConfigForm);
+			myContent.put("iqeditform", mod12ConfigForm.getInitialComponent());
+		} else if(ImsQTI21Resource.TYPE_NAME.equals(re.getOlatResource().getResourceableTypeName())) {
+			mod21ConfigForm = new QTI21EditForm(ureq, getWindowControl(), moduleConfiguration);
+			listenTo(mod21ConfigForm);
+			myContent.put("iqeditform", mod21ConfigForm.getInitialComponent());
+		} else if(OnyxModule.isOnyxTest(re.getOlatResource())) {
+			modOnyxConfigForm = new IQEditForm(ureq, getWindowControl(), moduleConfiguration, re);
+			listenTo(modOnyxConfigForm);
+			myContent.put("iqeditform", modOnyxConfigForm.getInitialComponent());
+		} else {
+			mod12ConfigForm = new IQ12EditForm(ureq, getWindowControl(), moduleConfiguration);
+			listenTo(mod12ConfigForm);
+			myContent.put("iqeditform", mod12ConfigForm.getInitialComponent());
+		}
+	}
+	
+	private void setOnyxVariables(RepositoryEntry entry) {
+		myContent.contextPut("onyxDisplayName", entry.getDisplayname());
+		myContent.contextPut("showOutcomes", Boolean.TRUE);
+		Map<String, String> outcomes = new HashMap<String, String>();
+		try {
+			OnyxReporterConnector onyxReporter = new OnyxReporterConnector();
+			outcomes = onyxReporter.getPossibleOutcomeVariables(courseNode);
+		} catch (OnyxReporterException e) {
+			getWindowControl().setWarning(translate("reporter.unavailable"));
+		}
+		myContent.contextPut("outcomes", outcomes);
+	}
+
+	/**
+	 * @param identity
+	 * @param repository entry
+	 * @return
+	 */
+	private boolean isEditable(Identity identity, Roles roles, RepositoryEntry re) {
+		boolean isOnyx = OnyxModule.isOnyxTest(re.getOlatResource());
+		if (isOnyx) {
+			return false;
+		}
+
+		return (securityManager.isIdentityPermittedOnResourceable(identity, Constants.PERMISSION_HASROLE, Constants.ORESOURCE_ADMIN)
+				|| repositoryManager.isOwnerOfRepositoryEntry(identity, re)
+				|| repositoryManager.isInstitutionalRessourceManagerFor(identity, roles, re));
+	}
+
+	@Override
+	public void event(UserRequest ureq, Component source, Event event) {
+		if (previewLink == source){
+			doPreview(ureq);
+		} else if (chooseTestButton == source){
+			doChooseTestAndSurvey(ureq);
+		} else if (changeTestButton == source) {
+			RepositoryEntry re = courseNode.getReferencedRepositoryEntry();
+			if(re == null) {
+				showError("error.test.undefined.long", courseNode.getShortTitle());
+			} else if(type.equals(AssessmentInstance.QMD_ENTRY_TYPE_SELF)) {
+				doChangeSelfTest(ureq);
+			} else if(type.equals(AssessmentInstance.QMD_ENTRY_TYPE_ASSESS) || type.equals(AssessmentInstance.QMD_ENTRY_TYPE_SURVEY)) {
+				doChangeTestAndSurvey(ureq, re);
+			}	
+		} else if (editTestButton == source) {
+			CourseNodeFactory.getInstance().launchReferencedRepoEntryEditor(ureq, getWindowControl(), courseNode);
+		}
+	}
+	
+	@Override
+	public void event(UserRequest urequest, Controller source, Event event) {
+		if (source.equals(searchController)) {
+			if (event == ReferencableEntriesSearchController.EVENT_REPOSITORY_ENTRY_SELECTED) {
+				// repository search controller done				
+				cmc.deactivate();
+				RepositoryEntry re = searchController.getSelectedEntry();
+				doIQReference(urequest, re);
+				updateEditController(urequest);
+				checkEssay(re);
+			}
+		} else if (source == fccecontr) {
+			if (event == FileChooseCreateEditController.FILE_CHANGED_EVENT) {
+			    String chosenFile = fccecontr.getChosenFile();
+			    if (chosenFile != null){
+			        moduleConfiguration.set(IQEditController.CONFIG_KEY_DISCLAIMER, fccecontr.getChosenFile());
+			    }  else {
+			        moduleConfiguration.remove(IQEditController.CONFIG_KEY_DISCLAIMER);
+			    }
+				fireEvent(urequest, NodeEditController.NODECONFIG_CHANGED_EVENT);
+			} else if (event == FileChooseCreateEditController.ALLOW_RELATIVE_LINKS_CHANGED_EVENT) {
+				allowRelativeLinks = fccecontr.getAllowRelativeLinks();
+				courseNode.getModuleConfiguration().setBooleanEntry(IQEditController.CONFIG_KEY_ALLOW_RELATIVE_LINKS, allowRelativeLinks.booleanValue());
+				fireEvent(urequest, NodeEditController.NODECONFIG_CHANGED_EVENT);
+			}
+		} else if (source == replaceWizard) {
+			if(event == Event.CANCELLED_EVENT) {
+				cmc.deactivate();
+			} else if(event == Event.DONE_EVENT) {
+				cmc.deactivate();
+				String repositorySoftKey = (String) moduleConfiguration.get(IQEditController.CONFIG_KEY_REPOSITORY_SOFTKEY);
+				Long repKey = repositoryManager.lookupRepositoryEntryBySoftkey(repositorySoftKey, true).getKey();
+				QTIResultManager.getInstance().deleteAllResults(course.getResourceableId(), courseNode.getIdent(), repKey);
+				IQEditController.removeIQReference(moduleConfiguration);
+				VFSStatus isDeleted = iqManager.removeQtiSerFiles(course.getResourceableId(), courseNode.getIdent());
+				if (!isDeleted.equals(VFSConstants.YES)) {
+					// couldn't removed qtiser files
+					logWarn("Couldn't removed course node folder! Course resourceable id: " + course.getResourceableId() + ", Course node ident: " + courseNode.getIdent(), null);
+				}
+				doIQReference(urequest, replaceWizard.getSelectedRepositoryEntry());
+				fireEvent(urequest, NodeEditController.NODECONFIG_CHANGED_EVENT);
+			}
+		} else if (source == mod12ConfigForm) {
+			if (event == Event.DONE_EVENT) {
+				fireEvent(urequest, NodeEditController.NODECONFIG_CHANGED_EVENT);
+			}
+		} else if (source == mod21ConfigForm) {
+			if (event == Event.DONE_EVENT || event == Event.CHANGED_EVENT) {
+				fireEvent(urequest, NodeEditController.NODECONFIG_CHANGED_EVENT);
+			}
+		} else if (source == modOnyxConfigForm) {
+			if (event == Event.DONE_EVENT || event == Event.CHANGED_EVENT) {
+				fireEvent(urequest, NodeEditController.NODECONFIG_CHANGED_EVENT);
+			}
+		}
+	}
+	
+	private void doPreview(UserRequest ureq) {
+		removeAsListenerAndDispose(previewLayoutCtr);
+		
+		RepositoryEntry re = getIQReference(moduleConfiguration, false);
+		if(re != null && !OnyxModule.isOnyxTest(re.getOlatResource())) {
+			if(ImsQTI21Resource.TYPE_NAME.equals(re.getOlatResource().getResourceableTypeName())) {
+				//TODO
+			} else {
+				long courseResId = course.getResourceableId().longValue();
+				Controller previewController = iqManager.createIQDisplayController(moduleConfiguration, new IQPreviewSecurityCallback(), ureq, getWindowControl(), courseResId, courseNode.getIdent(), null);
+				previewLayoutCtr = new LayoutMain3ColsController(ureq, getWindowControl(), previewController);
+				stackPanel.pushController(translate("preview"), previewLayoutCtr);
+			}
+		}
+	}
+	
+	private void doChooseTestAndSurvey(UserRequest ureq) {
+		removeAsListenerAndDispose(cmc);
+		removeAsListenerAndDispose(searchController);
+		
+		if (type.equals(AssessmentInstance.QMD_ENTRY_TYPE_SURVEY)) {
+			searchController = new ReferencableEntriesSearchController(getWindowControl(), ureq, 
+					SurveyFileResource.TYPE_NAME, translate("command.chooseSurvey"));
+		} else { // test and selftest use same repository resource type
+			searchController = new ReferencableEntriesSearchController(getWindowControl(), ureq, 
+					TestFileResource.TYPE_NAME, translate("command.chooseTest"));
+		}			
+		listenTo(searchController);
+		cmc = new CloseableModalController(getWindowControl(), translate("close"), searchController.getInitialComponent(), true, translate("command.chooseRepFile"));
+		cmc.activate();
+	}
+	
+	private void doChangeSelfTest(UserRequest ureq) {
+		removeAsListenerAndDispose(cmc);
+		removeAsListenerAndDispose(searchController);
+		
+		String[] types = new String[]{ TestFileResource.TYPE_NAME };
+		searchController = new ReferencableEntriesSearchController(getWindowControl(), ureq, types, translate("command.chooseTest"));
+		listenTo(searchController);
+		
+		cmc = new CloseableModalController(getWindowControl(), translate("close"), searchController.getInitialComponent());
+		listenTo(searchController);
+		cmc.activate();
+	}
+	
+	private void doChangeTestAndSurvey(UserRequest ureq, RepositoryEntry re) {
+		removeAsListenerAndDispose(cmc);
+		removeAsListenerAndDispose(searchController);
+		
+		String[] types;
+		if(type.equals(AssessmentInstance.QMD_ENTRY_TYPE_ASSESS)) {//test
+			types = new String[]{ TestFileResource.TYPE_NAME, ImsQTI21Resource.TYPE_NAME };
+		} else {//survey
+			types = new String[]{ SurveyFileResource.TYPE_NAME };
+		}
+		
+		if (moduleConfiguration.get(IQEditController.CONFIG_KEY_TYPE_QTI) == null) {
+			updateQtiType(re);
+		}
+
+		int onyxSuccess = 0;
+		if (moduleConfiguration.get(IQEditController.CONFIG_KEY_TYPE_QTI) != null && moduleConfiguration.get(IQEditController.CONFIG_KEY_TYPE_QTI).equals(IQEditController.CONFIG_VALUE_QTI2)) {
+			if (courseNode.getClass().equals(IQSURVCourseNode.class)) {
+				File surveyDir = new File(course.getCourseEnvironment().getCourseBaseContainer()
+						.getBasefile() + File.separator + courseNode.getIdent() + File.separator);
+				if (surveyDir != null && surveyDir.exists() && surveyDir.listFiles().length > 0) {
+					onyxSuccess = surveyDir.listFiles().length;
+				}
+			} else {
+				onyxSuccess = QTIResultManager.getInstance().countResults(course.getResourceableId(), courseNode.getIdent(), re.getKey());
+			}
+		}
+		
+		
+		if (moduleConfiguration.get(IQEditController.CONFIG_KEY_TYPE_QTI) != null
+				&& moduleConfiguration.get(IQEditController.CONFIG_KEY_TYPE_QTI).equals(IQEditController.CONFIG_VALUE_QTI2)
+				&& onyxSuccess > 0) {
+			
+			replaceWizard = new IQEditReplaceWizard(ureq, getWindowControl(), course, courseNode, types, learners, null, onyxSuccess, true);
+			replaceWizard.addControllerListener(this);
+			
+			String title = replaceWizard.getAndRemoveWizardTitle();
+			cmc = new CloseableModalController(getWindowControl(), translate("close"), replaceWizard.getInitialComponent(), true, title);
+			cmc.activate();
+		} else {
+			
+			List<QTIResult> results = QTIResultManager.getInstance().selectResults(course.getResourceableId(), courseNode.getIdent(), re.getKey(), null, 1);
+			// test was passed from an user
+			boolean passed = (results != null && results.size() > 0) ? true : false;
+			// test was started and not passed
+			// it exists partly results for this test
+			List<Identity> identitiesWithQtiSerEntry = iqManager.getIdentitiesWithQtiSerEntry(course.getResourceableId(), courseNode.getIdent());
+			if(passed || identitiesWithQtiSerEntry.size() > 0) {
+				learners = new ArrayList<Identity>();
+				for(QTIResult result : results) {
+					Identity identity = result.getResultSet().getIdentity();
+					if(identity != null && !learners.contains(identity)){
+						learners.add(identity);
+					}
+				}
+				// add identities with qti.ser entry
+				for (Identity identity : identitiesWithQtiSerEntry) {
+					if(!learners.contains(identity)) {
+						learners.add(identity);
+					}
+				}
+				replaceWizard = new IQEditReplaceWizard(ureq, getWindowControl(), course, courseNode, types, learners, results, identitiesWithQtiSerEntry.size(), false);
+				replaceWizard.addControllerListener(this);
+				
+				cmc = new CloseableModalController(getWindowControl(), translate("close"), replaceWizard.getInitialComponent());
+				cmc.activate();
+			} else {
+				if(type.equals(AssessmentInstance.QMD_ENTRY_TYPE_ASSESS)) {//test					
+					searchController = new ReferencableEntriesSearchController(getWindowControl(), ureq, types, translate("command.chooseTest"));
+				} else {//survey
+					searchController = new ReferencableEntriesSearchController(getWindowControl(), ureq, types, translate("command.chooseSurvey"));
+				}
+				listenTo(searchController);
+				
+				cmc = new CloseableModalController(getWindowControl(), translate("close"), searchController.getInitialComponent());
+				cmc.activate();
+			}
+		}	
+	}
+
+	/**
+	 * This method updates the QTI Type in the editortreemodel.
+	 * 
+	 * @param re Needed to check if this Test is of QTI Type 2.1
+	 */
+	private void updateQtiType(RepositoryEntry re) {
+		boolean isOnyx = OnyxModule.isOnyxTest(re.getOlatResource());
+		if (isOnyx) {
+			moduleConfiguration.set(IQEditController.CONFIG_KEY_TYPE_QTI, IQEditController.CONFIG_VALUE_QTI2);
+		} else {
+			moduleConfiguration.set(IQEditController.CONFIG_KEY_TYPE_QTI, IQEditController.CONFIG_VALUE_QTI1);
+		}
+	}
+
+	private void checkEssay(RepositoryEntry re) {
+		if(OnyxModule.isOnyxTest(re.getOlatResource())) return;
+		if(courseNode instanceof IQSURVCourseNode || courseNode instanceof IQSELFCourseNode) return;
+		
+		TestFileResource fr = new TestFileResource();
+		fr.overrideResourceableId(re.getOlatResource().getResourceableId());
+		QTIEditorPackage qtiPackage = new QTIEditorPackageImpl(getIdentity(), fr, null, getTranslator());
+		Assessment ass = qtiPackage.getQTIDocument().getAssessment();
+
+		//Sections with their Items
+		List<Section> sections = ass.getSections();
+		for (Section section:sections) {
+			List<Item> items = section.getItems();
+			for (Item item:items) {
+				String ident = item.getIdent();
+				if(ident != null && ident.startsWith("QTIEDIT:ESSAY")) {
+					showWarning("warning.test.with.essay");
+					break;
+				}
+			}
+		}
+	}
+	
+	private void doIQReference(UserRequest urequest, RepositoryEntry re) {
+		// repository search controller done				
+		if (re != null) {
+			if (CoordinatorManager.getInstance().getCoordinator().getLocker().isLocked(re.getOlatResource(), null)) {
+				LockResult lockResult = CoordinatorManager.getInstance().getCoordinator().getLocker().acquireLock(re.getOlatResource(), urequest.getIdentity(), null);
+				String fullName = CoreSpringFactory.getImpl(UserManager.class).getUserDisplayName(lockResult.getOwner());
+				showError("error.entry.locked", fullName);
+				if(lockResult.isSuccess()) {
+					//improbable concurrency security
+					CoordinatorManager.getInstance().getCoordinator().getLocker().releaseLock(lockResult);
+				}
+			} else {
+				if(editTestButton != null) {
+					myContent.remove(editTestButton);
+				}
+
+				IQEditController.setIQReference(re, moduleConfiguration);
+				String displayName = StringHelper.escapeHtml(re.getDisplayname());
+				previewLink = LinkFactory.createCustomLink("command.preview", "command.preview", displayName, Link.NONTRANSLATED, myContent, this);
+				previewLink.setIconLeftCSS("o_icon o_icon-fw o_icon_preview");
+				previewLink.setCustomEnabledLinkCSS("o_preview");
+				previewLink.setTitle(getTranslator().translate("command.preview"));
+				myContent.contextPut("dontRenderRepositoryButton", new Boolean(true));
+				// If of type test, get min, max, cut - put in module config and push
+				// to velocity
+				
+				boolean isOnyx = OnyxModule.isOnyxTest(re.getOlatResource());
+				myContent.contextPut("isOnyx", new Boolean(isOnyx));
+				if(isOnyx) {
+					myContent.contextPut("onyxDisplayName", displayName);
+					moduleConfiguration.set(IQEditController.CONFIG_KEY_TYPE_QTI, IQEditController.CONFIG_VALUE_QTI2);
+					setOnyxVariables(re);
+				} else {
+					myContent.contextPut("showOutcomes", Boolean.FALSE);
+					moduleConfiguration.set(IQEditController.CONFIG_KEY_TYPE_QTI, IQEditController.CONFIG_VALUE_QTI1);
+					if (type.equals(AssessmentInstance.QMD_ENTRY_TYPE_ASSESS)) {
+						updateModuleConfigFromQTIFile(re.getOlatResource());
+						// Put values to velocity container
+						myContent.contextPut(IQEditController.CONFIG_KEY_MINSCORE, moduleConfiguration.get(IQEditController.CONFIG_KEY_MINSCORE));
+						myContent.contextPut(IQEditController.CONFIG_KEY_MAXSCORE, moduleConfiguration.get(IQEditController.CONFIG_KEY_MAXSCORE));
+						myContent.contextPut(IQEditController.CONFIG_KEY_CUTVALUE, moduleConfiguration.get(IQEditController.CONFIG_KEY_CUTVALUE));
+					}
+					if (isEditable(urequest.getIdentity(), urequest.getUserSession().getRoles(), re)) {
+						editTestButton = LinkFactory.createButtonSmall("command.editRepFile", myContent, this);
+					}
+				}
+				fireEvent(urequest, NodeEditController.NODECONFIG_CHANGED_EVENT);
+			}
+		}
+	}
+
+	/**
+	 * Ge the qti file soft key repository reference 
+	 * @param config
+	 * @param strict
+	 * @return RepositoryEntry
+	 */
+	private RepositoryEntry getIQReference(ModuleConfiguration config, boolean strict) {
+		if (config == null) {
+			if (strict) {
+				throw new AssertException("missing config in IQ");
+			} else {
+				return null;
+			}
+		}
+		String repoSoftkey = (String) config.get(IQEditController.CONFIG_KEY_REPOSITORY_SOFTKEY);
+		if (repoSoftkey == null) {
+			if (strict) {
+				throw new AssertException("invalid config when being asked for references");
+			} else {
+				return null;
+			}
+		}
+
+		return RepositoryManager.getInstance().lookupRepositoryEntryBySoftkey(repoSoftkey, strict);
+	}
+
+	/**
+	 * Update the module configuration from the qti file: read min/max/cut values
+	 * @param res
+	 */
+	private void updateModuleConfigFromQTIFile(OLATResource res) {
+		FileResourceManager frm = FileResourceManager.getInstance();
+		File unzippedRoot = frm.unzipFileResource(res);
+		//with VFS FIXME:pb:c: remove casts to LocalFileImpl and LocalFolderImpl if no longer needed.
+		VFSContainer vfsUnzippedRoot = new LocalFolderImpl(unzippedRoot);
+		VFSItem vfsQTI = vfsUnzippedRoot.resolve("qti.xml");
+		if (vfsQTI==null){
+			throw new AssertException("qti file did not exist even it should be guaranteed by repositor check-in ");
+		}
+		//ensures that InputStream is closed in every case.
+		Document doc = QTIHelper.getDocument((LocalFileImpl)vfsQTI);
+		if(doc == null){
+			//error reading qti file (existence check was made before)
+			throw new AssertException("qti file could not be read " + ((LocalFileImpl)vfsQTI).getBasefile().getAbsolutePath());
+		}
+		// Extract min, max and cut value
+		Float minValue = null, maxValue = null, cutValue = null;
+		Element decvar = (Element) doc.selectSingleNode("questestinterop/assessment/outcomes_processing/outcomes/decvar");
+		if (decvar != null) {
+			Attribute minval = decvar.attribute("minvalue");
+			if (minval != null) {
+				String mv = minval.getValue();
+				try {
+					minValue = new Float(Float.parseFloat(mv));
+				} catch (NumberFormatException e1) {
+					// if not correct in qti file -> ignore
+				}
+			}
+			Attribute maxval = decvar.attribute("maxvalue");
+			if (maxval != null) {
+				String mv = maxval.getValue();
+				try {
+					maxValue = new Float(Float.parseFloat(mv));
+				} catch (NumberFormatException e1) {
+					// if not correct in qti file -> ignore
+				}
+			}
+			Attribute cutval = decvar.attribute("cutvalue");
+			if (cutval != null) {
+				String cv = cutval.getValue();
+				try {
+					cutValue = new Float(Float.parseFloat(cv));
+				} catch (NumberFormatException e1) {
+					// if not correct in qti file -> ignore
+				}
+			}
+		}
+		// Put values to module configuration
+		moduleConfiguration.set(IQEditController.CONFIG_KEY_MINSCORE, minValue);
+		moduleConfiguration.set(IQEditController.CONFIG_KEY_MAXSCORE, maxValue);
+		moduleConfiguration.set(IQEditController.CONFIG_KEY_CUTVALUE, cutValue);
+	}
+
+	/**
+	 * @see org.olat.core.gui.control.DefaultController#doDispose(boolean)
+	 */
+	@Override
+	protected void doDispose() {
+		//child controllers registered with listenTo() get disposed in BasicController
+		if (previewLayoutCtr != null) {
+			previewLayoutCtr.dispose();
+			previewLayoutCtr = null;
+		}
+	}
+}
\ No newline at end of file
diff --git a/src/main/java/org/olat/course/nodes/iq/IQControllerCreator.java b/src/main/java/org/olat/course/nodes/iq/IQControllerCreator.java
deleted file mode 100644
index bf336a2d04ca607def421861cf4fe5d12bd20e08..0000000000000000000000000000000000000000
--- a/src/main/java/org/olat/course/nodes/iq/IQControllerCreator.java
+++ /dev/null
@@ -1,100 +0,0 @@
-/**
-* OLAT - Online Learning and Training<br>
-* http://www.olat.org
-* <p>
-* Licensed under the Apache License, Version 2.0 (the "License"); <br>
-* you may not use this file except in compliance with the License.<br>
-* You may obtain a copy of the License at
-* <p>
-* http://www.apache.org/licenses/LICENSE-2.0
-* <p>
-* Unless required by applicable law or agreed to in writing,<br>
-* software distributed under the License is distributed on an "AS IS" BASIS, <br>
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br>
-* See the License for the specific language governing permissions and <br>
-* limitations under the License.
-* <p>
-* Copyright (c) since 2004 at Multimedia- & E-Learning Services (MELS),<br>
-* University of Zurich, Switzerland.
-* <hr>
-* <a href="http://www.openolat.org">
-* OpenOLAT - Online Learning and Training</a><br>
-* This file has been modified by the OpenOLAT community. Changes are licensed
-* under the Apache 2.0 license as the original file.
-*/
-package org.olat.course.nodes.iq;
-
-import org.olat.core.gui.UserRequest;
-import org.olat.core.gui.components.stack.BreadcrumbPanel;
-import org.olat.core.gui.control.Controller;
-import org.olat.core.gui.control.WindowControl;
-import org.olat.core.gui.control.generic.tabbable.TabbableController;
-import org.olat.course.ICourse;
-import org.olat.course.groupsandrights.CourseGroupManager;
-import org.olat.course.nodes.IQSELFCourseNode;
-import org.olat.course.nodes.IQSURVCourseNode;
-import org.olat.course.nodes.IQTESTCourseNode;
-import org.olat.course.run.userview.UserCourseEnvironment;
-
-public interface IQControllerCreator {
-
-	/**
-	 * The iq test edit screen in the course editor.
-	 * @param ureq
-	 * @param wControl
-	 * @param course
-	 * @param courseNode
-	 * @param groupMgr
-	 * @param euce
-	 * @return
-	 */
-	public TabbableController createIQTestEditController(UserRequest ureq, WindowControl wControl, BreadcrumbPanel stackPanel, ICourse course,
-			IQTESTCourseNode courseNode, CourseGroupManager groupMgr, UserCourseEnvironment euce);
-
-	/**
-	 * The iq test edit screen in the course editor.
-	 * @param ureq
-	 * @param wControl
-	 * @param course
-	 * @param courseNode
-	 * @param groupMgr
-	 * @param euce
-	 * @return
-	 */
-	public TabbableController createIQSelftestEditController(UserRequest ureq, WindowControl wControl, BreadcrumbPanel stackPanel, ICourse course,
-			IQSELFCourseNode courseNode, CourseGroupManager groupMgr, UserCourseEnvironment euce);
-
-	/**
-	 * The iq test edit screen in the course editor.
-	 * @param ureq
-	 * @param wControl
-	 * @param course
-	 * @param courseNode
-	 * @param groupMgr
-	 * @param euce
-	 * @return
-	 */
-	public TabbableController createIQSurveyEditController(UserRequest ureq, WindowControl wControl, BreadcrumbPanel stackPanel, ICourse course,
-			IQSURVCourseNode courseNode, CourseGroupManager groupMgr, UserCourseEnvironment euce);
-
-	/**
-	 * 
-	 * @param ureq
-	 * @param wControl
-	 * @param userCourseEnv
-	 * @param ne
-	 * @param courseNode
-	 * @return
-	 */
-	public Controller createIQTestRunController(UserRequest ureq, WindowControl wControl, UserCourseEnvironment userCourseEnv,
-			IQTESTCourseNode courseNode);
-
-	public Controller createIQTestPreviewController(UserRequest ureq, WindowControl wControl, UserCourseEnvironment userCourseEnv,
-			IQTESTCourseNode courseNode);
-
-	public Controller createIQSelftestRunController(UserRequest ureq, WindowControl wControl, UserCourseEnvironment userCourseEnv,
-			IQSELFCourseNode courseNode);
-
-	public Controller createIQSurveyRunController(UserRequest ureq, WindowControl wControl, UserCourseEnvironment userCourseEnv,
-			IQSURVCourseNode courseNode);
-}
\ No newline at end of file
diff --git a/src/main/java/org/olat/course/nodes/iq/IQControllerCreatorOlat.java b/src/main/java/org/olat/course/nodes/iq/IQControllerCreatorOlat.java
deleted file mode 100644
index 84d29418f8c3b6e8544fbae4927bb81f0bcb68f2..0000000000000000000000000000000000000000
--- a/src/main/java/org/olat/course/nodes/iq/IQControllerCreatorOlat.java
+++ /dev/null
@@ -1,216 +0,0 @@
-/**
-* OLAT - Online Learning and Training<br>
-* http://www.olat.org
-* <p>
-* Licensed under the Apache License, Version 2.0 (the "License"); <br>
-* you may not use this file except in compliance with the License.<br>
-* You may obtain a copy of the License at
-* <p>
-* http://www.apache.org/licenses/LICENSE-2.0
-* <p>
-* Unless required by applicable law or agreed to in writing,<br>
-* software distributed under the License is distributed on an "AS IS" BASIS, <br>
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br>
-* See the License for the specific language governing permissions and <br>
-* limitations under the License.
-* <p>
-* Copyright (c) since 2004 at Multimedia- & E-Learning Services (MELS),<br>
-* University of Zurich, Switzerland.
-* <hr>
-* <a href="http://www.openolat.org">
-* OpenOLAT - Online Learning and Training</a><br>
-* This file has been modified by the OpenOLAT community. Changes are licensed
-* under the Apache 2.0 license as the original file.
-*/
-package org.olat.course.nodes.iq;
-
-import org.olat.core.gui.UserRequest;
-import org.olat.core.gui.components.stack.BreadcrumbPanel;
-import org.olat.core.gui.control.Controller;
-import org.olat.core.gui.control.WindowControl;
-import org.olat.core.gui.control.generic.messages.MessageUIFactory;
-import org.olat.core.gui.control.generic.tabbable.TabbableController;
-import org.olat.core.gui.translator.Translator;
-import org.olat.core.id.OLATResourceable;
-import org.olat.core.id.Roles;
-import org.olat.core.util.Util;
-import org.olat.core.util.coordinate.CoordinatorManager;
-import org.olat.course.ICourse;
-import org.olat.course.assessment.AssessmentManager;
-import org.olat.course.groupsandrights.CourseGroupManager;
-import org.olat.course.nodes.IQSELFCourseNode;
-import org.olat.course.nodes.IQSURVCourseNode;
-import org.olat.course.nodes.IQTESTCourseNode;
-import org.olat.course.run.userview.UserCourseEnvironment;
-import org.olat.ims.qti.fileresource.SurveyFileResource;
-import org.olat.ims.qti.fileresource.TestFileResource;
-import org.olat.modules.ModuleConfiguration;
-import org.olat.modules.iq.IQSecurityCallback;
-import org.olat.repository.RepositoryEntry;
-
-import de.bps.onyx.plugin.run.OnyxRunController;
-
-/**
- * Description:<br>
- * TODO: patrickb Class Description for IQControllerCreatorOlat
- * 
- * <P>
- * Initial Date:  18.06.2010 <br>
- * @author patrickb
- */
-public class IQControllerCreatorOlat implements IQControllerCreator {
-
-	/**
-	 * The iq test edit screen in the course editor.
-	 * @param ureq
-	 * @param wControl
-	 * @param course
-	 * @param courseNode
-	 * @param groupMgr
-	 * @param euce
-	 * @return
-	 */
-	public TabbableController createIQTestEditController(UserRequest ureq, WindowControl wControl, BreadcrumbPanel stackPanel, ICourse course, IQTESTCourseNode courseNode, CourseGroupManager groupMgr, UserCourseEnvironment euce){
-		return new IQEditController(ureq, wControl, stackPanel, course, courseNode, euce);
-	}
-	
-
-	/**
-	 * The iq test edit screen in the course editor.
-	 * @param ureq
-	 * @param wControl
-	 * @param course
-	 * @param courseNode
-	 * @param groupMgr
-	 * @param euce
-	 * @return
-	 */
-	public TabbableController createIQSelftestEditController(UserRequest ureq, WindowControl wControl, BreadcrumbPanel stackPanel, ICourse course, IQSELFCourseNode courseNode, CourseGroupManager groupMgr, UserCourseEnvironment euce){
-		return new IQEditController(ureq, wControl, stackPanel, course, courseNode, euce);
-	}
-	
-
-	/**
-	 * The iq test edit screen in the course editor.
-	 * @param ureq
-	 * @param wControl
-	 * @param course
-	 * @param courseNode
-	 * @param groupMgr
-	 * @param euce
-	 * @return
-	 */
-	public TabbableController createIQSurveyEditController(UserRequest ureq, WindowControl wControl, BreadcrumbPanel stackPanel, ICourse course, IQSURVCourseNode courseNode, CourseGroupManager groupMgr, UserCourseEnvironment euce){
-		return new IQEditController(ureq, wControl, stackPanel, course, courseNode, euce);
-	}
-	
-	/**
-	 * 
-	 * @param ureq
-	 * @param wControl
-	 * @param userCourseEnv
-	 * @param ne
-	 * @param courseNode
-	 * @return
-	 */
-	@Override
-	public Controller createIQTestRunController(UserRequest ureq, WindowControl wControl, UserCourseEnvironment userCourseEnv, IQTESTCourseNode courseNode) {
-		Controller controller;
-		// Do not allow guests to start tests
-		Roles roles = ureq.getUserSession().getRoles();
-		Translator trans = Util.createPackageTranslator(IQTESTCourseNode.class, ureq.getLocale());
-		if (roles.isGuestOnly()) {
-			String title = trans.translate("guestnoaccess.title");
-			String message = trans.translate("guestnoaccess.message");
-			controller = MessageUIFactory.createInfoMessage(ureq, wControl, title, message);
-		} else {
-			ModuleConfiguration config = courseNode.getModuleConfiguration();
-			boolean onyx = IQEditController.CONFIG_VALUE_QTI2.equals(config.get(IQEditController.CONFIG_KEY_TYPE_QTI));
-			if (onyx) {
-				controller = new OnyxRunController(userCourseEnv, config, ureq, wControl, courseNode);
-			} else {
-				AssessmentManager am = userCourseEnv.getCourseEnvironment().getAssessmentManager();
-				IQSecurityCallback sec = new CourseIQSecurityCallback(courseNode, am, ureq.getIdentity());
-				RepositoryEntry repositoryEntry = courseNode.getReferencedRepositoryEntry();
-				OLATResourceable ores = repositoryEntry.getOlatResource();
-				Long resId = ores.getResourceableId();
-				TestFileResource fr = new TestFileResource();
-				fr.overrideResourceableId(resId);
-				if(!CoordinatorManager.getInstance().getCoordinator().getLocker().isLocked(fr, null)) {
-					//QTI1
-					controller = new IQRunController(userCourseEnv, courseNode.getModuleConfiguration(), sec, ureq, wControl, courseNode);
-				} else {
-					String title = trans.translate("editor.lock.title");
-					String message = trans.translate("editor.lock.message");
-					controller = MessageUIFactory.createInfoMessage(ureq, wControl, title, message);
-				}
-			}
-		}
-		return controller;
-	}
-	
-	@Override
-	public Controller createIQTestPreviewController(UserRequest ureq, WindowControl wControl, UserCourseEnvironment userCourseEnv, IQTESTCourseNode courseNode) {
-		Controller controller;
-		ModuleConfiguration config = courseNode.getModuleConfiguration();
-		boolean onyx = IQEditController.CONFIG_VALUE_QTI2.equals(config.get(IQEditController.CONFIG_KEY_TYPE_QTI));
-		if (onyx) {
-			controller = new OnyxRunController(ureq, wControl, courseNode);
-		} else {
-			controller = new IQPreviewController(ureq, wControl, userCourseEnv, courseNode);
-		}
-		return controller;
-	}
-
-	@Override
-	public Controller createIQSelftestRunController(UserRequest ureq, WindowControl wControl, UserCourseEnvironment userCourseEnv, IQSELFCourseNode courseNode) {
-		Controller controller;
-		ModuleConfiguration config = courseNode.getModuleConfiguration();
-		AssessmentManager am = userCourseEnv.getCourseEnvironment().getAssessmentManager();
-		boolean onyx = IQEditController.CONFIG_VALUE_QTI2.equals(config.get(IQEditController.CONFIG_KEY_TYPE_QTI));
-		if (onyx) {
-			controller = new OnyxRunController(userCourseEnv, config, ureq, wControl, courseNode);
-		} else {
-			IQSecurityCallback sec = new CourseIQSecurityCallback(courseNode, am, ureq.getIdentity());
-			controller = new IQRunController(userCourseEnv, courseNode.getModuleConfiguration(), sec, ureq, wControl, courseNode);
-		}
-		return controller;
-	}
-
-	@Override
-	public Controller createIQSurveyRunController(UserRequest ureq, WindowControl wControl, UserCourseEnvironment userCourseEnv, IQSURVCourseNode courseNode) {
-		Controller controller;
-		
-		// Do not allow guests to start questionnaires
-		Roles roles = ureq.getUserSession().getRoles();
-		if (roles.isGuestOnly()) {
-			Translator trans = Util.createPackageTranslator(IQSURVCourseNode.class, ureq.getLocale());
-			String title = trans.translate("guestnoaccess.title");
-			String message = trans.translate("guestnoaccess.message");
-			controller = MessageUIFactory.createInfoMessage(ureq, wControl, title, message);
-		} else {
-			ModuleConfiguration config = courseNode.getModuleConfiguration();
-			boolean onyx = IQEditController.CONFIG_VALUE_QTI2.equals(config.get(IQEditController.CONFIG_KEY_TYPE_QTI));
-			if (onyx) {
-				controller = new OnyxRunController(userCourseEnv, config, ureq, wControl, courseNode);
-			} else {
-				RepositoryEntry repositoryEntry = courseNode.getReferencedRepositoryEntry();
-				OLATResourceable ores = repositoryEntry.getOlatResource();
-				Long resId = ores.getResourceableId();
-				SurveyFileResource fr = new SurveyFileResource();
-				fr.overrideResourceableId(resId);
-				if(!CoordinatorManager.getInstance().getCoordinator().getLocker().isLocked(fr, null)) {
-					AssessmentManager am = userCourseEnv.getCourseEnvironment().getAssessmentManager();
-					IQSecurityCallback sec = new CourseIQSecurityCallback(courseNode, am, ureq.getIdentity());
-					controller = new IQRunController(userCourseEnv, courseNode.getModuleConfiguration(), sec, ureq, wControl, courseNode);
-				} else {
-					Translator trans = Util.createPackageTranslator(IQSURVCourseNode.class, ureq.getLocale());
-					String title = trans.translate("editor.lock.title");
-					String message = trans.translate("editor.lock.message");
-					controller = MessageUIFactory.createInfoMessage(ureq, wControl, title, message);
-				}
-			}
-		}
-		return controller;
-	}
-}
\ No newline at end of file
diff --git a/src/main/java/org/olat/course/nodes/iq/IQEditController.java b/src/main/java/org/olat/course/nodes/iq/IQEditController.java
index ee6a8238195e78e63faae87db4cfeb3b42fd2a28..04dd24ab2b318c103ea519afb59d81f136f9719f 100644
--- a/src/main/java/org/olat/course/nodes/iq/IQEditController.java
+++ b/src/main/java/org/olat/course/nodes/iq/IQEditController.java
@@ -25,88 +25,30 @@
 
 package org.olat.course.nodes.iq;
 
-import java.io.File;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import org.dom4j.Attribute;
-import org.dom4j.Document;
-import org.dom4j.Element;
-import org.olat.basesecurity.BaseSecurityManager;
-import org.olat.basesecurity.Constants;
-import org.olat.commons.file.filechooser.FileChooseCreateEditController;
-import org.olat.commons.file.filechooser.LinkChooseCreateEditController;
-import org.olat.core.CoreSpringFactory;
-import org.olat.core.commons.fullWebApp.LayoutMain3ColsController;
 import org.olat.core.gui.UserRequest;
 import org.olat.core.gui.components.Component;
-import org.olat.core.gui.components.link.Link;
-import org.olat.core.gui.components.link.LinkFactory;
-import org.olat.core.gui.components.panel.Panel;
 import org.olat.core.gui.components.stack.BreadcrumbPanel;
 import org.olat.core.gui.components.tabbedpane.TabbedPane;
-import org.olat.core.gui.components.velocity.VelocityContainer;
 import org.olat.core.gui.control.Controller;
 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.tabbable.ActivateableTabbableDefaultController;
-import org.olat.core.id.Identity;
-import org.olat.core.id.Roles;
 import org.olat.core.logging.AssertException;
-import org.olat.core.logging.OLog;
-import org.olat.core.logging.Tracing;
-import org.olat.core.util.StringHelper;
-import org.olat.core.util.coordinate.CoordinatorManager;
-import org.olat.core.util.coordinate.LockResult;
-import org.olat.core.util.vfs.LocalFileImpl;
-import org.olat.core.util.vfs.LocalFolderImpl;
-import org.olat.core.util.vfs.VFSConstants;
-import org.olat.core.util.vfs.VFSContainer;
-import org.olat.core.util.vfs.VFSItem;
-import org.olat.core.util.vfs.VFSStatus;
 import org.olat.course.ICourse;
 import org.olat.course.assessment.AssessmentHelper;
 import org.olat.course.condition.Condition;
 import org.olat.course.condition.ConditionEditController;
 import org.olat.course.editor.NodeEditController;
 import org.olat.course.nodes.AbstractAccessableCourseNode;
-import org.olat.course.nodes.CourseNodeFactory;
 import org.olat.course.nodes.IQSELFCourseNode;
 import org.olat.course.nodes.IQSURVCourseNode;
 import org.olat.course.nodes.IQTESTCourseNode;
 import org.olat.course.run.userview.UserCourseEnvironment;
-import org.olat.course.tree.CourseInternalLinkTreeModel;
-import org.olat.fileresource.FileResourceManager;
-import org.olat.ims.qti.QTIResult;
-import org.olat.ims.qti.QTIResultManager;
-import org.olat.ims.qti.editor.QTIEditorPackage;
-import org.olat.ims.qti.editor.QTIEditorPackageImpl;
-import org.olat.ims.qti.editor.beecom.objects.Assessment;
-import org.olat.ims.qti.editor.beecom.objects.Item;
-import org.olat.ims.qti.editor.beecom.objects.Section;
-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.process.QTIHelper;
 import org.olat.modules.ModuleConfiguration;
-import org.olat.modules.iq.IQManager;
-import org.olat.modules.iq.IQPreviewSecurityCallback;
 import org.olat.repository.RepositoryEntry;
 import org.olat.repository.RepositoryManager;
-import org.olat.repository.controllers.ReferencableEntriesSearchController;
-import org.olat.repository.handlers.RepositoryHandler;
-import org.olat.repository.handlers.RepositoryHandlerFactory;
-import org.olat.resource.OLATResource;
-import org.olat.user.UserManager;
-
-import de.bps.onyx.plugin.OnyxModule;
-import de.bps.onyx.plugin.course.nodes.iq.IQEditForm;
-import de.bps.webservices.clients.onyxreporter.OnyxReporterConnector;
-import de.bps.webservices.clients.onyxreporter.OnyxReporterException;
 
 /**
  * Description:<BR/>
@@ -123,8 +65,7 @@ public class IQEditController extends ActivateableTabbableDefaultController impl
 	public static final String PANE_TAB_IQCONFIG_SELF = "pane.tab.iqconfig.self";
 	public static final String PANE_TAB_IQCONFIG_TEST = "pane.tab.iqconfig.test";
 	public static final String PANE_TAB_ACCESSIBILITY = "pane.tab.accessibility";
-	private static final String VC_CHOSENTEST = "chosentest";
-	private static final String ACTION_CORRECT ="correcttest";
+
 	/** configuration key: repository sof key reference to qti file*/
 	public static final String CONFIG_KEY_REPOSITORY_SOFTKEY = "repoSoftkey";
 	/** configuration key: the disclaimer text*/
@@ -192,36 +133,23 @@ public class IQEditController extends ActivateableTabbableDefaultController impl
 	public static final Object CONFIG_VALUE_QTI1 = "qti1";
 	public static final String CONFIG_KEY_IS_SURVEY = "issurv";
 
-	private OLog log = Tracing.createLoggerFor(IQEditController.class);
 	private final String[] paneKeys;
 
-	private ModuleConfiguration moduleConfiguration;
-	private Panel main;
-	private VelocityContainer myContent;
 
-	private IQEditForm modOnyxConfigForm;
-	private IQ12EditForm mod12ConfigForm;
-	private ReferencableEntriesSearchController searchController;
 	private ICourse course;
-	private ConditionEditController accessibilityCondContr;
-	private AbstractAccessableCourseNode courseNode;
+	
 	private String type;
 	private UserCourseEnvironment euce;
+	private AbstractAccessableCourseNode courseNode;
+	private ModuleConfiguration moduleConfiguration;
+
 	private TabbedPane myTabbedPane;
-	private FileChooseCreateEditController fccecontr;
-	private Controller correctQTIcontroller;
-	private Boolean allowRelativeLinks;
-	private Link previewLink;
-	private Link chooseTestButton;
-	private Link changeTestButton;
-	private IQEditReplaceWizard replaceWizard;
-	private List<Identity> learners;
 	private Controller previewLayoutCtr;
-	private CloseableModalController cmc;
-	private Link editTestButton;
+
 	private final BreadcrumbPanel stackPanel;
 	
-	private final IQManager iqManager;
+	private ConditionEditController accessibilityCondContr;
+	private IQConfigurationController configurationCtrl;
 
 	/**
 	 * Constructor for the IMS QTI edit controller for a test course node
@@ -233,7 +161,7 @@ public class IQEditController extends ActivateableTabbableDefaultController impl
 	 * @param groupMgr
 	 * @param euce
 	 */
-	IQEditController(UserRequest ureq, WindowControl wControl, BreadcrumbPanel stackPanel, ICourse course, IQTESTCourseNode courseNode, UserCourseEnvironment euce) {
+	public IQEditController(UserRequest ureq, WindowControl wControl, BreadcrumbPanel stackPanel, ICourse course, IQTESTCourseNode courseNode, UserCourseEnvironment euce) {
 		super(ureq, wControl);
 		this.stackPanel = stackPanel;
 		this.moduleConfiguration = courseNode.getModuleConfiguration();
@@ -242,22 +170,22 @@ public class IQEditController extends ActivateableTabbableDefaultController impl
 		this.courseNode = courseNode;
 		this.euce = euce;
 		
-		iqManager = CoreSpringFactory.getImpl(IQManager.class);
 		
 		type = AssessmentInstance.QMD_ENTRY_TYPE_ASSESS;
 		this.PANE_TAB_IQCONFIG_XXX = PANE_TAB_IQCONFIG_TEST;
 		paneKeys = new String[]{PANE_TAB_IQCONFIG_XXX,PANE_TAB_ACCESSIBILITY};
 		// put some default values
-		if (moduleConfiguration.get(CONFIG_KEY_ENABLECANCEL) == null)
+		if (moduleConfiguration.get(CONFIG_KEY_ENABLECANCEL) == null) {
 			moduleConfiguration.set(CONFIG_KEY_ENABLECANCEL, Boolean.FALSE);
-		if (moduleConfiguration.get(CONFIG_KEY_ENABLESUSPEND) == null)
+		}
+		if (moduleConfiguration.get(CONFIG_KEY_ENABLESUSPEND) == null) {
 			moduleConfiguration.set(CONFIG_KEY_ENABLESUSPEND, Boolean.FALSE);
-		if(moduleConfiguration.get(CONFIG_KEY_RENDERMENUOPTION) == null)
+		}
+		if(moduleConfiguration.get(CONFIG_KEY_RENDERMENUOPTION) == null) {
 			moduleConfiguration.set(CONFIG_KEY_RENDERMENUOPTION, Boolean.FALSE);
+		}
 		
-		init(ureq, wControl);
-		myContent.contextPut("repEntryTitle", translate("choosenfile.test"));
-		myContent.contextPut("type", type);
+		init(ureq);
 	}
 
 	/**
@@ -270,26 +198,26 @@ public class IQEditController extends ActivateableTabbableDefaultController impl
 	 * @param groupMgr
 	 * @param euce
 	 */
-	 IQEditController(UserRequest ureq, WindowControl wControl, BreadcrumbPanel stackPanel, ICourse course, IQSELFCourseNode courseNode , UserCourseEnvironment euce) {
+	 public IQEditController(UserRequest ureq, WindowControl wControl, BreadcrumbPanel stackPanel, ICourse course, IQSELFCourseNode courseNode , UserCourseEnvironment euce) {
 		super(ureq, wControl);
 		this.stackPanel = stackPanel;
 		this.moduleConfiguration = courseNode.getModuleConfiguration();
 		this.course = course;
 		this.courseNode = courseNode;
 		this.euce = euce;
-		iqManager = CoreSpringFactory.getImpl(IQManager.class);
+
 		type = AssessmentInstance.QMD_ENTRY_TYPE_SELF;
 		this.PANE_TAB_IQCONFIG_XXX = PANE_TAB_IQCONFIG_SELF;
 		paneKeys = new String[]{PANE_TAB_IQCONFIG_XXX,PANE_TAB_ACCESSIBILITY};
 		// put some default values
-		if (moduleConfiguration.get(CONFIG_KEY_ENABLECANCEL) == null)
+		if (moduleConfiguration.get(CONFIG_KEY_ENABLECANCEL) == null) {
 			moduleConfiguration.set(CONFIG_KEY_ENABLECANCEL, Boolean.TRUE);
-		if (moduleConfiguration.get(CONFIG_KEY_ENABLESUSPEND) == null)
+		}
+		if (moduleConfiguration.get(CONFIG_KEY_ENABLESUSPEND) == null) {
 			moduleConfiguration.set(CONFIG_KEY_ENABLESUSPEND, Boolean.TRUE);
+		}
 
-		init(ureq, wControl);
-		myContent.contextPut("repEntryTitle", translate("choosenfile.self"));
-		myContent.contextPut("type", type);
+		init(ureq);
 	}
 
 	/**
@@ -302,14 +230,14 @@ public class IQEditController extends ActivateableTabbableDefaultController impl
 	 * @param groupMgr
 	 * @param euce
 	 */
-	 IQEditController(UserRequest ureq, WindowControl wControl, BreadcrumbPanel stackPanel, ICourse course, IQSURVCourseNode courseNode, UserCourseEnvironment euce) {
+	 public IQEditController(UserRequest ureq, WindowControl wControl, BreadcrumbPanel stackPanel, ICourse course, IQSURVCourseNode courseNode, UserCourseEnvironment euce) {
 		super(ureq, wControl);
 		this.stackPanel = stackPanel;
 		this.moduleConfiguration = courseNode.getModuleConfiguration();
 		this.course = course;
 		this.courseNode = courseNode;
 		this.euce = euce;
-		iqManager = CoreSpringFactory.getImpl(IQManager.class);
+
 		type = AssessmentInstance.QMD_ENTRY_TYPE_SURVEY;
 		this.PANE_TAB_IQCONFIG_XXX = PANE_TAB_IQCONFIG_SURV;
 		paneKeys = new String[]{PANE_TAB_IQCONFIG_XXX,PANE_TAB_ACCESSIBILITY};
@@ -322,468 +250,45 @@ public class IQEditController extends ActivateableTabbableDefaultController impl
 			moduleConfiguration.setBooleanEntry(CONFIG_KEY_ALLOW_RELATIVE_LINKS,false);
 		}
 		
-		init(ureq, wControl);
-		myContent.contextPut("repEntryTitle", translate("choosenfile.surv"));
-		myContent.contextPut("type", type);
-		chooseTestButton.setCustomDisplayText(translate("command.createSurvey"));
+		init(ureq);
 	}
 
-	private void init(UserRequest ureq, WindowControl wControl) {		
-		main = new Panel("iqeditpanel");
-		
-		myContent = createVelocityContainer("edit");		
-		chooseTestButton = LinkFactory.createButtonSmall("command.chooseRepFile", myContent, this);
-		chooseTestButton.setElementCssClass("o_sel_test_choose_repofile");
-		changeTestButton = LinkFactory.createButtonSmall("command.changeRepFile", myContent, this);
-		changeTestButton.setElementCssClass("o_sel_test_change_repofile");
-		
-
-		// fetch repository entry
-		RepositoryEntry re = null;
-		String displayName = "";
-		String repoSoftkey = (String) moduleConfiguration.get(CONFIG_KEY_REPOSITORY_SOFTKEY);
-		if (repoSoftkey != null) {
-			re = getIQReference(moduleConfiguration, false);
-			displayName = StringHelper.escapeHtml(re.getDisplayname());
-		}
-		 
-		myContent.contextPut(VC_CHOSENTEST, re == null ? translate("no.file.chosen") : displayName);
-		if (re != null) {
-			myContent.contextPut("dontRenderRepositoryButton", new Boolean(true));
-			// Put values to velocity container
+	private void init(UserRequest ureq) {		
+		configurationCtrl = new IQConfigurationController(ureq, getWindowControl(), this.stackPanel, course, courseNode, euce, type);
+		listenTo(configurationCtrl);
 
-			boolean isOnyx = OnyxModule.isOnyxTest(re.getOlatResource());
-			if(isOnyx) {
-				setOnyxVariables(re);
-			} else {
-				if (isEditable(ureq.getIdentity(), ureq.getUserSession().getRoles(), re)) {
-					editTestButton = LinkFactory.createButtonSmall("command.editRepFile", myContent, this);
-				}
-				myContent.contextPut("showOutcomes", Boolean.FALSE);
-				myContent.contextPut(CONFIG_KEY_MINSCORE, moduleConfiguration.get(CONFIG_KEY_MINSCORE));
-				myContent.contextPut(CONFIG_KEY_MAXSCORE, moduleConfiguration.get(CONFIG_KEY_MAXSCORE));
-				myContent.contextPut(CONFIG_KEY_CUTVALUE, moduleConfiguration.get(CONFIG_KEY_CUTVALUE));
-			}
-
-			previewLink = LinkFactory.createCustomLink("command.preview", "command.preview", displayName, Link.NONTRANSLATED, myContent, this);
-			previewLink.setIconLeftCSS("o_icon o_icon-fw o_icon_preview");
-			previewLink.setCustomEnabledLinkCSS("o_preview");
-			previewLink.setTitle(getTranslator().translate("command.preview"));
-		}
-
-		String disclaimer = (String) moduleConfiguration.get(CONFIG_KEY_DISCLAIMER);
-		//allowRelativeLinks  = courseNode.getModuleConfiguration().getBooleanEntry(CONFIG_KEY_ALLOW_RELATIVE_LINKS);
-
-		String legend = translate("fieldset.chosecreateeditfile");
-	
-		allowRelativeLinks  = moduleConfiguration.getBooleanEntry(CONFIG_KEY_ALLOW_RELATIVE_LINKS);
-		if(allowRelativeLinks==null){
-			allowRelativeLinks=Boolean.FALSE;
-		}
-		fccecontr = new LinkChooseCreateEditController(ureq, wControl, disclaimer, allowRelativeLinks, course.getCourseFolderContainer(), type, legend, new CourseInternalLinkTreeModel(course.getEditorTreeModel()) );		
-		listenTo(fccecontr);
-		
-		Component fcContent = fccecontr.getInitialComponent();
-		myContent.put("filechoosecreateedit", fcContent);
-		
 		Condition accessCondition = courseNode.getPreConditionAccess();
 		accessibilityCondContr = new ConditionEditController(ureq, getWindowControl(), accessCondition,
 				AssessmentHelper.getAssessableNodes(course.getEditorTreeModel(), courseNode),euce);		
 		listenTo(accessibilityCondContr);
-
-		main.setContent(myContent);
-		
-		updateEditController(ureq);
-	}
-	
-	private void updateEditController(UserRequest ureq) {
-		removeAsListenerAndDispose(mod12ConfigForm);
-		removeAsListenerAndDispose(modOnyxConfigForm);
-		
-		RepositoryEntry re = getIQReference(moduleConfiguration, false);
-		if(re == null || !OnyxModule.isOnyxTest(re.getOlatResource())) {
-			mod12ConfigForm = new IQ12EditForm(ureq, getWindowControl(), moduleConfiguration);
-			listenTo(mod12ConfigForm);
-			myContent.put("iqeditform", mod12ConfigForm.getInitialComponent());
-		} else {
-			modOnyxConfigForm = new IQEditForm(ureq, getWindowControl(), moduleConfiguration, re);
-			listenTo(modOnyxConfigForm);
-			myContent.put("iqeditform", modOnyxConfigForm.getInitialComponent());
-		}
-	}
-	
-	private void setOnyxVariables(RepositoryEntry entry) {
-		myContent.contextPut("onyxDisplayName", entry.getDisplayname());
-		myContent.contextPut("showOutcomes", Boolean.TRUE);
-		Map<String, String> outcomes = new HashMap<String, String>();
-		try {
-			OnyxReporterConnector onyxReporter = new OnyxReporterConnector();
-			outcomes = onyxReporter.getPossibleOutcomeVariables(courseNode);
-		} catch (OnyxReporterException e) {
-			getWindowControl().setWarning(translate("reporter.unavailable"));
-		}
-		myContent.contextPut("outcomes", outcomes);
 	}
 
-	/**
-	 * @param identity
-	 * @param repository entry
-	 * @return
-	 */
-	private boolean isEditable(Identity identity, Roles roles, RepositoryEntry re) {
-		boolean isOnyx = OnyxModule.isOnyxTest(re.getOlatResource());
-		if (isOnyx) {
-			return false;
-		}
-
-		return (BaseSecurityManager.getInstance().isIdentityPermittedOnResourceable(identity, Constants.PERMISSION_HASROLE, Constants.ORESOURCE_ADMIN)
-				|| RepositoryManager.getInstance().isOwnerOfRepositoryEntry(identity, re)
-				|| RepositoryManager.getInstance().isInstitutionalRessourceManagerFor(identity, roles, re));
-	}
-
-	/**
-	 * @see org.olat.core.gui.control.DefaultController#event(org.olat.core.gui.UserRequest,
-	 *      org.olat.core.gui.components.Component, org.olat.core.gui.control.Event)
-	 */
+	@Override
 	public void event(UserRequest ureq, Component source, Event event) {
-		 if (source == myContent) {
-			if(event.getCommand().equals(ACTION_CORRECT)){
-				/* FIXME:pb:remove this elseif code, as the use case "correct" is started from details view only
-				 * - check if the test is in use at the moment
-				 * - check if already results exist
-				 * - check if test is referenced from other courses
-				 */
-				String repoSoftKey = (String)moduleConfiguration.get(CONFIG_KEY_REPOSITORY_SOFTKEY);
-				RepositoryEntry re = RepositoryManager.getInstance().lookupRepositoryEntryBySoftkey(repoSoftKey,false);
-				if(re==null) {
-					//not found
-				} else {
-					RepositoryHandler typeToEdit = RepositoryHandlerFactory.getInstance().getRepositoryHandler(re);
-					correctQTIcontroller = typeToEdit.createEditorController(re, ureq, getWindowControl(), null);
-					getWindowControl().pushToMainArea(correctQTIcontroller.getInitialComponent());					
-					listenTo(correctQTIcontroller);
-				}
-			}
-		} else if (source == previewLink){
-			removeAsListenerAndDispose(previewLayoutCtr);
-			// handle preview
-			long courseResId = course.getResourceableId().longValue();
-			Controller previewController = iqManager.createIQDisplayController(moduleConfiguration, new IQPreviewSecurityCallback(), ureq, getWindowControl(), courseResId, courseNode.getIdent(), null);
-			previewLayoutCtr = new LayoutMain3ColsController(ureq, getWindowControl(), previewController);
-			stackPanel.pushController(translate("preview"), previewLayoutCtr);
-			
-		} else if (source == chooseTestButton){// initiate search controller
-			if (type.equals(AssessmentInstance.QMD_ENTRY_TYPE_SURVEY)) {
-				searchController = new ReferencableEntriesSearchController(getWindowControl(), ureq, 
-						SurveyFileResource.TYPE_NAME, translate("command.chooseSurvey"));
-			} else { // test and selftest use same repository resource type
-				searchController = new ReferencableEntriesSearchController(getWindowControl(), ureq, 
-						TestFileResource.TYPE_NAME, translate("command.chooseTest"));
-			}			
-			listenTo(searchController);
-			cmc = new CloseableModalController(getWindowControl(), translate("close"), searchController.getInitialComponent(), true, translate("command.chooseRepFile"));
-			cmc.activate();
-		} else if (source == changeTestButton) {//change associated test
-			if(type.equals(AssessmentInstance.QMD_ENTRY_TYPE_SELF)) {//selftest
-				String[] types = new String[]{TestFileResource.TYPE_NAME};
-				searchController = new ReferencableEntriesSearchController(getWindowControl(), ureq, types, translate("command.chooseTest"));
-				cmc = new CloseableModalController(getWindowControl(), translate("close"), searchController.getInitialComponent());
-				listenTo(searchController);
-			} else if(type.equals(AssessmentInstance.QMD_ENTRY_TYPE_ASSESS) | type.equals(AssessmentInstance.QMD_ENTRY_TYPE_SURVEY)) {//test, survey
-				String[] types;
-				if(type.equals(AssessmentInstance.QMD_ENTRY_TYPE_ASSESS)) {//test
-					types = new String[]{TestFileResource.TYPE_NAME};
-				} else {//survey
-					types = new String[]{SurveyFileResource.TYPE_NAME};
-				}
-				
-				RepositoryEntry re = courseNode.getReferencedRepositoryEntry();
-				if(re == null) {
-					showError("error.test.undefined.long", courseNode.getShortTitle());
-					return;
-				}
-				
-				if (moduleConfiguration.get(CONFIG_KEY_TYPE_QTI) == null) {
-					updateQtiType(re);
-				}
-
-				int onyxSuccess = 0;
-				if (moduleConfiguration.get(CONFIG_KEY_TYPE_QTI) != null && moduleConfiguration.get(CONFIG_KEY_TYPE_QTI).equals(CONFIG_VALUE_QTI2)) {
-					if (courseNode.getClass().equals(IQSURVCourseNode.class)) {
-						File surveyDir = new File(course.getCourseEnvironment().getCourseBaseContainer()
-								.getBasefile() + File.separator + courseNode.getIdent() + File.separator);
-						if (surveyDir != null && surveyDir.exists() && surveyDir.listFiles().length > 0) {
-							onyxSuccess = surveyDir.listFiles().length;
-						}
-					} else {
-						onyxSuccess = QTIResultManager.getInstance().countResults(course.getResourceableId(), courseNode.getIdent(), re.getKey());
-					}
-				}
-				if (moduleConfiguration.get(CONFIG_KEY_TYPE_QTI) != null
-						&& moduleConfiguration.get(CONFIG_KEY_TYPE_QTI).equals(CONFIG_VALUE_QTI2)
-						&& onyxSuccess > 0) {
-					replaceWizard = new IQEditReplaceWizard(ureq, getWindowControl(), course, courseNode, types, learners, null, onyxSuccess, true);
-					replaceWizard.addControllerListener(this);
-					String title = replaceWizard.getAndRemoveWizardTitle();
-					cmc = new CloseableModalController(getWindowControl(), translate("close"), replaceWizard.getInitialComponent(), true, title);
-				} else {
-					List<QTIResult> results = QTIResultManager.getInstance().selectResults(course.getResourceableId(), courseNode.getIdent(), re.getKey(), null, 1);
-					// test was passed from an user
-					boolean passed = (results != null && results.size() > 0) ? true : false;
-					// test was started and not passed
-					// it exists partly results for this test
-					List<Identity> identitiesWithQtiSerEntry = iqManager.getIdentitiesWithQtiSerEntry(course.getResourceableId(), courseNode.getIdent());
-					if(passed || identitiesWithQtiSerEntry.size() > 0) {
-						learners = new ArrayList<Identity>();
-						for(QTIResult result : results) {
-							Identity identity = result.getResultSet().getIdentity();
-							if(identity != null && !learners.contains(identity)) learners.add(identity);
-						}
-						// add identities with qti.ser entry
-						for (Identity identity : identitiesWithQtiSerEntry) {
-							if(!learners.contains(identity)) learners.add(identity);
-						}
-						replaceWizard = new IQEditReplaceWizard(ureq, getWindowControl(), course, courseNode, types, learners, results, identitiesWithQtiSerEntry.size(), false);
-						replaceWizard.addControllerListener(this);
-						cmc = new CloseableModalController(getWindowControl(), translate("close"), replaceWizard.getInitialComponent());
-					} else {
-						if(type.equals(AssessmentInstance.QMD_ENTRY_TYPE_ASSESS)) {//test					
-							searchController = new ReferencableEntriesSearchController(getWindowControl(), ureq, types, translate("command.chooseTest"));
-						} else {//survey
-							searchController = new ReferencableEntriesSearchController(getWindowControl(), ureq, types, translate("command.chooseSurvey"));
-						}
-						listenTo(searchController);
-						cmc = new CloseableModalController(getWindowControl(), translate("close"), searchController.getInitialComponent());
-					}
-				}
-			}
-			cmc.activate();
-		}
-		else if (source == editTestButton) {
-			CourseNodeFactory.getInstance().launchReferencedRepoEntryEditor(ureq, getWindowControl(), courseNode);
-		}
+		//
 	}
 
-	/**
-	 * This method updates the QTI Type in the editortreemodel.
-	 * 
-	 * @param re Needed to check if this Test is of QTI Type 2.1
-	 */
-	private void updateQtiType(RepositoryEntry re) {
-		boolean isOnyx = OnyxModule.isOnyxTest(re.getOlatResource());
-		if (isOnyx) {
-			moduleConfiguration.set(CONFIG_KEY_TYPE_QTI, CONFIG_VALUE_QTI2);
-		} else {
-			moduleConfiguration.set(CONFIG_KEY_TYPE_QTI, CONFIG_VALUE_QTI1);
-		}
-	}
-
-	/**
-	 * @see org.olat.core.gui.control.DefaultController#event(org.olat.core.gui.UserRequest, org.olat.core.gui.control.Controller, org.olat.core.gui.control.Event)
-	 */
 	@Override
 	public void event(UserRequest urequest, Controller source, Event event) {
-		if (source.equals(searchController)) {
-			if (event == ReferencableEntriesSearchController.EVENT_REPOSITORY_ENTRY_SELECTED) {
-				// repository search controller done				
-				cmc.deactivate();
-				RepositoryEntry re = searchController.getSelectedEntry();
-				doIQReference(urequest, re);
-				updateEditController(urequest);
-				checkEssay(re);
-			}
-		} else if (source == accessibilityCondContr) {
+		if (source == accessibilityCondContr) {
 			if (event == Event.CHANGED_EVENT) {
 				Condition cond = accessibilityCondContr.getCondition();
 				courseNode.setPreConditionAccess(cond);
 				fireEvent(urequest, NodeEditController.NODECONFIG_CHANGED_EVENT);
 			}
-		} else if (source == fccecontr) {
-			if (event == FileChooseCreateEditController.FILE_CHANGED_EVENT) {
-			    String chosenFile = fccecontr.getChosenFile();
-			    if (chosenFile != null){
-			        moduleConfiguration.set(CONFIG_KEY_DISCLAIMER, fccecontr.getChosenFile());
-			    }
-			    else {
-			        moduleConfiguration.remove(CONFIG_KEY_DISCLAIMER);
-			    }
+		} else if (source == configurationCtrl) {
+			if (event == NodeEditController.NODECONFIG_CHANGED_EVENT) {
 				fireEvent(urequest, NodeEditController.NODECONFIG_CHANGED_EVENT);
-			} else if (event == FileChooseCreateEditController.ALLOW_RELATIVE_LINKS_CHANGED_EVENT) {
-				allowRelativeLinks = fccecontr.getAllowRelativeLinks();
-				courseNode.getModuleConfiguration().setBooleanEntry(CONFIG_KEY_ALLOW_RELATIVE_LINKS, allowRelativeLinks.booleanValue());
-				fireEvent(urequest, NodeEditController.NODECONFIG_CHANGED_EVENT);
-			}
-		} else if (source == correctQTIcontroller){
-			if(event == Event.DONE_EVENT){
-				//getWindowControl().pop();
 			}
-		} else if (source == replaceWizard) {
-			if(event == Event.CANCELLED_EVENT) {
-				cmc.deactivate();
-			} else if(event == Event.DONE_EVENT) {
-				cmc.deactivate();
-				String repositorySoftKey = (String) moduleConfiguration.get(IQEditController.CONFIG_KEY_REPOSITORY_SOFTKEY);
-				Long repKey = RepositoryManager.getInstance().lookupRepositoryEntryBySoftkey(repositorySoftKey, true).getKey();
-				QTIResultManager.getInstance().deleteAllResults(course.getResourceableId(), courseNode.getIdent(), repKey);
-				removeIQReference(moduleConfiguration);
-				VFSStatus isDeleted = iqManager.removeQtiSerFiles(course.getResourceableId(), courseNode.getIdent());
-				if (!isDeleted.equals(VFSConstants.YES)) {
-					// couldn't removed qtiser files
-					log.warn("Couldn't removed course node folder! Course resourceable id: " + course.getResourceableId() + ", Course node ident: " + courseNode.getIdent());
-				}
-				doIQReference(urequest, replaceWizard.getSelectedRepositoryEntry());
-			}
-		} else if (source == mod12ConfigForm) { // config form action
-			if (event == Event.DONE_EVENT) {				
-				doMod12ConfigForm(mod12ConfigForm);
-				fireEvent(urequest, NodeEditController.NODECONFIG_CHANGED_EVENT);
-			}
-		} else if (source == modOnyxConfigForm) {
-			if (event == Event.DONE_EVENT || event == Event.CHANGED_EVENT) {
-				doModOnyxConfigForm(modOnyxConfigForm);
-				fireEvent(urequest, NodeEditController.NODECONFIG_CHANGED_EVENT);
-			}
-		}
-	}
-	
-	private void checkEssay(RepositoryEntry re) {
-		if(OnyxModule.isOnyxTest(re.getOlatResource())) return;
-		if(courseNode instanceof IQSURVCourseNode || courseNode instanceof IQSELFCourseNode) return;
-		
-		TestFileResource fr = new TestFileResource();
-		fr.overrideResourceableId(re.getOlatResource().getResourceableId());
-		QTIEditorPackage qtiPackage = new QTIEditorPackageImpl(getIdentity(), fr, null, getTranslator());
-		Assessment ass = qtiPackage.getQTIDocument().getAssessment();
-
-		//Sections with their Items
-		List<Section> sections = ass.getSections();
-		for (Section section:sections) {
-			List<Item> items = section.getItems();
-			for (Item item:items) {
-				String ident = item.getIdent();
-				if(ident != null && ident.startsWith("QTIEDIT:ESSAY")) {
-					showWarning("warning.test.with.essay");
-					break;
-				}
-			}
-		}
-	}
-	
-	private void doModOnyxConfigForm(IQEditForm modConfigForm) {
-		moduleConfiguration.set(CONFIG_KEY_TEMPLATE, modConfigForm.getTemplate());
-		if (!(type.equals(AssessmentInstance.QMD_ENTRY_TYPE_SURVEY))) {
-			moduleConfiguration.set(CONFIG_KEY_ATTEMPTS, modConfigForm.getAttempts());
-			moduleConfiguration.set(CONFIG_KEY_CUTVALUE, modConfigForm.getCutValue());
-		}
-		moduleConfiguration.set(CONFIG_KEY_DATE_DEPENDENT_RESULTS, new Boolean(modConfigForm.isShowResultsDateDependent()));
-		moduleConfiguration.set(CONFIG_KEY_RESULTS_START_DATE, modConfigForm.getShowResultsStartDate());
-		moduleConfiguration.set(CONFIG_KEY_RESULTS_END_DATE, modConfigForm.getShowResultsEndDate());
-		moduleConfiguration.set(CONFIG_KEY_RESULT_ON_HOME_PAGE, modConfigForm.isShowResultsOnHomePage());
-		//<OLATCE-982>
-		moduleConfiguration.set(CONFIG_KEY_ALLOW_SHOW_SOLUTION, modConfigForm.allowShowSolution());
-		//</OLATCE-982>
-		//<OLATCE-2009>
-		moduleConfiguration.set(CONFIG_KEY_ALLOW_SUSPENSION_ALLOWED, modConfigForm.allowSuspension());
-		//</OLATCE-2009>
-	}
-	
-	private void doMod12ConfigForm(IQ12EditForm modConfigForm) {
-		moduleConfiguration.set(CONFIG_KEY_DISPLAYMENU, new Boolean(modConfigForm.isDisplayMenu()));
-		moduleConfiguration.set(CONFIG_FULLWINDOW, new Boolean(modConfigForm.isFullWindow()));
-		
-		if (modConfigForm.isDisplayMenu()) {
-			moduleConfiguration.set(CONFIG_KEY_RENDERMENUOPTION, modConfigForm.isMenuRenderSectionsOnly());
-			moduleConfiguration.set(CONFIG_KEY_ENABLEMENU, new Boolean(modConfigForm.isEnableMenu()));
-		} else {
-			// set default values when menu is not displayed
-			moduleConfiguration.set(CONFIG_KEY_RENDERMENUOPTION, Boolean.FALSE);
-			moduleConfiguration.set(CONFIG_KEY_ENABLEMENU, Boolean.FALSE); 
-		}
-		
-		moduleConfiguration.set(CONFIG_KEY_QUESTIONPROGRESS, new Boolean(modConfigForm.isDisplayQuestionProgress()));
-		moduleConfiguration.set(CONFIG_KEY_SEQUENCE, modConfigForm.getSequence());
-		moduleConfiguration.set(CONFIG_KEY_ENABLECANCEL, new Boolean(modConfigForm.isEnableCancel()));
-		moduleConfiguration.set(CONFIG_KEY_ENABLESUSPEND, new Boolean(modConfigForm.isEnableSuspend()));
-		moduleConfiguration.set(CONFIG_KEY_QUESTIONTITLE, new Boolean(modConfigForm.isDisplayQuestionTitle()));
-		moduleConfiguration.set(CONFIG_KEY_AUTOENUM_CHOICES, new Boolean(modConfigForm.isAutoEnumChoices()));
-		moduleConfiguration.set(CONFIG_KEY_MEMO, new Boolean(modConfigForm.isProvideMemoField()));
-		// Only tests and selftests have summaries and score progress
-		if (!type.equals(AssessmentInstance.QMD_ENTRY_TYPE_SURVEY)) {
-			moduleConfiguration.set(CONFIG_KEY_SUMMARY, modConfigForm.getSummary());
-			moduleConfiguration.set(CONFIG_KEY_SCOREPROGRESS, new Boolean(modConfigForm.isDisplayScoreProgress()));
-			moduleConfiguration.set(CONFIG_KEY_ENABLESCOREINFO, new Boolean(modConfigForm.isEnableScoreInfo()));
-			moduleConfiguration.set(CONFIG_KEY_DATE_DEPENDENT_RESULTS, new Boolean(modConfigForm.isShowResultsDateDependent()));
-			moduleConfiguration.set(CONFIG_KEY_RESULTS_START_DATE, modConfigForm.getShowResultsStartDate());
-			moduleConfiguration.set(CONFIG_KEY_RESULTS_END_DATE, modConfigForm.getShowResultsEndDate());
-			moduleConfiguration.set(CONFIG_KEY_RESULT_ON_FINISH, modConfigForm.isShowResultsAfterFinishTest());
-			moduleConfiguration.set(CONFIG_KEY_RESULT_ON_HOME_PAGE, modConfigForm.isShowResultsOnHomePage());
-		}
-		// Only tests have a limitation on number of attempts
-		if (type.equals(AssessmentInstance.QMD_ENTRY_TYPE_ASSESS)) {
-			moduleConfiguration.set(CONFIG_KEY_ATTEMPTS, modConfigForm.getAttempts());
-			moduleConfiguration.set(CONFIG_KEY_BLOCK_AFTER_SUCCESS, new Boolean(modConfigForm.isBlockAfterSuccess()));
-		}
+		} 
 	}
 	
-	private void doIQReference(UserRequest urequest, RepositoryEntry re) {
-		// repository search controller done				
-		if (re != null) {
-			if (CoordinatorManager.getInstance().getCoordinator().getLocker().isLocked(re.getOlatResource(), null)) {
-				LockResult lockResult = CoordinatorManager.getInstance().getCoordinator().getLocker().acquireLock(re.getOlatResource(), urequest.getIdentity(), null);
-				String fullName = CoreSpringFactory.getImpl(UserManager.class).getUserDisplayName(lockResult.getOwner());
-				showError("error.entry.locked", fullName);
-				if(lockResult.isSuccess()) {
-					//improbable concurrency security
-					CoordinatorManager.getInstance().getCoordinator().getLocker().releaseLock(lockResult);
-				}
-			} else {
-				if(editTestButton != null) {
-					myContent.remove(editTestButton);
-				}
-
-				setIQReference(re, moduleConfiguration);
-				String displayName = StringHelper.escapeHtml(re.getDisplayname());
-				previewLink = LinkFactory.createCustomLink("command.preview", "command.preview", displayName, Link.NONTRANSLATED, myContent, this);
-				previewLink.setIconLeftCSS("o_icon o_icon-fw o_icon_preview");
-				previewLink.setCustomEnabledLinkCSS("o_preview");
-				previewLink.setTitle(getTranslator().translate("command.preview"));
-				myContent.contextPut("dontRenderRepositoryButton", new Boolean(true));
-				// If of type test, get min, max, cut - put in module config and push
-				// to velocity
-				
-				boolean isOnyx = OnyxModule.isOnyxTest(re.getOlatResource());
-				myContent.contextPut("isOnyx", new Boolean(isOnyx));
-				if(isOnyx) {
-					myContent.contextPut("onyxDisplayName", displayName);
-					moduleConfiguration.set(CONFIG_KEY_TYPE_QTI, CONFIG_VALUE_QTI2);
-					setOnyxVariables(re);
-				} else {
-					myContent.contextPut("showOutcomes", Boolean.FALSE);
-					moduleConfiguration.set(CONFIG_KEY_TYPE_QTI, CONFIG_VALUE_QTI1);
-					if (type.equals(AssessmentInstance.QMD_ENTRY_TYPE_ASSESS)) {
-						updateModuleConfigFromQTIFile(re.getOlatResource());
-						// Put values to velocity container
-						myContent.contextPut(CONFIG_KEY_MINSCORE, moduleConfiguration.get(CONFIG_KEY_MINSCORE));
-						myContent.contextPut(CONFIG_KEY_MAXSCORE, moduleConfiguration.get(CONFIG_KEY_MAXSCORE));
-						myContent.contextPut(CONFIG_KEY_CUTVALUE, moduleConfiguration.get(CONFIG_KEY_CUTVALUE));
-					}
-					if (isEditable(urequest.getIdentity(), urequest.getUserSession().getRoles(), re)) {
-						editTestButton = LinkFactory.createButtonSmall("command.editRepFile", myContent, this);
-					}
-				}
-				fireEvent(urequest, NodeEditController.NODECONFIG_CHANGED_EVENT);
-			}
-		}
-	}
-
-	/**
-	 * @see org.olat.core.gui.control.generic.tabbable.TabbableDefaultController#addTabs(org.olat.core.gui.components.TabbedPane)
-	 */
+	@Override
 	public void addTabs(TabbedPane tabbedPane) {
 		myTabbedPane = tabbedPane;
 		tabbedPane.addTab(translate(PANE_TAB_ACCESSIBILITY), accessibilityCondContr.getWrappedDefaultAccessConditionVC(translate("condition.accessibility.title")));
 		//PANE_TAB_IQCONFIG_XXX is set during construction time
-		tabbedPane.addTab(translate(PANE_TAB_IQCONFIG_XXX), main);
+		tabbedPane.addTab(translate(PANE_TAB_IQCONFIG_XXX), configurationCtrl.getInitialComponent());
 	}
 
 	/**
@@ -831,66 +336,7 @@ public class IQEditController extends ActivateableTabbableDefaultController impl
 		moduleConfiguration.remove(IQEditController.CONFIG_KEY_REPOSITORY_SOFTKEY);
 	}
 
-	/**
-	 * Update the module configuration from the qti file: read min/max/cut values
-	 * @param res
-	 */
-	private void updateModuleConfigFromQTIFile(OLATResource res) {
-		FileResourceManager frm = FileResourceManager.getInstance();
-		File unzippedRoot = frm.unzipFileResource(res);
-		//with VFS FIXME:pb:c: remove casts to LocalFileImpl and LocalFolderImpl if no longer needed.
-		VFSContainer vfsUnzippedRoot = new LocalFolderImpl(unzippedRoot);
-		VFSItem vfsQTI = vfsUnzippedRoot.resolve("qti.xml");
-		if (vfsQTI==null){
-			throw new AssertException("qti file did not exist even it should be guaranteed by repositor check-in ");
-		}
-		//ensures that InputStream is closed in every case.
-		Document doc = QTIHelper.getDocument((LocalFileImpl)vfsQTI);
-		if(doc == null){
-			//error reading qti file (existence check was made before)
-			throw new AssertException("qti file could not be read " + ((LocalFileImpl)vfsQTI).getBasefile().getAbsolutePath());
-		}
-		// Extract min, max and cut value
-		Float minValue = null, maxValue = null, cutValue = null;
-		Element decvar = (Element) doc.selectSingleNode("questestinterop/assessment/outcomes_processing/outcomes/decvar");
-		if (decvar != null) {
-			Attribute minval = decvar.attribute("minvalue");
-			if (minval != null) {
-				String mv = minval.getValue();
-				try {
-					minValue = new Float(Float.parseFloat(mv));
-				} catch (NumberFormatException e1) {
-					// if not correct in qti file -> ignore
-				}
-			}
-			Attribute maxval = decvar.attribute("maxvalue");
-			if (maxval != null) {
-				String mv = maxval.getValue();
-				try {
-					maxValue = new Float(Float.parseFloat(mv));
-				} catch (NumberFormatException e1) {
-					// if not correct in qti file -> ignore
-				}
-			}
-			Attribute cutval = decvar.attribute("cutvalue");
-			if (cutval != null) {
-				String cv = cutval.getValue();
-				try {
-					cutValue = new Float(Float.parseFloat(cv));
-				} catch (NumberFormatException e1) {
-					// if not correct in qti file -> ignore
-				}
-			}
-		}
-		// Put values to module configuration
-		moduleConfiguration.set(CONFIG_KEY_MINSCORE, minValue);
-		moduleConfiguration.set(CONFIG_KEY_MAXSCORE, maxValue);
-		moduleConfiguration.set(CONFIG_KEY_CUTVALUE, cutValue);
-	}
-
-	/**
-	 * @see org.olat.core.gui.control.DefaultController#doDispose(boolean)
-	 */
+	@Override
 	protected void doDispose() {
     //child controllers registered with listenTo() get disposed in BasicController
 		if (previewLayoutCtr != null) {
@@ -899,13 +345,13 @@ public class IQEditController extends ActivateableTabbableDefaultController impl
 		}
 	}
 	
+	@Override
 	public String[] getPaneKeys() {
 		return paneKeys;
 	}
 
+	@Override
 	public TabbedPane getTabbedPane() {
 		return myTabbedPane;
 	}
-
-
 }
\ No newline at end of file
diff --git a/src/main/java/org/olat/course/nodes/iq/IQPreviewController.java b/src/main/java/org/olat/course/nodes/iq/IQPreviewController.java
index 1eac23ac2146a3acd043f8b8e573437ea1f56561..e6f82f133f68736bafcc645e25b9ba126b4bf8a1 100644
--- a/src/main/java/org/olat/course/nodes/iq/IQPreviewController.java
+++ b/src/main/java/org/olat/course/nodes/iq/IQPreviewController.java
@@ -42,7 +42,7 @@ import org.olat.course.run.userview.UserCourseEnvironment;
  * 
  * @author Felix Jost
  */
-class IQPreviewController extends BasicController {
+public class IQPreviewController extends BasicController {
 
 	private PreviewForm pf;
 	private final UserCourseEnvironment userCourseEnv;
@@ -55,7 +55,7 @@ class IQPreviewController extends BasicController {
 	 * @param cn
 	 * @param ne
 	 */
-	IQPreviewController(UserRequest ureq, WindowControl wControl, UserCourseEnvironment userCourseEnv, IQTESTCourseNode cn) {
+	public IQPreviewController(UserRequest ureq, WindowControl wControl, UserCourseEnvironment userCourseEnv, IQTESTCourseNode cn) {
 		super(ureq, wControl);
 
 		this.userCourseEnv = userCourseEnv;
@@ -65,9 +65,12 @@ class IQPreviewController extends BasicController {
 		putInitialPanel(pf.getInitialComponent());
 	}
 
+	@Override
 	public void event(UserRequest ureq, Component source, Event event) {
 		//
 	}
+	
+	@Override
 	public void event(UserRequest ureq, Controller source, Event event) {
 		if (source == pf) {
 			if (event == Event.DONE_EVENT) {
@@ -86,6 +89,7 @@ class IQPreviewController extends BasicController {
 	/**
 	 * @see org.olat.core.gui.control.DefaultController#doDispose(boolean)
 	 */
+	@Override
 	protected void doDispose() {
 	// nothing to dispose
 	}
diff --git a/src/main/java/org/olat/course/nodes/iq/IQRunController.java b/src/main/java/org/olat/course/nodes/iq/IQRunController.java
index 3dccffb6e16d48444d8e2b83ea848dec92fac413..f716c37f0447566e798d16277bc0a995b48cebf0 100644
--- a/src/main/java/org/olat/course/nodes/iq/IQRunController.java
+++ b/src/main/java/org/olat/course/nodes/iq/IQRunController.java
@@ -139,7 +139,7 @@ public class IQRunController extends BasicController implements GenericEventList
 	 * @param wControl
 	 * @param testCourseNode
 	 */
-	IQRunController(UserCourseEnvironment userCourseEnv, ModuleConfiguration moduleConfiguration, IQSecurityCallback secCallback, UserRequest ureq, WindowControl wControl, IQTESTCourseNode testCourseNode) {
+	public IQRunController(UserCourseEnvironment userCourseEnv, ModuleConfiguration moduleConfiguration, IQSecurityCallback secCallback, UserRequest ureq, WindowControl wControl, IQTESTCourseNode testCourseNode) {
 		super(ureq, wControl, Util.createPackageTranslator(CourseNode.class, ureq.getLocale()));
 		
 		this.modConfig = moduleConfiguration;
@@ -230,7 +230,7 @@ public class IQRunController extends BasicController implements GenericEventList
 	 * @param wControl
 	 * @param selftestCourseNode
 	 */
-	IQRunController(UserCourseEnvironment userCourseEnv, ModuleConfiguration moduleConfiguration, IQSecurityCallback secCallback, UserRequest ureq, WindowControl wControl, IQSELFCourseNode selftestCourseNode) {
+	public IQRunController(UserCourseEnvironment userCourseEnv, ModuleConfiguration moduleConfiguration, IQSecurityCallback secCallback, UserRequest ureq, WindowControl wControl, IQSELFCourseNode selftestCourseNode) {
 		super(ureq, wControl, Util.createPackageTranslator(CourseNode.class, ureq.getLocale()));
 		
 		this.modConfig = moduleConfiguration;
@@ -271,7 +271,7 @@ public class IQRunController extends BasicController implements GenericEventList
 	 * @param wControl
 	 * @param surveyCourseNode
 	 */
-	IQRunController(UserCourseEnvironment userCourseEnv, ModuleConfiguration moduleConfiguration, IQSecurityCallback secCallback, UserRequest ureq, WindowControl wControl, IQSURVCourseNode surveyCourseNode) {
+	public IQRunController(UserCourseEnvironment userCourseEnv, ModuleConfiguration moduleConfiguration, IQSecurityCallback secCallback, UserRequest ureq, WindowControl wControl, IQSURVCourseNode surveyCourseNode) {
 		super(ureq, wControl, Util.createPackageTranslator(CourseNode.class, ureq.getLocale()));
 		
 		this.modConfig = moduleConfiguration;
diff --git a/src/main/java/org/olat/course/nodes/iq/IQUIFactory.java b/src/main/java/org/olat/course/nodes/iq/IQUIFactory.java
deleted file mode 100644
index e6c086868382556f92f8745915e9e923939f53a2..0000000000000000000000000000000000000000
--- a/src/main/java/org/olat/course/nodes/iq/IQUIFactory.java
+++ /dev/null
@@ -1,97 +0,0 @@
-/**
-* OLAT - Online Learning and Training<br>
-* http://www.olat.org
-* <p>
-* Licensed under the Apache License, Version 2.0 (the "License"); <br>
-* you may not use this file except in compliance with the License.<br>
-* You may obtain a copy of the License at
-* <p>
-* http://www.apache.org/licenses/LICENSE-2.0
-* <p>
-* Unless required by applicable law or agreed to in writing,<br>
-* software distributed under the License is distributed on an "AS IS" BASIS, <br>
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br>
-* See the License for the specific language governing permissions and <br>
-* limitations under the License.
-* <p>
-* Copyright (c) since 2004 at Multimedia- & E-Learning Services (MELS),<br>
-* University of Zurich, Switzerland.
-* <hr>
-* <a href="http://www.openolat.org">
-* OpenOLAT - Online Learning and Training</a><br>
-* This file has been modified by the OpenOLAT community. Changes are licensed
-* under the Apache 2.0 license as the original file.
-*/
-package org.olat.course.nodes.iq;
-
-import org.olat.core.gui.UserRequest;
-import org.olat.core.gui.components.stack.BreadcrumbPanel;
-import org.olat.core.gui.control.Controller;
-import org.olat.core.gui.control.WindowControl;
-import org.olat.core.gui.control.generic.tabbable.TabbableController;
-import org.olat.course.ICourse;
-import org.olat.course.groupsandrights.CourseGroupManager;
-import org.olat.course.nodes.IQSELFCourseNode;
-import org.olat.course.nodes.IQSURVCourseNode;
-import org.olat.course.nodes.IQTESTCourseNode;
-import org.olat.course.run.userview.UserCourseEnvironment;
-
-/**
- * Description:<br>
- * TODO: patrickb Class Description for IQUIFactory
- * 
- * <P>
- * Initial Date: 18.06.2010 <br>
- * 
- * @author patrickb
- */
-public class IQUIFactory {
-
-	/**
-	 * [SPRING] builds the SpecificControllerCreator as argument in the
-	 * constructor. This "extension point" was created during ONYX integration
-	 * review. It delegates creation to the factory instead of using new
-	 * XXXController(..) creation of different IQxyzRun / IQxyzEdit /
-	 * IQxyzPreviewControllers within the IQxyzCourseNodes.
-	 */
-	private static IQControllerCreator iqControllerCreator = new IQControllerCreatorOlat();
-
-	public IQUIFactory() {
-		//
-	}
-
-	public static TabbableController createIQTestEditController(UserRequest ureq, WindowControl wControl, BreadcrumbPanel stackPanel, ICourse course,
-			IQTESTCourseNode courseNode, CourseGroupManager groupMgr, UserCourseEnvironment euce) {
-		return IQUIFactory.iqControllerCreator.createIQTestEditController(ureq, wControl, stackPanel, course, courseNode, groupMgr, euce);
-	}
-
-	public static TabbableController createIQSelftestEditController(UserRequest ureq, WindowControl wControl, BreadcrumbPanel stackPanel, ICourse course,
-			IQSELFCourseNode courseNode, CourseGroupManager groupMgr, UserCourseEnvironment euce) {
-		return IQUIFactory.iqControllerCreator.createIQSelftestEditController(ureq, wControl, stackPanel, course, courseNode, groupMgr, euce);
-	}
-
-	public static TabbableController createIQSurveyEditController(UserRequest ureq, WindowControl wControl, BreadcrumbPanel stackPanel, ICourse course,
-			IQSURVCourseNode courseNode, CourseGroupManager groupMgr, UserCourseEnvironment euce) {
-		return IQUIFactory.iqControllerCreator.createIQSurveyEditController(ureq, wControl, stackPanel,  course, courseNode, groupMgr, euce);
-	}
-
-	public static Controller createIQTestRunController(UserRequest ureq, WindowControl wControl, UserCourseEnvironment userCourseEnv,
-			IQTESTCourseNode courseNode) {
-		return IQUIFactory.iqControllerCreator.createIQTestRunController(ureq, wControl, userCourseEnv, courseNode);
-	}
-
-	public static Controller createIQTestPreviewController(UserRequest ureq, WindowControl wControl, UserCourseEnvironment userCourseEnv,
-			IQTESTCourseNode courseNode) {
-		return IQUIFactory.iqControllerCreator.createIQTestPreviewController(ureq, wControl, userCourseEnv, courseNode);
-	}
-
-	public static Controller createIQSelftestRunController(UserRequest ureq, WindowControl wControl, UserCourseEnvironment userCourseEnv,
-			IQSELFCourseNode courseNode) {
-		return IQUIFactory.iqControllerCreator.createIQSelftestRunController(ureq, wControl, userCourseEnv, courseNode);
-	}
-
-	public static Controller createIQSurveyRunController(UserRequest ureq, WindowControl wControl, UserCourseEnvironment userCourseEnv,
-			IQSURVCourseNode courseNode) {
-		return IQUIFactory.iqControllerCreator.createIQSurveyRunController(ureq, wControl, userCourseEnv, courseNode);
-	}
-}
diff --git a/src/main/java/org/olat/course/nodes/qti21/QTI21AssessmentDetailsController.java b/src/main/java/org/olat/course/nodes/iq/QTI21AssessmentDetailsController.java
similarity index 94%
rename from src/main/java/org/olat/course/nodes/qti21/QTI21AssessmentDetailsController.java
rename to src/main/java/org/olat/course/nodes/iq/QTI21AssessmentDetailsController.java
index 68c2617b2fe540c37593efdbb8f03ae4097bbe44..1711070cd9f1d277406c0e3937a76857f7ed6ec3 100644
--- a/src/main/java/org/olat/course/nodes/qti21/QTI21AssessmentDetailsController.java
+++ b/src/main/java/org/olat/course/nodes/iq/QTI21AssessmentDetailsController.java
@@ -17,7 +17,7 @@
  * frentix GmbH, http://www.frentix.com
  * <p>
  */
-package org.olat.course.nodes.qti21;
+package org.olat.course.nodes.iq;
 
 import java.util.List;
 
@@ -39,8 +39,8 @@ 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.id.Identity;
-import org.olat.course.nodes.QTI21AssessmentCourseNode;
-import org.olat.course.nodes.qti21.QTI21TestSessionTableModel.TSCols;
+import org.olat.course.nodes.IQTESTCourseNode;
+import org.olat.course.nodes.iq.QTI21TestSessionTableModel.TSCols;
 import org.olat.course.run.userview.UserCourseEnvironment;
 import org.olat.ims.qti21.QTI21Service;
 import org.olat.ims.qti21.UserTestSession;
@@ -61,7 +61,7 @@ public class QTI21AssessmentDetailsController extends FormBasicController {
 	
 	private Identity assessedIdentity;
 	private RepositoryEntry courseEntry;
-	private QTI21AssessmentCourseNode courseNode;
+	private IQTESTCourseNode courseNode;
 	
 	private CloseableModalController cmc;
 	private AssessmentResultController resultCtrl;
@@ -70,7 +70,7 @@ public class QTI21AssessmentDetailsController extends FormBasicController {
 	private QTI21Service qtiService;
 	
 	public QTI21AssessmentDetailsController(UserRequest ureq, WindowControl wControl,
-			UserCourseEnvironment userCourseEnvironment, QTI21AssessmentCourseNode courseNode) {
+			UserCourseEnvironment userCourseEnvironment, IQTESTCourseNode courseNode) {
 		super(ureq, wControl, "assessment_details");
 		
 		this.courseNode = courseNode;
diff --git a/src/main/java/org/olat/course/nodes/qti21/QTI21AssessmentRunController.java b/src/main/java/org/olat/course/nodes/iq/QTI21AssessmentRunController.java
similarity index 93%
rename from src/main/java/org/olat/course/nodes/qti21/QTI21AssessmentRunController.java
rename to src/main/java/org/olat/course/nodes/iq/QTI21AssessmentRunController.java
index 95210ef329465ac909f13bb11bb8002485f2a198..6380df660fdbdd7d2fb817f919df49ca82221049 100644
--- a/src/main/java/org/olat/course/nodes/qti21/QTI21AssessmentRunController.java
+++ b/src/main/java/org/olat/course/nodes/iq/QTI21AssessmentRunController.java
@@ -17,7 +17,7 @@
  * frentix GmbH, http://www.frentix.com
  * <p>
  */
-package org.olat.course.nodes.qti21;
+package org.olat.course.nodes.iq;
 
 import java.text.DateFormat;
 import java.util.Date;
@@ -40,6 +40,7 @@ import org.olat.core.logging.activity.ThreadLocalUserActivityLogger;
 import org.olat.core.util.Formatter;
 import org.olat.core.util.StringHelper;
 import org.olat.core.util.UserSession;
+import org.olat.core.util.Util;
 import org.olat.core.util.event.EventBus;
 import org.olat.core.util.event.GenericEventListener;
 import org.olat.core.util.resource.OresHelper;
@@ -49,9 +50,8 @@ import org.olat.course.ICourse;
 import org.olat.course.assessment.AssessmentHelper;
 import org.olat.course.auditing.UserNodeAuditManager;
 import org.olat.course.nodes.AssessableCourseNode;
-import org.olat.course.nodes.QTI21AssessmentCourseNode;
-import org.olat.course.nodes.iq.AssessmentEvent;
-import org.olat.course.nodes.iq.IQEditController;
+import org.olat.course.nodes.CourseNode;
+import org.olat.course.nodes.IQTESTCourseNode;
 import org.olat.course.run.scoring.ScoreEvaluation;
 import org.olat.course.run.userview.UserCourseEnvironment;
 import org.olat.ims.qti.process.AssessmentInstance;
@@ -83,14 +83,14 @@ public class QTI21AssessmentRunController extends BasicController implements Gen
 	private final UserSession userSession;
 	private final ModuleConfiguration config;
 	private final UserCourseEnvironment userCourseEnv;
-	private final QTI21AssessmentCourseNode courseNode;
+	private final IQTESTCourseNode courseNode;
 	
 	private AssessmentTestDisplayController displayCtrl;
 	private LayoutMain3ColsController displayContainerController;
 	
 	public QTI21AssessmentRunController(UserRequest ureq, WindowControl wControl,
-			UserCourseEnvironment userCourseEnv, QTI21AssessmentCourseNode courseNode) {
-		super(ureq, wControl);
+			UserCourseEnvironment userCourseEnv, IQTESTCourseNode courseNode) {
+		super(ureq, wControl, Util.createPackageTranslator(CourseNode.class, ureq.getLocale()));
 		
 		this.courseNode = courseNode;
 		this.userCourseEnv = userCourseEnv;
@@ -98,7 +98,7 @@ public class QTI21AssessmentRunController extends BasicController implements Gen
 		config = courseNode.getModuleConfiguration();
 		singleUserEventCenter = ureq.getUserSession().getSingleUserEventCenter();
 		
-		mainVC = createVelocityContainer("run");
+		mainVC = createVelocityContainer("assessment_run");
 		init();
 		initAssessment(ureq);
 		putInitialPanel(mainVC);
@@ -112,11 +112,11 @@ public class QTI21AssessmentRunController extends BasicController implements Gen
 	
 	private void initAssessment(UserRequest ureq) {
 	    // config : show score info
-		boolean enableScoreInfo= config.getBooleanSafe(QTI21AssessmentCourseNode.CONFIG_KEY_ENABLESCOREINFO);
+		boolean enableScoreInfo= config.getBooleanSafe(IQEditController.CONFIG_KEY_ENABLESCOREINFO);
 		mainVC.contextPut("enableScoreInfo", new Boolean(enableScoreInfo));	
 	   
 	    // configuration data
-		mainVC.contextPut("attemptsConfig", config.get(QTI21AssessmentCourseNode.CONFIG_KEY_ATTEMPTS));
+		mainVC.contextPut("attemptsConfig", config.get(IQEditController.CONFIG_KEY_ATTEMPTS));
 	    // user data
 	    if (!(courseNode instanceof AssessableCourseNode)) {
 	    	throw new AssertException("exposeUserTestDataToVC can only be called for test nodes, not for selftest or questionnaire");
@@ -126,7 +126,7 @@ public class QTI21AssessmentRunController extends BasicController implements Gen
 		ScoreEvaluation scoreEval = acn.getUserScoreEvaluation(userCourseEnv);
 		
 		//block if test passed (and config set to check it)
-		boolean blockAfterSuccess = config.getBooleanSafe(QTI21AssessmentCourseNode.CONFIG_KEY_BLOCK_AFTER_SUCCESS);
+		boolean blockAfterSuccess = config.getBooleanSafe(IQEditController.CONFIG_KEY_BLOCK_AFTER_SUCCESS);
 		Boolean blocked = Boolean.FALSE;
 		if(blockAfterSuccess) {
 			Boolean passed = scoreEval.getPassed();
@@ -253,7 +253,7 @@ public class QTI21AssessmentRunController extends BasicController implements Gen
 			Controller disposedRestartController = new LayoutMain3ColsController(ureq, getWindowControl(), empty, courseCloser.getInitialComponent(), "disposed course while in assessment run " + courseResId);
 			displayContainerController.setDisposedMessageController(disposedRestartController);
 			
-			boolean fullWindow = config.getBooleanSafe(QTI21AssessmentCourseNode.CONFIG_FULLWINDOW);
+			boolean fullWindow = config.getBooleanSafe(IQEditController.CONFIG_FULLWINDOW);
 			if(fullWindow) {
 				displayContainerController.setAsFullscreen(ureq);
 			}
diff --git a/src/main/java/org/olat/course/nodes/iq/QTI21EditForm.java b/src/main/java/org/olat/course/nodes/iq/QTI21EditForm.java
new file mode 100644
index 0000000000000000000000000000000000000000..6c1187d84dea621a0ef043958216360069607279
--- /dev/null
+++ b/src/main/java/org/olat/course/nodes/iq/QTI21EditForm.java
@@ -0,0 +1,78 @@
+/**
+ * <a href="http://www.openolat.org">
+ * OpenOLAT - Online Learning and Training</a><br>
+ * <p>
+ * Licensed under the Apache License, Version 2.0 (the "License"); <br>
+ * you may not use this file except in compliance with the License.<br>
+ * You may obtain a copy of the License at the
+ * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a>
+ * <p>
+ * Unless required by applicable law or agreed to in writing,<br>
+ * software distributed under the License is distributed on an "AS IS" BASIS, <br>
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br>
+ * See the License for the specific language governing permissions and <br>
+ * limitations under the License.
+ * <p>
+ * Initial code contributed and copyrighted by<br>
+ * frentix GmbH, http://www.frentix.com
+ * <p>
+ */
+package org.olat.course.nodes.iq;
+
+import org.olat.core.gui.UserRequest;
+import org.olat.core.gui.components.form.flexible.FormItemContainer;
+import org.olat.core.gui.components.form.flexible.elements.SelectionElement;
+import org.olat.core.gui.components.form.flexible.impl.FormBasicController;
+import org.olat.core.gui.control.Controller;
+import org.olat.core.gui.control.Event;
+import org.olat.core.gui.control.WindowControl;
+import org.olat.modules.ModuleConfiguration;
+
+/**
+ * 
+ * Initial date: 26.06.2015<br>
+ * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
+ *
+ */
+public class QTI21EditForm extends FormBasicController {
+	
+
+	private SelectionElement fullWindowEl;
+	
+	private ModuleConfiguration modConfig;
+	
+	public QTI21EditForm(UserRequest ureq, WindowControl wControl, ModuleConfiguration modConfig) {
+		super(ureq, wControl);
+		
+		this.modConfig = modConfig;
+		
+		initForm(ureq);
+	}
+
+	@Override
+	protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) {
+		boolean fullWindow = modConfig.getBooleanSafe(IQEditController.CONFIG_FULLWINDOW);
+		fullWindowEl = uifactory.addCheckboxesHorizontal("fullwindow", "qti.form.fullwindow", formLayout, new String[]{"x"}, new String[]{""});
+		fullWindowEl.select("x", fullWindow);
+		
+		uifactory.addSpacerElement("submitSpacer", formLayout, true);
+		uifactory.addFormSubmitButton("submit", formLayout);
+	}
+	
+	@Override
+	protected void doDispose() {
+		//
+	}
+
+	@Override
+	protected void formOK(UserRequest ureq) {
+		modConfig.setBooleanEntry(IQEditController.CONFIG_FULLWINDOW, fullWindowEl.isSelected(0));
+
+		fireEvent(ureq, Event.DONE_EVENT);
+	}
+
+
+	
+	
+
+}
diff --git a/src/main/java/org/olat/course/nodes/qti21/QTI21TestSessionTableModel.java b/src/main/java/org/olat/course/nodes/iq/QTI21TestSessionTableModel.java
similarity index 98%
rename from src/main/java/org/olat/course/nodes/qti21/QTI21TestSessionTableModel.java
rename to src/main/java/org/olat/course/nodes/iq/QTI21TestSessionTableModel.java
index fee59918170ab8d4767c27f3042d5f5631926823..5f833c95f847951131aec9a5b07da3a95d607b29 100644
--- a/src/main/java/org/olat/course/nodes/qti21/QTI21TestSessionTableModel.java
+++ b/src/main/java/org/olat/course/nodes/iq/QTI21TestSessionTableModel.java
@@ -17,7 +17,7 @@
  * frentix GmbH, http://www.frentix.com
  * <p>
  */
-package org.olat.course.nodes.qti21;
+package org.olat.course.nodes.iq;
 
 import java.util.Date;
 
diff --git a/src/main/java/org/olat/course/nodes/qti21/_content/assessment_details.html b/src/main/java/org/olat/course/nodes/iq/_content/assessment_details.html
similarity index 100%
rename from src/main/java/org/olat/course/nodes/qti21/_content/assessment_details.html
rename to src/main/java/org/olat/course/nodes/iq/_content/assessment_details.html
diff --git a/src/main/java/org/olat/course/nodes/qti21/_content/run.html b/src/main/java/org/olat/course/nodes/iq/_content/assessment_run.html
similarity index 98%
rename from src/main/java/org/olat/course/nodes/qti21/_content/run.html
rename to src/main/java/org/olat/course/nodes/iq/_content/assessment_run.html
index a308a1e59eeb0a20e794867462bf4b74929d33e3..522ebc77612459af89939bd364bac9be2b71c921 100644
--- a/src/main/java/org/olat/course/nodes/qti21/_content/run.html
+++ b/src/main/java/org/olat/course/nodes/iq/_content/assessment_run.html
@@ -115,7 +115,7 @@
 	#end
 		
 	<div class="o_statusinfo">
-		<p>$r.translate("intro.assessment")</p>
+		<p>$r.translate("Intro.test")</p>
 		<p>$r.translate("info.assessment")</p>
 		#if ($hasChatWindowOpen)
 		<p>$r.translate("close.chat.windows.for.test")</p>
diff --git a/src/main/java/org/olat/course/nodes/iq/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/course/nodes/iq/_i18n/LocalStrings_de.properties
index 181bb6a9505e6561fa9ce95b7a4749243b4613f5..f0bc80024a49b81ff9ddd8b572ff579acb52773d 100644
--- a/src/main/java/org/olat/course/nodes/iq/_i18n/LocalStrings_de.properties
+++ b/src/main/java/org/olat/course/nodes/iq/_i18n/LocalStrings_de.properties
@@ -197,4 +197,6 @@ showResults.detailed=Resultate
 showResults.title=Resultate
 showResults.visibility=Die Resultate werden von "{0}" bis "{1}" angezeigt.
 start=Start
+table.header.lastModified=Last modified
+table.header.results=Resultaten
 warning.test.with.essay=$org.olat.ims.qti.editor\:warning.test.with.essay
\ No newline at end of file
diff --git a/src/main/java/org/olat/course/nodes/iq/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/course/nodes/iq/_i18n/LocalStrings_en.properties
index 96bad3020270ab1694f4addcf799f1e13b3792f3..13220c94554c0a4d79893d007fa0b295bfb273a8 100644
--- a/src/main/java/org/olat/course/nodes/iq/_i18n/LocalStrings_en.properties
+++ b/src/main/java/org/olat/course/nodes/iq/_i18n/LocalStrings_en.properties
@@ -197,4 +197,6 @@ showResults.detailed=Results
 showResults.title=Results
 showResults.visibility=Your results will be displayed from "{0}" until "{1}"
 start=Start
+table.header.lastModified=Last modified
+table.header.results=Results
 warning.test.with.essay=$org.olat.ims.qti.editor\:warning.test.with.essay
diff --git a/src/main/java/org/olat/course/nodes/qti21/QTI21AssessmentCourseNodeConfiguration.java b/src/main/java/org/olat/course/nodes/qti21/QTI21AssessmentCourseNodeConfiguration.java
deleted file mode 100644
index b5dbd2a5559f6685d2b6ee90a85158dedb3ba721..0000000000000000000000000000000000000000
--- a/src/main/java/org/olat/course/nodes/qti21/QTI21AssessmentCourseNodeConfiguration.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/**
- * <a href="http://www.openolat.org">
- * OpenOLAT - Online Learning and Training</a><br>
- * <p>
- * Licensed under the Apache License, Version 2.0 (the "License"); <br>
- * you may not use this file except in compliance with the License.<br>
- * You may obtain a copy of the License at the
- * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a>
- * <p>
- * Unless required by applicable law or agreed to in writing,<br>
- * software distributed under the License is distributed on an "AS IS" BASIS, <br>
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br>
- * See the License for the specific language governing permissions and <br>
- * limitations under the License.
- * <p>
- * Initial code contributed and copyrighted by<br>
- * frentix GmbH, http://www.frentix.com
- * <p>
- */
-package org.olat.course.nodes.qti21;
-
-import java.util.Locale;
-
-import org.olat.core.gui.translator.Translator;
-import org.olat.core.util.Util;
-import org.olat.course.nodes.AbstractCourseNodeConfiguration;
-import org.olat.course.nodes.CourseNode;
-import org.olat.course.nodes.CourseNodeConfiguration;
-import org.olat.course.nodes.CourseNodeGroup;
-import org.olat.course.nodes.QTI21AssessmentCourseNode;
-
-/**
- * 
- * Initial date: 23.02.2015<br>
- * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
- *
- */
-public class QTI21AssessmentCourseNodeConfiguration extends AbstractCourseNodeConfiguration {
-
-	@Override
-	public CourseNode getInstance() {
-		return new QTI21AssessmentCourseNode();
-	}
-
-	@Override
-	public String getLinkText(Locale locale) {
-		Translator fallback = Util.createPackageTranslator(CourseNodeConfiguration.class, locale);
-		Translator translator = Util.createPackageTranslator(this.getClass(), locale, fallback);
-		return translator.translate("title_qti21assessment");
-	}
-
-	@Override
-	public String getIconCSSClass() {
-		return "o_qtiassessment_icon";
-	}
-
-	@Override
-	public String getAlias() {
-		return "qti21assessment";
-	}
-
-	@Override
-	public String getGroup() {
-		return CourseNodeGroup.assessment.name();
-	}
-}
diff --git a/src/main/java/org/olat/course/nodes/qti21/QTI21EditController.java b/src/main/java/org/olat/course/nodes/qti21/QTI21EditController.java
deleted file mode 100644
index 68662cd71d064c6a3118e80b5f45f1071e4fd862..0000000000000000000000000000000000000000
--- a/src/main/java/org/olat/course/nodes/qti21/QTI21EditController.java
+++ /dev/null
@@ -1,121 +0,0 @@
-/**
- * <a href="http://www.openolat.org">
- * OpenOLAT - Online Learning and Training</a><br>
- * <p>
- * Licensed under the Apache License, Version 2.0 (the "License"); <br>
- * you may not use this file except in compliance with the License.<br>
- * You may obtain a copy of the License at the
- * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a>
- * <p>
- * Unless required by applicable law or agreed to in writing,<br>
- * software distributed under the License is distributed on an "AS IS" BASIS, <br>
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br>
- * See the License for the specific language governing permissions and <br>
- * limitations under the License.
- * <p>
- * Initial code contributed and copyrighted by<br>
- * frentix GmbH, http://www.frentix.com
- * <p>
- */
-package org.olat.course.nodes.qti21;
-
-import org.olat.core.gui.UserRequest;
-import org.olat.core.gui.components.Component;
-import org.olat.core.gui.components.stack.BreadcrumbPanel;
-import org.olat.core.gui.components.tabbedpane.TabbedPane;
-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.tabbable.ActivateableTabbableDefaultController;
-import org.olat.course.ICourse;
-import org.olat.course.assessment.AssessmentHelper;
-import org.olat.course.condition.Condition;
-import org.olat.course.condition.ConditionEditController;
-import org.olat.course.editor.NodeEditController;
-import org.olat.course.nodes.QTI21AssessmentCourseNode;
-import org.olat.course.run.userview.UserCourseEnvironment;
-import org.olat.course.tree.CourseEditorTreeModel;
-
-/**
- * 
- * Initial date: 19.05.2015<br>
- * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
- *
- */
-public class QTI21EditController extends ActivateableTabbableDefaultController {
-	
-
-	public static final String PANE_TAB_CONFIG_RE = "pane.tab.config.entry";
-	public static final String PANE_TAB_ACCESSIBILITY = "pane.tab.accessibility";
-	
-	public static final String[] paneKeys = {
-		PANE_TAB_ACCESSIBILITY, PANE_TAB_CONFIG_RE
-	};
-	
-	private TabbedPane myTabbedPane;
-	private final QTI21AssessmentCourseNode qtiNode;
-	
-	private final ConditionEditController accessibilityCondCtrl;
-	private final QTI21ReferenceConfigurationController referenceCtrl;
-	
-	public QTI21EditController(UserRequest ureq, WindowControl wControl, BreadcrumbPanel stackPanel,
-			QTI21AssessmentCourseNode qtiNode, ICourse course, UserCourseEnvironment euce) {
-		super(ureq, wControl);
-		
-		this.qtiNode = qtiNode;
-		
-		// Accessibility precondition
-		Condition accessCondition = qtiNode.getPreConditionAccess();
-		CourseEditorTreeModel editorModel = course.getEditorTreeModel();
-		accessibilityCondCtrl = new ConditionEditController(ureq, getWindowControl(),
-				accessCondition, AssessmentHelper.getAssessableNodes(editorModel, qtiNode), euce);		
-		listenTo(accessibilityCondCtrl);
-		
-		referenceCtrl = new QTI21ReferenceConfigurationController(ureq, getWindowControl(), stackPanel, qtiNode);
-		listenTo(referenceCtrl);
-	}
-	
-	@Override
-	protected void doDispose() {
-		//
-	}
-
-	@Override
-	public void addTabs(TabbedPane tabbedPane) {
-		myTabbedPane = tabbedPane;
-		tabbedPane.addTab(translate(PANE_TAB_ACCESSIBILITY), accessibilityCondCtrl.getWrappedDefaultAccessConditionVC(translate("condition.accessibility.title")));
-		tabbedPane.addTab(translate(PANE_TAB_CONFIG_RE), referenceCtrl.getInitialComponent());
-	}
-
-	@Override
-	public String[] getPaneKeys() {
-		return paneKeys;
-	}
-
-	@Override
-	public TabbedPane getTabbedPane() {
-		return myTabbedPane;
-	}
-
-	@Override
-	protected void event(UserRequest ureq, Component source, Event event) {
-		//
-	}
-
-	@Override
-	protected void event(UserRequest ureq, Controller source, Event event) {
-		if (source == accessibilityCondCtrl) {
-			if (event == Event.CHANGED_EVENT) {
-				Condition cond = accessibilityCondCtrl.getCondition();
-				qtiNode.setPreConditionAccess(cond);
-				fireEvent(ureq, NodeEditController.NODECONFIG_CHANGED_EVENT);
-			}
-		} else if(referenceCtrl == source) {
-			if (event == Event.CHANGED_EVENT) {
-				fireEvent(ureq, NodeEditController.NODECONFIG_CHANGED_EVENT);
-			}
-		}
-
-		super.event(ureq, source, event);
-	}
-}
diff --git a/src/main/java/org/olat/course/nodes/qti21/QTI21ReferenceConfigurationController.java b/src/main/java/org/olat/course/nodes/qti21/QTI21ReferenceConfigurationController.java
deleted file mode 100644
index 4e12be4ae19e5482abf893fec99caa85542af94d..0000000000000000000000000000000000000000
--- a/src/main/java/org/olat/course/nodes/qti21/QTI21ReferenceConfigurationController.java
+++ /dev/null
@@ -1,225 +0,0 @@
-/**
- * <a href="http://www.openolat.org">
- * OpenOLAT - Online Learning and Training</a><br>
- * <p>
- * Licensed under the Apache License, Version 2.0 (the "License"); <br>
- * you may not use this file except in compliance with the License.<br>
- * You may obtain a copy of the License at the
- * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a>
- * <p>
- * Unless required by applicable law or agreed to in writing,<br>
- * software distributed under the License is distributed on an "AS IS" BASIS, <br>
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br>
- * See the License for the specific language governing permissions and <br>
- * limitations under the License.
- * <p>
- * Initial code contributed and copyrighted by<br>
- * frentix GmbH, http://www.frentix.com
- * <p>
- */
-package org.olat.course.nodes.qti21;
-
-import java.io.File;
-
-import org.olat.core.gui.UserRequest;
-import org.olat.core.gui.components.Component;
-import org.olat.core.gui.components.link.Link;
-import org.olat.core.gui.components.link.LinkFactory;
-import org.olat.core.gui.components.stack.BreadcrumbPanel;
-import org.olat.core.gui.components.velocity.VelocityContainer;
-import org.olat.core.gui.control.Controller;
-import org.olat.core.gui.control.Event;
-import org.olat.core.gui.control.WindowControl;
-import org.olat.core.gui.control.controller.BasicController;
-import org.olat.core.gui.control.generic.closablewrapper.CloseableModalController;
-import org.olat.core.id.Identity;
-import org.olat.core.id.Roles;
-import org.olat.core.util.StringHelper;
-import org.olat.course.nodes.CourseNodeFactory;
-import org.olat.course.nodes.MSCourseNode;
-import org.olat.course.nodes.QTI21AssessmentCourseNode;
-import org.olat.fileresource.FileResourceManager;
-import org.olat.fileresource.types.ImsQTI21Resource;
-import org.olat.ims.qti21.QTI21Constants;
-import org.olat.ims.qti21.QTI21Service;
-import org.olat.ims.qti21.ui.InMemoryOutcomesListener;
-import org.olat.ims.qti21.ui.AssessmentTestDisplayController;
-import org.olat.modules.ModuleConfiguration;
-import org.olat.repository.RepositoryEntry;
-import org.olat.repository.controllers.ReferencableEntriesSearchController;
-import org.olat.resource.OLATResource;
-import org.springframework.beans.factory.annotation.Autowired;
-
-import uk.ac.ed.ph.jqtiplus.node.outcome.declaration.OutcomeDeclaration;
-import uk.ac.ed.ph.jqtiplus.node.test.AssessmentTest;
-import uk.ac.ed.ph.jqtiplus.resolution.ResolvedAssessmentTest;
-import uk.ac.ed.ph.jqtiplus.value.NumberValue;
-import uk.ac.ed.ph.jqtiplus.value.Value;
-
-/**
- * 
- * Initial date: 19.05.2015<br>
- * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
- *
- */
-public class QTI21ReferenceConfigurationController extends BasicController {
-	
-	private Link previewLink, editLink;
-	private final VelocityContainer mainVC;
-	private final Link chooseButton, changeButton;
-	private final BreadcrumbPanel stackPanel;
-
-	private Controller previewCtr;
-	private CloseableModalController cmc;
-	private ReferencableEntriesSearchController searchController;
-	
-	private QTI21AssessmentCourseNode courseNode;
-	private final ModuleConfiguration config;
-	
-	@Autowired
-	private QTI21Service qtiService;
-	
-	public QTI21ReferenceConfigurationController(UserRequest ureq, WindowControl wControl, BreadcrumbPanel stackPanel,
-			QTI21AssessmentCourseNode courseNode) {
-		super(ureq, wControl);
-		
-		this.courseNode = courseNode;
-		this.stackPanel = stackPanel;
-		config = courseNode.getModuleConfiguration();
-		mainVC = createVelocityContainer("reference");
-		
-		chooseButton = LinkFactory.createButtonSmall("command.create", mainVC, this);
-		chooseButton.setElementCssClass("o_sel_qti21_choose_repofile");
-		changeButton = LinkFactory.createButtonSmall("command.change", mainVC, this);
-		changeButton.setElementCssClass("o_sel_qti21_change_repofile");
-		
-		if (config.get(QTI21AssessmentCourseNode.CONFIG_KEY_REPOSITORY_SOFTKEY) != null) {
-			// fetch repository entry to display the repository entry title of the chosen cp
-			RepositoryEntry re = courseNode.getReferencedRepositoryEntry();
-			if (re == null) { // we cannot display the entries name, because the
-				// repository entry had been deleted between the time when it was chosen here, and now				
-				showError("error.entry.missing");
-				mainVC.contextPut("showPreviewButton", Boolean.FALSE);
-				mainVC.contextPut("chosen", translate("no.test.chosen"));
-			} else {
-				if (isEditable(ureq.getIdentity(), ureq.getUserSession().getRoles(), re)) {
-					editLink = LinkFactory.createButtonSmall("edit", mainVC, this);
-				}
-				mainVC.contextPut("showPreviewButton", Boolean.TRUE);
-				String displayname = StringHelper.escapeHtml(re.getDisplayname());
-				previewLink = LinkFactory.createCustomLink("command.preview", "command.preview", displayname, Link.NONTRANSLATED, mainVC, this);
-				previewLink.setIconLeftCSS("o_icon o_icon-fw o_icon_preview");
-				previewLink.setTitle(getTranslator().translate("command.preview"));
-				updateModuleConfigFromQTIFile(re.getOlatResource());
-			}
-		} else {
-			// no valid config yet
-			mainVC.contextPut("showPreviewButton", Boolean.FALSE);
-			mainVC.contextPut("chosen", translate("no.test.chosen"));
-		}
-		
-		putInitialPanel(mainVC);
-	}
-	
-	private boolean isEditable(Identity identity, Roles roles, RepositoryEntry entry) {
-		return identity != null && roles != null && entry != null;
-	}
-	
-	@Override
-	protected void doDispose() {
-		//
-	}
-
-	@Override
-	protected void event(UserRequest ureq, Component source, Event event) {
-		if (source == chooseButton || source == changeButton) {
-			removeAsListenerAndDispose(searchController);
-			searchController = new ReferencableEntriesSearchController(getWindowControl(), ureq, 
-					ImsQTI21Resource.TYPE_NAME, translate("choose"));			
-			listenTo(searchController);
-			
-			removeAsListenerAndDispose(cmc);
-			cmc = new CloseableModalController(getWindowControl(), translate("close"),
-					searchController.getInitialComponent(), true, translate("choose.assessment"));
-			listenTo(cmc);
-			cmc.activate();
-		} else if (source == previewLink){
-			// Preview as modal dialogue only if the config is valid
-			RepositoryEntry re = courseNode.getReferencedRepositoryEntry();
-			if (re == null) { // we cannot preview it, because the repository entry
-				// had been deleted between the time when it was chosen here, and now				
-				showError("error.entry.missing");
-			} else {
-				removeAsListenerAndDispose(previewCtr);
-				InMemoryOutcomesListener listener = new InMemoryOutcomesListener();
-				previewCtr = new AssessmentTestDisplayController(ureq, getWindowControl(), listener, re, null, null);
-				stackPanel.pushController(translate("preview"), previewCtr);
-			}
-		} else if (source == editLink) {
-			CourseNodeFactory.getInstance().launchReferencedRepoEntryEditor(ureq, getWindowControl(), courseNode);
-		}
-	}
-	
-	@Override
-	public void event(UserRequest urequest, Controller source, Event event) {
-		if (source == searchController) {
-			if (event == ReferencableEntriesSearchController.EVENT_REPOSITORY_ENTRY_SELECTED) { 
-				// search controller done
-				// -> close closeable modal controller
-				cmc.deactivate();
-				RepositoryEntry re = searchController.getSelectedEntry();
-				if (re != null) {
-					config.setStringValue(QTI21AssessmentCourseNode.CONFIG_KEY_REPOSITORY_SOFTKEY, re.getSoftkey());
-					updateModuleConfigFromQTIFile(re.getOlatResource());
-					mainVC.contextPut("showPreviewButton", Boolean.TRUE);
-					
-					String displayname = StringHelper.escapeHtml(re.getDisplayname());
-					previewLink = LinkFactory.createCustomLink("command.preview", "command.preview", displayname, Link.NONTRANSLATED, mainVC, this);
-					previewLink.setCustomEnabledLinkCSS("o_preview");
-					previewLink.setTitle(getTranslator().translate("command.preview"));
-					// remove existing edit link, add new one if user is allowed to edit this CP
-					if (editLink != null) {
-						mainVC.remove(editLink);
-						editLink = null;
-					}
-					if (isEditable(urequest.getIdentity(), urequest.getUserSession().getRoles(), re)) {
-						editLink = LinkFactory.createButtonSmall("edit", mainVC, this);
-					}
-					// fire event so the updated config is saved by the editormaincontroller
-					fireEvent(urequest, Event.CHANGED_EVENT);
-				}
-			}
-		}
-	}
-
-	private void updateModuleConfigFromQTIFile(OLATResource res) {
-		FileResourceManager frm = FileResourceManager.getInstance();
-		File fUnzippedDirRoot = frm.unzipFileResource(res);
-		
-		ResolvedAssessmentTest resolvedAssessmentTest = qtiService.loadAndResolveAssessmentObject(fUnzippedDirRoot);
-		AssessmentTest test = resolvedAssessmentTest.getTestLookup().getRootNodeHolder().getRootNode();
-
-		Float minValue = null, maxValue = null, cutValue = null;
-		for (OutcomeDeclaration declaration : test.getOutcomeDeclarations()) {
-			if(QTI21Constants.SCORE_IDENTIFIER.equals(declaration.getIdentifier())) {
-				minValue = extractValue(declaration);
-			} else if(QTI21Constants.MAXSCORE_IDENTIFIER.equals(declaration.getIdentifier())) {
-				maxValue = extractValue(declaration);
-			}
-        }
-	
-		// Put values to module configuration
-		config.set(MSCourseNode.CONFIG_KEY_SCORE_MIN, minValue);
-		config.set(MSCourseNode.CONFIG_KEY_SCORE_MAX, maxValue);
-		config.set(MSCourseNode.CONFIG_KEY_PASSED_CUT_VALUE, cutValue);
-	}
-	
-	private Float extractValue(OutcomeDeclaration declaration) {
-		Float floatValue = null;
-		Value value = declaration.getDefaultValue().evaluate();
-		if(value instanceof NumberValue) {
-			floatValue = (float)((NumberValue)value).doubleValue();
-		}
-		return floatValue;
-	}
-}
diff --git a/src/main/java/org/olat/course/nodes/qti21/_content/reference.html b/src/main/java/org/olat/course/nodes/qti21/_content/reference.html
deleted file mode 100644
index 326221574620cfbb58f62ef8012d8af85c846bce..0000000000000000000000000000000000000000
--- a/src/main/java/org/olat/course/nodes/qti21/_content/reference.html
+++ /dev/null
@@ -1,26 +0,0 @@
-<fieldset class="o_form form-horizontal ">
-	<legend>$r.translate("header")</legend>
-	
-	#if ($showPreviewButton)
-		<div class="form-group">
-			<label class="control-label col-sm-3">$r.translate("chosen")</label>
-			<div class="col-sm-9"><p class="form-control-static">$r.render("command.preview")</p></div>
-		</div>
-		<div class="form-group">
-			<div class="col-sm-offset-3 col-sm-9">
-			$r.render("command.change")	    
-			#if($r.available("edit"))
-				$r.render("edit")
-			#end
-			</div>
-		</div>
-	#else
-		<div class="form-group">
-			<label class="control-label col-sm-3">$r.translate("chosen")</label>
-			<div class="col-sm-9"><p class="form-control-static">$chosen</p></div>
-		</div>
-		<div class="form-group">
-			<div class="col-sm-offset-3 col-sm-9">$r.render("command.create")</div>
-		</div>    
-	#end
-</fieldset>
\ No newline at end of file
diff --git a/src/main/java/org/olat/course/nodes/qti21/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/course/nodes/qti21/_i18n/LocalStrings_de.properties
deleted file mode 100644
index e930ac2fe760ea2ccca45bb9cadbf59981e63ff2..0000000000000000000000000000000000000000
--- a/src/main/java/org/olat/course/nodes/qti21/_i18n/LocalStrings_de.properties
+++ /dev/null
@@ -1,24 +0,0 @@
-#Wed Feb 25 12:01:15 CET 2015
-condition.accessibility.title=Zugang
-chosen=Gew\u00E4hlter QTI 2.1 Assessment
-choose.assessment=QTI 2.1 Assessment ausw\u00E4hlen
-command.preview=Vorschau anzeigen
-command.change=QTI 2.1 Assessment auswechseln
-command.create=QTI 2.1 Assessment w\u00E4hlen, erstellen oder importieren
-command.choose=QTI 2.1 Assessment w\u00E4hlen
-command.close=Ansicht schliessen
-header=QTI 2.1 Assessment ausw\u00E4hlen
-
-no.test.chosen=<i>Kein QTI 2.1 Assessment ausgew\u00E4hlt</i>
-error.entry.missing=Der Assessment, den Sie anzeigen m\u00F6chten, wurde in der Zwischenzeit in der Ablage der Lernressourcen gel\u00F6scht.
-pane.tab.accessibility=Zugang
-pane.tab.config.entry=Konfiguration
-
-qti.form.attempts.noLimit=$org.olat.course.nodes.iq\:qti.form.attempts.noLimit
-qti.form.attempts=$org.olat.course.nodes.iq\:qti.form.attempts
-score.noscoreinfoyet=$org.olat.course.nodes.iq\:score.noscoreinfoyet
-intro.assessment=$org.olat.course.nodes.iq\:Intro.test
-info.assessment=$org.olat.course.nodes.iq\:info.assessment
-
-table.header.lastModified=Last modified
-table.header.results=Resultaten
\ No newline at end of file
diff --git a/src/main/java/org/olat/course/nodes/qti21/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/course/nodes/qti21/_i18n/LocalStrings_en.properties
deleted file mode 100644
index aa8e10ae6dd5151315a22293ccb79f814bd5a338..0000000000000000000000000000000000000000
--- a/src/main/java/org/olat/course/nodes/qti21/_i18n/LocalStrings_en.properties
+++ /dev/null
@@ -1,7 +0,0 @@
-#Wed Feb 25 12:08:35 CET 2015
-condition.accessibility.title=Access
-pane.tab.accessibility=Access
-pane.tab.config.entry=Configuration
-
-intro.assessment=$org.olat.course.nodes.iq\:Intro.test
-info.assessment=$org.olat.course.nodes.iq\:info.assessment
diff --git a/src/main/java/org/olat/ims/qti/statistics/QTIStatisticResourceResult.java b/src/main/java/org/olat/ims/qti/statistics/QTIStatisticResourceResult.java
index 49d1f64577fe17f489c5d189cc05f9fea00a22d8..efa1cc32aff0ea9e682a18513fc9ce1e7f5443d7 100644
--- a/src/main/java/org/olat/ims/qti/statistics/QTIStatisticResourceResult.java
+++ b/src/main/java/org/olat/ims/qti/statistics/QTIStatisticResourceResult.java
@@ -42,6 +42,7 @@ import org.olat.course.nodes.QTICourseNode;
 import org.olat.course.nodes.TitledWrapperHelper;
 import org.olat.course.statistic.StatisticResourceNode;
 import org.olat.course.statistic.StatisticResourceResult;
+import org.olat.fileresource.types.ImsQTI21Resource;
 import org.olat.ims.qti.editor.beecom.objects.Item;
 import org.olat.ims.qti.editor.beecom.objects.QTIDocument;
 import org.olat.ims.qti.editor.beecom.objects.Section;
@@ -53,6 +54,7 @@ import org.olat.ims.qti.statistics.model.StatisticAssessment;
 import org.olat.ims.qti.statistics.ui.QTI12AssessmentStatisticsController;
 import org.olat.ims.qti.statistics.ui.QTI12ItemStatisticsController;
 import org.olat.ims.qti.statistics.ui.QTI21OnyxAssessmentStatisticsController;
+import org.olat.ims.qti21.statistics.ui.QTI21AssessmentTestStatisticsController;
 import org.olat.repository.RepositoryEntry;
 
 import de.bps.onyx.plugin.OnyxModule;
@@ -85,6 +87,8 @@ public class QTIStatisticResourceResult implements StatisticResourceResult {
 		qtiRepositoryEntry = courseNode.getReferencedRepositoryEntry();
 		if(OnyxModule.isOnyxTest(qtiRepositoryEntry.getOlatResource())) {
 			type = QTIType.onyx;
+		} else if(ImsQTI21Resource.TYPE_NAME.equals(qtiRepositoryEntry.getOlatResource().getResourceableTypeName())) {
+			type = QTIType.qtiworks;
 		} else {
 			resolver = new ImsRepositoryResolver(qtiRepositoryEntry);
 			Document doc = resolver.getQTIDocument();
@@ -146,6 +150,10 @@ public class QTIStatisticResourceResult implements StatisticResourceResult {
 			subTreeModel = new GenericTreeModel();
 			StatisticResourceNode rootTreeNode = new StatisticResourceNode(courseNode, this);
 			subTreeModel.setRootNode(rootTreeNode);
+		} else if(type == QTIType.qtiworks) {
+			subTreeModel = new GenericTreeModel();
+			StatisticResourceNode rootTreeNode = new StatisticResourceNode(courseNode, this);
+			subTreeModel.setRootNode(rootTreeNode);
 		} else if(qtiDocument == null) {
 			subTreeModel = null;
 		} else {
@@ -185,6 +193,8 @@ public class QTIStatisticResourceResult implements StatisticResourceResult {
 		Controller ctrl;
 		if (type == QTIType.onyx){
 			ctrl = new QTI21OnyxAssessmentStatisticsController(ureq, wControl, this, printMode);
+		} else if(type == QTIType.qtiworks) {
+			ctrl = new QTI21AssessmentTestStatisticsController(ureq, wControl, this, printMode);
 		} else {
 			ctrl = new QTI12AssessmentStatisticsController(ureq, wControl, stackPanel, this, printMode);
 		}
diff --git a/src/main/java/org/olat/ims/qti/statistics/QTIType.java b/src/main/java/org/olat/ims/qti/statistics/QTIType.java
index 6c53e7603df97f664908d0c0b35254d70a3e08f0..2233db01a86e116c80c4aae1d7137ace148f2da1 100644
--- a/src/main/java/org/olat/ims/qti/statistics/QTIType.java
+++ b/src/main/java/org/olat/ims/qti/statistics/QTIType.java
@@ -28,6 +28,7 @@ public enum QTIType {
 	test,
 	survey,
 	self,
-	onyx
+	onyx,
+	qtiworks
 
 }
diff --git a/src/main/java/org/olat/ims/qti/statistics/ui/StatisticFormatter.java b/src/main/java/org/olat/ims/qti/statistics/ui/StatisticFormatter.java
index 2901e1aaf208edfd269e2ea9dbd3b186e35dea1c..b90ce474f89180349a0b861f455413756b05656f 100644
--- a/src/main/java/org/olat/ims/qti/statistics/ui/StatisticFormatter.java
+++ b/src/main/java/org/olat/ims/qti/statistics/ui/StatisticFormatter.java
@@ -30,24 +30,24 @@ import java.util.concurrent.TimeUnit;
  * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
  *
  */
-class StatisticFormatter {
+public class StatisticFormatter {
 	
 	private final static DecimalFormat numberFormat = new DecimalFormat("#0.#", new DecimalFormatSymbols(Locale.ENGLISH));
 	private final static DecimalFormat scoreFormat = new DecimalFormat("#0.##", new DecimalFormatSymbols(Locale.ENGLISH));
 	
-	protected static String getLabel(int i) {
+	public static String getLabel(int i) {
 		String label = Character.toString((char)(65 + i));
 		return label;
 	}
 	
-	protected static String format(Float score) {
+	public static String format(Float score) {
 		if(score == null) return "";
 		synchronized(numberFormat) {
 			return numberFormat.format(score);
 		}
 	}
 	
-	protected static String format(double score) {
+	public static String format(double score) {
 		if(Double.isNaN(score)) {
 			return "";
 		}
@@ -57,7 +57,7 @@ class StatisticFormatter {
 		}
 	}
 	
-	protected static String formatTwo(double score) {
+	public static String formatTwo(double score) {
 		if(Double.isNaN(score)) {
 			return "";
 		}
@@ -67,7 +67,7 @@ class StatisticFormatter {
 		}
 	}
 	
-	protected static String duration(long duration) {
+	public static String duration(long duration) {
 		return String.format("%d min %d sec", 
 			    TimeUnit.MILLISECONDS.toMinutes(duration),
 			    TimeUnit.MILLISECONDS.toSeconds(duration) - 
@@ -75,7 +75,7 @@ class StatisticFormatter {
 			);
 	}
 	
-	protected static String getModeString(List<Double> modes) {
+	public static String getModeString(List<Double> modes) {
 		StringBuilder sb = new StringBuilder();
 		for(Double mode:modes) {
 			if(sb.length() > 0) sb.append(", ");
diff --git a/src/main/java/org/olat/ims/qti21/statistics/ui/QTI21AssessmentTestStatisticsController.java b/src/main/java/org/olat/ims/qti21/statistics/ui/QTI21AssessmentTestStatisticsController.java
new file mode 100644
index 0000000000000000000000000000000000000000..ea39aa70f509bfd0ab00665520e1902d94cfac78
--- /dev/null
+++ b/src/main/java/org/olat/ims/qti21/statistics/ui/QTI21AssessmentTestStatisticsController.java
@@ -0,0 +1,105 @@
+/**
+ * <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.ims.qti21.statistics.ui;
+
+import static org.olat.ims.qti.statistics.ui.StatisticFormatter.duration;
+import static org.olat.ims.qti.statistics.ui.StatisticFormatter.format;
+import static org.olat.ims.qti.statistics.ui.StatisticFormatter.getModeString;
+
+import org.olat.core.gui.UserRequest;
+import org.olat.core.gui.components.Component;
+import org.olat.core.gui.components.chart.BarSeries;
+import org.olat.core.gui.components.chart.StatisticsComponent;
+import org.olat.core.gui.components.velocity.VelocityContainer;
+import org.olat.core.gui.control.Event;
+import org.olat.core.gui.control.WindowControl;
+import org.olat.core.gui.control.controller.BasicController;
+import org.olat.ims.qti.statistics.QTIStatisticResourceResult;
+import org.olat.ims.qti.statistics.model.StatisticAssessment;
+
+/**
+ * 
+ * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
+ *
+ */
+public class QTI21AssessmentTestStatisticsController extends BasicController {
+	
+	private final VelocityContainer mainVC;
+	
+	private final QTIStatisticResourceResult resourceResult;
+
+	public QTI21AssessmentTestStatisticsController(UserRequest ureq, WindowControl wControl,
+			QTIStatisticResourceResult resourceResult, boolean printMode) {
+		super(ureq, wControl);
+		
+		this.resourceResult = resourceResult;
+
+		mainVC = createVelocityContainer("statistics_assessment_test");
+		mainVC.put("loadd3js", new StatisticsComponent("d3loader"));
+		mainVC.contextPut("printMode", new Boolean(printMode));
+		putInitialPanel(mainVC);
+
+		StatisticAssessment stats = resourceResult.getQTIStatisticAssessment();
+		initScoreHistogram(stats);
+		initDurationHistogram(stats);
+		initCourseNodeInformation(stats);
+	}
+	
+	@Override
+	protected void doDispose() {
+		//
+	}
+
+	private void initCourseNodeInformation(StatisticAssessment stats) {
+		mainVC.contextPut("numOfParticipants", stats.getNumOfParticipants());
+	
+		mainVC.contextPut("type", resourceResult.getType());
+		mainVC.contextPut("numOfPassed", stats.getNumOfPassed());
+		mainVC.contextPut("numOfFailed", stats.getNumOfFailed());
+
+		mainVC.contextPut("average", format(stats.getAverage()));
+		mainVC.contextPut("range", format(stats.getRange()));
+		mainVC.contextPut("standardDeviation", format(stats.getStandardDeviation()));
+		mainVC.contextPut("mode", getModeString(stats.getMode()));
+		mainVC.contextPut("median", format(stats.getMedian()));
+		
+		String duration = duration(stats.getAverageDuration());
+		mainVC.contextPut("averageDuration", duration);
+	}
+
+	private void initScoreHistogram(StatisticAssessment stats) {
+		VelocityContainer scoreHistogramVC = createVelocityContainer("histogram_score");
+		scoreHistogramVC.contextPut("datas", BarSeries.datasToString(stats.getScores()));
+		mainVC.put("scoreHistogram", scoreHistogramVC);
+	}
+	
+	private void initDurationHistogram(StatisticAssessment stats) {
+		if(!BarSeries.hasNotNullDatas(stats.getDurations())) return;
+		
+		VelocityContainer durationHistogramVC = createVelocityContainer("histogram_duration");
+		durationHistogramVC.contextPut("datas", BarSeries.datasToString(stats.getDurations()));
+		mainVC.put("durationHistogram", durationHistogramVC);
+	}
+	
+	@Override
+	protected void event(UserRequest ureq, Component source, Event event) {
+		//
+	}
+}
\ No newline at end of file
diff --git a/src/main/java/org/olat/ims/qti21/statistics/ui/_content/histogram_duration.html b/src/main/java/org/olat/ims/qti21/statistics/ui/_content/histogram_duration.html
new file mode 100644
index 0000000000000000000000000000000000000000..35c29532a9ad9b2d5ca81eabbd82a4ac101a6205
--- /dev/null
+++ b/src/main/java/org/olat/ims/qti21/statistics/ui/_content/histogram_duration.html
@@ -0,0 +1,16 @@
+<div class="o_print_break_avoid">
+	<h4>$r.translate("chart.duration.histogramm")</h4>
+	<div id="$r.getId('d3div')"><div id='$r.getId("d3holder")' class='d3chart' style='width:90%;height:300px'></div>
+	<script type='text/javascript'>
+	/* <![CDATA[ */
+	jQuery(function () {
+		jQuery('#$r.getId("d3holder")').qtiStatistics('histogramDuration', {
+			values: [$datas],
+	        xBottomLegend: '$r.translate("chart.duration.histogramm.legend")',
+	        yLeftLegend: '$r.translate("chart.percent.participants")',
+	        yRightLegend:'$r.translate("chart.percent.participants.num")'
+		});
+	});
+	/* ]]> */</script>
+	</div>
+</div>
\ No newline at end of file
diff --git a/src/main/java/org/olat/ims/qti21/statistics/ui/_content/histogram_score.html b/src/main/java/org/olat/ims/qti21/statistics/ui/_content/histogram_score.html
new file mode 100644
index 0000000000000000000000000000000000000000..ae649ab3882f44d4b788d924324d7f55d4401806
--- /dev/null
+++ b/src/main/java/org/olat/ims/qti21/statistics/ui/_content/histogram_score.html
@@ -0,0 +1,17 @@
+<div class="o_print_break_avoid">
+	<h4>$r.translate("chart.score.histogramm")</h4>
+	<div id="$r.getId('d3div')"><div id='$r.getId("d3holder")' class='d3chart' style='width:90%;height:300px'></div>
+	<script type='text/javascript'>
+	/* <![CDATA[ */
+	jQuery(function () {
+		jQuery('#$r.getId("d3holder")').qtiStatistics('histogramScore', {
+			values: [$datas],
+	        cut: #if($cutValue) $cutValue #else null #end,
+	        xBottomLegend: '$r.translate("chart.points")',
+	        yLeftLegend: '$r.translate("chart.percent.participants")',
+	        yRightLegend:'$r.translate("chart.percent.participants.num")'
+		});
+	});
+	/* ]]> */</script>
+	</div>
+</div>
\ No newline at end of file
diff --git a/src/main/java/org/olat/ims/qti21/statistics/ui/_content/statistics_assessment_test.html b/src/main/java/org/olat/ims/qti21/statistics/ui/_content/statistics_assessment_test.html
new file mode 100644
index 0000000000000000000000000000000000000000..ce36d19f2a62b040887d8c8351213cdb3a1be6f1
--- /dev/null
+++ b/src/main/java/org/olat/ims/qti21/statistics/ui/_content/statistics_assessment_test.html
@@ -0,0 +1,28 @@
+<div class="panel panel-default">
+	<div class="panel-heading"><h4>$r.translate("fig.title")</h4></div>	  	
+	<table class="table"><tbody>
+		<tr><th>$r.translate("fig.participants")</th>
+			<td>$numOfParticipants</td>
+			<th>$r.translate("fig.avg")</th>
+			<td>$average</td></tr>
+		<tr><th>$r.translate("fig.span")</th>
+			<td>$range</td>
+			<th>$r.translate("fig.stddev")</th>
+			<td>$standardDeviation</td></tr>
+		<tr><th>$r.translate("fig.mode")</th>
+			<td>$mode</td>
+			<th>$r.translate("fig.median")</th>
+			<td>$median</td></tr>
+		<tr><th>$r.translate("fig.averagedur")</th>
+			<td>$averageDuration</td>
+			<th></th><td></td>
+			</tr>
+	</tbody></table>
+</div>
+
+#if($r.available("scoreHistogram"))
+	$r.render("scoreHistogram")
+#end
+#if($r.available("durationHistogram"))
+	$r.render("durationHistogram")
+#end
\ No newline at end of file
diff --git a/src/main/java/org/olat/ims/qti21/statistics/ui/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/ims/qti21/statistics/ui/_i18n/LocalStrings_de.properties
new file mode 100644
index 0000000000000000000000000000000000000000..194e348eb41f401639be05c8d6a7cbb50ed0cb51
--- /dev/null
+++ b/src/main/java/org/olat/ims/qti21/statistics/ui/_i18n/LocalStrings_de.properties
@@ -0,0 +1,10 @@
+#Tue Apr 15 11:18:52 CEST 2014
+fig.participants=$org.olat.ims.qti.statistics.ui\:fig.participants
+fig.title=$org.olat.ims.qti.statistics.ui\:fig.title
+fig.avg=$org.olat.ims.qti.statistics.ui\:fig.avg
+fig.span=$org.olat.ims.qti.statistics.ui\:fig.span
+fig.averagedur=$org.olat.ims.qti.statistics.ui\:fig.averagedur
+fig.stddev=$org.olat.ims.qti.statistics.ui\:fig.stddev
+fig.mode=$org.olat.ims.qti.statistics.ui\:fig.mode
+fig.median=$org.olat.ims.qti.statistics.ui\:fig.median
+chart.score.histogramm=$org.olat.ims.qti.statistics.ui\:chart.score.histogramm
\ No newline at end of file
diff --git a/src/main/java/org/olat/ims/qti21/statistics/ui/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/ims/qti21/statistics/ui/_i18n/LocalStrings_en.properties
new file mode 100644
index 0000000000000000000000000000000000000000..f1522eed4892055ce37922e5f9b8198df10aec9d
--- /dev/null
+++ b/src/main/java/org/olat/ims/qti21/statistics/ui/_i18n/LocalStrings_en.properties
@@ -0,0 +1,3 @@
+#Tue Apr 15 11:18:52 CEST 2014
+fig.participants=$org.olat.ims.qti.statistics.ui\:fig.participants
+fig.title=$org.olat.ims.qti.statistics.ui\:fig.title
\ No newline at end of file