/** * 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.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.ControllerEventListener; 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.core.logging.AssertException; 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.highscore.ui.HighScoreEditController; import org.olat.course.nodes.AbstractAccessableCourseNode; 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.process.AssessmentInstance; import org.olat.modules.ModuleConfiguration; import org.olat.repository.RepositoryEntry; import org.olat.repository.RepositoryManager; /** * Description:<BR/> * Edit controller for the qti test, selftest and survey course node * <P/> * Initial Date: Oct 13, 2004 * * @author Felix Jost */ public class IQEditController extends ActivateableTabbableDefaultController implements ControllerEventListener { public final String PANE_TAB_IQCONFIG_XXX; public final String PANE_TAB_IQLAYOUTCONFIG = "pane.tab.iqconfig.layout"; public static final String PANE_TAB_IQCONFIG_SURV = "pane.tab.iqconfig.surv"; 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 PANE_TAB_HIGHSCORE = "pane.tab.highscore"; /** configuration key: repository sof key reference to qti file*/ public static final String CONFIG_KEY_REPOSITORY_SOFTKEY = "repoSoftkey"; /** configuration key: the disclaimer text*/ public static final String CONFIG_KEY_DISCLAIMER = "disc"; /** configuration key: enable menu switch*/ public static final String CONFIG_KEY_ENABLEMENU = "enableMenu"; /** configuration key: display menu switch*/ public static final String CONFIG_KEY_DISPLAYMENU = "displayMenu"; /** configuration key: all questions, section titles only */ public static final String CONFIG_KEY_RENDERMENUOPTION="renderMenu"; /** configuration key: enable score progress switch*/ public static final String CONFIG_KEY_SCOREPROGRESS = "displayScoreProgress"; /** configuration key: enable cancel switch*/ public static final String CONFIG_KEY_ENABLECANCEL = "enableCancel"; /** configuration key: enable suspend switch*/ public static final String CONFIG_KEY_ENABLESUSPEND = "enableSuspend"; /** configuration key: enable question progress switch*/ public static final String CONFIG_KEY_QUESTIONPROGRESS = "displayQuestionProgss"; /** configuration key: enable question progress switch*/ public static final String CONFIG_KEY_QUESTIONTITLE = "displayQuestionTitle"; /** configuration key: enable automatic enumeration of "choice" options */ public static final String CONFIG_KEY_AUTOENUM_CHOICES = "autoEnumerateChoices"; /** configuration key: provide memo field */ public static final String CONFIG_KEY_MEMO = "provideMemoField"; /** configuration key: question sequence: item or selection */ public static final String CONFIG_KEY_SEQUENCE = "sequence"; /** configuration key: mode*/ public static final String CONFIG_KEY_TYPE = "mode"; /** configuration key: show summary: compact or detailed */ public static final String CONFIG_KEY_SUMMARY = "summary"; /** configuration key: max attempts*/ public static final String CONFIG_KEY_ATTEMPTS = "attempts"; /** configuration key: max attempts*/ public static final String CONFIG_KEY_BLOCK_AFTER_SUCCESS = "blockAfterSuccess"; /** configuration key: minimal score*/ public static final String CONFIG_KEY_MINSCORE = "minscore"; /** configuration key: maximal score*/ public static final String CONFIG_KEY_MAXSCORE = "maxscore"; /** configuration key: cut value (socre > cut = passed) */ public static final String CONFIG_KEY_CUTVALUE = "cutvalue"; /** configuration key for the filename */ public static final String CONFIG_KEY_FILE = "file"; /** configuration key: should relative links like ../otherfolder/my.css be allowed? **/ public static final String CONFIG_KEY_ALLOW_RELATIVE_LINKS = "allowRelativeLinks"; /** configuration key: enable 'show score infos' on start page */ public static final String CONFIG_KEY_ENABLESCOREINFO = "enableScoreInfo"; //<OLATCE-982> public static final String CONFIG_KEY_ALLOW_SHOW_SOLUTION = "showSolution"; //</OLATCE-982> //<OLATCE-2009> public static final String CONFIG_KEY_ALLOW_SUSPENSION_ALLOWED = "suspendAllowed"; //</OLATCE-2009> /** Test in full window mode*/ public final static String CONFIG_FULLWINDOW = "fullwindow"; /** Enable manual correction */ public final static String CONFIG_CORRECTION_MODE = "correctionMode"; /** Test in full window mode*/ public final static String CONFIG_ALLOW_ANONYM = "allowAnonym"; /** Digitally signed the assessment results */ public final static String CONFIG_DIGITAL_SIGNATURE = "digitalSignature"; /** Send the signature per mail */ public final static String CONFIG_DIGITAL_SIGNATURE_SEND_MAIL = "digitalSignatureMail"; /** configuration key: use configuration of the reference repository entry */ public static final String CONFIG_KEY_CONFIG_REF = "configFromRef"; /** configuration key: use a time limit for the test in seconds */ public static final String CONFIG_KEY_TIME_LIMIT = "timeLimit"; public final static String CORRECTION_AUTO = "auto"; public final static String CORRECTION_MANUAL = "manual"; public static final String CONFIG_KEY_DATE_DEPENDENT_RESULTS = "dateDependentResults"; public static final String CONFIG_KEY_RESULTS_START_DATE = "resultsStartDate"; public static final String CONFIG_KEY_RESULTS_END_DATE = "resultsEndDate"; public static final String CONFIG_KEY_RESULT_ON_FINISH = "showResultsOnFinish"; public static final String CONFIG_KEY_RESULT_ON_HOME_PAGE = "showResultsOnHomePage"; public static final String CONFIG_KEY_TEMPLATE = "templateid"; public static final String CONFIG_KEY_TYPE_QTI = "qtitype"; public static final String CONFIG_VALUE_QTI2 = "qti2"; public static final String CONFIG_VALUE_QTI21 = "qti2w"; public static final Object CONFIG_VALUE_QTI1 = "qti1"; public static final String CONFIG_KEY_IS_SURVEY = "issurv"; private final String[] paneKeys; private ICourse course; private String type; private UserCourseEnvironment euce; private AbstractAccessableCourseNode courseNode; private ModuleConfiguration moduleConfiguration; private TabbedPane myTabbedPane; private Controller previewLayoutCtr; private final BreadcrumbPanel stackPanel; private ConditionEditController accessibilityCondContr; private IQConfigurationController configurationCtrl; private IQLayoutConfigurationController layoutConfigurationCtrl; private HighScoreEditController highScoreNodeConfigController; /** * Constructor for the IMS QTI edit controller for a test course node * * @param ureq The user request * @param wControl The window controller * @param course The course * @param courseNode The test course node * @param groupMgr * @param 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(); //o_clusterOk by guido: save to hold reference to course inside editor this.course = course; this.courseNode = courseNode; this.euce = euce; 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) { moduleConfiguration.set(CONFIG_KEY_ENABLECANCEL, Boolean.FALSE); } if (moduleConfiguration.get(CONFIG_KEY_ENABLESUSPEND) == null) { moduleConfiguration.set(CONFIG_KEY_ENABLESUSPEND, Boolean.FALSE); } if(moduleConfiguration.get(CONFIG_KEY_RENDERMENUOPTION) == null) { moduleConfiguration.set(CONFIG_KEY_RENDERMENUOPTION, Boolean.FALSE); } init(ureq); } /** * Constructor for the IMS QTI edit controller for a self-test course node * * @param ureq The user request * @param wControl The window controller * @param course The course * @param courseNode The self course node * @param groupMgr * @param 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; 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) { moduleConfiguration.set(CONFIG_KEY_ENABLECANCEL, Boolean.TRUE); } if (moduleConfiguration.get(CONFIG_KEY_ENABLESUSPEND) == null) { moduleConfiguration.set(CONFIG_KEY_ENABLESUSPEND, Boolean.TRUE); } init(ureq); } /** * Constructor for the IMS QTI edit controller for a survey course node * * @param ureq The user request * @param wControl The window controller * @param course The course * @param courseNode The survey course node * @param groupMgr * @param 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; 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}; // put some default values if (moduleConfiguration.get(CONFIG_KEY_SCOREPROGRESS) == null){ moduleConfiguration.set(CONFIG_KEY_SCOREPROGRESS, Boolean.FALSE); } if(moduleConfiguration.getBooleanEntry(CONFIG_KEY_ALLOW_RELATIVE_LINKS)==null){ moduleConfiguration.setBooleanEntry(CONFIG_KEY_ALLOW_RELATIVE_LINKS,false); } init(ureq); } private void init(UserRequest ureq) { configurationCtrl = new IQConfigurationController(ureq, getWindowControl(), stackPanel, course, courseNode, type); listenTo(configurationCtrl); layoutConfigurationCtrl = new IQLayoutConfigurationController(ureq, getWindowControl(), course, courseNode, type); listenTo(layoutConfigurationCtrl); if (AssessmentInstance.QMD_ENTRY_TYPE_ASSESS.equals(type)) { highScoreNodeConfigController = new HighScoreEditController(ureq, getWindowControl(), moduleConfiguration); listenTo(highScoreNodeConfigController); } Condition accessCondition = courseNode.getPreConditionAccess(); accessibilityCondContr = new ConditionEditController(ureq, getWindowControl(), euce, accessCondition, AssessmentHelper.getAssessableNodes(course.getEditorTreeModel(), courseNode)); listenTo(accessibilityCondContr); } @Override public void event(UserRequest ureq, Component source, Event event) { // } @Override public void event(UserRequest urequest, Controller source, Event event) { if (source == accessibilityCondContr) { if (event == Event.CHANGED_EVENT) { Condition cond = accessibilityCondContr.getCondition(); courseNode.setPreConditionAccess(cond); fireEvent(urequest, NodeEditController.NODECONFIG_CHANGED_EVENT); } } else if (source == configurationCtrl) { if (event == NodeEditController.NODECONFIG_CHANGED_EVENT) { fireEvent(urequest, NodeEditController.NODECONFIG_CHANGED_EVENT); layoutConfigurationCtrl.updateEditController(urequest); } } else if (source == highScoreNodeConfigController){ if (event == Event.DONE_EVENT) { fireEvent(urequest, NodeEditController.NODECONFIG_CHANGED_EVENT); } } else if (source == layoutConfigurationCtrl) { if (event == NodeEditController.NODECONFIG_CHANGED_EVENT) { fireEvent(urequest, NodeEditController.NODECONFIG_CHANGED_EVENT); configurationCtrl.updateEditController(urequest, false); layoutConfigurationCtrl.updateEditController(urequest); } } } @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), configurationCtrl.getInitialComponent()); tabbedPane.addTab(translate(PANE_TAB_IQLAYOUTCONFIG), layoutConfigurationCtrl.getInitialComponent()); if (AssessmentInstance.QMD_ENTRY_TYPE_ASSESS.equals(type)) { tabbedPane.addTab(translate(PANE_TAB_HIGHSCORE) , highScoreNodeConfigController.getInitialComponent()); } } /** * Ge the qti file soft key repository reference * @param config * @param strict * @return RepositoryEntry */ public static 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(CONFIG_KEY_REPOSITORY_SOFTKEY); if (repoSoftkey == null) { if (strict) { throw new AssertException("invalid config when being asked for references"); } else { return null; } } RepositoryManager rm = RepositoryManager.getInstance(); return rm.lookupRepositoryEntryBySoftkey(repoSoftkey, strict); } /** * Set the referenced repository entry. * * @param re * @param moduleConfiguration */ public static void setIQReference(RepositoryEntry re, ModuleConfiguration moduleConfiguration) { moduleConfiguration.set(CONFIG_KEY_REPOSITORY_SOFTKEY, re.getSoftkey()); } /** * Remove the reference to the repository entry. * * @param moduleConfiguration */ public static void removeIQReference(ModuleConfiguration moduleConfiguration) { moduleConfiguration.remove(IQEditController.CONFIG_KEY_REPOSITORY_SOFTKEY); } @Override protected void doDispose() { //child controllers registered with listenTo() get disposed in BasicController if (previewLayoutCtr != null) { previewLayoutCtr.dispose(); previewLayoutCtr = null; } } @Override public String[] getPaneKeys() { return paneKeys; } @Override public TabbedPane getTabbedPane() { return myTabbedPane; } }