/** * <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.qti.statistics; import java.io.InputStream; import java.util.Date; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Locale; import java.util.Map; import javax.servlet.http.HttpServletResponse; import org.olat.basesecurity.Group; import org.olat.core.gui.media.MediaResource; import org.olat.core.logging.OLATRuntimeException; import org.olat.core.logging.OLog; import org.olat.core.logging.Tracing; import org.olat.core.util.Formatter; import org.olat.core.util.StringHelper; import org.olat.course.nodes.CourseNode; import org.olat.ims.qti.QTIResult; import org.olat.ims.qti.QTIResultManager; import org.olat.ims.qti.editor.beecom.parser.ItemParser; import org.olat.ims.qti.export.QTIArchiver; import org.olat.ims.qti.export.QTIExportEssayItemFormatConfig; import org.olat.ims.qti.export.QTIExportFIBItemFormatConfig; import org.olat.ims.qti.export.QTIExportFormatter; import org.olat.ims.qti.export.QTIExportFormatterCSVType1; import org.olat.ims.qti.export.QTIExportFormatterCSVType3; import org.olat.ims.qti.export.QTIExportItemFormatConfig; import org.olat.ims.qti.export.QTIExportKPRIMItemFormatConfig; import org.olat.ims.qti.export.QTIExportMCQItemFormatConfig; import org.olat.ims.qti.export.QTIExportManager; import org.olat.ims.qti.export.QTIExportSCQItemFormatConfig; import org.olat.ims.qti.export.helper.QTIItemObject; import org.olat.ims.qti.export.helper.QTIObjectTreeBuilder; /** * * Initial date: 17.03.2014<br> * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com * */ public class QTIStatisticsResource implements MediaResource { private static final OLog log = Tracing.createLoggerFor(QTIStatisticsResource.class); private final Locale locale; private final String encoding = "UTF-8"; private final QTIStatisticResourceResult resourceResult; public QTIStatisticsResource(QTIStatisticResourceResult resourceResult, Locale locale) { this.resourceResult = resourceResult; this.locale = locale; } @Override public boolean acceptRanges() { return false; } @Override public String getContentType() { return "application/zip"; } @Override public Long getSize() { return null; } @Override public InputStream getInputStream() { return null; } @Override public Long getLastModified() { return null; } @Override public void prepare(HttpServletResponse hres) { try { hres.setCharacterEncoding(encoding); } catch (Exception e) { log.error("", e); } CourseNode courseNode = resourceResult.getTestCourseNode(); String label = courseNode.getType() + "_" + StringHelper.transformDisplayNameToFileSystemName(courseNode.getShortName()) + "_" + Formatter.formatDatetimeFilesystemSave(new Date(System.currentTimeMillis())) + ".csv"; String urlEncodedLabel = StringHelper.urlEncodeUTF8(label); hres.setHeader("Content-Disposition","attachment; filename*=UTF-8''" + urlEncodedLabel); hres.setHeader("Content-Description", urlEncodedLabel); try { String sep = "\\t"; // fields separated by String emb = "\""; // fields embedded by String car = "\\r\\n"; // carriage return sep = QTIArchiver.convert2CtrlChars(sep); car = QTIArchiver.convert2CtrlChars(car); int exportType = 1; QTIExportFormatter formatter; if (QTIType.test.equals(resourceResult.getType())){ exportType = 1; formatter = new QTIExportFormatterCSVType1(locale, sep, emb, car, true); } else if (QTIType.survey.equals(resourceResult.getType())) { exportType = 2; formatter = new QTIExportFormatterCSVType3(locale, null, sep, emb, car, true); } else { return; } Long qtiRepoEntryKey = resourceResult.getQTIRepositoryEntry().getKey(); List<QTIItemObject> itemList = new QTIObjectTreeBuilder().getQTIItemObjectList(resourceResult.getResolver()); formatter.setMapWithExportItemConfigs(getQTIItemConfigs(itemList)); QTIResultManager qrm = QTIResultManager.getInstance(); QTIStatisticSearchParams params = resourceResult.getSearchParams(); List<Group> limitToGroups = params.isMayViewAllUsersAssessments() ? null : params.getLimitToGroups(); List<QTIResult> results = qrm.selectResults(resourceResult.getCourseOres().getResourceableId(), courseNode.getIdent(), qtiRepoEntryKey, limitToGroups, exportType); QTIExportManager.getInstance().exportResults(formatter, results, itemList, hres.getOutputStream()); } catch (Exception e) { log.error("", e); } } @Override public void release() { // } /** * Copy of QTIArchiveWizardController.getQTIItemConfigs but with all options set * to true except for the time column. * * @param itemList * @return */ private final static Map<Class<?>, QTIExportItemFormatConfig> getQTIItemConfigs(List<QTIItemObject> itemList){ Map<Class<?>, QTIExportItemFormatConfig> itConfigs = new HashMap<>(); for (Iterator<QTIItemObject> iter = itemList.iterator(); iter.hasNext();) { QTIItemObject item = iter.next(); if (item.getItemIdent().startsWith(ItemParser.ITEM_PREFIX_SCQ)){ if (itConfigs.get(QTIExportSCQItemFormatConfig.class) == null){ QTIExportSCQItemFormatConfig confSCQ = new QTIExportSCQItemFormatConfig(true, true, true, false); itConfigs.put(QTIExportSCQItemFormatConfig.class, confSCQ); } } else if (item.getItemIdent().startsWith(ItemParser.ITEM_PREFIX_MCQ)){ if (itConfigs.get(QTIExportMCQItemFormatConfig.class) == null){ QTIExportMCQItemFormatConfig confMCQ = new QTIExportMCQItemFormatConfig(true, true, true, false); itConfigs.put(QTIExportMCQItemFormatConfig.class, confMCQ ); } } else if (item.getItemIdent().startsWith(ItemParser.ITEM_PREFIX_KPRIM)){ if (itConfigs.get(QTIExportKPRIMItemFormatConfig.class) == null){ QTIExportKPRIMItemFormatConfig confKPRIM = new QTIExportKPRIMItemFormatConfig(true, true, true, false); itConfigs.put(QTIExportKPRIMItemFormatConfig.class, confKPRIM); } } else if (item.getItemIdent().startsWith(ItemParser.ITEM_PREFIX_ESSAY)){ if (itConfigs.get(QTIExportEssayItemFormatConfig.class) == null){ QTIExportEssayItemFormatConfig confEssay = new QTIExportEssayItemFormatConfig(true, false); itConfigs.put(QTIExportEssayItemFormatConfig.class, confEssay); } } else if (item.getItemIdent().startsWith(ItemParser.ITEM_PREFIX_FIB)){ if (itConfigs.get(QTIExportFIBItemFormatConfig.class) == null){ QTIExportFIBItemFormatConfig confFIB = new QTIExportFIBItemFormatConfig(true, true, false); itConfigs.put(QTIExportFIBItemFormatConfig.class, confFIB); } } //if cannot find the type via the ItemParser, look for the QTIItemObject type else if (item.getItemType().equals(QTIItemObject.TYPE.A)){ QTIExportEssayItemFormatConfig confEssay = new QTIExportEssayItemFormatConfig(true, false); itConfigs.put(QTIExportEssayItemFormatConfig.class, confEssay); } else if (item.getItemType().equals(QTIItemObject.TYPE.R)){ QTIExportSCQItemFormatConfig confSCQ = new QTIExportSCQItemFormatConfig(true, true, true, false); itConfigs.put(QTIExportSCQItemFormatConfig.class, confSCQ); } else if (item.getItemType().equals(QTIItemObject.TYPE.C)){ QTIExportMCQItemFormatConfig confMCQ = new QTIExportMCQItemFormatConfig(true, true, true, false); itConfigs.put(QTIExportMCQItemFormatConfig.class, confMCQ ); } else if (item.getItemType().equals(QTIItemObject.TYPE.B)){ QTIExportFIBItemFormatConfig confFIB = new QTIExportFIBItemFormatConfig(true, true, false); itConfigs.put(QTIExportFIBItemFormatConfig.class, confFIB); } else { throw new OLATRuntimeException(null,"Can not resolve QTIItem type", null); } } return itConfigs; } }