/**
* 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.
* <p>
*/
package org.olat.course.nodes.st;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.olat.core.gui.components.form.Form;
import org.olat.core.gui.formelements.IntegerElement;
import org.olat.core.gui.formelements.SpacerElement;
import org.olat.core.gui.formelements.StaticMultipleSelectionElement;
import org.olat.core.gui.formelements.StaticSingleSelectionElement;
import org.olat.core.gui.formelements.VisibilityDependsOnSelectionRule;
import org.olat.core.gui.translator.Translator;
import org.olat.course.editor.StatusDescription;
import org.olat.course.nodes.CourseNode;
import org.olat.course.run.scoring.ScoreCalculator;
/**
* Description:<br>
* This form is used to generate score and passed expression for structure
* course nodes in an easy way. See EditScoreCalculationExpertForm for the
* expert way.
* <p>
*
* @author gnaegi
*/
public class EditScoreCalculationEasyForm extends Form {
private StaticSingleSelectionElement hasScore, passedType;
private StaticMultipleSelectionElement scoreNodeIdents, passedNodeIdents;
private IntegerElement passedCutValue;
private ScoreCalculator sc;
private static final String DELETED_NODE_IDENTIFYER = "deletedNode";
private List<CourseNode> assessableNodesList;
/**
* @param name
* @param trans
* @param scoreCalculator
* @param nodeIdentList
*/
public EditScoreCalculationEasyForm(String name, Translator translator, ScoreCalculator scoreCalculator, List<CourseNode> nodeIdentList) {
super(name, translator);
sc = scoreCalculator;
this.assessableNodesList = nodeIdentList;
String[] hasScoreKeys = new String[] { Boolean.TRUE.toString(), Boolean.FALSE.toString() };
String[] hasScoreValues = new String[] { translate("scform.hasScore.yes"), translate("no") };
hasScore = new StaticSingleSelectionElement("scform.hasScore", hasScoreKeys, hasScoreValues);
addFormElement("hasScore", hasScore);
if (scoreCalculator != null && scoreCalculator.getSumOfScoreNodes() != null && scoreCalculator.getSumOfScoreNodes().size() > 0) {
hasScore.select(Boolean.TRUE.toString(), true);
} else {
hasScore.select(Boolean.FALSE.toString(), true); // default
}
// assessable child nodes
scoreNodeIdents = initNodeSelectionElement("scform.scoreNodeIndents", scoreCalculator, (scoreCalculator == null ? null
: scoreCalculator.getSumOfScoreNodes()), nodeIdentList);
addFormElement("scoreNodeIdents", scoreNodeIdents);
SpacerElement spacer = new SpacerElement(true, false);
addFormElement("spacer", spacer);
// passed configuration
String[] passedTypeKeys = new String[] { ScoreCalculator.PASSED_TYPE_NONE, ScoreCalculator.PASSED_TYPE_CUTVALUE,
ScoreCalculator.PASSED_TYPE_INHERIT };
String[] passedTypeValues = new String[] { translate("no"), translate("scform.passedtype.cutvalue"),
translate("scform.passedtype.inherit") };
passedType = new StaticSingleSelectionElement("scform.passedtype", passedTypeKeys, passedTypeValues);
addFormElement("passedType", passedType);
if (scoreCalculator != null && scoreCalculator.getPassedType() != null) {
passedType.select(scoreCalculator.getPassedType(), true);
} else {
passedType.select(ScoreCalculator.PASSED_TYPE_NONE, true); // default
}
int cutinitval = 0;
if (scoreCalculator != null) cutinitval = scoreCalculator.getPassedCutValue();
passedCutValue = new IntegerElement("scform.passedCutValue", cutinitval, 4);
addFormElement("passedCutValue", passedCutValue);
passedNodeIdents = initNodeSelectionElement("scform.passedNodeIndents", scoreCalculator, (scoreCalculator == null ? null
: scoreCalculator.getPassedNodes()), nodeIdentList);
addFormElement("passedNodeIdents", passedNodeIdents);
// rules
VisibilityDependsOnSelectionRule rule = new VisibilityDependsOnSelectionRule(hasScore, scoreNodeIdents, Boolean.TRUE.toString(), true,
"false", true);
addVisibilityDependsOnSelectionRule(rule);
rule = new VisibilityDependsOnSelectionRule(passedType, passedNodeIdents, ScoreCalculator.PASSED_TYPE_INHERIT, true, "false", true);
addVisibilityDependsOnSelectionRule(rule);
rule = new VisibilityDependsOnSelectionRule(passedType, passedCutValue, ScoreCalculator.PASSED_TYPE_CUTVALUE, true, "0", true);
addVisibilityDependsOnSelectionRule(rule);
setSubmitKey("submit");
setCancelButton();
}
/**
* Initializes the node selection form elements first check if the form has a
* selection on a node that has been deleted in since the last edition of this
* form. if so, set remember this to later add a dummy placeholder for the
* deleted node. We do not just ignore this since the form would look ok then
* to the user, the generated rule visible in the expert mode however would
* still be invalid. user must explicitly uncheck this deleted node reference.
*
* @param elemId name of the generated form element
* @param scoreCalculator
* @param selectedNodeList List of course nodes that are preselected
* @param allNodesList List of all assessable course nodes
* @return StaticMultipleSelectionElement The configured form element
*/
private StaticMultipleSelectionElement initNodeSelectionElement(String elemId, ScoreCalculator scoreCalculator, List selectedNodeList,
List allNodesList) {
Translator trans = getTranslator();
boolean addDeletedNodeIdent = false;
if (scoreCalculator != null && selectedNodeList != null) {
for (Iterator iter = selectedNodeList.iterator(); iter.hasNext();) {
String nodeIdent = (String) iter.next();
boolean found = false;
for (Iterator nodeIter = allNodesList.iterator(); nodeIter.hasNext();) {
CourseNode node = (CourseNode) nodeIter.next();
if (node.getIdent().equals(nodeIdent)) {
found = true;
}
}
if (!found) addDeletedNodeIdent = true;
}
}
String[] nodeKeys = new String[allNodesList.size() + (addDeletedNodeIdent ? 1 : 0)];
String[] nodeValues = new String[allNodesList.size() + (addDeletedNodeIdent ? 1 : 0)];
for (int i = 0; i < allNodesList.size(); i++) {
CourseNode courseNode = (CourseNode) allNodesList.get(i);
nodeKeys[i] = courseNode.getIdent();
nodeValues[i] = courseNode.getShortName() + " (Id:" + courseNode.getIdent() + ")";
}
// add a deleted dummy node at last position
if (addDeletedNodeIdent) {
nodeKeys[allNodesList.size()] = DELETED_NODE_IDENTIFYER;
nodeValues[allNodesList.size()] = translate("scform.deletedNode");
}
StaticMultipleSelectionElement mse = new StaticMultipleSelectionElement(elemId, nodeKeys, nodeValues, false);
// preselect nodes from configuration
if (scoreCalculator != null && selectedNodeList != null) {
for (Iterator iter = selectedNodeList.iterator(); iter.hasNext();) {
String nodeIdent = (String) iter.next();
boolean found = false;
for (Iterator nodeIter = allNodesList.iterator(); nodeIter.hasNext();) {
CourseNode node = (CourseNode) nodeIter.next();
if (node.getIdent().equals(nodeIdent)) {
found = true;
}
}
if (found) {
mse.select(nodeIdent, true);
} else {
mse.select(DELETED_NODE_IDENTIFYER, true);
}
}
}
return mse;
}
/**
* @see org.olat.core.gui.components.Form#validate(org.olat.core.gui.UserRequest)
*/
public boolean validate() {
if (hasScore.getSelectedKey().equals(Boolean.TRUE.toString())) {
if (scoreNodeIdents.getSelectedKeys().size() == 0) {
scoreNodeIdents.setErrorKey("scform.scoreNodeIndents.error");
return false;
} else if (scoreNodeIdents.getSelectedKeys().contains(DELETED_NODE_IDENTIFYER)) {
scoreNodeIdents.setErrorKey("scform.deletedNode.error");
return false;
}
}
if (passedType.getSelectedKey().equals(ScoreCalculator.PASSED_TYPE_INHERIT)) {
if (passedNodeIdents.getSelectedKeys().size() == 0) {
passedNodeIdents.setErrorKey("scform.passedNodeIndents.error");
return false;
}
} else if (passedType.getSelectedKey().equals(ScoreCalculator.PASSED_TYPE_CUTVALUE)) {
if (!passedCutValue.isInteger("scform.passedFactor.error")) return false;
if (hasScore.getSelectedKey().equals(Boolean.FALSE.toString())) {
passedType.setErrorKey("scform.passedType.error");
return false;
}
}
return true;
}
/**
* @return ScoreCalcualtor or null if no score calculator is set
*/
public ScoreCalculator getScoreCalulator() {
if (hasScore.getSelectedKey().equals(Boolean.FALSE.toString()) && passedType.getSelectedKey().equals(ScoreCalculator.PASSED_TYPE_NONE)) { return null; }
// ScoreCalculator sc = new ScoreCalculator(null, null);
// 1) score configuration
if (hasScore.getSelectedKey().equals(Boolean.TRUE.toString())) {
sc.setSumOfScoreNodes(new ArrayList(scoreNodeIdents.getSelectedKeys()));
}else {
//reset
sc.setSumOfScoreNodes(null);
}
// 2) passed configuration
if (passedType.getSelectedKey().equals(ScoreCalculator.PASSED_TYPE_NONE)) {
sc.setPassedType(ScoreCalculator.PASSED_TYPE_NONE);
} else if (passedType.getSelectedKey().equals(ScoreCalculator.PASSED_TYPE_CUTVALUE)) {
sc.setPassedType(ScoreCalculator.PASSED_TYPE_CUTVALUE);
sc.setPassedCutValue(passedCutValue.getIntvalue());
} else if (passedType.getSelectedKey().equals(ScoreCalculator.PASSED_TYPE_INHERIT)) {
sc.setPassedType(ScoreCalculator.PASSED_TYPE_INHERIT);
sc.setPassedNodes(new ArrayList(passedNodeIdents.getSelectedKeys()));
}
// update score and passed expression from easy mode configuration
sc.setScoreExpression(sc.getScoreExpressionFromEasyModeConfiguration());
sc.setPassedExpression(sc.getPassedExpressionFromEasyModeConfiguration());
if (sc.getScoreExpression() == null && sc.getPassedExpression() == null) return null;
sc.setExpertMode(false);
return sc;
}
/**
*
* @return Returns a list with the invalid node descriptions,
* ("invalid" is a node that is not associated with a test resource)
*/
public List<String> getInvalidNodeDescriptions() {
List<String> testElemWithNoResource = new ArrayList<String>();
List<String> selectedNodesIds = new ArrayList<String>(scoreNodeIdents.getSelectedKeys());
for (Iterator nodeIter = assessableNodesList.iterator(); nodeIter.hasNext();) {
CourseNode node = (CourseNode) nodeIter.next();
if (selectedNodesIds.contains(node.getIdent())) {
StatusDescription isConfigValid = node.isConfigValid();
if (isConfigValid != null && isConfigValid.isError()) {
String nodeDescription = node.getShortName() + " (Id:" + node.getIdent() + ")";
if (!testElemWithNoResource.contains(nodeDescription)) {
testElemWithNoResource.add(nodeDescription);
}
}
}
}
return testElemWithNoResource;
}
}