/**
*
* BPS Bildungsportal Sachsen GmbH
* Bahnhofstrasse 6
* 09111 Chemnitz
* Germany
*
* Copyright (c) 2005-2008 by BPS Bildungsportal Sachsen GmbH
* http://www.bps-system.de
*
* All rights reserved.
*/
package de.bps.onyx.plugin.run;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import org.olat.core.gui.UserRequest;
import org.olat.core.gui.Windows;
import org.olat.core.gui.components.Component;
import org.olat.core.gui.components.htmlsite.HtmlStaticPageComponent;
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.iframe.IFrameDisplayController;
import org.olat.core.id.Identity;
import org.olat.core.id.OLATResourceable;
import org.olat.core.logging.Tracing;
import org.olat.core.util.vfs.VFSContainer;
import org.olat.core.util.vfs.VFSLeaf;
import org.olat.course.assessment.AssessmentHelper;
import org.olat.course.nodes.CourseNode;
import org.olat.course.nodes.IQSELFCourseNode;
import org.olat.course.nodes.IQSURVCourseNode;
import org.olat.course.nodes.IQTESTCourseNode;
import de.bps.onyx.plugin.course.nodes.iq.IQEditController;
import org.olat.course.run.scoring.ScoreEvaluation;
import org.olat.course.run.userview.UserCourseEnvironment;
import org.olat.fileresource.FileResourceManager;
import org.olat.modules.ModuleConfiguration;
import org.olat.modules.iq.IQSecurityCallback;
import org.olat.repository.RepositoryEntry;
import de.bps.webservices.clients.onyxreporter.OnyxReporterException;
import de.bps.webservices.clients.onyxreporter.OnyxReporterWebserviceManager;
import de.bps.webservices.clients.onyxreporter.OnyxReporterWebserviceManagerFactory;
import de.bps.onyx.plugin.OnyxModule;
import de.bps.onyx.plugin.OnyxResultManager;
import de.bps.onyx.plugin.wsclient.OnyxPluginServices;
import de.bps.onyx.plugin.wsclient.PluginService;
/**
* @author Ingmar Kroll
*/
public class OnyxRunController extends BasicController {
private VelocityContainer myContent, onyxReporterVC, onyxPlugin;
private ModuleConfiguration modConfig;
private IQTESTCourseNode courseNodeTest;
private IQSURVCourseNode courseNodeSurvey;
private IQSELFCourseNode courseNodeSelf;
private UserCourseEnvironment userCourseEnv;
private Link startButton, onyxBack;
private IFrameDisplayController iFrameCtr;
private String CP;
private String uniqueId;
private OnyxModalController onyxPluginController;
private final static int NOENTRYVIEW = -1;
private final static int DISCVIEW = 0;
private final static int SURVEYVIEW = 1;
private final static int ENDVIEW = 2;
private Link showOnyxReporterButton;
public OnyxRunController(UserRequest ureq, WindowControl wControl, OLATResourceable fileResource) {
super(ureq, wControl);
VelocityContainer vc = showOnyxTestInModalController(ureq, fileResource);
putInitialPanel(vc);
}
/**
* Constructor for a test run controller
*
* @param userCourseEnv
* @param moduleConfiguration
* @param secCallback
* @param ureq
* @param wControl
* @param testCourseNode
*/
public OnyxRunController(UserCourseEnvironment userCourseEnv, ModuleConfiguration moduleConfiguration, IQSecurityCallback secCallback,
UserRequest ureq, WindowControl wControl, IQSURVCourseNode courseNode) {
super(ureq, wControl);
this.modConfig = moduleConfiguration;
this.userCourseEnv = userCourseEnv;
myContent = createVelocityContainer("onyxrun");
this.courseNodeSurvey = courseNode;
this.CP = getCP(courseNode.getReferencedRepositoryEntry().getOlatResource());
putInitialPanel(myContent);
Windows.getWindows(ureq).getWindowManager().setAjaxEnabled(false);
showView(ureq, SURVEYVIEW);
}
/**
* Constructor for a test run controller
*
* @param userCourseEnv
* @param moduleConfiguration
* @param secCallback
* @param ureq
* @param wControl
* @param testCourseNode
*/
public OnyxRunController(UserCourseEnvironment userCourseEnv, ModuleConfiguration moduleConfiguration, IQSecurityCallback secCallback,
UserRequest ureq, WindowControl wControl, IQSELFCourseNode courseNode) {
super(ureq, wControl);
this.modConfig = moduleConfiguration;
this.userCourseEnv = userCourseEnv;
myContent = createVelocityContainer("onyxrun");
this.courseNodeSelf = courseNode;
this.CP = getCP(courseNode.getReferencedRepositoryEntry().getOlatResource());
putInitialPanel(myContent);
Windows.getWindows(ureq).getWindowManager().setAjaxEnabled(false);
showView(ureq, DISCVIEW);
}
/**
* Constructor for a test run controller
*
* @param userCourseEnv
* @param moduleConfiguration
* @param secCallback
* @param ureq
* @param wControl
* @param testCourseNode
*/
public OnyxRunController(UserCourseEnvironment userCourseEnv, ModuleConfiguration moduleConfiguration, IQSecurityCallback secCallback,
UserRequest ureq, WindowControl wControl, IQTESTCourseNode courseNode) {
super(ureq, wControl);
this.modConfig = moduleConfiguration;
this.userCourseEnv = userCourseEnv;
myContent = createVelocityContainer("onyxrun");
this.courseNodeTest= courseNode;
this.CP=getCP(courseNode.getReferencedRepositoryEntry().getOlatResource());
putInitialPanel(myContent);
Windows.getWindows(ureq).getWindowManager().setAjaxEnabled(false);
int confValue = 1;
if (moduleConfiguration.get(IQEditController.CONFIG_KEY_ATTEMPTS) == null) {
confValue = 0;
} else {
confValue = Integer.valueOf(moduleConfiguration.get(IQEditController.CONFIG_KEY_ATTEMPTS).toString()).intValue();
}
if (confValue == 0 || courseNode.getUserAttempts(userCourseEnv).intValue() < confValue) {
// running allowed
showView(ureq, DISCVIEW);
} else {
// only one time allowed
showView(ureq, NOENTRYVIEW);
}
}
private void showView(UserRequest ureq, int viewmode) {
myContent.contextPut("viewmode", new Integer(viewmode));
int c = 1; //per default
try {
c = Integer.valueOf(modConfig.get(IQEditController.CONFIG_KEY_ATTEMPTS).toString()).intValue();
} catch (Exception e) {
// nothing to do
}
if (c != 0) {
myContent.contextPut("attemptsConfig", String.valueOf(c));
}
if (viewmode != SURVEYVIEW) {
ScoreEvaluation se = null;
if (courseNodeTest != null) {
myContent.contextPut("attempts", courseNodeTest.getUserAttempts(userCourseEnv));
myContent.contextPut("comment", courseNodeTest.getUserUserComment(userCourseEnv));
if (courseNodeTest.getUserAttempts(userCourseEnv) > 0) {
se = courseNodeTest.getUserScoreEvaluation(userCourseEnv);
}
} else if (courseNodeSelf != null) {
myContent.contextPut("self", Boolean.TRUE);
se = courseNodeSelf.getUserScoreEvaluation(userCourseEnv);
}
boolean hasResult = se != null && se.getScore() != null;
if (hasResult) {
myContent.contextPut("hasResult", Boolean.TRUE);
boolean isPassesSet = se.getPassed() != null;
myContent.contextPut(IQEditController.CONFIG_KEY_RESULT_ON_HOME_PAGE, modConfig.get(IQEditController.CONFIG_KEY_RESULT_ON_HOME_PAGE));
if (isPassesSet) {
myContent.contextPut("passed", se.getPassed());
} else {
myContent.contextPut("passed", "");
}
float score = se.getScore();
myContent.contextPut("score", AssessmentHelper.getRoundedScore(score));
} else {
myContent.contextPut("hasResult", Boolean.FALSE);
}
showOnyxReporterButton = LinkFactory.createButtonSmall("cmd.showOnyxReporter", myContent, this);
}
switch (viewmode) {
case DISCVIEW:
// push title and learning objectives, only visible on intro page
if (courseNodeTest != null) {
myContent.contextPut("menuTitle", courseNodeTest.getShortTitle());
myContent.contextPut("displayTitle", courseNodeTest.getLongTitle());
} else if (courseNodeSelf != null) {
myContent.contextPut("menuTitle", courseNodeSelf.getShortTitle());
myContent.contextPut("displayTitle", courseNodeSelf.getLongTitle());
}
// fetch disclaimer file
String sDisclaimer = (String) modConfig.get(IQEditController.CONFIG_KEY_DISCLAIMER);
if (sDisclaimer != null) {
setDisclaimer(sDisclaimer, ureq);
}
startButton = LinkFactory.createButton("startapplet", myContent, this);
break;
case ENDVIEW:
break;
case SURVEYVIEW:
//fetch disclaimer file
String sDisc = (String) modConfig.get(IQEditController.CONFIG_KEY_DISCLAIMER);
if (sDisc != null) {
setDisclaimer(sDisc, ureq);
}
// push title and learning objectives, only visible on intro page
myContent.contextPut("menuTitle", courseNodeSurvey.getShortTitle());
myContent.contextPut("displayTitle", courseNodeSurvey.getLongTitle());
myContent.contextPut("showReporter", Boolean.FALSE);
myContent.contextPut("attempts", courseNodeSurvey.getUserAttempts(userCourseEnv));
startButton = LinkFactory.createButton("startapplet", myContent, this);
boolean isAuthor = ureq.getUserSession().getRoles().isAuthor() ||
ureq.getUserSession().getRoles().isOLATAdmin();
if (isAuthor) {
myContent.contextPut("showReporter", Boolean.TRUE);
showOnyxReporterButton = LinkFactory.createCustomLink("cmd.showOnyxReporter", "cmd.showOnyxReporter", "onyxreporter.button.survey", Link.BUTTON_SMALL, myContent, this);
}
break;
}
}
/**
* @param sDisclaimer
* @param ureq
*/
private void setDisclaimer (String sDisclaimer, UserRequest ureq) {
VFSContainer baseContainer = userCourseEnv.getCourseEnvironment().getCourseFolderContainer();
int lastSlash = sDisclaimer.lastIndexOf('/');
if (lastSlash != -1) {
baseContainer = (VFSContainer) baseContainer.resolve(sDisclaimer.substring(0, lastSlash));
sDisclaimer = sDisclaimer.substring(lastSlash);
// first check if disclaimer exists on filesystem
if (baseContainer == null || baseContainer.resolve(sDisclaimer) == null) {
showWarning("disclaimer.file.invalid", sDisclaimer);
} else {
//screenreader do not like iframes, display inline
if (getWindowControl().getWindowBackOffice().getWindowManager().isForScreenReader()) {
HtmlStaticPageComponent disclaimerComp = new HtmlStaticPageComponent("disc", baseContainer);
myContent.put("disc", disclaimerComp);
disclaimerComp.setCurrentURI(sDisclaimer);
myContent.contextPut("hasDisc", Boolean.TRUE);
} else {
iFrameCtr = new IFrameDisplayController(ureq, getWindowControl(), baseContainer);
listenTo(iFrameCtr);//dispose automatically
myContent.put("disc", iFrameCtr.getInitialComponent());
iFrameCtr.setCurrentURI(sDisclaimer);
myContent.contextPut("hasDisc", Boolean.TRUE);
}
}
}
}
/**
* @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)
*/
public void event(UserRequest ureq, Controller controller, Event event) {
if (controller == onyxPluginController) {
if (courseNodeSurvey != null) {
showView(ureq, SURVEYVIEW);
} else if (courseNodeTest != null) {
int confValue = 1;
try {
confValue = Integer.valueOf(modConfig.get(IQEditController.CONFIG_KEY_ATTEMPTS).toString()).intValue();
} catch (NullPointerException e) {
Tracing.createLoggerFor(this.getClass()).error("Onyx-Test Anzahl Ausfuehrungen nicht in Konfig", e);
}
int userAttempts = 0;
userAttempts = courseNodeTest.getUserAttempts(userCourseEnv).intValue();
if (confValue == 0 || userAttempts < confValue) {
// running allowed
showView(ureq, DISCVIEW);
} else {
// only one time allowed
showView(ureq, NOENTRYVIEW);
}
} else {
showView(ureq, DISCVIEW);
}
//tell the RunMainController that it has to be updated
fireEvent(ureq, Event.DONE_EVENT);
}
}
/**
* @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)
*/
public void event(UserRequest ureq, Component source, Event event) {
if (source == startButton) {
//increase attempts when starting the test -> attempts do not depend on test
//running correct
onyxPlugin = createVelocityContainer("onyxstart");
String onyxBackLabel = "onyx.back";
if (courseNodeTest != null) {
onyxPlugin.contextPut("isSurvey", Boolean.FALSE);
} else if (courseNodeSurvey != null) {
onyxPlugin.contextPut("isSurvey", Boolean.TRUE);
onyxBackLabel = "onyx.survey.back";
}
try {
connectToOnyxWS(ureq);
String urlonyxplugin = OnyxModule.getUserViewLocation() + "?id=" + this.uniqueId;
onyxPlugin.contextPut("urlonyxplugin", urlonyxplugin);
onyxPluginController = new OnyxModalController(getWindowControl(), "close", onyxPlugin, false);
onyxBack = LinkFactory.createCustomLink("onyx.back", "onyx.back", onyxBackLabel, Link.BUTTON_SMALL, onyxPlugin, onyxPluginController);
onyxPluginController.setBackButton(onyxBack);
listenTo(onyxPluginController);
onyxPluginController.activate();
//now increase attampts; if an exception occurred before, this will be not reached
if (courseNodeTest != null) {
courseNodeTest.incrementUserAttempts(userCourseEnv);
} else if (courseNodeSurvey != null) {
courseNodeSurvey.incrementUserAttempts(userCourseEnv);
} else if(courseNodeSelf != null){
courseNodeSelf.incrementUserAttempts(userCourseEnv);
}
} catch(Exception e) {
getWindowControl().setError(translate("error.connectonyxws"));
Tracing.createLoggerFor(this.getClass()).warn("could not connect to OnyxPlugin webservice", e);
}
return;
} else if (source == showOnyxReporterButton) {
onyxReporterVC = createVelocityContainer("onyxreporter");
int error = showOnyxReporter(ureq);
if (error == 0) {
CloseableModalController cmc = new CloseableModalController(getWindowControl(), "close", onyxReporterVC);
cmc.activate();
} else if (error == 1) {
getWindowControl().setInfo(translate("oynxreporter.noresults"));
Tracing.createLoggerFor(this.getClass()).error("could not connect to OnyxPlugin webservice");
} else if (error == 2) {
getWindowControl().setError(translate("onyxreporter.error"));
Tracing.createLoggerFor(this.getClass()).error("could not connect to OnyxPlugin webservice");
}
return;
}
showView(ureq, ENDVIEW);
}
/**
* This methods calls the OnyxReporter and shows it in an iframe.
* @param ureq The UserRequest for getting the identity and role of the current user.
* @return 0 OK
* 1 NO RESULTS
* 2 ERROR
*/
private int showOnyxReporter(UserRequest ureq) {
OnyxReporterWebserviceManager onyxReporter = OnyxReporterWebserviceManagerFactory.getInstance().fabricate("OnyxReporterWebserviceClient");
if (onyxReporter != null) {
List identity = new ArrayList();
String iframeSrc = "";
try {
if (courseNodeTest != null) {
identity.add(userCourseEnv.getIdentityEnvironment().getIdentity());
long assasmentId = courseNodeTest.getUserScoreEvaluation(userCourseEnv).getAssessmentID();
onyxReporter.setAssassmentId(assasmentId);
iframeSrc = onyxReporter.startReporter(ureq, identity, courseNodeTest, true);
} else {
String path = userCourseEnv.getCourseEnvironment().getCourseBaseContainer()
.getBasefile() + File.separator + courseNodeSurvey.getIdent() + File.separator;
iframeSrc = onyxReporter.startReporterForSurvey(ureq, courseNodeSurvey, path);
}
} catch (OnyxReporterException oE) {
if (oE.getMessage().equals("noresults")) {
oE.printStackTrace();
return 1;
}
} catch (Exception e) {
e.printStackTrace();
return 2;
}
onyxReporterVC.contextPut("iframeOK", Boolean.TRUE);
onyxReporterVC.contextPut("onyxReportLink", iframeSrc);
return 0;
} else {
return 2;
}
}
/**
* Static metohd to start the an onyx test as learningressource or bookmark.
* @param ureq
* @param repositoryEntry
*/
public VelocityContainer showOnyxTestInModalController(UserRequest ureq, OLATResourceable fileResource) {
OnyxPluginServices onyxplugin = new PluginService().getOnyxPluginServicesPort();
String CP = getCP(fileResource);
String language = ureq.getLocale().toString().toLowerCase();
String tempalteId = "onyxdefault";
this.uniqueId = OnyxResultManager.getUniqueIdForShowOnly();
try {
File cpFile = new File(CP);
Long fileLength = cpFile.length();
byte[] byteArray = new byte[fileLength.intValue()];
System.out.println("CP : "+CP);
java.io.FileInputStream inp = new java.io.FileInputStream(cpFile);
inp.read(byteArray);
onyxplugin.run(this.uniqueId, byteArray, language, "", tempalteId);
} catch (FileNotFoundException e) {
Tracing.createLoggerFor(this.getClass()).error("Cannot find CP of Onyx Test with assassmentId: " + uniqueId, e);
} catch (IOException e) {
Tracing.createLoggerFor(this.getClass()).error("Cannot find CP of Onyx Test with assassmentId: " + uniqueId, e);
}
String urlonyxplugin = OnyxModule.getUserViewLocation() + "?id=" + this.uniqueId;
onyxPlugin = createVelocityContainer("onyxstart");
onyxPlugin.contextPut("isSurvey", Boolean.FALSE);
onyxPlugin.contextPut("urlonyxplugin", urlonyxplugin);
onyxPlugin.contextPut("nohint", Boolean.TRUE);
onyxPluginController = new OnyxModalController(getWindowControl(), "close", onyxPlugin, false);
onyxBack = LinkFactory.createCustomLink("onyx.back", "onyx.back", "onyx.back", Link.BUTTON_SMALL, onyxPlugin, onyxPluginController);
onyxBack.setVisible(false);
onyxPluginController.setBackButton(onyxBack);
return onyxPlugin;
}
private void connectToOnyxWS(UserRequest ureq) {
OnyxPluginServices onyxplugin = new PluginService().getOnyxPluginServicesPort();
CourseNode courseNode = null;
if (courseNodeTest != null) {
courseNode = courseNodeTest;
} else if (courseNodeSurvey != null) {
courseNode = courseNodeSurvey;
} else if (courseNodeSelf != null) {
courseNode = courseNodeSelf;
}
this.uniqueId = OnyxResultManager.getUniqueId(ureq.getIdentity(), courseNode, this.userCourseEnv);
String instructions = new String();
try {
String sDisclaimer = (String) modConfig.get(IQEditController.CONFIG_KEY_DISCLAIMER);
if (sDisclaimer != null) {
VFSLeaf disc = (VFSLeaf) this.userCourseEnv.getCourseEnvironment().getCourseFolderContainer().resolve(sDisclaimer);
BufferedReader r_disc = new BufferedReader(new InputStreamReader(disc.getInputStream()));
String disc_s=new String();
while (r_disc.ready()){
disc_s+=r_disc.readLine();
}
instructions = disc_s;
}
} catch (IOException e) {
Tracing.createLoggerFor(this.getClass()).error("could not read disclaimer");
}
String language = ureq.getLocale().toString().toLowerCase();
String tempalteId = "onyxdefault";
String tempalteId_config=(String) modConfig.get(IQEditController.CONFIG_KEY_TEMPLATE);
if(tempalteId_config!=null&&tempalteId_config.length()>0){
tempalteId=tempalteId_config;
}
try {
File cpFile = new File(CP);
Long fileLength = cpFile.length();
byte[] byteArray = new byte[fileLength.intValue()];
System.out.println("CP : "+CP);
java.io.FileInputStream inp = new java.io.FileInputStream(cpFile);
inp.read(byteArray);
onyxplugin.run(this.uniqueId, byteArray, language, instructions, tempalteId);
} catch (FileNotFoundException e) {
Tracing.createLoggerFor(this.getClass()).error("Cannot find CP of Onyx Test with assassmentId: " + uniqueId, e);
} catch (IOException e) {
Tracing.createLoggerFor(this.getClass()).error("Cannot find CP of Onyx Test with assassmentId: " + uniqueId, e);
}
}
private static String getCP(OLATResourceable fileResource){
//get content-package (= onyx test zip-file)
//OLATResourceable fileResource = repositoryEntry.getOlatResource();
String unzipedDir = FileResourceManager.getInstance().unzipFileResource(fileResource).getAbsolutePath();
String zipdirName = FileResourceManager.ZIPDIR;
//String name = repositoryEntry.getResourcename();//getDisplayname();
String name = FileResourceManager.getInstance().getFileResource(fileResource).getName();
String pathToFile = unzipedDir.substring(0, unzipedDir.indexOf(zipdirName));
String completePath = (pathToFile + name);
File cpFile = new File(completePath);
if (!cpFile.exists()) {
//look for imported file
String importedFileName = "repo.zip";
File impFile = new File(pathToFile + importedFileName);
if (impFile.exists()) {
impFile.renameTo(cpFile);
} else {
Tracing.createLoggerFor(OnyxRunController.class).error("Cannot open Onyx CP File: " + completePath + " , also the imported repo.zip is not here!");
}
}
return completePath;
}
@Override
protected void doDispose() {
if (onyxPluginController != null && onyxPluginController.isOpen()) {
onyxPluginController.close();
}
}
private class OnyxModalController extends CloseableModalController {
public OnyxModalController(WindowControl wControl, String closeButtonText, Component modalContent, boolean showCloseIcon) {
super(wControl, closeButtonText, modalContent, showCloseIcon);
}
private Link backButton;
private boolean open = false;
public void activate() {
super.activate();
open = true;
}
public boolean isOpen() {
return open;
}
public void setBackButton(Link button) {
backButton = button;
}
public void close() {
open = false;
getWindowControl().pop();
}
public void event(UserRequest ureq, Component source, Event event) {
if (source == backButton) {
close();
fireEvent(ureq, CLOSE_MODAL_EVENT);
}
}
}
}