/** * <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.FlexiTableElement; 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.BulkAssessmentColumnSettings; import org.olat.course.assessment.model.BulkAssessmentDatas; import org.olat.course.assessment.model.BulkAssessmentRow; 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"); setFormContextHelp("Using Course Tools#bulkassessment_map"); AssessableCourseNode courseNode = (AssessableCourseNode)getFromRunContext("courseNode"); BulkAssessmentSettings settings = new BulkAssessmentSettings(courseNode); String[] usernameKeys = new String[numOfColumns]; String[] usernameValues = new String[numOfColumns]; String[] otherKeys = new String[numOfColumns + 1]; String[] otherValues = new String[numOfColumns + 1]; for(int i=0; i<numOfColumns; i++) { usernameKeys[i] = "col" + i; usernameValues[i] = translate("column", Integer.toString(i + 1)); otherKeys[i] = "col" + i; otherValues[i] = translate("column", Integer.toString(i + 1)); } otherKeys[otherKeys.length - 1] = "col9999"; otherValues[otherValues.length - 1] = translate("column.dontuse"); FormLayoutContainer choosersCont = FormLayoutContainer.createDefaultFormLayout("choosers", getTranslator()); choosersCont.setRootForm(mainForm); formLayout.add(choosersCont); int pos = 0; userNameColumnEl = uifactory.addDropdownSingleselect("table.header.identifier", choosersCont, usernameKeys, usernameValues, null); if(columnsSettings != null && columnsSettings.getUsernameColumn() < usernameKeys.length) { userNameColumnEl.select(getSelectedKey(pos++, columnsSettings.getUsernameColumn(), usernameKeys), true); } else if(usernameKeys.length > 0){ userNameColumnEl.select(usernameKeys[Math.min(pos++, usernameKeys.length - 1)], true); } if(settings.isHasScore()) { scoreColumnEl = uifactory.addDropdownSingleselect("table.header.score", choosersCont, otherKeys, otherValues, null); if(columnsSettings != null && columnsSettings.getScoreColumn() < otherKeys.length) { scoreColumnEl.select(getSelectedKey(pos++, columnsSettings.getScoreColumn(), otherKeys), true); } else if(otherKeys.length > 0) { scoreColumnEl.select(otherKeys[Math.min(pos++, otherKeys.length - 1)], true); } } if(settings.isHasPassed() && settings.getCut() == null) { passedColumnEl = uifactory.addDropdownSingleselect("table.header.passed", choosersCont, otherKeys, otherValues, null); if(columnsSettings != null && columnsSettings.getPassedColumn() < otherKeys.length) { passedColumnEl.select(getSelectedKey(pos++, columnsSettings.getPassedColumn(), otherKeys), true); } else if(otherKeys.length > 0) { passedColumnEl.select(otherKeys[Math.min(pos++, otherKeys.length - 1)], true); } } if(settings.isHasUserComment()) { commentColumnEl = uifactory.addDropdownSingleselect("table.header.comment", choosersCont, otherKeys, otherValues, null); if(columnsSettings != null && columnsSettings.getCommentColumn() < otherKeys.length) { commentColumnEl.select(getSelectedKey(pos++, columnsSettings.getCommentColumn(), otherKeys), true); } else if(otherKeys.length > 0) { commentColumnEl.select(otherKeys[Math.min(pos++, otherKeys.length - 1)], 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); FlexiTableElement tableEl = uifactory.addTableElement(getWindowControl(), "overviewList", overviewDataModel, getTranslator(), formLayout); tableEl.setCustomizeColumns(false); } 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 boolean validateFormLogic(UserRequest ureq) { boolean allOk = true; userNameColumnEl.clearError(); if(userNameColumnEl != null && !userNameColumnEl.isOneSelected()) { userNameColumnEl.setErrorKey("form.legende.mandatory", null); allOk &= false; } return allOk & super.validateFormLogic(ureq); } @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()]; 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; } } }