/**
* 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.ims.qti.export;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
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.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.gui.control.generic.wizard.Step;
import org.olat.core.gui.control.generic.wizard.StepRunnerCallback;
import org.olat.core.gui.control.generic.wizard.StepsMainRunController;
import org.olat.core.gui.control.generic.wizard.StepsRunContext;
import org.olat.core.gui.media.MediaResource;
import org.olat.core.id.OLATResourceable;
import org.olat.course.CourseFactory;
import org.olat.course.ICourse;
import org.olat.course.assessment.model.AssessmentNodeData;
import org.olat.course.nodes.CourseNode;
import org.olat.course.nodes.IQSURVCourseNode;
/**
*
* @author schneider
*
* Comment:
* Archives all QTI results from a specific QTI node in the personal folder
* of the current user.
*/
public class CourseQTIArchiveController extends BasicController {
private CloseableModalController cmc;
private StepsMainRunController archiveWizardCtrl;
private Link startExportDummyButton, startExportButton;
private final OLATResourceable courseOres;
private final List<AssessmentNodeData> nodeList;
/**
* Constructor for the assessment tool controller.
* @param ureq
* @param wControl
* @param course
*/
public CourseQTIArchiveController(UserRequest ureq, WindowControl wControl, OLATResourceable courseOres) {
super(ureq, wControl);
this.courseOres = courseOres;
VelocityContainer introVC = createVelocityContainer("intro");
startExportDummyButton = LinkFactory.createButtonSmall("command.start.exportwizard.dummy", introVC, this);
startExportButton = LinkFactory.createButtonSmall("command.start.exportwizard", introVC, this);
nodeList = doNodeChoose(ureq);
if (nodeList == null || nodeList.isEmpty()) {
introVC.contextPut("hasQTINodes", Boolean.FALSE);
} else {
introVC.contextPut("hasQTINodes", Boolean.TRUE);
}
putInitialPanel(introVC);
}
/**
* @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 == startExportButton){
doArchive(ureq, true);
} else if (source == startExportDummyButton) {
doArchive(ureq, false);
}
}
/**
* @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 ureq, Controller source, Event event) {
if (source == archiveWizardCtrl){
getWindowControl().pop();
cleanUp();
} else if(cmc == source) {
cleanUp();
}
}
private void cleanUp() {
removeAsListenerAndDispose(archiveWizardCtrl);
removeAsListenerAndDispose(cmc);
archiveWizardCtrl = null;
cmc = null;
}
private void doArchive(UserRequest ureq, boolean advanced) {
StepRunnerCallback finish = new FinishArchive();
Step start = new Archive_1_SelectNodeStep(ureq, courseOres, nodeList, advanced);
archiveWizardCtrl = new StepsMainRunController(ureq, getWindowControl(), start, finish, null,
translate("archive.wizard.title"), "o_sel_test_archive_wizard");
listenTo(archiveWizardCtrl);
getWindowControl().pushAsModalDialog(archiveWizardCtrl.getInitialComponent());
}
public class FinishArchive implements StepRunnerCallback {
@Override
public Step execute(UserRequest uureq, WindowControl lwControl, StepsRunContext runContext) {
try {
QTIArchiver archiver = (QTIArchiver)runContext.get("archiver");
MediaResource resource = archiver.export();
uureq.getDispatchResult().setResultingMediaResource(resource);
} catch (IOException e) {
logError("", e);
}
return StepsMainRunController.DONE_MODIFIED;
}
}
/**
* A filtered list of course nodes
* @param ureq
* @return
*/
private List<AssessmentNodeData> doNodeChoose(UserRequest ureq){
// get list of course node data and populate table data model
ICourse course = CourseFactory.loadCourse(courseOres);
CourseNode rootNode = course.getRunStructure().getRootNode();
return addQTINodesAndParentsToList(0, rootNode);
}
/**
* Recursive method that adds tasks nodes and all its parents to a list
* @param recursionLevel
* @param courseNode
* @return A list of Object[indent, courseNode, selectable]
*/
private List<AssessmentNodeData> addQTINodesAndParentsToList(int recursionLevel, CourseNode courseNode) {
// 1) Get list of children data using recursion of this method
List<AssessmentNodeData> childrenData = new ArrayList<>();
for (int i = 0; i < courseNode.getChildCount(); i++) {
CourseNode child = (CourseNode) courseNode.getChildAt(i);
List<AssessmentNodeData> childData = addQTINodesAndParentsToList( (recursionLevel + 1), child);
if (childData != null) {
childrenData.addAll(childData);
}
}
if (childrenData.size() > 0 || courseNode instanceof IQSURVCourseNode) {
// Store node data in hash map. This hash map serves as data model for
// the tasks overview table. Leave user data empty since not used in
// this table. (use only node data)
AssessmentNodeData nodeData = new AssessmentNodeData(recursionLevel, courseNode);
if (courseNode instanceof IQSURVCourseNode) {
nodeData.setSelectable(true);
} else {
nodeData.setSelectable(false);
}
List<AssessmentNodeData> nodeAndChildren = new ArrayList<>();
nodeAndChildren.add(nodeData);
nodeAndChildren.addAll(childrenData);
return nodeAndChildren;
}
return null;
}
/**
* @see org.olat.core.gui.control.DefaultController#doDispose(boolean)
*/
@Override
protected void doDispose() {
//
}
}