Package org.olat.course.nodes.ms

Source Code of org.olat.course.nodes.ms.MSEditFormController

/**
* 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) 2009 frentix GmbH<br>
* http://www.frentix.com<br>
* <p>
*/

package org.olat.course.nodes.ms;

import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import org.olat.core.gui.UserRequest;
import org.olat.core.gui.components.form.flexible.DependencyRuleApplayable;
import org.olat.core.gui.components.form.flexible.FormItem;
import org.olat.core.gui.components.form.flexible.FormItemContainer;
import org.olat.core.gui.components.form.flexible.elements.RichTextElement;
import org.olat.core.gui.components.form.flexible.elements.SingleSelection;
import org.olat.core.gui.components.form.flexible.elements.TextElement;
import org.olat.core.gui.components.form.flexible.impl.FormBasicController;
import org.olat.core.gui.components.form.flexible.impl.FormEvent;
import org.olat.core.gui.components.form.flexible.impl.FormLayoutContainer;
import org.olat.core.gui.components.form.flexible.impl.rules.RulesFactory;
import org.olat.core.gui.control.Controller;
import org.olat.core.gui.control.Event;
import org.olat.core.gui.control.WindowControl;
import org.olat.core.util.StringHelper;
import org.olat.course.nodes.MSCourseNode;
import org.olat.modules.ModuleConfiguration;

/**
* Provides a FlexiForm for the assesment settings dialog, including custom
* rules for when to show which dialog element.
*
* @author twuersch
*
*/
public class MSEditFormController extends FormBasicController {

  /** Configuration this controller will modify. */
  private ModuleConfiguration modConfig;

  /** Dropdown for choosing whether score will be awarded or not. */
  private SingleSelection scoreGranted;

  /** Dropdown for choosing whether pass/fail will be displayed or not. */
  private SingleSelection displayPassed;

  /**
   * Dropdown for choosing whether pass and fail will be decided automatically
   * or manually.
   */
  private SingleSelection displayType;

  /** Dropdown for choosing whether results will be commented individually. */
  private SingleSelection commentFlag;

  /** Text input element for the minimum score. */
  private TextElement minVal;

  /** Text input element for the maximum score. */
  private TextElement maxVal;

  /** Text input element for the passing score. */
  private TextElement cutVal;

  /** Rich text input element for a notice to all users. */
  private RichTextElement infotextUser;

  /** Rich text input element for a notice to all tutors. */
  private RichTextElement infotextCoach;

  /** The keys for true / false dropdowns. */
  private String[] trueFalseKeys;

  /** The keys for yes/no dropdowns. */
  private String[] yesNoValues;

  /** The keys for manual/automatic scoring dropdown. */
  private String[] passedTypeValues;

  /**
   * Creates this controller.
   *
   * @param ureq
   * @param wControl
   * @param modConfig
   */
  public MSEditFormController(UserRequest ureq, WindowControl wControl, ModuleConfiguration modConfig) {
    super(ureq, wControl, FormBasicController.LAYOUT_DEFAULT);
    this.modConfig = modConfig;
    this.trueFalseKeys = new String[] { Boolean.TRUE.toString(), Boolean.FALSE.toString() };
    this.yesNoValues = new String[] { translate("form.yes"), translate("form.no") };

    this.passedTypeValues = new String[] { translate("form.passedtype.cutval"), translate("form.passedtype.manual") };
    initForm(ureq);
  }

  /**
   *
   * @see org.olat.core.gui.components.form.flexible.impl.FormBasicController#doDispose
   *      ()
   */
  @Override
  protected void doDispose() {
  // Don't dispose anything
  }

  /**
   *
   * @see org.olat.core.gui.components.form.flexible.impl.FormBasicController#formOK
   *      (org.olat.core.gui.UserRequest)
   */
  @Override
  protected void formOK(UserRequest ureq) {
    fireEvent(ureq, Event.DONE_EVENT);
  }

  /**
   *
   * @see org.olat.core.gui.components.form.flexible.impl.FormBasicController#formNOK
   *      (org.olat.core.gui.UserRequest)
   */
  @Override
  protected void formNOK(UserRequest ureq) {
    fireEvent(ureq, Event.FAILED_EVENT);
  }

  /**
   * @see org.olat.core.gui.components.form.flexible.impl.FormBasicController#formCancelled(org.olat.core.gui.UserRequest)
   */
  @Override
  protected void formCancelled(UserRequest ureq) {
    fireEvent(ureq, Event.CANCELLED_EVENT);
  }

  /**
   * @see org.olat.core.gui.components.form.flexible.impl.FormBasicController#initForm
   *      (org.olat.core.gui.components.form.flexible.FormItemContainer,
   *      org.olat.core.gui.control.Controller, org.olat.core.gui.UserRequest)
   */
  @Override
  protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) {
    // Create the "score granted" field...
    scoreGranted = uifactory.addDropdownSingleselect("form.score", formLayout, trueFalseKeys, yesNoValues, null);
    scoreGranted.addActionListener(this, FormEvent.ONCHANGE);
    Boolean sf = (Boolean) modConfig.get(MSCourseNode.CONFIG_KEY_HAS_SCORE_FIELD);

    boolean firstTime = true;
    if (sf == null) sf = Boolean.TRUE;
    else firstTime = false; // when the score flag is set then this can't be a
    // new MS bb

    scoreGranted.select(sf.toString(), true);

    // ...minimum value...
    Float min = (Float) modConfig.get(MSCourseNode.CONFIG_KEY_SCORE_MIN);
    if (min == null) {
      min = new Float(0.0);
    }
    minVal = uifactory.addTextElement("form.min", "form.min", 8, min.toString(), formLayout);
    minVal.setDisplaySize(5);

    Float max = (Float) modConfig.get(MSCourseNode.CONFIG_KEY_SCORE_MAX);
    if (max == null) {
      max = new Float(0.0);
    }
    // ...and maximum value input.
    maxVal = uifactory.addTextElement("form.max", "form.max", 8, max.toString(), formLayout);
    maxVal.setDisplaySize(5);

    uifactory.addSpacerElement("spacer1", formLayout, false);

    // Create the "display passed / failed" dropdown...
    displayPassed = uifactory.addDropdownSingleselect("form.passed", formLayout, trueFalseKeys, yesNoValues, null);
    displayPassed.addActionListener(this, FormEvent.ONCHANGE);
    Boolean pf = (Boolean) modConfig.get(MSCourseNode.CONFIG_KEY_HAS_PASSED_FIELD);
    if (pf == null) pf = Boolean.TRUE;
    displayPassed.select(pf.toString(), true);

    // ...the automatic / manual dropdown (note that TRUE means automatic and
    // FALSE means manually)...
    Float cut = (Float) modConfig.get(MSCourseNode.CONFIG_KEY_PASSED_CUT_VALUE);
    displayType = uifactory.addDropdownSingleselect("form.passed.type", formLayout, trueFalseKeys, passedTypeValues, null);
    displayType.addActionListener(this, FormEvent.ONCHANGE);

    if (cut != null || firstTime) {
      displayType.select(trueFalseKeys[0], true);
    } else {
      displayType.select(trueFalseKeys[1], true);
    }

    // ...and the passing grade input field.
    if (cut == null) cut = new Float(0.0);
    cutVal = uifactory.addTextElement("form.cut", "form.cut", 8, cut.toString(), formLayout);
    cutVal.setDisplaySize(5);

    uifactory.addSpacerElement("spacer2", formLayout, false);

    // Create the "individual comment" dropdown.
    commentFlag = uifactory.addDropdownSingleselect("form.comment", formLayout, trueFalseKeys, yesNoValues, null);
    Boolean cf = (Boolean) modConfig.get(MSCourseNode.CONFIG_KEY_HAS_COMMENT_FIELD);
    if (cf == null) cf = Boolean.TRUE;
    commentFlag.select(cf.toString(), true);

    uifactory.addSpacerElement("spacer3", formLayout, false);

    // Create the rich text fields.
    String infoUser = (String) modConfig.get(MSCourseNode.CONFIG_KEY_INFOTEXT_USER);
    if (infoUser == null) infoUser = new String("");
    infotextUser = uifactory.addRichTextElementForStringDataMinimalistic("infotextUser", "form.infotext.user", infoUser, 10, -1, false,
        formLayout, ureq.getUserSession(), getWindowControl());

    String infoCoach = (String) modConfig.get(MSCourseNode.CONFIG_KEY_INFOTEXT_COACH);
    if (infoCoach == null) infoCoach = new String("");
    infotextCoach = uifactory.addRichTextElementForStringDataMinimalistic("infotextCoach", "form.infotext.coach", infoCoach, 10, -1, false,
        formLayout, ureq.getUserSession(), getWindowControl());

    /*
     * The following rules ensure that if score is not granted, there is still
     * the possiblity to manually assign a passing or failing grade.
     *
     * Since the custom rules defined in the following lines are hard to read,
     * the first one is annotated:
     */
    RulesFactory.createCustomRule(scoreGranted, Boolean.TRUE.toString(), new HashSet<FormItem>(), formLayout).setDependencyRuleApplayable(
        new DependencyRuleApplayable() {
          /*
           * What the line above means is: If the dropdown field "scoreGranted"
           * changes its selection key to "true", then execute the statements of
           * this rule, defined in the apply(...) method below. If you look into
           * the documentation, you see that the third parameter (of type
           * HashSet<FormItem>) would be the targets, but this is left
           * intentionally empty since we can refer the targets (like minVal,
           * maxVal etc.) directly from inside the following apply(...) method.
           */
          @SuppressWarnings( { "synthetic-access", "unused" })
          public void apply(FormItem triggerElement, Object triggerVal, Set<FormItem> targets) {
            minVal.setEnabled(true);
            maxVal.setEnabled(true);
            if (displayPassed.getSelectedKey().equals(Boolean.TRUE.toString())) {
              displayType.setEnabled(true);
              if (displayType.getSelectedKey().equals(Boolean.TRUE.toString())) {
                cutVal.setEnabled(true);
              } else {
                cutVal.setEnabled(false);
              }
            }
          }
        });

    RulesFactory.createCustomRule(scoreGranted, Boolean.FALSE.toString(), new HashSet<FormItem>(), formLayout).setDependencyRuleApplayable(
        new DependencyRuleApplayable() {
          @SuppressWarnings( { "synthetic-access", "unused" })
          public void apply(FormItem triggerElement, Object triggerVal, Set<FormItem> targets) {

            minVal.setEnabled(false);
            maxVal.setEnabled(false);
            if (displayPassed.getSelectedKey().equals(Boolean.TRUE.toString())) {
              displayType.select(Boolean.FALSE.toString(), true);
              displayType.setEnabled(false);
              cutVal.setEnabled(false);
            } else {
              displayType.setEnabled(false);
              cutVal.setEnabled(false);
            }
          }
        });

    RulesFactory.createCustomRule(displayPassed, Boolean.TRUE.toString(), new HashSet<FormItem>(), formLayout).setDependencyRuleApplayable(
        new DependencyRuleApplayable() {
          @SuppressWarnings( { "synthetic-access", "unused" })
          public void apply(FormItem triggerElement, Object triggerVal, Set<FormItem> targets) {
            if (scoreGranted.getSelectedKey().equals(Boolean.TRUE.toString())) {
              displayType.setEnabled(true);
              cutVal.setEnabled(true);
            } else {
              displayType.select(Boolean.FALSE.toString(), true);
              displayType.setEnabled(false);
              cutVal.setEnabled(false);
            }
          }
        });

    RulesFactory.createCustomRule(displayPassed, Boolean.FALSE.toString(), new HashSet<FormItem>(), formLayout)
        .setDependencyRuleApplayable(new DependencyRuleApplayable() {
          @SuppressWarnings( { "synthetic-access", "unused" })
          public void apply(FormItem triggerElement, Object triggerVal, Set<FormItem> targets) {
            displayType.setEnabled(false);
            cutVal.setEnabled(false);
          }
        });

    RulesFactory.createCustomRule(displayType, Boolean.TRUE.toString(), new HashSet<FormItem>(), formLayout).setDependencyRuleApplayable(
        new DependencyRuleApplayable() {
          @SuppressWarnings( { "synthetic-access", "unused" })
          public void apply(FormItem triggerElement, Object triggerVal, Set<FormItem> targets) {
            if (scoreGranted.getSelectedKey().equals(Boolean.TRUE.toString())) {
              cutVal.setEnabled(true);
            } else {
              cutVal.setEnabled(false);
            }
          }
        });

    RulesFactory.createCustomRule(displayType, Boolean.FALSE.toString(), new HashSet<FormItem>(), formLayout).setDependencyRuleApplayable(
        new DependencyRuleApplayable() {
          @SuppressWarnings( { "synthetic-access", "unused" })
          public void apply(FormItem triggerElement, Object triggerVal, Set<FormItem> targets) {
            cutVal.setEnabled(false);
          }
        });

    // Create submit and cancel buttons
    final FormLayoutContainer buttonLayout = FormLayoutContainer.createButtonLayout("buttonLayout", getTranslator());
    formLayout.add(buttonLayout);
    uifactory.addFormSubmitButton("submit", buttonLayout);
    uifactory.addFormCancelButton("cancel", buttonLayout, ureq, getWindowControl());
  }

  /**
   * @see org.olat.core.gui.components.form.flexible.impl.FormBasicController#validateFormLogic(org.olat.core.gui.UserRequest)
   */
  @Override
  protected boolean validateFormLogic(UserRequest ureq) {
    // coach info text
    if (infotextCoach.getValue().length() > 4000) {
      infotextCoach.setErrorKey("input.toolong", null);
      return false;
    } else {
      infotextCoach.clearError();
    }
    // user info text
    if (infotextUser.getValue().length() > 4000) {
      infotextUser.setErrorKey("input.toolong", null);
      return false;
    } else {
      infotextUser.clearError();
    }
    // score flag
    if (scoreGranted.getSelectedKey().equals(Boolean.TRUE.toString())) {
      if (!minVal.getValue().matches("^[0-9]+\\.?[0-9]*$")) {
        minVal.setErrorKey("form.error.wrongFloat", null);
        return false;
      } else {
        minVal.clearError();
      }
      if (!maxVal.getValue().matches("^[0-9]+\\.?[0-9]*$")) {
        maxVal.setErrorKey("form.error.wrongFloat", null);
        return false;
      } else if (Float.parseFloat(minVal.getValue()) > Float.parseFloat(maxVal.getValue())) {
        maxVal.setErrorKey("form.error.minGreaterThanMax", null);
        return false;
      } else {
        maxVal.clearError();
      }
    }
    // display flag   
    if (displayPassed.getSelectedKey().equals(Boolean.TRUE.toString()) && displayType.getSelectedKey().equals(Boolean.TRUE.toString())) {
      if (Boolean.valueOf(displayType.getSelectedKey()).booleanValue() && scoreGranted.getSelectedKey().equals(Boolean.FALSE.toString())) {
        displayType.setErrorKey("form.error.cutButNoScore", null);
      } else {
        displayType.clearError();
      }
      if (!cutVal.getValue().matches("^[0-9]+\\.?[0-9]*$")) {
        cutVal.setErrorKey("form.error.wrongFloat", null);
        return false;
      } else if (Float.parseFloat(cutVal.getValue()) < Float.parseFloat(minVal.getValue())
          || Float.parseFloat(cutVal.getValue()) > Float.parseFloat(maxVal.getValue())) {
        cutVal.setErrorKey("form.error.cutOutOfRange", null);
        return false;
      } else {
        cutVal.clearError();
      }
    }
    return true && super.validateFormLogic(ureq);
  }

  /**
   * Sets this form to be write-protected.
   *
   * @param displayOnly
   */
  public void setDisplayOnly(boolean displayOnly) {
    Map<String, FormItem> formItems = flc.getFormComponents();
    for (String formItemName : formItems.keySet()) {
      formItems.get(formItemName).setVisible(true);
      formItems.get(formItemName).setEnabled(!displayOnly);
    }
  }

  /**
   * @param moduleConfiguration
   */
  public void updateModuleConfiguration(ModuleConfiguration moduleConfiguration) {
    // mandatory score flag
    Boolean sf = new Boolean(scoreGranted.getSelectedKey());
    moduleConfiguration.set(MSCourseNode.CONFIG_KEY_HAS_SCORE_FIELD, sf);
    if (sf.booleanValue()) {
      // do min/max value
      moduleConfiguration.set(MSCourseNode.CONFIG_KEY_SCORE_MIN, new Float(minVal.getValue()));
      moduleConfiguration.set(MSCourseNode.CONFIG_KEY_SCORE_MAX, new Float(maxVal.getValue()));
    } else {
      // remove old config
      moduleConfiguration.remove(MSCourseNode.CONFIG_KEY_SCORE_MIN);
      moduleConfiguration.remove(MSCourseNode.CONFIG_KEY_SCORE_MAX);
    }

    // mandatory passed flag
    Boolean pf = new Boolean(displayPassed.getSelectedKey());
    moduleConfiguration.set(MSCourseNode.CONFIG_KEY_HAS_PASSED_FIELD, pf);
    if (pf.booleanValue()) {
      // do cut value
      Boolean cf = new Boolean(displayType.getSelectedKey());
      if (cf.booleanValue()) {
        moduleConfiguration.set(MSCourseNode.CONFIG_KEY_PASSED_CUT_VALUE, new Float(cutVal.getValue()));
      } else {
        // remove old config
        moduleConfiguration.remove(MSCourseNode.CONFIG_KEY_PASSED_CUT_VALUE);
      }
    } else {
      // remove old config
      moduleConfiguration.remove(MSCourseNode.CONFIG_KEY_PASSED_CUT_VALUE);
    }

    // mandatory comment flag
    moduleConfiguration.set(MSCourseNode.CONFIG_KEY_HAS_COMMENT_FIELD, new Boolean(commentFlag.getSelectedKey()));

    // set info text only if something is in there
    String iu = infotextUser.getValue();
    if (StringHelper.containsNonWhitespace(iu)) {
      moduleConfiguration.set(MSCourseNode.CONFIG_KEY_INFOTEXT_USER, iu);
    } else {
      // remove old config
      moduleConfiguration.remove(MSCourseNode.CONFIG_KEY_INFOTEXT_USER);
    }

    String ic = infotextCoach.getValue();
    if (StringHelper.containsNonWhitespace(ic)) {
      moduleConfiguration.set(MSCourseNode.CONFIG_KEY_INFOTEXT_COACH, ic);
    } else {
      // remove old config
      moduleConfiguration.remove(MSCourseNode.CONFIG_KEY_INFOTEXT_COACH);
    }
  }

  /**
   * @param config the module configuration
   * @return true if valid, false otherwhise
   */
  public static boolean isConfigValid(ModuleConfiguration config) {
    boolean isValid = true;
    Object confElement;

    // score flag is mandatory
    confElement = config.get(MSCourseNode.CONFIG_KEY_HAS_SCORE_FIELD);
    if (confElement != null && confElement instanceof Boolean) {
      Boolean hasScore = (Boolean) confElement;
      if (hasScore.booleanValue()) {
        // score min and max are mandatory if score flag is set to true
        confElement = config.get(MSCourseNode.CONFIG_KEY_SCORE_MIN);
        isValid = (confElement != null && confElement instanceof Float);
        confElement = config.get(MSCourseNode.CONFIG_KEY_SCORE_MAX);
        isValid = (confElement != null && confElement instanceof Float);
      }
    } else return false;

    // passed flag is mandatory
    confElement = config.get(MSCourseNode.CONFIG_KEY_HAS_PASSED_FIELD);
    if (confElement != null && confElement instanceof Boolean) {
      Boolean hasPassed = (Boolean) confElement;
      if (hasPassed.booleanValue()) {
        // cut value is optional if passed flag set to true, but type must match
        confElement = config.get(MSCourseNode.CONFIG_KEY_PASSED_CUT_VALUE);
        if (!((confElement == null) || (confElement instanceof Float))) return false;
      }
    } else return false;

    // comment flag is mandatory
    confElement = config.get(MSCourseNode.CONFIG_KEY_HAS_COMMENT_FIELD);
    isValid = (confElement != null && confElement instanceof Boolean);

    // infotext is optional
    confElement = config.get(MSCourseNode.CONFIG_KEY_INFOTEXT_USER);
    if (!((confElement == null) || (confElement instanceof String))) return false;

    confElement = config.get(MSCourseNode.CONFIG_KEY_INFOTEXT_COACH);
    if (!((confElement == null) || (confElement instanceof String))) return false;

    return isValid;
  }
}
TOP

Related Classes of org.olat.course.nodes.ms.MSEditFormController

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.