/**
* <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.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.olat.basesecurity.BaseSecurity;
import org.olat.core.CoreSpringFactory;
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.impl.Form;
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.id.Identity;
import org.olat.core.id.UserConstants;
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;
import org.olat.user.UserManager;
/**
*
* Initial date: 18.11.2013<br>
* @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
*
*/
public class ValidationStepForm extends StepFormBasicController {
private static final String[] userPropsToSearch = new String[]{ UserConstants.EMAIL, UserConstants.INSTITUTIONALEMAIL, UserConstants.INSTITUTIONALUSERIDENTIFIER };
private ValidDataModel validModel;
private ValidDataModel invalidModel;
private FlexiTableElement validTableEl;
private FlexiTableElement invalidTableEl;
private final UserManager userManager;
private final BaseSecurity securityManager;
public ValidationStepForm(UserRequest ureq, WindowControl wControl, StepsRunContext runContext, Form rootForm) {
super(ureq, wControl, rootForm, runContext, LAYOUT_CUSTOM, "validation");
userManager = CoreSpringFactory.getImpl(UserManager.class);
securityManager = CoreSpringFactory.getImpl(BaseSecurity.class);
initForm(ureq);
doValidate();
}
@Override
protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) {
AssessableCourseNode courseNode = (AssessableCourseNode)getFromRunContext("courseNode");
BulkAssessmentSettings settings = new BulkAssessmentSettings(courseNode);
FlexiTableColumnModel tableColumnModel = FlexiTableDataModelFactory.createFlexiTableColumnModel();
tableColumnModel.addFlexiColumnModel(new DefaultFlexiColumnModel("table.header.identifier", Cols.identifier.ordinal()));
tableColumnModel.addFlexiColumnModel(new DefaultFlexiColumnModel("table.header.lastName", Cols.lastName.ordinal()));
tableColumnModel.addFlexiColumnModel(new DefaultFlexiColumnModel("table.header.firstName", Cols.firstName.ordinal()));
if(settings.isHasScore()) {
tableColumnModel.addFlexiColumnModel(new DefaultFlexiColumnModel("table.header.score", Cols.score.ordinal(), new ScoreCellRenderer(settings)));
}
if(settings.isHasPassed() && settings.getCut() == null) {
tableColumnModel.addFlexiColumnModel(new DefaultFlexiColumnModel("table.header.passed", Cols.passed.ordinal(), new PassedCellRenderer()));
}
if(settings.isHasUserComment()) {
tableColumnModel.addFlexiColumnModel(new DefaultFlexiColumnModel("table.header.comment", Cols.comment.ordinal()));
}
if(settings.isHasReturnFiles()) {
tableColumnModel.addFlexiColumnModel(new DefaultFlexiColumnModel("table.header.numOfReturnFiles", Cols.numOfReturnFiles.ordinal()));
}
validModel = new ValidDataModel(Collections.<UserData>emptyList());
validModel.setTableColumnModel(tableColumnModel);
validTableEl = uifactory.addTableElement(getWindowControl(), "validList", validModel, getTranslator(), formLayout);
validTableEl.setCustomizeColumns(false);
invalidModel = new ValidDataModel(Collections.<UserData>emptyList());
invalidModel.setTableColumnModel(tableColumnModel);
invalidTableEl = uifactory.addTableElement(getWindowControl(), "notFoundList", invalidModel, getTranslator(), formLayout);
invalidTableEl.setCustomizeColumns(false);
flc.contextPut("settings", settings);
}
@Override
protected void doDispose() {
//
}
private void doValidate() {
BulkAssessmentDatas datas = (BulkAssessmentDatas)getFromRunContext("datas");
if(datas.getRows() != null) {
doValidateRows(datas);
}
flc.contextPut("hasNoItems", Boolean.valueOf(datas.getRows() == null || datas.getRows().size() == 0));
}
private void doValidateRows(BulkAssessmentDatas datas) {
List<BulkAssessmentRow> rows = datas.getRows();
List<String> assessedIdList = new ArrayList<String>(rows.size());
for(BulkAssessmentRow row : rows) {
assessedIdList.add(row.getAssessedId());
}
Map<String,Identity> idToIdentityMap = loadAssessedIdentities(assessedIdList);
List<UserData> validDatas = new ArrayList<UserData>(idToIdentityMap.size());
List<UserData> invalidDatas = new ArrayList<UserData>(rows.size() - idToIdentityMap.size());
for(BulkAssessmentRow row : datas.getRows()) {
Identity foundIdentity = idToIdentityMap.get(row.getAssessedId());
if(foundIdentity == null) {
invalidDatas.add(new UserData(row, null));
} else {
row.setIdentityKey(foundIdentity.getKey());
validDatas.add(new UserData(row, foundIdentity));
}
}
validModel.setObjects(validDatas);
invalidModel.setObjects(invalidDatas);
flc.contextPut("hasValidItems", Boolean.valueOf(validDatas.size()>0));
flc.contextPut("hasInvalidItems", Boolean.valueOf(invalidDatas.size()>0));
validTableEl.reset();
invalidTableEl.reset();
}
private Map<String,Identity> loadAssessedIdentities(List<String> assessedIdList) {
Map<String,Identity> idToIdentityMap = new HashMap<String, Identity>();
for(String assessedId : assessedIdList) {
Identity identity = securityManager.findIdentityByName(assessedId);
if(identity != null) {
idToIdentityMap.put(assessedId, identity);
continue;
}
for(String prop : userPropsToSearch) {
identity = userManager.findIdentityKeyWithProperty(prop, assessedId);
if(identity != null) {
idToIdentityMap.put(assessedId, identity);
continue;
}
}
}
return idToIdentityMap;
}
@Override
protected void formOK(UserRequest ureq) {
if (validModel.getRowCount() == 0) {
// do not continue wizard without valid data
return;
}
BulkAssessmentDatas datas = (BulkAssessmentDatas)getFromRunContext("datas");
List<BulkAssessmentRow> rows = new ArrayList<>(validModel.getRowCount() + invalidModel.getRowCount());
for(int i=validModel.getRowCount(); i-->0; ) {
rows.add(validModel.getObject(i).getRow());
}
for(int i=invalidModel.getRowCount(); i-->0; ) {
rows.add(invalidModel.getObject(i).getRow());
}
datas.setRows(rows);
addToRunContext("datas", datas);
fireEvent(ureq, StepsEvent.ACTIVATE_NEXT);
}
private static class UserData {
private final Identity identity;
private final BulkAssessmentRow row;
public UserData(BulkAssessmentRow row, Identity identity) {
this.row = row;
this.identity = identity;
}
public String getAssessedIdentifier() {
return row.getAssessedId();
}
public String getFirstName() {
return identity == null ? null : identity.getUser().getProperty(UserConstants.FIRSTNAME, null);
}
public String getLastName() {
return identity == null ? null : identity.getUser().getProperty(UserConstants.LASTNAME, null);
}
public Float getScore() {
return row.getScore();
}
public Boolean getPassed() {
return row.getPassed();
}
public String getComment() {
return row.getComment();
}
public int getNumOfReturnFiles() {
return row.getReturnFiles() == null ? 0 : row.getReturnFiles().size();
}
public BulkAssessmentRow getRow() {
if(identity != null) {
row.setIdentityKey(identity.getKey());
}
return row;
}
}
private enum Cols {
identifier,
lastName,
firstName,
score,
passed,
status,
comment,
numOfReturnFiles
}
private static class ValidDataModel extends DefaultTableDataModel<UserData> implements FlexiTableDataModel<UserData> {
private FlexiTableColumnModel columnModel;
public ValidDataModel(List<UserData> nodes) {
super(nodes);
}
@Override
public FlexiTableColumnModel getTableColumnModel() {
return columnModel;
}
@Override
public void setTableColumnModel(FlexiTableColumnModel tableColumnModel) {
this.columnModel = tableColumnModel;
}
@Override
public int getColumnCount() {
return 5;
}
@Override
public Object getValueAt(int row, int col) {
UserData data = getObject(row);
switch(Cols.values()[col]) {
case identifier: return data.getAssessedIdentifier();
case firstName: return data.getFirstName();
case lastName: return data.getLastName();
case score: return data.getScore();
case passed: return data.getPassed();
case status: return data.getPassed();
case comment: return data.getComment();
case numOfReturnFiles: return data.getNumOfReturnFiles();
default: return null;
}
}
}
}