Index: lams_build/lib/lams/lams.jar
===================================================================
diff -u -r76f496c7c7d8cafecbe2b6c0a85a408c60d568b8 -r33a5ad24fad4e3e2d3d8f0c67d88ccb5167affe7
Binary files differ
Index: lams_common/src/java/org/lamsfoundation/lams/util/ValidationUtil.java
===================================================================
diff -u -re66bf3aa8146d04b064b169513609b2a28a35149 -r33a5ad24fad4e3e2d3d8f0c67d88ccb5167affe7
--- lams_common/src/java/org/lamsfoundation/lams/util/ValidationUtil.java (.../ValidationUtil.java) (revision e66bf3aa8146d04b064b169513609b2a28a35149)
+++ lams_common/src/java/org/lamsfoundation/lams/util/ValidationUtil.java (.../ValidationUtil.java) (revision 33a5ad24fad4e3e2d3d8f0c67d88ccb5167affe7)
@@ -26,6 +26,8 @@
import java.util.regex.Matcher;
import java.util.regex.Pattern;
+import org.apache.commons.lang.StringUtils;
+
/**
* Utility methods for String validation.
*/
@@ -109,4 +111,33 @@
Matcher m = pattern.matcher(input.trim());
return m.matches();
}
+
+ /**
+ * Checks whether min words limit is reached
+ *
+ * @param text
+ * @param minWordsLimit
+ * @param isDerivedFromCKEditor whether the text was acquired from CKEditor
+ * @return
+ */
+ public static boolean isMinWordsLimitReached(String text, int minWordsLimit, boolean isDerivedFromCKEditor) {
+
+ if (minWordsLimit <= 0) {
+ return true;
+ } else if (StringUtils.isBlank(text)) {
+ return false;
+ }
+
+ // HTML tags stripping
+ if (isDerivedFromCKEditor) {
+ text = WebUtil.removeHTMLtags(text); // text.replaceAll("/<\/?[a-z][^>]*>/gi", '');
+ } else {
+ text = text.replaceAll("(?:
)", " ");
+ }
+
+ int wordCount = (text.length() == 0) ? 0 : text.replaceAll("[\'\";:,\\.\\?\\-!]+", "").trim().split("\\S+").length;//.match(/\S+/g) || []) ;
+
+ // check min words limit is reached
+ return (wordCount >= minWordsLimit);
+ }
}
Index: lams_tool_assessment/src/java/org/lamsfoundation/lams/tool/assessment/web/action/LearningAction.java
===================================================================
diff -u -r57dfab8f97ff1bad83bc50605c6dce9b8ef4e4f3 -r33a5ad24fad4e3e2d3d8f0c67d88ccb5167affe7
--- lams_tool_assessment/src/java/org/lamsfoundation/lams/tool/assessment/web/action/LearningAction.java (.../LearningAction.java) (revision 57dfab8f97ff1bad83bc50605c6dce9b8ef4e4f3)
+++ lams_tool_assessment/src/java/org/lamsfoundation/lams/tool/assessment/web/action/LearningAction.java (.../LearningAction.java) (revision 33a5ad24fad4e3e2d3d8f0c67d88ccb5167affe7)
@@ -76,6 +76,7 @@
import org.lamsfoundation.lams.tool.assessment.web.form.ReflectionForm;
import org.lamsfoundation.lams.usermanagement.dto.UserDTO;
import org.lamsfoundation.lams.util.DateUtil;
+import org.lamsfoundation.lams.util.ValidationUtil;
import org.lamsfoundation.lams.util.WebUtil;
import org.lamsfoundation.lams.web.session.SessionManager;
import org.lamsfoundation.lams.web.util.AttributeNames;
@@ -886,18 +887,12 @@
&& (question.getMinWordsLimit() > 0)) {
String answer = new String(question.getAnswerString());
-
- // HTML tags stripping
- if (question.isAllowRichEditor()) {
- answer = WebUtil.removeHTMLtags(answer); // answer.replaceAll("/<\/?[a-z][^>]*>/gi", '');
- } else {
- answer = answer.replaceAll("(?:
)", " ");
- }
-
- int wordCount = (answer.length() == 0) ? 0 : answer.replaceAll("[\'\";:,\\.\\?\\-!]+", "").split("\\S+").length;//.match(/\S+/g) || []) ;
+ boolean isMinWordsLimitReached = ValidationUtil.isMinWordsLimitReached(answer,
+ question.getMinWordsLimit(), question.isAllowRichEditor());
+
// check min words limit is reached
- if (wordCount < question.getMinWordsLimit()) {
+ if (!isMinWordsLimitReached) {
isAllQuestionsReachedMinWordsLimit = false;
break;
}
Index: lams_tool_laqa/src/java/org/lamsfoundation/lams/tool/qa/web/QaLearningAction.java
===================================================================
diff -u -r40937c574021c496d91487979b905b23a193b766 -r33a5ad24fad4e3e2d3d8f0c67d88ccb5167affe7
--- lams_tool_laqa/src/java/org/lamsfoundation/lams/tool/qa/web/QaLearningAction.java (.../QaLearningAction.java) (revision 40937c574021c496d91487979b905b23a193b766)
+++ lams_tool_laqa/src/java/org/lamsfoundation/lams/tool/qa/web/QaLearningAction.java (.../QaLearningAction.java) (revision 33a5ad24fad4e3e2d3d8f0c67d88ccb5167affe7)
@@ -75,6 +75,7 @@
import org.lamsfoundation.lams.usermanagement.User;
import org.lamsfoundation.lams.usermanagement.dto.UserDTO;
import org.lamsfoundation.lams.util.DateUtil;
+import org.lamsfoundation.lams.util.ValidationUtil;
import org.lamsfoundation.lams.util.WebUtil;
import org.lamsfoundation.lams.web.action.LamsDispatchAction;
import org.lamsfoundation.lams.web.session.SessionManager;
@@ -151,42 +152,36 @@
boolean isTestHarness = Boolean.valueOf(request.getParameter("testHarness"));
String answerParamName = "answer" + questionIndex + (isTestHarness ? "__textarea" : "");
String answer = request.getParameter(answerParamName);
- // String answerPresentable = QaUtils.replaceNewLines(answer);
Integer questionIndexInteger = new Integer(questionIndex);
mapAnswers.put(questionIndexInteger.toString(), answer);
mapAnswersPresentable.put(questionIndexInteger.toString(), answer);
+
+ //validate
+ ActionMessages newErrors = validateQuestionAnswer(answer, questionIndexInteger, generalLearnerFlowDTO);
+ errors.add(newErrors);
- Map questionMap = generalLearnerFlowDTO.getMapQuestionContentLearner();
- QaQuestionDTO dto = questionMap.get(questionIndexInteger);
- if (dto.isRequired() && isEmpty(answer)) {
- errors.add(Globals.ERROR_KEY, new ActionMessage("error.required", questionIndexInteger));
- forwardName = QaAppConstants.LOAD_LEARNER;
- } else {
- // store
+ // store
+ if (errors.isEmpty()) {
QaLearningAction.qaService.updateResponseWithNewAnswer(answer, toolSessionID, new Long(
questionIndex));
}
}
- saveErrors(request, errors);
} else {
- mapAnswers = storeSequentialAnswer(qaLearningForm, request, generalLearnerFlowDTO, true);
+ Object[] results = storeSequentialAnswer(qaLearningForm, request, generalLearnerFlowDTO, true);
+ mapAnswers = (Map) results[0];
+ errors = (ActionMessages) results[1];
mapAnswersPresentable = (Map) sessionMap.get(QaAppConstants.MAP_ALL_RESULTS_KEY);
mapAnswersPresentable = QaLearningAction.removeNewLinesMap(mapAnswersPresentable);
-
- // only need to check the final question as the others will have been checked when the user clicked next.
- Map questionMap = generalLearnerFlowDTO.getMapQuestionContentLearner();
- int numQuestions = questionMap.size();
- Integer finalQuestionIndex = new Integer(numQuestions);
- QaQuestionDTO dto = questionMap.get(finalQuestionIndex);
- if (dto.isRequired() && isEmpty(mapAnswersPresentable.get(finalQuestionIndex.toString()))) {
- errors.add(Globals.ERROR_KEY, new ActionMessage("error.required", finalQuestionIndex));
- forwardName = QaAppConstants.LOAD_LEARNER;
- }
}
+ if (!errors.isEmpty()) {
+ saveErrors(request, errors);
+ forwardName = QaAppConstants.LOAD_LEARNER;
+ }
+
//in case noReeditAllowed finalize response so user can't refresh the page and post answers again
if (errors.isEmpty() && qaContent.isNoReeditAllowed()) {
qaQueUsr.setResponseFinalized(true);
@@ -572,15 +567,15 @@
* @param getNextQuestion
* @return
*/
- private Map storeSequentialAnswer(ActionForm form, HttpServletRequest request,
+ private Object[] storeSequentialAnswer(ActionForm form, HttpServletRequest request,
GeneralLearnerFlowDTO generalLearnerFlowDTO, boolean getNextQuestion) {
QaLearningForm qaLearningForm = (QaLearningForm) form;
String httpSessionID = qaLearningForm.getHttpSessionID();
SessionMap sessionMap = (SessionMap) request.getSession().getAttribute(httpSessionID);
String currentQuestionIndex = qaLearningForm.getCurrentQuestionIndex();
- Map mapAnswers = (Map) sessionMap.get(QaAppConstants.MAP_ALL_RESULTS_KEY);
+ Map mapAnswers = (Map) sessionMap.get(QaAppConstants.MAP_ALL_RESULTS_KEY);
if (mapAnswers == null) {
mapAnswers = new TreeMap(new QaComparator());
}
@@ -595,22 +590,19 @@
int nextQuestionOffset = getNextQuestion ? 1 : -1;
- // is this question required and are they trying to go to the next question?
- // if so, check if the answer is blank and generate an error if it is blank.
- Map questionContentMap = generalLearnerFlowDTO.getMapQuestionContentLearner();
- QaQuestionDTO dto = questionContentMap.get(new Integer(currentQuestionIndex));
- boolean isRequiredQuestionMissed = dto.isRequired() && isEmpty(newAnswer);
- if (getNextQuestion && isRequiredQuestionMissed) {
- ActionMessages errors = new ActionMessages();
- errors.add(Globals.ERROR_KEY, new ActionMessage("error.required", currentQuestionIndex));
- saveErrors(request, errors);
- nextQuestionOffset = 0;
+ // validation only if trying to go to the next question
+ ActionMessages errors = new ActionMessages();
+ if (getNextQuestion) {
+ errors = validateQuestionAnswer(newAnswer, new Integer(currentQuestionIndex), generalLearnerFlowDTO);
}
// store
- if (!isRequiredQuestionMissed) {
+ if (errors.isEmpty()) {
QaLearningAction.qaService.updateResponseWithNewAnswer(newAnswer, qaLearningForm.getToolSessionID(),
new Long(currentQuestionIndex));
+ } else {
+ saveErrors(request, errors);
+ nextQuestionOffset = 0;
}
sessionMap.put(QaAppConstants.MAP_ALL_RESULTS_KEY, mapAnswers);
@@ -651,9 +643,31 @@
request.setAttribute(QaAppConstants.GENERAL_LEARNER_FLOW_DTO, generalLearnerFlowDTO);
- return mapSequentialAnswers;
+ return new Object[]{mapSequentialAnswers, errors};
}
+
+ private ActionMessages validateQuestionAnswer(String newAnswer, Integer questionIndex,
+ GeneralLearnerFlowDTO generalLearnerFlowDTO) {
+ ActionMessages errors = new ActionMessages();
+
+ Map questionMap = generalLearnerFlowDTO.getMapQuestionContentLearner();
+ QaQuestionDTO dto = questionMap.get(questionIndex);
+ // if so, check if the answer is blank and generate an error if it is blank.
+ boolean isRequiredQuestionMissed = dto.isRequired() && isEmpty(newAnswer);
+ if (isRequiredQuestionMissed) {
+ errors.add(Globals.ERROR_KEY, new ActionMessage("error.required", questionIndex));
+ }
+
+ boolean isMinWordsLimitReached = ValidationUtil.isMinWordsLimitReached(newAnswer, dto.getMinWordsLimit(),
+ Boolean.parseBoolean(generalLearnerFlowDTO.getAllowRichEditor()));
+ if (!isMinWordsLimitReached) {
+ errors.add(Globals.ERROR_KEY, new ActionMessage("label.minimum.number.words", ": " + dto.getMinWordsLimit()));
+ }
+
+ return errors;
+ }
+
/**
* Is this string empty? Need to strip out all HTML tags first otherwise an empty DIV might look like a valid answer
* Smileys and math functions only put in an img tag so explicitly look for that.