diff --git a/src/main/java/org/olat/core/commons/services/taskexecutor/model/PersistentTask.java b/src/main/java/org/olat/core/commons/services/taskexecutor/model/PersistentTask.java index 602cd1c80e3be6b8a0465890020ea0cb35e93c45..45f8c1bdb842c3c78d1a2acdff5d80512e7ae864 100644 --- a/src/main/java/org/olat/core/commons/services/taskexecutor/model/PersistentTask.java +++ b/src/main/java/org/olat/core/commons/services/taskexecutor/model/PersistentTask.java @@ -65,8 +65,8 @@ public class PersistentTask implements Task, CreateInfo, ModifiedInfo, Persistab private static final long serialVersionUID = 800884851125711998L; @Id - @GeneratedValue(generator = "system-uuid") - @GenericGenerator(name = "system-uuid", strategy = "hilo") + @GeneratedValue(generator = "system-uuid") + @GenericGenerator(name = "system-uuid", strategy = "hilo") @Column(name="id", nullable=false, unique=true, insertable=true, updatable=false) private Long key; @@ -108,7 +108,7 @@ public class PersistentTask implements Task, CreateInfo, ModifiedInfo, Persistab @Column(name="e_executor_boot_id", nullable=true, insertable=true, updatable=true) private String executorBootId; - @Column(name="e_task", nullable=false, insertable=true, updatable=false) + @Column(name="e_task", nullable=false, insertable=true, updatable=true) private String task; @Override diff --git a/src/main/java/org/olat/course/assessment/bulk/BulkAssessment_2_DatasStep.java b/src/main/java/org/olat/course/assessment/bulk/BulkAssessment_2_DatasStep.java index 8537bf944398d13daba269df3d62b8360e2b2f62..6f312cdc08deea2b2479b6cea30122a23723b18f 100644 --- a/src/main/java/org/olat/course/assessment/bulk/BulkAssessment_2_DatasStep.java +++ b/src/main/java/org/olat/course/assessment/bulk/BulkAssessment_2_DatasStep.java @@ -39,7 +39,7 @@ import org.olat.course.nodes.AssessableCourseNode; public class BulkAssessment_2_DatasStep extends BasicStep { private final Task task; - private final BulkAssessmentDatas datas; + private final BulkAssessmentDatas savedDatas; private final AssessableCourseNode courseNode; private boolean hasPreviousStep = true; @@ -58,13 +58,18 @@ public class BulkAssessment_2_DatasStep extends BasicStep { * @param datas */ public BulkAssessment_2_DatasStep(UserRequest ureq, AssessableCourseNode courseNode, - BulkAssessmentDatas datas, Task task) { + BulkAssessmentDatas savedDatas, Task task) { super(ureq); this.task = task; - this.datas = datas; + this.savedDatas = savedDatas; this.courseNode = courseNode; setI18nTitleAndDescr("data.title", "data.title"); - setNextStep(new BulkAssessment_3_ValidationStep(ureq)); + if(savedDatas == null) { + setNextStep(new BulkAssessment_2b_ChooseColumnsStep(ureq)); + } else { + setNextStep(new BulkAssessment_2b_ChooseColumnsStep(ureq, savedDatas.getColumnsSettings())); + } + hasPreviousStep = (courseNode == null ? false : true); } @@ -84,9 +89,8 @@ public class BulkAssessment_2_DatasStep extends BasicStep { } DataStepForm ctrl; - if(datas != null) { - context.put("datas", datas); - ctrl = new DataStepForm(ureq, wControl, courseNode, datas, context, form); + if(savedDatas != null) { + ctrl = new DataStepForm(ureq, wControl, courseNode, savedDatas, context, form); } else { ctrl = new DataStepForm(ureq, wControl, context, form); } diff --git a/src/main/java/org/olat/course/assessment/bulk/BulkAssessment_2b_ChooseColumnsStep.java b/src/main/java/org/olat/course/assessment/bulk/BulkAssessment_2b_ChooseColumnsStep.java new file mode 100644 index 0000000000000000000000000000000000000000..60b37cebabcc1d4c31c1d64956bc85e93871df0d --- /dev/null +++ b/src/main/java/org/olat/course/assessment/bulk/BulkAssessment_2b_ChooseColumnsStep.java @@ -0,0 +1,74 @@ +/** + * <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.assessment.bulk; + +import org.olat.core.gui.UserRequest; +import org.olat.core.gui.components.form.flexible.impl.Form; +import org.olat.core.gui.control.WindowControl; +import org.olat.core.gui.control.generic.wizard.BasicStep; +import org.olat.core.gui.control.generic.wizard.PrevNextFinishConfig; +import org.olat.core.gui.control.generic.wizard.StepFormController; +import org.olat.core.gui.control.generic.wizard.StepsRunContext; +import org.olat.course.assessment.model.BulkAssessmentColumnSettings; + +/** + * + * Initial date: 9.1.2014<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +public class BulkAssessment_2b_ChooseColumnsStep extends BasicStep { + + private final BulkAssessmentColumnSettings savedColumnsSettings; + + /** + * This constructor start the edit the bulk update. + * @param ureq + * @param courseNode + * @param datas + */ + public BulkAssessment_2b_ChooseColumnsStep(UserRequest ureq) { + this(ureq, null); + } + + /** + * This constructor start the edit the bulk update. + * @param ureq + * @param courseNode + * @param datas + */ + public BulkAssessment_2b_ChooseColumnsStep(UserRequest ureq, BulkAssessmentColumnSettings savedColumnsSettings) { + super(ureq); + this.savedColumnsSettings = savedColumnsSettings; + setI18nTitleAndDescr("chooseColumns.title", "chooseColumns.title"); + setNextStep(new BulkAssessment_3_ValidationStep(ureq)); + } + + @Override + public PrevNextFinishConfig getInitialPrevNextFinishConfig() { + return new PrevNextFinishConfig(true, true, false); + } + + @Override + public StepFormController getStepController(UserRequest ureq, WindowControl wControl, StepsRunContext context, Form form) { + ChooseColumnsStepForm ctrl = new ChooseColumnsStepForm(ureq, wControl, savedColumnsSettings, context, form); + return ctrl; + } +} diff --git a/src/main/java/org/olat/course/assessment/bulk/ChooseColumnsStepForm.java b/src/main/java/org/olat/course/assessment/bulk/ChooseColumnsStepForm.java new file mode 100644 index 0000000000000000000000000000000000000000..97f8251f8dedf0483ecfb461cb0a58f1fcc16c23 --- /dev/null +++ b/src/main/java/org/olat/course/assessment/bulk/ChooseColumnsStepForm.java @@ -0,0 +1,316 @@ +/** + * <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.assessment.bulk; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.olat.core.gui.UserRequest; +import org.olat.core.gui.components.form.flexible.FormItemContainer; +import org.olat.core.gui.components.form.flexible.elements.SingleSelection; +import org.olat.core.gui.components.form.flexible.impl.Form; +import org.olat.core.gui.components.form.flexible.impl.FormLayoutContainer; +import org.olat.core.gui.components.form.flexible.impl.elements.table.DefaultFlexiColumnModel; +import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTableColumnModel; +import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTableDataModel; +import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTableDataModelFactory; +import org.olat.core.gui.components.table.DefaultTableDataModel; +import org.olat.core.gui.control.Controller; +import org.olat.core.gui.control.WindowControl; +import org.olat.core.gui.control.generic.wizard.StepFormBasicController; +import org.olat.core.gui.control.generic.wizard.StepsEvent; +import org.olat.core.gui.control.generic.wizard.StepsRunContext; +import org.olat.core.util.StringHelper; +import org.olat.course.assessment.model.BulkAssessmentDatas; +import org.olat.course.assessment.model.BulkAssessmentRow; +import org.olat.course.assessment.model.BulkAssessmentColumnSettings; +import org.olat.course.assessment.model.BulkAssessmentSettings; +import org.olat.course.nodes.AssessableCourseNode; + +/** + * + * Initial date: 9.1.2014<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +public class ChooseColumnsStepForm extends StepFormBasicController { + + private int numOfColumns; + private SingleSelection userNameColumnEl, scoreColumnEl, passedColumnEl, commentColumnEl; + private final OverviewDataModel overviewDataModel; + private final BulkAssessmentColumnSettings columnsSettings; + + public ChooseColumnsStepForm(UserRequest ureq, WindowControl wControl, BulkAssessmentColumnSettings columnsSettings, + StepsRunContext runContext, Form rootForm) { + super(ureq, wControl, rootForm, runContext, LAYOUT_VERTICAL, null); + setTranslator(new HeaderColumnTranslator(getTranslator())); + this.columnsSettings = columnsSettings; + + @SuppressWarnings("unchecked") + List<String[]> splittedRows = (List<String[]>)getFromRunContext("splittedRows"); + if(splittedRows.size() > 0) { + numOfColumns = splittedRows.get(0).length; + } + + overviewDataModel = new OverviewDataModel(splittedRows); + initForm(ureq); + } + + @Override + protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) { + setFormTitle("chooseColumns.title"); + setFormDescription("chooseColumns.description"); + + AssessableCourseNode courseNode = (AssessableCourseNode)getFromRunContext("courseNode"); + BulkAssessmentSettings settings = new BulkAssessmentSettings(courseNode); + + String[] theKeys = new String[numOfColumns]; + String[] theValues = new String[numOfColumns]; + for(int i=0; i<numOfColumns; i++) { + theKeys[i] = "col" + i; + theValues[i] = translate("column", Integer.toString(i + 1)); + } + + FormLayoutContainer choosersCont = FormLayoutContainer.createDefaultFormLayout("choosers", getTranslator()); + choosersCont.setRootForm(mainForm); + formLayout.add(choosersCont); + + int pos = 0; + userNameColumnEl = uifactory.addDropdownSingleselect("table.header.identifier", choosersCont, theKeys, theValues, null); + if(columnsSettings != null && columnsSettings.getUsernameColumn() < theKeys.length) { + userNameColumnEl.select(getSelectedKey(pos++, columnsSettings.getUsernameColumn(), theKeys), true); + } else { + userNameColumnEl.select(theKeys[pos++], true); + } + if(settings.isHasScore()) { + scoreColumnEl = uifactory.addDropdownSingleselect("table.header.score", choosersCont, theKeys, theValues, null); + if(columnsSettings != null && columnsSettings.getScoreColumn() < theKeys.length) { + scoreColumnEl.select(getSelectedKey(pos++, columnsSettings.getScoreColumn(), theKeys), true); + } else { + scoreColumnEl.select(theKeys[pos++], true); + } + } + if(settings.isHasPassed() && settings.getCut() == null) { + passedColumnEl = uifactory.addDropdownSingleselect("table.header.passed", choosersCont, theKeys, theValues, null); + if(columnsSettings != null && columnsSettings.getPassedColumn() < theKeys.length) { + passedColumnEl.select(getSelectedKey(pos++, columnsSettings.getPassedColumn(), theKeys), true); + } else { + passedColumnEl.select(theKeys[pos++], true); + } + } + if(settings.isHasUserComment()) { + commentColumnEl = uifactory.addDropdownSingleselect("table.header.comment", choosersCont, theKeys, theValues, null); + if(columnsSettings != null && columnsSettings.getCommentColumn() < theKeys.length) { + commentColumnEl.select(getSelectedKey(pos++, columnsSettings.getCommentColumn(), theKeys), true); + } else { + commentColumnEl.select(theKeys[pos++], true); + } + } + + FlexiTableColumnModel tableColumnModel = FlexiTableDataModelFactory.createFlexiTableColumnModel(); + for(int i=0; i<numOfColumns; i++) { + DefaultFlexiColumnModel colModel = new DefaultFlexiColumnModel("ccc" + (i+1), i); + tableColumnModel.addFlexiColumnModel(colModel); + } + + overviewDataModel.setTableColumnModel(tableColumnModel); + uifactory.addTableElement(ureq, getWindowControl(), "overviewList", overviewDataModel, formLayout); + } + + private String getSelectedKey(int pos, int settings, String[] theKeys) { + int selectionPos = pos; + if(settings >= 0 && settings < theKeys.length) { + selectionPos = settings; + } + return theKeys[selectionPos]; + } + + @Override + protected void doDispose() { + // + } + + @Override + protected void formOK(UserRequest ureq) { + BulkAssessmentDatas datas = (BulkAssessmentDatas)getFromRunContext("datas"); + List<BulkAssessmentRow> rows = datas.getRows(); + Map<String, BulkAssessmentRow> assessedIdToRow = new HashMap<>(); + for(BulkAssessmentRow row:rows) { + assessedIdToRow.put(row.getAssessedId(), row); + } + + BulkAssessmentColumnSettings settings = datas.getColumnsSettings(); + if(settings == null) { + settings = new BulkAssessmentColumnSettings(); + datas.setColumnsSettings(settings); + } + settings.setUsernameColumn(getColumnPosition(userNameColumnEl)); + settings.setScoreColumn(getColumnPosition(scoreColumnEl)); + settings.setPassedColumn(getColumnPosition(passedColumnEl)); + settings.setCommentColumn(getColumnPosition(commentColumnEl)); + + List<String[]> splittedRows = overviewDataModel.getObjects(); + for(String[] values:splittedRows) { + createRow(values, settings, rows, assessedIdToRow); + } + + fireEvent(ureq, StepsEvent.ACTIVATE_NEXT); + } + + private int getColumnPosition(SingleSelection el) { + if(el == null) return 9999; + String selectedKey = el.getSelectedKey(); + if(selectedKey == null || selectedKey.length() < 4) return 9999; + String pos = selectedKey.substring(3); + if(StringHelper.isLong(pos)) { + return Integer.parseInt(pos); + } + return 9999; + } + + + /** + * Create a row object from an array of strings. The array + * is assessed identity identifier, score, status, comment. + * @param values + * @return + */ + private void createRow(String[] values, BulkAssessmentColumnSettings settings, + List<BulkAssessmentRow> rows, Map<String, BulkAssessmentRow> assessedIdToRow) { + int valuesLength = values.length; + if(valuesLength <= 0 || valuesLength <= settings.getUsernameColumn()) { + return; + } + + String identifyer = values[settings.getUsernameColumn()]; + identifyer.trim(); + if (!StringHelper.containsNonWhitespace(identifyer)) { + identifyer = "-"; + } + + BulkAssessmentRow row; + if(assessedIdToRow.containsKey(identifyer)) { + row = assessedIdToRow.get(identifyer); + } else { + row = new BulkAssessmentRow(); + row.setAssessedId(identifyer); + rows.add(row); + } + + if(valuesLength > settings.getScoreColumn()) { + String scoreStr = values[settings.getScoreColumn()]; + scoreStr= scoreStr.trim(); + Float score; + if (StringHelper.containsNonWhitespace(scoreStr)) { + try { + // accept writing with , or . + score = Float.parseFloat(scoreStr.replace(',', '.')); + } catch (NumberFormatException e) { + score = null; + } + } else { + // only set new numbers, ignore everything else + score = null; + } + row.setScore(score); + } + + if(valuesLength > settings.getPassedColumn()) { + String passedStr = values[settings.getPassedColumn()]; + passedStr= passedStr.trim(); + Boolean passed; + if ("y".equalsIgnoreCase(passedStr) + || "yes".equalsIgnoreCase(passedStr) + || "passed".equalsIgnoreCase(passedStr) + || "true".equalsIgnoreCase(passedStr) + || "1".equalsIgnoreCase(passedStr)) { + passed = Boolean.TRUE; + } else if ("n".equalsIgnoreCase(passedStr) + || "no".equalsIgnoreCase(passedStr) + || "false".equalsIgnoreCase(passedStr) + || "failed".equalsIgnoreCase(passedStr) + || "0".equalsIgnoreCase(passedStr)) { + passed = Boolean.FALSE; + } else { + // only set defined values, ignore everything else + passed = null; + } + row.setPassed(passed); + } + + if(valuesLength > settings.getCommentColumn()) { + String commentStr = values[settings.getCommentColumn()]; + // add any additional comment which probably is just a comma in a escaped string + if (valuesLength > 4) { + for (int i = 4; i < valuesLength; i++) { + commentStr += "," + values[i]; + } + } + commentStr= commentStr.trim(); + + if(commentStr.isEmpty()) { + // ignore empty values + row.setComment(null); + } else if("\"\"".equals(commentStr) || "''".equals(commentStr)) { + row.setComment(""); + } else { + row.setComment(commentStr); + } + } + } + + private static class OverviewDataModel extends DefaultTableDataModel<String[]> implements FlexiTableDataModel<String[]> { + private FlexiTableColumnModel columnModel; + + public OverviewDataModel(List<String[]> nodes) { + super(nodes); + } + + @Override + public FlexiTableColumnModel getTableColumnModel() { + return columnModel; + } + + @Override + public int getRowCount() { + return Math.min(3, super.getRowCount()); + } + + @Override + public void setTableColumnModel(FlexiTableColumnModel tableColumnModel) { + this.columnModel = tableColumnModel; + } + + @Override + public int getColumnCount() { + return columnModel.getColumnCount(); + } + + @Override + public Object getValueAt(int row, int col) { + String[] data = getObject(row); + if(data != null && col >= 0 && col < data.length) { + return data[col]; + } + return null; + } + } +} diff --git a/src/main/java/org/olat/course/assessment/bulk/DataStepForm.java b/src/main/java/org/olat/course/assessment/bulk/DataStepForm.java index a4cd38c02c4fed5e1c9c2b5023454e3d825f52ca..206d695692f3376e01e6eff4d466d0fe91e4891f 100644 --- a/src/main/java/org/olat/course/assessment/bulk/DataStepForm.java +++ b/src/main/java/org/olat/course/assessment/bulk/DataStepForm.java @@ -77,7 +77,8 @@ public class DataStepForm extends StepFormBasicController { private FileElement returnFileEl; private SingleSelection delimiter; - private BulkAssessmentDatas datas; + private OlatRootFileImpl targetArchive; + private BulkAssessmentDatas savedDatas; private final AssessableCourseNode courseNode; private OlatRootFolderImpl bulkAssessmentTmpDir; @@ -89,11 +90,11 @@ public class DataStepForm extends StepFormBasicController { initForm(ureq); } - public DataStepForm(UserRequest ureq, WindowControl wControl, AssessableCourseNode courseNode, BulkAssessmentDatas datas, + public DataStepForm(UserRequest ureq, WindowControl wControl, AssessableCourseNode courseNode, BulkAssessmentDatas savedDatas, StepsRunContext runContext, Form rootForm) { super(ureq, wControl, rootForm, runContext, LAYOUT_VERTICAL, null); - this.datas = datas; + this.savedDatas = savedDatas; this.courseNode = courseNode; addToRunContext("courseNode", courseNode); initForm(ureq); @@ -112,8 +113,8 @@ public class DataStepForm extends StepFormBasicController { setFormContextHelp("org.olat.course.assessment.bulk", "bulkassessment_data.html","help.hover.bulkassessment_data"); String dataVal = ""; - if(datas != null && StringHelper.containsNonWhitespace(datas.getDataBackupFile())) { - OlatRootFileImpl file = new OlatRootFileImpl(datas.getDataBackupFile(), null); + if(savedDatas != null && StringHelper.containsNonWhitespace(savedDatas.getDataBackupFile())) { + OlatRootFileImpl file = new OlatRootFileImpl(savedDatas.getDataBackupFile(), null); InputStream in = file.getInputStream(); try { dataVal = IOUtils.toString(in); @@ -150,8 +151,8 @@ public class DataStepForm extends StepFormBasicController { Set<String> mimes = new HashSet<String>(); mimes.add(WebappHelper.getMimeType("file.zip")); returnFileEl.limitToMimeType(mimes, "return.mime", null); - if(datas != null && StringHelper.containsNonWhitespace(datas.getReturnFiles())) { - targetArchive = new OlatRootFileImpl(datas.getReturnFiles(), null); + if(savedDatas != null && StringHelper.containsNonWhitespace(savedDatas.getReturnFiles())) { + targetArchive = new OlatRootFileImpl(savedDatas.getReturnFiles(), null); if(targetArchive.exists()) { returnFileEl.setInitialFile(targetArchive.getBasefile()); } @@ -173,7 +174,10 @@ public class DataStepForm extends StepFormBasicController { return; } setFormWarning(null); // reset error - BulkAssessmentDatas datas = new BulkAssessmentDatas(); + BulkAssessmentDatas datas = (BulkAssessmentDatas)getFromRunContext("datas"); + if(datas == null) { + datas = new BulkAssessmentDatas(); + } if(bulkAssessmentTmpDir == null) { OlatRootFolderImpl bulkAssessmentDir = new OlatRootFolderImpl("/bulkassessment/", null); @@ -181,7 +185,9 @@ public class DataStepForm extends StepFormBasicController { } backupInputDatas(val, datas, bulkAssessmentTmpDir); - List<BulkAssessmentRow> rows = processInputData(val); + List<String[]> splittedRows = splitRawData(val); + addToRunContext("splittedRows", splittedRows); + List<BulkAssessmentRow> rows = new ArrayList<>(100); if(returnFileEl != null) { processReturnFiles(datas, rows, bulkAssessmentTmpDir); } @@ -190,14 +196,43 @@ public class DataStepForm extends StepFormBasicController { fireEvent(ureq, StepsEvent.ACTIVATE_NEXT); } + private List<String[]> splitRawData(String idata) { + String[] lines = idata.split("\r?\n"); + int numOfLines = lines.length; + + List<String[]> rows = new ArrayList<String[]>(numOfLines); + + String d; + if (delimiter.getSelectedKey().startsWith("t")) { + d = "\t"; + } else { + d = ","; + } + + for (int i = 0; i < numOfLines; i++) { + String line = lines[i]; + if(StringHelper.containsNonWhitespace(line)){ + String[] values = line.split(d,-1); + rows.add(values); + } + } + return rows; + } + /** * Backup the input field for later editing purpose * @param val * @param datas */ private void backupInputDatas(String val, BulkAssessmentDatas datas, OlatRootFolderImpl tmpDir) { - String inputFilename = UUID.randomUUID().toString() + ".csv"; - OlatRootFileImpl inputFile = tmpDir.createChildLeaf(inputFilename); + OlatRootFileImpl inputFile = null; + if(StringHelper.containsNonWhitespace(datas.getDataBackupFile())) { + inputFile = new OlatRootFileImpl(datas.getDataBackupFile(), null); + } + if(inputFile == null) { + String inputFilename = UUID.randomUUID().toString() + ".csv"; + inputFile = tmpDir.createChildLeaf(inputFilename); + } OutputStream out = inputFile.getOutputStream(false); try { @@ -210,8 +245,6 @@ public class DataStepForm extends StepFormBasicController { } } - private OlatRootFileImpl targetArchive; - private void processReturnFiles(BulkAssessmentDatas datas, List<BulkAssessmentRow> rows, OlatRootFolderImpl tmpDir) { File uploadedFile = returnFileEl.getUploadFile(); if(uploadedFile == null) { @@ -317,115 +350,4 @@ public class DataStepForm extends StepFormBasicController { } } } - - private List<BulkAssessmentRow> processInputData(String idata) { - String[] lines = idata.split("\r?\n"); - int numOfLines = lines.length; - - List<BulkAssessmentRow> rows = new ArrayList<BulkAssessmentRow>(numOfLines); - - String d; - if (delimiter.getSelectedKey().startsWith("t")) { - d = "\t"; - } else { - d = ","; - } - - for (int i = 0; i < numOfLines; i++) { - String line = lines[i]; - - if(StringHelper.containsNonWhitespace(line)){ - String[] values = line.split(d,-1); - BulkAssessmentRow row = createRow(values); - if(row != null) { - rows.add(row); - } - } - } - return rows; - } - - /** - * Create a row object from an array of strings. The array - * is assessed identity identifier, score, status, comment. - * @param values - * @return - */ - private BulkAssessmentRow createRow(String[] values) { - int valuesLength = values.length; - if(valuesLength <= 0) { - return null; - } - - BulkAssessmentRow row = new BulkAssessmentRow(); - String identifyer = values[0]; - identifyer.trim(); - if (!StringHelper.containsNonWhitespace(identifyer)) { - identifyer = "-"; - } - row.setAssessedId(identifyer); - - if(valuesLength > 1) { - String scoreStr = values[1]; - scoreStr= scoreStr.trim(); - Float score; - if (StringHelper.containsNonWhitespace(scoreStr)) { - try { - // accept writing with , or . - score = Float.parseFloat(scoreStr.replace(',', '.')); - } catch (NumberFormatException e) { - score = null; - } - } else { - // only set new numbers, ignore everything else - score = null; - } - row.setScore(score); - } - - if(valuesLength > 2) { - String passedStr = values[2]; - passedStr= passedStr.trim(); - Boolean passed; - if ("y".equalsIgnoreCase(passedStr) - || "yes".equalsIgnoreCase(passedStr) - || "passed".equalsIgnoreCase(passedStr) - || "true".equalsIgnoreCase(passedStr) - || "1".equalsIgnoreCase(passedStr)) { - passed = Boolean.TRUE; - } else if ("n".equalsIgnoreCase(passedStr) - || "no".equalsIgnoreCase(passedStr) - || "false".equalsIgnoreCase(passedStr) - || "failed".equalsIgnoreCase(passedStr) - || "0".equalsIgnoreCase(passedStr)) { - passed = Boolean.FALSE; - } else { - // only set defined values, ignore everything else - passed = null; - } - row.setPassed(passed); - } - - if(valuesLength > 3) { - String commentStr = values[3]; - // add any additional comment which probably is just a comma in a escaped string - if (valuesLength > 4) { - for (int i = 4; i < valuesLength; i++) { - commentStr += "," + values[i]; - } - } - commentStr= commentStr.trim(); - - if(commentStr.isEmpty()) { - // ignore empty values - row.setComment(null); - } else if("\"\"".equals(commentStr) || "''".equals(commentStr)) { - row.setComment(""); - } else { - row.setComment(commentStr); - } - } - - return row; - } -} +} \ No newline at end of file diff --git a/src/main/java/org/olat/course/assessment/bulk/HeaderColumnTranslator.java b/src/main/java/org/olat/course/assessment/bulk/HeaderColumnTranslator.java new file mode 100644 index 0000000000000000000000000000000000000000..e703eb3e820f84dfc1b6926f6c216193ed1c8354 --- /dev/null +++ b/src/main/java/org/olat/course/assessment/bulk/HeaderColumnTranslator.java @@ -0,0 +1,89 @@ +/** +* 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. +* <p> +*/ + +package org.olat.course.assessment.bulk; + +import java.util.Locale; + +import org.apache.log4j.Level; +import org.olat.core.gui.translator.Translator; +/** + * + * Description:<br> + * Proxy for the column numbering + * + * <P> + * Initial Date: 19.12.2005 <br> + * + * @author Alexander Schneider + */ +public class HeaderColumnTranslator implements Translator { + private Translator origTranslator; + + public HeaderColumnTranslator(Translator origTranslator){ + this.origTranslator = origTranslator; + } + + public String translate(String key) { + return translate(key, null); + } + + @Override + public String translate(String key, String[] args) { + return translate(key, args, Level.WARN); + } + + @Override + public String translate(String key, String[] args, Level missingTranslationLogLevel) { + String val; + if(key.startsWith("ccc")){ + String t = key.substring(3); + val = origTranslator.translate("column", new String[]{t}); + }else if (key.startsWith("hhh")){ + val = key.substring(3); + }else{ + val = origTranslator.translate(key, args, missingTranslationLogLevel); + } + return val; + } + + /** + * @see org.olat.core.gui.translator.Translator#translate(java.lang.String, + * java.lang.String[], boolean) + */ + public String translate(String key, String[] args, boolean fallBackToDefaultLocale) { + // no fall back to default locale + return translate(key, args); + } + + public Locale getLocale() { + return origTranslator.getLocale(); + } + + public void setLocale(Locale locale) { + origTranslator.setLocale(locale); + } +} diff --git a/src/main/java/org/olat/course/assessment/bulk/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/course/assessment/bulk/_i18n/LocalStrings_de.properties index 601a82cf4afd23a52734ab2585aaedd77e7ddd32..3902d0de67d697743d2934faaeacc8edb9b2f839 100644 --- a/src/main/java/org/olat/course/assessment/bulk/_i18n/LocalStrings_de.properties +++ b/src/main/java/org/olat/course/assessment/bulk/_i18n/LocalStrings_de.properties @@ -64,6 +64,9 @@ chelp.bulkassessment_schedule.intro=Eine Massenbewertung kann entweder sofort od chelp.bulkassessment_schedule.title=Massenbewertung\: Planung choose.node.desc=W\u00E4hlen Sie einen bewertbaren Baustein aus diesem Kurs f\u00FCr den eine Massenbewertung durchgef\u00FChrt werden soll. choose.node.title=Kursbaustein ausw\u00E4hlen +column=Spalte {0} +chooseColumns.title=Bestimmen der zu interpretierenden Spalte +chooseColumns.description=W\u00E4hlen Sie aus, welche Spalte OLAT als was interpretieren soll. confirmation.mail.body=Ihre Massenbewertung des Kursbausteins {1} im Kurs {0} wurde wie geplant f\u00FCr {3} Benutzer am {4} ausgef\u00FChrt.\n\n{2} confirmation.mail.subject=Geplante Massenbewertung {0} {1} ausgef\u00FChrt data=Daten diff --git a/src/main/java/org/olat/course/assessment/model/BulkAssessmentColumnSettings.java b/src/main/java/org/olat/course/assessment/model/BulkAssessmentColumnSettings.java new file mode 100644 index 0000000000000000000000000000000000000000..cd106d7695751b1fb80c045dde5e13b605aeb724 --- /dev/null +++ b/src/main/java/org/olat/course/assessment/model/BulkAssessmentColumnSettings.java @@ -0,0 +1,70 @@ +/** + * <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.assessment.model; + +import java.io.Serializable; + +/** + * + * Initial date: 09.01.2014<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +public class BulkAssessmentColumnSettings implements Serializable { + + private static final long serialVersionUID = -8726013806107035722L; + + private int usernameColumn; + private int scoreColumn; + private int passedColumn; + private int commentColumn; + + public int getUsernameColumn() { + return usernameColumn; + } + + public void setUsernameColumn(int usernameColumn) { + this.usernameColumn = usernameColumn; + } + + public int getScoreColumn() { + return scoreColumn; + } + + public void setScoreColumn(int scoreColumn) { + this.scoreColumn = scoreColumn; + } + + public int getPassedColumn() { + return passedColumn; + } + + public void setPassedColumn(int passedColumn) { + this.passedColumn = passedColumn; + } + + public int getCommentColumn() { + return commentColumn; + } + + public void setCommentColumn(int commentColumn) { + this.commentColumn = commentColumn; + } +} diff --git a/src/main/java/org/olat/course/assessment/model/BulkAssessmentDatas.java b/src/main/java/org/olat/course/assessment/model/BulkAssessmentDatas.java index d2e07fa6ed48d3529f83195dfb07634be634706f..d0225276893cd89db58f00e3f8a8443cb71b274d 100644 --- a/src/main/java/org/olat/course/assessment/model/BulkAssessmentDatas.java +++ b/src/main/java/org/olat/course/assessment/model/BulkAssessmentDatas.java @@ -34,6 +34,15 @@ public class BulkAssessmentDatas implements Serializable { private List<BulkAssessmentRow> rows; private String returnFiles; private String dataBackupFile; + private BulkAssessmentColumnSettings columnsSettings; + + public BulkAssessmentColumnSettings getColumnsSettings() { + return columnsSettings; + } + + public void setColumnsSettings(BulkAssessmentColumnSettings columnsSettings) { + this.columnsSettings = columnsSettings; + } public int getRowsSize() { return rows == null ? 0 : rows.size(); diff --git a/src/test/java/org/olat/core/commons/services/taskexecutor/PersistentTaskDAOTest.java b/src/test/java/org/olat/core/commons/services/taskexecutor/PersistentTaskDAOTest.java index 6b0c4ab8e316b8a6e8ffdb2303c40937448c5b97..bcabb8960fdabb45db29e5cc5882f6f1f61fba03 100644 --- a/src/test/java/org/olat/core/commons/services/taskexecutor/PersistentTaskDAOTest.java +++ b/src/test/java/org/olat/core/commons/services/taskexecutor/PersistentTaskDAOTest.java @@ -33,6 +33,8 @@ import org.olat.core.commons.persistence.DB; import org.olat.core.commons.services.taskexecutor.manager.PersistentTaskDAO; import org.olat.core.commons.services.taskexecutor.model.PersistentTask; import org.olat.core.id.Identity; +import org.olat.core.logging.OLog; +import org.olat.core.logging.Tracing; import org.olat.core.util.WebappHelper; import org.olat.core.util.xml.XStreamHelper; import org.olat.repository.RepositoryEntry; @@ -48,12 +50,13 @@ import org.springframework.beans.factory.annotation.Autowired; */ public class PersistentTaskDAOTest extends OlatTestCase { + private static final OLog log = Tracing.createLoggerFor(PersistentTaskDAOTest.class); + @Autowired private DB dbInstance; @Autowired private PersistentTaskDAO persistentTaskDao; - @Test public void createTask() { String name = "Task 0"; @@ -118,6 +121,30 @@ public class PersistentTaskDAOTest extends OlatTestCase { Assert.assertEquals(TaskStatus.inWork, todo.getStatus()); } + @Test + public void updateTask() { + //create + String name = "Task to update"; + PersistentTask task = persistentTaskDao.createTask(name, new DummyTask()); + dbInstance.commitAndCloseSession(); + + //update + PersistentTask todo = persistentTaskDao.pickTaskForRun(task.getKey()); + DummyTask taskToUpdate = new DummyTask(); + taskToUpdate.setMarkerValue("new marker"); + persistentTaskDao.updateTask(todo, taskToUpdate, null, null); + dbInstance.commitAndCloseSession(); + + //reload and check + PersistentTask loadedTask = persistentTaskDao.loadTaskById(task.getKey()); + Runnable runnable = persistentTaskDao.deserializeTask(loadedTask); + + Assert.assertNotNull(runnable); + Assert.assertTrue(runnable instanceof DummyTask); + DummyTask dummyRunnable = (DummyTask)runnable; + Assert.assertEquals("new marker", dummyRunnable.getMarkerValue()); + } + @Test public void todo() { String name = UUID.randomUUID().toString(); @@ -471,10 +498,26 @@ public class PersistentTaskDAOTest extends OlatTestCase { public static class DummyTask implements Runnable, Serializable { private static final long serialVersionUID = 5193785402425324970L; + + private String markerValue; + + public DummyTask() { + this.markerValue = UUID.randomUUID().toString(); + } + + public String getMarkerValue() { + return markerValue; + } + + public void setMarkerValue(String markerValue) { + this.markerValue = markerValue; + } + + @Override public void run() { - // + log.info("Run: " + markerValue); } } }