Index: lams_tool_laqa/src/java/org/lamsfoundation/lams/tool/qa/util/AuthoringUtil.java =================================================================== diff -u --- lams_tool_laqa/src/java/org/lamsfoundation/lams/tool/qa/util/AuthoringUtil.java (revision 0) +++ lams_tool_laqa/src/java/org/lamsfoundation/lams/tool/qa/util/AuthoringUtil.java (revision 32eb376c59d7c17cfa9d51cac14c00aae8cf44ff) @@ -0,0 +1,89 @@ +/**************************************************************** + * Copyright (C) 2005 LAMS Foundation (http://lamsfoundation.org) + * ============================================================= + * License Information: http://lamsfoundation.org/licensing/lams/2.0/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + * USA + * + * http://www.gnu.org/licenses/gpl.txt + * **************************************************************** + */ + + +package org.lamsfoundation.lams.tool.qa.util; + +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; + +import org.lamsfoundation.lams.tool.qa.QaAppConstants; +import org.lamsfoundation.lams.tool.qa.dto.QaQuestionDTO; + +/** + * Keeps all operations needed for Authoring mode. + * + * @author Ozgur Demirtas + */ +public class AuthoringUtil implements QaAppConstants { + + public static List reorderUpdateQuestionDTOs(List questionDTOs, + QaQuestionDTO qaQuestionContentDTONew, String editableQuestionIndex) { + + List listFinalQuestionDTO = new LinkedList(); + + int queIndex = 0; + Iterator iter = questionDTOs.iterator(); + while (iter.hasNext()) { + QaQuestionDTO qaQuestionDTO = (QaQuestionDTO) iter.next(); + + ++queIndex; + + String question = qaQuestionDTO.getQuestion(); + String displayOrder = qaQuestionDTO.getDisplayOrder(); + String feedback = qaQuestionDTO.getFeedback(); + boolean required = qaQuestionDTO.isRequired(); + int minWordsLimit = qaQuestionDTO.getMinWordsLimit(); + + if (displayOrder.equals(editableQuestionIndex)) { + qaQuestionDTO.setQuestion(qaQuestionContentDTONew.getQuestion()); + qaQuestionDTO.setDisplayOrder(qaQuestionContentDTONew.getDisplayOrder()); + qaQuestionDTO.setFeedback(qaQuestionContentDTONew.getFeedback()); + qaQuestionDTO.setRequired(qaQuestionContentDTONew.isRequired()); + qaQuestionDTO.setMinWordsLimit(qaQuestionContentDTONew.getMinWordsLimit()); + + listFinalQuestionDTO.add(qaQuestionDTO); + } else { + qaQuestionDTO.setQuestion(question); + qaQuestionDTO.setDisplayOrder(displayOrder); + qaQuestionDTO.setFeedback(feedback); + qaQuestionDTO.setRequired(required); + qaQuestionDTO.setMinWordsLimit(minWordsLimit); + + listFinalQuestionDTO.add(qaQuestionDTO); + + } + } + return listFinalQuestionDTO; + } + + public static boolean checkDuplicateQuestions(List questionDTOs, String newQuestion) { + for (QaQuestionDTO questionDTO : questionDTOs) { + if (questionDTO.getQuestion() != null && questionDTO.getQuestion().equals(newQuestion)) { + return true; + } + } + return false; + } +} \ No newline at end of file Index: lams_tool_laqa/src/java/org/lamsfoundation/lams/tool/qa/util/LearningUtil.java =================================================================== diff -u --- lams_tool_laqa/src/java/org/lamsfoundation/lams/tool/qa/util/LearningUtil.java (revision 0) +++ lams_tool_laqa/src/java/org/lamsfoundation/lams/tool/qa/util/LearningUtil.java (revision 32eb376c59d7c17cfa9d51cac14c00aae8cf44ff) @@ -0,0 +1,144 @@ +/**************************************************************** + * Copyright (C) 2005 LAMS Foundation (http://lamsfoundation.org) + * ============================================================= + * License Information: http://lamsfoundation.org/licensing/lams/2.0/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + * USA + * + * http://www.gnu.org/licenses/gpl.txt + * **************************************************************** + */ + +package org.lamsfoundation.lams.tool.qa.util; + +import java.util.Map; +import java.util.TreeMap; + +import javax.servlet.http.HttpServletRequest; + +import org.lamsfoundation.lams.tool.qa.QaAppConstants; +import org.lamsfoundation.lams.tool.qa.QaContent; +import org.lamsfoundation.lams.tool.qa.QaQueContent; +import org.lamsfoundation.lams.tool.qa.QaQueUsr; +import org.lamsfoundation.lams.tool.qa.QaUsrResp; +import org.lamsfoundation.lams.tool.qa.dto.GeneralLearnerFlowDTO; +import org.lamsfoundation.lams.tool.qa.dto.QaQuestionDTO; +import org.lamsfoundation.lams.tool.qa.service.IQaService; +import org.lamsfoundation.lams.tool.qa.web.form.QaLearningForm; +import org.lamsfoundation.lams.web.util.AttributeNames; + +/** + * Keeps all operations needed for Learning mode. + * + * @author Ozgur Demirtas + */ +public class LearningUtil implements QaAppConstants { + + public static void saveFormRequestData(HttpServletRequest request, QaLearningForm qaLearningForm) { + String toolSessionID = request.getParameter(AttributeNames.PARAM_TOOL_SESSION_ID); + qaLearningForm.setToolSessionID(toolSessionID); + + String userID = request.getParameter("userID"); + qaLearningForm.setUserID(userID); + + String httpSessionID = request.getParameter("httpSessionID"); + qaLearningForm.setHttpSessionID(httpSessionID); + + String totalQuestionCount = request.getParameter("totalQuestionCount"); + qaLearningForm.setTotalQuestionCount(totalQuestionCount); + } + + public static GeneralLearnerFlowDTO buildGeneralLearnerFlowDTO(IQaService service, QaContent qaContent) { + GeneralLearnerFlowDTO generalLearnerFlowDTO = new GeneralLearnerFlowDTO(); + generalLearnerFlowDTO.setActivityTitle(qaContent.getTitle()); + generalLearnerFlowDTO.setActivityInstructions(qaContent.getInstructions()); + generalLearnerFlowDTO.setReportTitleLearner(qaContent.getReportTitle()); + + if (qaContent.isQuestionsSequenced()) { + generalLearnerFlowDTO.setQuestionListingMode(QUESTION_LISTING_MODE_SEQUENTIAL); + } else { + generalLearnerFlowDTO.setQuestionListingMode(QUESTION_LISTING_MODE_COMBINED); + } + + generalLearnerFlowDTO.setUserNameVisible(new Boolean(qaContent.isUsernameVisible()).toString()); + generalLearnerFlowDTO.setShowOtherAnswers(qaContent.isShowOtherAnswers()); + generalLearnerFlowDTO.setAllowRichEditor(new Boolean(qaContent.isAllowRichEditor()).toString()); + generalLearnerFlowDTO + .setUseSelectLeaderToolOuput(new Boolean(qaContent.isUseSelectLeaderToolOuput()).toString()); + generalLearnerFlowDTO.setTotalQuestionCount(new Integer(qaContent.getQaQueContents().size())); + + //check if allow rate answers is ON and also that there is at least one non-comments rating criteria available + generalLearnerFlowDTO.setAllowRateAnswers(service.isRatingsEnabled(qaContent)); + + //create mapQuestions + Map mapQuestions = new TreeMap(); + for (QaQueContent question : qaContent.getQaQueContents()) { + int displayOrder = question.getDisplayOrder(); + if (displayOrder != 0) { + //add the question to the questions Map in the displayOrder + QaQuestionDTO questionDTO = new QaQuestionDTO(question); + mapQuestions.put(displayOrder, questionDTO); + } + } + generalLearnerFlowDTO.setMapQuestionContentLearner(mapQuestions); + + return generalLearnerFlowDTO; + } + + /** + */ + public static void populateAnswers(Map sessionMap, QaContent qaContent, QaQueUsr user, + Map mapQuestions, GeneralLearnerFlowDTO generalLearnerFlowDTO, + IQaService qaService) { + + //create mapAnswers + Map mapAnswers = (Map) sessionMap.get(MAP_ALL_RESULTS_KEY); + if (mapAnswers == null) { + mapAnswers = new TreeMap(new QaComparator()); + + // get responses from DB + Map mapAnswersFromDb = new TreeMap(); + for (QaQueContent question : qaContent.getQaQueContents()) { + Long questionUid = question.getUid(); + QaUsrResp response = qaService.getResponseByUserAndQuestion(user.getQueUsrId(), questionUid); + + String answer; + if (response == null) { + answer = null; + } else if (!user.isResponseFinalized() && response.getAnswerAutosaved() != null) { + answer = response.getAnswerAutosaved(); + } else { + answer = response.getAnswer(); + } + mapAnswersFromDb.put(String.valueOf(question.getDisplayOrder()), answer); + } + + // maybe we have come in from the review screen, if so get the answers from db. + if (mapAnswersFromDb.size() > 0) { + mapAnswers.putAll(mapAnswersFromDb); + } else { + for (Map.Entry pairs : mapQuestions.entrySet()) { + mapAnswers.put(pairs.getKey().toString(), ""); + } + } + } + String currentAnswer = mapAnswers.get("1"); + generalLearnerFlowDTO.setCurrentQuestionIndex(new Integer(1)); + generalLearnerFlowDTO.setCurrentAnswer(currentAnswer); + sessionMap.put(MAP_SEQUENTIAL_ANSWERS_KEY, mapAnswers); + generalLearnerFlowDTO.setMapAnswers(mapAnswers); + sessionMap.put(MAP_ALL_RESULTS_KEY, mapAnswers); + } +} Fisheye: Tag 32eb376c59d7c17cfa9d51cac14c00aae8cf44ff refers to a dead (removed) revision in file `lams_tool_laqa/src/java/org/lamsfoundation/lams/tool/qa/web/AuthoringUtil.java'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 32eb376c59d7c17cfa9d51cac14c00aae8cf44ff refers to a dead (removed) revision in file `lams_tool_laqa/src/java/org/lamsfoundation/lams/tool/qa/web/ClearSessionAction.java'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 32eb376c59d7c17cfa9d51cac14c00aae8cf44ff refers to a dead (removed) revision in file `lams_tool_laqa/src/java/org/lamsfoundation/lams/tool/qa/web/LearningUtil.java'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 32eb376c59d7c17cfa9d51cac14c00aae8cf44ff refers to a dead (removed) revision in file `lams_tool_laqa/src/java/org/lamsfoundation/lams/tool/qa/web/QaAction.java'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 32eb376c59d7c17cfa9d51cac14c00aae8cf44ff refers to a dead (removed) revision in file `lams_tool_laqa/src/java/org/lamsfoundation/lams/tool/qa/web/QaAdminAction.java'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 32eb376c59d7c17cfa9d51cac14c00aae8cf44ff refers to a dead (removed) revision in file `lams_tool_laqa/src/java/org/lamsfoundation/lams/tool/qa/web/QaAuthoringConditionAction.java'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 32eb376c59d7c17cfa9d51cac14c00aae8cf44ff refers to a dead (removed) revision in file `lams_tool_laqa/src/java/org/lamsfoundation/lams/tool/qa/web/QaLearningAction.java'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 32eb376c59d7c17cfa9d51cac14c00aae8cf44ff refers to a dead (removed) revision in file `lams_tool_laqa/src/java/org/lamsfoundation/lams/tool/qa/web/QaLearningStarterAction.java'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 32eb376c59d7c17cfa9d51cac14c00aae8cf44ff refers to a dead (removed) revision in file `lams_tool_laqa/src/java/org/lamsfoundation/lams/tool/qa/web/QaMonitoringAction.java'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 32eb376c59d7c17cfa9d51cac14c00aae8cf44ff refers to a dead (removed) revision in file `lams_tool_laqa/src/java/org/lamsfoundation/lams/tool/qa/web/QaMonitoringStarterAction.java'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 32eb376c59d7c17cfa9d51cac14c00aae8cf44ff refers to a dead (removed) revision in file `lams_tool_laqa/src/java/org/lamsfoundation/lams/tool/qa/web/QaPedagogicalPlannerAction.java'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 32eb376c59d7c17cfa9d51cac14c00aae8cf44ff refers to a dead (removed) revision in file `lams_tool_laqa/src/java/org/lamsfoundation/lams/tool/qa/web/QaStarterAction.java'. Fisheye: No comparison available. Pass `N' to diff? Index: lams_tool_laqa/src/java/org/lamsfoundation/lams/tool/qa/web/action/ClearSessionAction.java =================================================================== diff -u --- lams_tool_laqa/src/java/org/lamsfoundation/lams/tool/qa/web/action/ClearSessionAction.java (revision 0) +++ lams_tool_laqa/src/java/org/lamsfoundation/lams/tool/qa/web/action/ClearSessionAction.java (revision 32eb376c59d7c17cfa9d51cac14c00aae8cf44ff) @@ -0,0 +1,52 @@ +/**************************************************************** + * Copyright (C) 2005 LAMS Foundation (http://lamsfoundation.org) + * ============================================================= + * License Information: http://lamsfoundation.org/licensing/lams/2.0/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + * USA + * + * http://www.gnu.org/licenses/gpl.txt + * **************************************************************** + */ + + +package org.lamsfoundation.lams.tool.qa.web.action; + +import javax.servlet.http.HttpSession; + +import org.lamsfoundation.lams.authoring.web.LamsAuthoringFinishAction; +import org.lamsfoundation.lams.tool.ToolAccessMode; +import org.lamsfoundation.lams.tool.qa.QaAppConstants; + +/** + * This class give a chance to clear HttpSession when user save/close authoring + * page. + * + * + * + * + * + * @version $Revision$ + */ +public class ClearSessionAction extends LamsAuthoringFinishAction { + + @Override + public void clearSession(String customiseSessionID, HttpSession session, ToolAccessMode mode) { + if (mode.isAuthor()) { + session.removeAttribute(QaAppConstants.SUBMIT_SUCCESS); + } + } + +} Index: lams_tool_laqa/src/java/org/lamsfoundation/lams/tool/qa/web/action/QaAction.java =================================================================== diff -u --- lams_tool_laqa/src/java/org/lamsfoundation/lams/tool/qa/web/action/QaAction.java (revision 0) +++ lams_tool_laqa/src/java/org/lamsfoundation/lams/tool/qa/web/action/QaAction.java (revision 32eb376c59d7c17cfa9d51cac14c00aae8cf44ff) @@ -0,0 +1,979 @@ +/**************************************************************** + * Copyright (C) 2005 LAMS Foundation (http://lamsfoundation.org) + * ============================================================= + * License Information: http://lamsfoundation.org/licensing/lams/2.0/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + * USA + * + * http://www.gnu.org/licenses/gpl.txt + * **************************************************************** + */ + + +package org.lamsfoundation.lams.tool.qa.web.action; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Date; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.Set; +import java.util.SortedSet; +import java.util.TreeSet; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; + +import org.apache.commons.lang.StringUtils; +import org.apache.log4j.Logger; +import org.apache.struts.action.ActionForm; +import org.apache.struts.action.ActionForward; +import org.apache.struts.action.ActionMapping; +import org.apache.struts.action.ActionMessage; +import org.apache.struts.action.ActionMessages; +import org.lamsfoundation.lams.authoring.web.AuthoringConstants; +import org.lamsfoundation.lams.learningdesign.TextSearchConditionComparator; +import org.lamsfoundation.lams.rating.model.RatingCriteria; +import org.lamsfoundation.lams.tool.ToolAccessMode; +import org.lamsfoundation.lams.tool.qa.QaAppConstants; +import org.lamsfoundation.lams.tool.qa.QaCondition; +import org.lamsfoundation.lams.tool.qa.QaConfigItem; +import org.lamsfoundation.lams.tool.qa.QaContent; +import org.lamsfoundation.lams.tool.qa.QaQueContent; +import org.lamsfoundation.lams.tool.qa.dto.QaQuestionDTO; +import org.lamsfoundation.lams.tool.qa.service.IQaService; +import org.lamsfoundation.lams.tool.qa.service.QaServiceProxy; +import org.lamsfoundation.lams.tool.qa.util.AuthoringUtil; +import org.lamsfoundation.lams.tool.qa.util.QaQueContentComparator; +import org.lamsfoundation.lams.tool.qa.util.QaQuestionContentDTOComparator; +import org.lamsfoundation.lams.tool.qa.util.QaUtils; +import org.lamsfoundation.lams.tool.qa.web.form.QaAuthoringForm; +import org.lamsfoundation.lams.usermanagement.dto.UserDTO; +import org.lamsfoundation.lams.util.WebUtil; +import org.lamsfoundation.lams.web.action.LamsDispatchAction; +import org.lamsfoundation.lams.web.session.SessionManager; +import org.lamsfoundation.lams.web.util.AttributeNames; +import org.lamsfoundation.lams.web.util.SessionMap; + +/** + * Q&A Tool's authoring methods. Additionally, there is one more method that initializes authoring and it's located in + * QaStarterAction.java. + * + * @author Ozgur Demirtas + */ +public class QaAction extends LamsDispatchAction implements QaAppConstants { + private static Logger logger = Logger.getLogger(QaAction.class.getName()); + + private static IQaService qaService; + + @Override + public ActionForward unspecified(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) { + return mapping.findForward(QaAppConstants.LOAD_QUESTIONS); + } + + /** + * submits content into the tool database + */ + public ActionForward submitAllContent(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) throws IOException, ServletException { + + QaAuthoringForm qaAuthoringForm = (QaAuthoringForm) form; + qaService = QaServiceProxy.getQaService(getServlet().getServletContext()); + String httpSessionID = qaAuthoringForm.getHttpSessionID(); + SessionMap sessionMap = (SessionMap) request.getSession() + .getAttribute(httpSessionID); + + String contentFolderID = WebUtil.readStrParam(request, AttributeNames.PARAM_CONTENT_FOLDER_ID); + qaAuthoringForm.setContentFolderID(contentFolderID); + + String strToolContentID = request.getParameter(AttributeNames.PARAM_TOOL_CONTENT_ID); + Long toolContentID = new Long(strToolContentID); + + List questionDTOs = (List) sessionMap.get(QaAppConstants.LIST_QUESTION_DTOS); + + ActionMessages errors = new ActionMessages(); + if (questionDTOs.size() == 0) { + ActionMessage error = new ActionMessage("questions.none.submitted"); + errors.add(ActionMessages.GLOBAL_MESSAGE, error); + } + + String richTextTitle = request.getParameter(QaAppConstants.TITLE); + String richTextInstructions = request.getParameter(QaAppConstants.INSTRUCTIONS); + + qaAuthoringForm.setTitle(richTextTitle); + qaAuthoringForm.setInstructions(richTextInstructions); + + sessionMap.put(QaAppConstants.ACTIVITY_TITLE_KEY, richTextTitle); + sessionMap.put(QaAppConstants.ACTIVITY_INSTRUCTIONS_KEY, richTextInstructions); + + if (!errors.isEmpty()) { + saveErrors(request, errors); + QaAction.logger.debug("errors saved: " + errors); + } + + QaContent qaContent = qaService.getQaContent(toolContentID); + if (errors.isEmpty()) { + ToolAccessMode mode = WebUtil.readToolAccessModeAuthorDefaulted(request); + request.setAttribute(AttributeNames.ATTR_MODE, mode.toString()); + + List deletedQuestionDTOs = (List) sessionMap.get(LIST_DELETED_QUESTION_DTOS); + + // in case request is from monitoring module - recalculate User Answers + if (mode.isTeacher()) { + Set oldQuestions = qaContent.getQaQueContents(); + qaService.removeQuestionsFromCache(qaContent); + qaService.setDefineLater(strToolContentID, false); + + // audit log the teacher has started editing activity in monitor + qaService.auditLogStartEditingActivityInMonitor(toolContentID); + + // recalculate User Answers + qaService.recalculateUserAnswers(qaContent, oldQuestions, questionDTOs, deletedQuestionDTOs); + } + + // remove deleted questions + for (QaQuestionDTO deletedQuestionDTO : deletedQuestionDTOs) { + QaQueContent removeableQuestion = qaService.getQuestionByUid(deletedQuestionDTO.getUid()); + if (removeableQuestion != null) { + qaContent.getQaQueContents().remove(removeableQuestion); + qaService.removeQuestion(removeableQuestion); + } + } + + // store content + SortedSet conditionSet = (SortedSet) sessionMap + .get(QaAppConstants.ATTR_CONDITION_SET); + qaContent = saveOrUpdateQaContent(questionDTOs, request, qaContent, toolContentID, conditionSet); + + //reOrganizeDisplayOrder + List sortedQuestions = qaService.getAllQuestionEntriesSorted(qaContent.getUid().longValue()); + Iterator iter = sortedQuestions.iterator(); + int displayOrder = 1; + while (iter.hasNext()) { + QaQueContent question = iter.next(); + + QaQueContent existingQaQueContent = qaService.getQuestionByUid(question.getUid()); + existingQaQueContent.setDisplayOrder(displayOrder); + qaService.saveOrUpdateQuestion(existingQaQueContent); + displayOrder++; + } + + // ************************* Handle rating criterias ******************* + List oldCriterias = (List) sessionMap + .get(AttributeNames.ATTR_RATING_CRITERIAS); + qaService.saveRatingCriterias(request, oldCriterias, toolContentID); + + QaUtils.setFormProperties(request, qaAuthoringForm, strToolContentID, httpSessionID); + + request.setAttribute(AuthoringConstants.LAMS_AUTHORING_SUCCESS_FLAG, Boolean.TRUE); + + } else { + if (qaContent != null) { + QaUtils.setFormProperties(request, qaAuthoringForm, strToolContentID, httpSessionID); + } + } + + List delConditionList = getDeletedQaConditionList(sessionMap); + Iterator iter = delConditionList.iterator(); + while (iter.hasNext()) { + QaCondition condition = iter.next(); + iter.remove(); + qaService.deleteCondition(condition); + } + + qaAuthoringForm.resetUserAction(); + qaAuthoringForm.setToolContentID(strToolContentID); + qaAuthoringForm.setHttpSessionID(httpSessionID); + qaAuthoringForm.setCurrentTab("1"); + + request.setAttribute(QaAppConstants.LIST_QUESTION_DTOS, questionDTOs); + request.getSession().setAttribute(httpSessionID, sessionMap); + request.setAttribute(QaAppConstants.TOTAL_QUESTION_COUNT, new Integer(questionDTOs.size())); + sessionMap.put(QaAppConstants.LIST_QUESTION_DTOS, questionDTOs); + + return mapping.findForward(QaAppConstants.LOAD_QUESTIONS); + } + + private QaContent saveOrUpdateQaContent(List questionDTOs, HttpServletRequest request, + QaContent qaContent, Long toolContentId, Set conditions) { + UserDTO toolUser = (UserDTO) SessionManager.getSession().getAttribute(AttributeNames.USER); + + String richTextTitle = request.getParameter(QaAppConstants.TITLE); + String richTextInstructions = request.getParameter(QaAppConstants.INSTRUCTIONS); + String usernameVisible = request.getParameter(QaAppConstants.USERNAME_VISIBLE); + String allowRateQuestions = request.getParameter(QaAppConstants.ALLOW_RATE_ANSWERS); + String notifyTeachersOnResponseSubmit = request.getParameter(QaAppConstants.NOTIFY_TEACHERS_ON_RESPONSE_SUBMIT); + String showOtherAnswers = request.getParameter("showOtherAnswers"); + String questionsSequenced = request.getParameter(QaAppConstants.QUESTIONS_SEQUENCED); + String lockWhenFinished = request.getParameter("lockWhenFinished"); + String noReeditAllowed = request.getParameter("noReeditAllowed"); + String allowRichEditor = request.getParameter("allowRichEditor"); + String useSelectLeaderToolOuput = request.getParameter("useSelectLeaderToolOuput"); + String reflect = request.getParameter(QaAppConstants.REFLECT); + String reflectionSubject = request.getParameter(QaAppConstants.REFLECTION_SUBJECT); + int minimumRates = WebUtil.readIntParam(request, "minimumRates"); + int maximumRates = WebUtil.readIntParam(request, "maximumRates"); + + boolean questionsSequencedBoolean = false; + boolean lockWhenFinishedBoolean = false; + boolean noReeditAllowedBoolean = false; + boolean usernameVisibleBoolean = false; + boolean allowRateQuestionsBoolean = false; + boolean notifyTeachersOnResponseSubmitBoolean = false; + boolean showOtherAnswersBoolean = false; + boolean reflectBoolean = false; + boolean allowRichEditorBoolean = false; + boolean useSelectLeaderToolOuputBoolean = false; + + if (questionsSequenced != null && questionsSequenced.equalsIgnoreCase("1")) { + questionsSequencedBoolean = true; + } + + if (lockWhenFinished != null && lockWhenFinished.equalsIgnoreCase("1")) { + lockWhenFinishedBoolean = true; + } + + if (noReeditAllowed != null && noReeditAllowed.equalsIgnoreCase("1")) { + noReeditAllowedBoolean = true; + lockWhenFinishedBoolean = true; + } + + if (usernameVisible != null && usernameVisible.equalsIgnoreCase("1")) { + usernameVisibleBoolean = true; + } + + if (showOtherAnswers != null && showOtherAnswers.equalsIgnoreCase("1")) { + showOtherAnswersBoolean = true; + } + + if (allowRateQuestions != null && allowRateQuestions.equalsIgnoreCase("1") && showOtherAnswersBoolean) { + allowRateQuestionsBoolean = true; + } + + if (notifyTeachersOnResponseSubmit != null && notifyTeachersOnResponseSubmit.equalsIgnoreCase("1")) { + notifyTeachersOnResponseSubmitBoolean = true; + } + + if (allowRichEditor != null && allowRichEditor.equalsIgnoreCase("1")) { + allowRichEditorBoolean = true; + } + + if (useSelectLeaderToolOuput != null && useSelectLeaderToolOuput.equalsIgnoreCase("1")) { + useSelectLeaderToolOuputBoolean = true; + } + + if (reflect != null && reflect.equalsIgnoreCase("1")) { + reflectBoolean = true; + } + long userId = 0; + if (toolUser != null) { + userId = toolUser.getUserID().longValue(); + } else { + HttpSession ss = SessionManager.getSession(); + UserDTO user = (UserDTO) ss.getAttribute(AttributeNames.USER); + if (user != null) { + userId = user.getUserID().longValue(); + } else { + userId = 0; + } + } + + boolean newContent = false; + if (qaContent == null) { + qaContent = new QaContent(); + newContent = true; + } + + qaContent.setQaContentId(toolContentId); + qaContent.setTitle(richTextTitle); + qaContent.setInstructions(richTextInstructions); + qaContent.setUpdateDate(new Date(System.currentTimeMillis())); + /** keep updating this one */ + qaContent.setCreatedBy(userId); + /** make sure we are setting the userId from the User object above */ + + qaContent.setUsernameVisible(usernameVisibleBoolean); + qaContent.setAllowRateAnswers(allowRateQuestionsBoolean); + qaContent.setNotifyTeachersOnResponseSubmit(notifyTeachersOnResponseSubmitBoolean); + qaContent.setShowOtherAnswers(showOtherAnswersBoolean); + qaContent.setQuestionsSequenced(questionsSequencedBoolean); + qaContent.setLockWhenFinished(lockWhenFinishedBoolean); + qaContent.setNoReeditAllowed(noReeditAllowedBoolean); + qaContent.setReflect(reflectBoolean); + qaContent.setReflectionSubject(reflectionSubject); + qaContent.setAllowRichEditor(allowRichEditorBoolean); + qaContent.setUseSelectLeaderToolOuput(useSelectLeaderToolOuputBoolean); + qaContent.setMinimumRates(minimumRates); + qaContent.setMaximumRates(maximumRates); + + qaContent.setConditions(new TreeSet(new TextSearchConditionComparator())); + if (newContent) { + qaService.createQaContent(qaContent); + } else { + qaService.updateQaContent(qaContent); + } + + qaContent = qaService.getQaContent(toolContentId); + + for (QaCondition condition : conditions) { + condition.setQuestions(new TreeSet(new QaQueContentComparator())); + for (QaQuestionDTO dto : condition.temporaryQuestionDTOSet) { + for (QaQueContent queContent : qaContent.getQaQueContents()) { + if (dto.getDisplayOrder().equals(String.valueOf(queContent.getDisplayOrder()))) { + condition.getQuestions().add(queContent); + } + } + } + } + qaContent.setConditions(conditions); + qaService.updateQaContent(qaContent); + + // persist questions + int displayOrder = 0; + for (QaQuestionDTO questionDTO : questionDTOs) { + + String questionText = questionDTO.getQuestion(); + + // skip empty questions + if (questionText.isEmpty()) { + continue; + } + + ++displayOrder; + + QaQueContent question = qaService.getQuestionByUid(questionDTO.getUid()); + + // in case question doesn't exist + if (question == null) { + question = new QaQueContent(questionText, displayOrder, questionDTO.getFeedback(), + questionDTO.isRequired(), questionDTO.getMinWordsLimit(), qaContent); + qaContent.getQaQueContents().add(question); + question.setQaContent(qaContent); + + // in case question exists already + } else { + + question.setQuestion(questionText); + question.setFeedback(questionDTO.getFeedback()); + question.setDisplayOrder(displayOrder); + question.setRequired(questionDTO.isRequired()); + question.setMinWordsLimit(questionDTO.getMinWordsLimit()); + } + + qaService.saveOrUpdateQuestion(question); + } + + return qaContent; + } + + /** + * saveSingleQuestion + */ + public ActionForward saveSingleQuestion(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) throws IOException, ServletException { + + QaAuthoringForm qaAuthoringForm = (QaAuthoringForm) form; + + String httpSessionID = qaAuthoringForm.getHttpSessionID(); + + SessionMap sessionMap = (SessionMap) request.getSession() + .getAttribute(httpSessionID); + + String contentFolderID = WebUtil.readStrParam(request, AttributeNames.PARAM_CONTENT_FOLDER_ID); + qaAuthoringForm.setContentFolderID(contentFolderID); + + String strToolContentID = request.getParameter(AttributeNames.PARAM_TOOL_CONTENT_ID); + + String editQuestionBoxRequest = request.getParameter("editQuestionBoxRequest"); + + List questionDTOs = (List) sessionMap.get(QaAppConstants.LIST_QUESTION_DTOS); + + String newQuestion = request.getParameter("newQuestion"); + + String feedback = request.getParameter("feedback"); + + String editableQuestionIndex = request.getParameter("editableQuestionIndex"); + + String required = request.getParameter("required"); + boolean requiredBoolean = false; + if (required != null && required.equalsIgnoreCase("1")) { + requiredBoolean = true; + } + int minWordsLimit = WebUtil.readIntParam(request, "minWordsLimit"); + + if (newQuestion != null && newQuestion.length() > 0) { + if (editQuestionBoxRequest != null && editQuestionBoxRequest.equals("false")) { + //request for add and save + boolean duplicates = AuthoringUtil.checkDuplicateQuestions(questionDTOs, newQuestion); + + if (!duplicates) { + QaQuestionDTO qaQuestionDTO = null; + Iterator iter = questionDTOs.iterator(); + while (iter.hasNext()) { + qaQuestionDTO = iter.next(); + + String displayOrder = qaQuestionDTO.getDisplayOrder(); + if (displayOrder != null && !displayOrder.equals("")) { + if (displayOrder.equals(editableQuestionIndex)) { + break; + } + + } + } + + qaQuestionDTO.setQuestion(newQuestion); + qaQuestionDTO.setFeedback(feedback); + qaQuestionDTO.setDisplayOrder(editableQuestionIndex); + qaQuestionDTO.setRequired(requiredBoolean); + qaQuestionDTO.setMinWordsLimit(minWordsLimit); + + questionDTOs = AuthoringUtil.reorderUpdateQuestionDTOs(questionDTOs, qaQuestionDTO, + editableQuestionIndex); + } else { + //duplicate question entry, not adding + } + } else { + //request for edit and save + QaQuestionDTO qaQuestionDTO = null; + Iterator iter = questionDTOs.iterator(); + while (iter.hasNext()) { + qaQuestionDTO = iter.next(); + + String displayOrder = qaQuestionDTO.getDisplayOrder(); + + if (displayOrder != null && !displayOrder.equals("")) { + if (displayOrder.equals(editableQuestionIndex)) { + break; + } + + } + } + + qaQuestionDTO.setQuestion(newQuestion); + qaQuestionDTO.setFeedback(feedback); + qaQuestionDTO.setDisplayOrder(editableQuestionIndex); + qaQuestionDTO.setRequired(requiredBoolean); + qaQuestionDTO.setMinWordsLimit(minWordsLimit); + + questionDTOs = AuthoringUtil.reorderUpdateQuestionDTOs(questionDTOs, qaQuestionDTO, + editableQuestionIndex); + } + } else { + //entry blank, not adding + } + + request.setAttribute(QaAppConstants.LIST_QUESTION_DTOS, questionDTOs); + sessionMap.put(QaAppConstants.LIST_QUESTION_DTOS, questionDTOs); + + String richTextTitle = request.getParameter(QaAppConstants.TITLE); + String richTextInstructions = request.getParameter(QaAppConstants.INSTRUCTIONS); + + qaAuthoringForm.setTitle(richTextTitle); + qaAuthoringForm.setInstructions(richTextInstructions); + + sessionMap.put(QaAppConstants.ACTIVITY_TITLE_KEY, richTextTitle); + sessionMap.put(QaAppConstants.ACTIVITY_INSTRUCTIONS_KEY, richTextInstructions); + + request.getSession().setAttribute(httpSessionID, sessionMap); + + QaUtils.setFormProperties(request, qaAuthoringForm, strToolContentID, httpSessionID); + + qaAuthoringForm.setToolContentID(strToolContentID); + qaAuthoringForm.setHttpSessionID(httpSessionID); + qaAuthoringForm.setCurrentTab("1"); + + request.getSession().setAttribute(httpSessionID, sessionMap); + request.setAttribute(QaAppConstants.TOTAL_QUESTION_COUNT, new Integer(questionDTOs.size())); + return mapping.findForward(QaAppConstants.LOAD_QUESTIONS); + } + + /** + * addSingleQuestion + */ + public ActionForward addSingleQuestion(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) throws IOException, ServletException { + + QaAuthoringForm qaAuthoringForm = (QaAuthoringForm) form; + + String httpSessionID = qaAuthoringForm.getHttpSessionID(); + + SessionMap sessionMap = (SessionMap) request.getSession() + .getAttribute(httpSessionID); + + String contentFolderID = WebUtil.readStrParam(request, AttributeNames.PARAM_CONTENT_FOLDER_ID); + qaAuthoringForm.setContentFolderID(contentFolderID); + + String strToolContentID = request.getParameter(AttributeNames.PARAM_TOOL_CONTENT_ID); + + List questionDTOs = (List) sessionMap.get(QaAppConstants.LIST_QUESTION_DTOS); + + String newQuestion = request.getParameter("newQuestion"); + String feedback = request.getParameter("feedback"); + String required = request.getParameter("required"); + boolean requiredBoolean = false; + if (required != null && required.equalsIgnoreCase("1")) { + requiredBoolean = true; + } + int minWordsLimit = WebUtil.readIntParam(request, "minWordsLimit"); + + int listSize = questionDTOs.size(); + + if (newQuestion != null && newQuestion.length() > 0) { + boolean duplicates = AuthoringUtil.checkDuplicateQuestions(questionDTOs, newQuestion); + + if (!duplicates) { + QaQuestionDTO qaQuestionDTO = new QaQuestionDTO(newQuestion, new Long(listSize + 1).toString(), + feedback, requiredBoolean, minWordsLimit); + questionDTOs.add(qaQuestionDTO); + } else { + //entry duplicate, not adding + } + } else { + //entry blank, not adding + } + + request.setAttribute(QaAppConstants.LIST_QUESTION_DTOS, questionDTOs); + sessionMap.put(QaAppConstants.LIST_QUESTION_DTOS, questionDTOs); + + String richTextTitle = request.getParameter(QaAppConstants.TITLE); + String richTextInstructions = request.getParameter(QaAppConstants.INSTRUCTIONS); + + qaAuthoringForm.setTitle(richTextTitle); + qaAuthoringForm.setInstructions(richTextInstructions); + + sessionMap.put(QaAppConstants.ACTIVITY_TITLE_KEY, richTextTitle); + sessionMap.put(QaAppConstants.ACTIVITY_INSTRUCTIONS_KEY, richTextInstructions); + + request.getSession().setAttribute(httpSessionID, sessionMap); + + QaUtils.setFormProperties(request, qaAuthoringForm, strToolContentID, httpSessionID); + + qaAuthoringForm.setToolContentID(strToolContentID); + qaAuthoringForm.setHttpSessionID(httpSessionID); + qaAuthoringForm.setCurrentTab("1"); + + request.getSession().setAttribute(httpSessionID, sessionMap); + request.setAttribute(QaAppConstants.TOTAL_QUESTION_COUNT, new Integer(questionDTOs.size())); + return mapping.findForward(QaAppConstants.LOAD_QUESTIONS); + } + + /** + * opens up an new screen within the current page for adding a new question + */ + public ActionForward newQuestionBox(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) throws IOException, ServletException { + QaAuthoringForm qaAuthoringForm = (QaAuthoringForm) form; + + IQaService qaService = QaServiceProxy.getQaService(getServlet().getServletContext()); + + String httpSessionID = qaAuthoringForm.getHttpSessionID(); + + SessionMap sessionMap = (SessionMap) request.getSession() + .getAttribute(httpSessionID); + + String contentFolderID = WebUtil.readStrParam(request, AttributeNames.PARAM_CONTENT_FOLDER_ID); + + qaAuthoringForm.setContentFolderID(contentFolderID); + + String strToolContentID = request.getParameter(AttributeNames.PARAM_TOOL_CONTENT_ID); + + String richTextTitle = request.getParameter(QaAppConstants.TITLE); + + String richTextInstructions = request.getParameter(QaAppConstants.INSTRUCTIONS); + + qaAuthoringForm.setTitle(richTextTitle); + qaAuthoringForm.setInstructions(richTextInstructions); + + QaUtils.setFormProperties(request, qaAuthoringForm, strToolContentID, httpSessionID); + + Collection questionDTOs = (Collection) sessionMap + .get(QaAppConstants.LIST_QUESTION_DTOS); + + request.setAttribute(QaAppConstants.TOTAL_QUESTION_COUNT, new Integer(questionDTOs.size())); + + // Adding in the qa wizard data if it is turned on + if (qaService.getConfigItem(QaConfigItem.KEY_ENABLE_QAWIZARD) != null + && qaService.getConfigItem(QaConfigItem.KEY_ENABLE_QAWIZARD).getConfigValue().equals("true")) { + request.setAttribute(QaAppConstants.ATTR_WIZARD_ENABLED, true); + request.setAttribute(QaAppConstants.ATTR_WIZARD_CATEGORIES, qaService.getWizardCategories()); + } + + return mapping.findForward("newQuestionBox"); + } + + /** + * opens up an new screen within the current page for editing a question + */ + public ActionForward newEditableQuestionBox(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) throws IOException, ServletException { + QaAuthoringForm qaAuthoringForm = (QaAuthoringForm) form; + + String httpSessionID = qaAuthoringForm.getHttpSessionID(); + + SessionMap sessionMap = (SessionMap) request.getSession() + .getAttribute(httpSessionID); + + String questionIndex = request.getParameter("questionIndex"); + + qaAuthoringForm.setEditableQuestionIndex(questionIndex); + + List questionDTOs = (List) sessionMap.get(QaAppConstants.LIST_QUESTION_DTOS); + + String editableQuestion = ""; + String editableFeedback = ""; + boolean requiredBoolean = false; + int minWordsLimit = 0; + Iterator iter = questionDTOs.iterator(); + while (iter.hasNext()) { + QaQuestionDTO qaQuestionDTO = iter.next(); + String displayOrder = qaQuestionDTO.getDisplayOrder(); + + if (displayOrder != null && !displayOrder.equals("")) { + if (displayOrder.equals(questionIndex)) { + editableFeedback = qaQuestionDTO.getFeedback(); + editableQuestion = qaQuestionDTO.getQuestion(); + requiredBoolean = qaQuestionDTO.isRequired(); + minWordsLimit = qaQuestionDTO.getMinWordsLimit(); + break; + } + + } + } + + String contentFolderID = WebUtil.readStrParam(request, AttributeNames.PARAM_CONTENT_FOLDER_ID); + qaAuthoringForm.setContentFolderID(contentFolderID); + + String strToolContentID = request.getParameter(AttributeNames.PARAM_TOOL_CONTENT_ID); + + String richTextTitle = request.getParameter(QaAppConstants.TITLE); + String richTextInstructions = request.getParameter(QaAppConstants.INSTRUCTIONS); + + qaAuthoringForm.setTitle(richTextTitle); + qaAuthoringForm.setInstructions(richTextInstructions); + + QaUtils.setFormProperties(request, qaAuthoringForm, strToolContentID, httpSessionID); + + qaAuthoringForm.setRequired(requiredBoolean); + qaAuthoringForm.setMinWordsLimit(minWordsLimit); + qaAuthoringForm.setEditableQuestionText(editableQuestion); + qaAuthoringForm.setFeedback(editableFeedback); + + request.setAttribute(QaAppConstants.TOTAL_QUESTION_COUNT, new Integer(questionDTOs.size())); + + return mapping.findForward("editQuestionBox"); + } + + /** + * removes a question from the questions map + */ + public ActionForward removeQuestion(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) throws IOException, ServletException { + QaAuthoringForm qaAuthoringForm = (QaAuthoringForm) form; + + String httpSessionID = qaAuthoringForm.getHttpSessionID(); + SessionMap sessionMap = (SessionMap) request.getSession() + .getAttribute(httpSessionID); + + String questionIndexToDelete = request.getParameter("questionIndex"); + QaQuestionDTO questionToDelete = null; + List questionDTOs = (List) sessionMap.get(QaAppConstants.LIST_QUESTION_DTOS); + + List listFinalQuestionDTO = new LinkedList(); + int queIndex = 0; + for (QaQuestionDTO questionDTO : questionDTOs) { + + String questionText = questionDTO.getQuestion(); + String displayOrder = questionDTO.getDisplayOrder(); + + if (questionText != null && !questionText.equals("") && (!displayOrder.equals(questionIndexToDelete))) { + + ++queIndex; + questionDTO.setDisplayOrder(new Integer(queIndex).toString()); + listFinalQuestionDTO.add(questionDTO); + } + if ((questionText != null) && (!questionText.isEmpty()) && displayOrder.equals(questionIndexToDelete)) { + List deletedQuestionDTOs = (List) sessionMap + .get(LIST_DELETED_QUESTION_DTOS); + ; + deletedQuestionDTOs.add(questionDTO); + sessionMap.put(LIST_DELETED_QUESTION_DTOS, deletedQuestionDTOs); + questionToDelete = questionDTO; + } + } + request.setAttribute(QaAppConstants.LIST_QUESTION_DTOS, listFinalQuestionDTO); + sessionMap.put(QaAppConstants.LIST_QUESTION_DTOS, listFinalQuestionDTO); + request.setAttribute(QaAppConstants.TOTAL_QUESTION_COUNT, new Integer(listFinalQuestionDTO.size())); + + SortedSet conditions = (SortedSet) sessionMap.get(QaAppConstants.ATTR_CONDITION_SET); + Iterator conditionIter = conditions.iterator(); + while (conditionIter.hasNext()) { + QaCondition condition = conditionIter.next(); + Iterator dtoIter = condition.temporaryQuestionDTOSet.iterator(); + while (dtoIter.hasNext()) { + if (dtoIter.next() == questionToDelete) { + dtoIter.remove(); + } + } + if (condition.temporaryQuestionDTOSet.isEmpty()) { + conditionIter.remove(); + } + } + + String contentFolderID = WebUtil.readStrParam(request, AttributeNames.PARAM_CONTENT_FOLDER_ID); + qaAuthoringForm.setContentFolderID(contentFolderID); + String richTextTitle = request.getParameter(QaAppConstants.TITLE); + String richTextInstructions = request.getParameter(QaAppConstants.INSTRUCTIONS); + sessionMap.put(QaAppConstants.ACTIVITY_TITLE_KEY, richTextTitle); + sessionMap.put(QaAppConstants.ACTIVITY_INSTRUCTIONS_KEY, richTextInstructions); + String strToolContentID = request.getParameter(AttributeNames.PARAM_TOOL_CONTENT_ID); + qaAuthoringForm.setTitle(richTextTitle); + qaAuthoringForm.setInstructions(richTextInstructions); + request.getSession().setAttribute(httpSessionID, sessionMap); + QaUtils.setFormProperties(request, qaAuthoringForm, strToolContentID, httpSessionID); + qaAuthoringForm.setToolContentID(strToolContentID); + qaAuthoringForm.setHttpSessionID(httpSessionID); + qaAuthoringForm.setCurrentTab("1"); + + return mapping.findForward(QaAppConstants.LOAD_QUESTIONS); + } + + /** + * moves a question down in the list + */ + public ActionForward moveQuestionDown(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) throws IOException, ServletException { + QaAuthoringForm qaAuthoringForm = (QaAuthoringForm) form; + + String httpSessionID = qaAuthoringForm.getHttpSessionID(); + SessionMap sessionMap = (SessionMap) request.getSession() + .getAttribute(httpSessionID); + + String questionIndex = request.getParameter("questionIndex"); + + List questionDTOs = (List) sessionMap.get(QaAppConstants.LIST_QUESTION_DTOS); + + SortedSet conditionSet = (SortedSet) sessionMap + .get(QaAppConstants.ATTR_CONDITION_SET); + + questionDTOs = QaAction.swapQuestions(questionDTOs, questionIndex, "down", conditionSet); + + questionDTOs = QaAction.reorderQuestionDTOs(questionDTOs); + + sessionMap.put(QaAppConstants.LIST_QUESTION_DTOS, questionDTOs); + + String contentFolderID = WebUtil.readStrParam(request, AttributeNames.PARAM_CONTENT_FOLDER_ID); + qaAuthoringForm.setContentFolderID(contentFolderID); + + String richTextTitle = request.getParameter(QaAppConstants.TITLE); + + String richTextInstructions = request.getParameter(QaAppConstants.INSTRUCTIONS); + + sessionMap.put(QaAppConstants.ACTIVITY_TITLE_KEY, richTextTitle); + sessionMap.put(QaAppConstants.ACTIVITY_INSTRUCTIONS_KEY, richTextInstructions); + + String strToolContentID = request.getParameter(AttributeNames.PARAM_TOOL_CONTENT_ID); + + qaAuthoringForm.setTitle(richTextTitle); + qaAuthoringForm.setInstructions(richTextInstructions); + request.getSession().setAttribute(httpSessionID, sessionMap); + + QaUtils.setFormProperties(request, qaAuthoringForm, strToolContentID, httpSessionID); + + qaAuthoringForm.setToolContentID(strToolContentID); + qaAuthoringForm.setHttpSessionID(httpSessionID); + qaAuthoringForm.setCurrentTab("1"); + + request.setAttribute(QaAppConstants.LIST_QUESTION_DTOS, questionDTOs); + + request.setAttribute(QaAppConstants.TOTAL_QUESTION_COUNT, new Integer(questionDTOs.size())); + return mapping.findForward(QaAppConstants.LOAD_QUESTIONS); + } + + /** + * moves a question up in the list + */ + public ActionForward moveQuestionUp(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) throws IOException, ServletException { + QaAuthoringForm qaAuthoringForm = (QaAuthoringForm) form; + + String httpSessionID = qaAuthoringForm.getHttpSessionID(); + + SessionMap sessionMap = (SessionMap) request.getSession() + .getAttribute(httpSessionID); + + String questionIndex = request.getParameter("questionIndex"); + + List questionDTOs = (List) sessionMap.get(QaAppConstants.LIST_QUESTION_DTOS); + + SortedSet conditionSet = (SortedSet) sessionMap + .get(QaAppConstants.ATTR_CONDITION_SET); + questionDTOs = QaAction.swapQuestions(questionDTOs, questionIndex, "up", conditionSet); + + questionDTOs = QaAction.reorderQuestionDTOs(questionDTOs); + + sessionMap.put(QaAppConstants.LIST_QUESTION_DTOS, questionDTOs); + + String contentFolderID = WebUtil.readStrParam(request, AttributeNames.PARAM_CONTENT_FOLDER_ID); + + qaAuthoringForm.setContentFolderID(contentFolderID); + + String richTextTitle = request.getParameter(QaAppConstants.TITLE); + + String richTextInstructions = request.getParameter(QaAppConstants.INSTRUCTIONS); + + sessionMap.put(QaAppConstants.ACTIVITY_TITLE_KEY, richTextTitle); + sessionMap.put(QaAppConstants.ACTIVITY_INSTRUCTIONS_KEY, richTextInstructions); + + String strToolContentID = request.getParameter(AttributeNames.PARAM_TOOL_CONTENT_ID); + + qaAuthoringForm.setTitle(richTextTitle); + qaAuthoringForm.setInstructions(richTextInstructions); + + request.getSession().setAttribute(httpSessionID, sessionMap); + + QaUtils.setFormProperties(request, qaAuthoringForm, strToolContentID, httpSessionID); + + qaAuthoringForm.setToolContentID(strToolContentID); + qaAuthoringForm.setHttpSessionID(httpSessionID); + qaAuthoringForm.setCurrentTab("1"); + + request.setAttribute(QaAppConstants.LIST_QUESTION_DTOS, questionDTOs); + + request.setAttribute(QaAppConstants.TOTAL_QUESTION_COUNT, new Integer(questionDTOs.size())); + return mapping.findForward(QaAppConstants.LOAD_QUESTIONS); + } + + private static List swapQuestions(List questionDTOs, String questionIndex, + String direction, Set conditions) { + + int intQuestionIndex = new Integer(questionIndex).intValue(); + int intOriginalQuestionIndex = intQuestionIndex; + + int replacedQuestionIndex = 0; + if (direction.equals("down")) { + // direction down + replacedQuestionIndex = ++intQuestionIndex; + } else { + // direction up + replacedQuestionIndex = --intQuestionIndex; + } + + QaQuestionDTO mainQuestion = QaAction.getQuestionAtDisplayOrder(questionDTOs, intOriginalQuestionIndex); + + QaQuestionDTO replacedQuestion = QaAction.getQuestionAtDisplayOrder(questionDTOs, replacedQuestionIndex); + + List newQuestionDtos = new LinkedList(); + + Iterator iter = questionDTOs.iterator(); + while (iter.hasNext()) { + QaQuestionDTO questionDTO = iter.next(); + QaQuestionDTO tempQuestion = null; + + if (!questionDTO.getDisplayOrder().equals(new Integer(intOriginalQuestionIndex).toString()) + && !questionDTO.getDisplayOrder().equals(new Integer(replacedQuestionIndex).toString())) { + // normal copy + tempQuestion = questionDTO; + + } else if (questionDTO.getDisplayOrder().equals(new Integer(intOriginalQuestionIndex).toString())) { + // move type 1 + tempQuestion = replacedQuestion; + + } else if (questionDTO.getDisplayOrder().equals(new Integer(replacedQuestionIndex).toString())) { + // move type 1 + tempQuestion = mainQuestion; + } + + newQuestionDtos.add(tempQuestion); + } + + // references in conditions also need to be changed + if (conditions != null) { + for (QaCondition condition : conditions) { + SortedSet newQuestionDTOSet = new TreeSet( + new QaQuestionContentDTOComparator()); + for (QaQuestionDTO dto : newQuestionDtos) { + if (condition.temporaryQuestionDTOSet.contains(dto)) { + newQuestionDTOSet.add(dto); + } + } + condition.temporaryQuestionDTOSet = newQuestionDTOSet; + } + } + + return newQuestionDtos; + } + + private static QaQuestionDTO getQuestionAtDisplayOrder(List questionDTOs, + int intOriginalQuestionIndex) { + + Iterator iter = questionDTOs.iterator(); + while (iter.hasNext()) { + QaQuestionDTO qaQuestionDTO = iter.next(); + if (new Integer(intOriginalQuestionIndex).toString().equals(qaQuestionDTO.getDisplayOrder())) { + return qaQuestionDTO; + } + } + return null; + } + + private static List reorderQuestionDTOs(List questionDTOs) { + List listFinalQuestionDTO = new LinkedList(); + + int queIndex = 0; + Iterator iter = questionDTOs.iterator(); + while (iter.hasNext()) { + QaQuestionDTO qaQuestionDTO = iter.next(); + + String question = qaQuestionDTO.getQuestion(); + String feedback = qaQuestionDTO.getFeedback(); + boolean required = qaQuestionDTO.isRequired(); + int minWordsLimit = qaQuestionDTO.getMinWordsLimit(); + + if (question != null && !question.equals("")) { + ++queIndex; + + qaQuestionDTO.setQuestion(question); + qaQuestionDTO.setDisplayOrder(new Integer(queIndex).toString()); + qaQuestionDTO.setFeedback(feedback); + qaQuestionDTO.setRequired(required); + qaQuestionDTO.setMinWordsLimit(minWordsLimit); + + listFinalQuestionDTO.add(qaQuestionDTO); + } + } + return listFinalQuestionDTO; + } + + /** + * Get the deleted condition list, which could be persisted or non-persisted + * items. + * + * @param request + * @return + */ + private List getDeletedQaConditionList(SessionMap sessionMap) { + List list = (List) sessionMap.get(QaAppConstants.ATTR_DELETED_CONDITION_LIST); + if (list == null) { + list = new ArrayList(); + sessionMap.put(QaAppConstants.ATTR_DELETED_CONDITION_LIST, list); + } + return list; + } +} Index: lams_tool_laqa/src/java/org/lamsfoundation/lams/tool/qa/web/action/QaAdminAction.java =================================================================== diff -u --- lams_tool_laqa/src/java/org/lamsfoundation/lams/tool/qa/web/action/QaAdminAction.java (revision 0) +++ lams_tool_laqa/src/java/org/lamsfoundation/lams/tool/qa/web/action/QaAdminAction.java (revision 32eb376c59d7c17cfa9d51cac14c00aae8cf44ff) @@ -0,0 +1,396 @@ +/**************************************************************** + * Copyright (C) 2008 LAMS Foundation (http://lamsfoundation.org) + * ============================================================= + * License Information: http://lamsfoundation.org/licensing/lams/2.0/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2.0 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 * USA + * + * http://www.gnu.org/licenses/gpl.txt + * **************************************************************** + */ + + +package org.lamsfoundation.lams.tool.qa.web.action; + +import java.io.IOException; +import java.io.OutputStream; +import java.io.StringReader; +import java.util.SortedSet; +import java.util.TreeSet; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; + +import org.apache.log4j.Logger; +import org.apache.struts.action.ActionForm; +import org.apache.struts.action.ActionForward; +import org.apache.struts.action.ActionMapping; +import org.lamsfoundation.lams.learningdesign.service.ExportToolContentException; +import org.lamsfoundation.lams.tool.qa.QaConfigItem; +import org.lamsfoundation.lams.tool.qa.QaWizardCategory; +import org.lamsfoundation.lams.tool.qa.QaWizardCognitiveSkill; +import org.lamsfoundation.lams.tool.qa.QaWizardQuestion; +import org.lamsfoundation.lams.tool.qa.service.IQaService; +import org.lamsfoundation.lams.tool.qa.service.QaServiceProxy; +import org.lamsfoundation.lams.tool.qa.web.form.QaAdminForm; +import org.lamsfoundation.lams.web.action.LamsDispatchAction; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.NamedNodeMap; +import org.w3c.dom.NodeList; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; + +import com.thoughtworks.xstream.XStream; +import com.thoughtworks.xstream.converters.reflection.SunUnsafeReflectionProvider; +import com.thoughtworks.xstream.security.AnyTypePermission; + +/** + * Handles the admin page for question and answer which includes the settings + * and items for the q&a question wizard + * + * @author lfoxton + * + * + */ +public class QaAdminAction extends LamsDispatchAction { + + private static Logger logger = Logger.getLogger(QaAdminAction.class.getName()); + + public static final String ATTR_CATEGORIES = "categories"; + public static final String ATTR_CATEGORY = "category"; + public static final String ATTR_QUESTION = "question"; + public static final String ATTR_SKILL = "skill"; + public static final String ATTR_TITLE = "title"; + public static final String ATTR_UID = "uid"; + public static final String NULL = "null"; + public static final String FILE_EXPORT = "qa-wizard.xml"; + + private IQaService qaService; + + /** + * Sets up the admin page + */ + @Override + public ActionForward unspecified(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) { + // set up qaService + if (qaService == null) { + qaService = QaServiceProxy.getQaService(this.getServlet().getServletContext()); + } + + QaAdminForm adminForm = (QaAdminForm) form; + + QaConfigItem enableQaWizard = qaService.getConfigItem(QaConfigItem.KEY_ENABLE_QAWIZARD); + if (enableQaWizard != null) { + adminForm.setQaWizardEnabled(enableQaWizard.getConfigValue()); + } + + request.setAttribute("error", false); + request.setAttribute(ATTR_CATEGORIES, getQaWizardCategories()); + + return mapping.findForward("config"); + } + + /** + * Saves admin page, if the wizard is enabled, saves the wizard content + * + * @param mapping + * @param form + * @param request + * @param response + * @return + */ + public ActionForward saveContent(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) { + QaAdminForm adminForm = (QaAdminForm) form; + + // set up mdlForumService + if (qaService == null) { + qaService = QaServiceProxy.getQaService(this.getServlet().getServletContext()); + } + + QaConfigItem enableQaWizard = qaService.getConfigItem(QaConfigItem.KEY_ENABLE_QAWIZARD); + + if (adminForm.getQaWizardEnabled() != null && adminForm.getQaWizardEnabled()) { + enableQaWizard.setConfigValue(QaAdminForm.TRUE); + + // get the wizard content and save + if (adminForm.getSerialiseXML() != null && !adminForm.getSerialiseXML().trim().equals("")) { + updateWizardFromXML(adminForm.getSerialiseXML().trim()); + } + + // remove any wizard items that were removed + removeWizardItems(adminForm.getDeleteCategoriesCSV(), adminForm.getDeleteSkillsCSV(), + adminForm.getDeleteQuestionsCSV()); + } else { + enableQaWizard.setConfigValue(QaAdminForm.FALSE); + } + qaService.saveOrUpdateConfigItem(enableQaWizard); + + request.setAttribute(ATTR_CATEGORIES, getQaWizardCategories()); + request.setAttribute("savedSuccess", true); + return mapping.findForward("config"); + + } + + /** + * Gets the complete set of wizard categories + * + * @return + */ + public SortedSet getQaWizardCategories() { + return qaService.getWizardCategories(); + } + + /** + * Removes all the removed wizard items from the db using CSV values + * + * @param categoriesCSV + * @param skillsCSV + * @param questionsCSV + */ + public void removeWizardItems(String categoriesCSV, String skillsCSV, String questionsCSV) { + + // remove categories + if (categoriesCSV != null && !categoriesCSV.equals("")) { + String categoryUIDs[] = categoriesCSV.split(","); + for (int i = 0; i < categoryUIDs.length; i++) { + qaService.deleteWizardCategoryByUID(Long.parseLong(categoryUIDs[i])); + } + } + + // remove skills + if (skillsCSV != null && !skillsCSV.equals("")) { + String skillUIDs[] = skillsCSV.split(","); + for (int i = 0; i < skillUIDs.length; i++) { + qaService.deleteWizardSkillByUID(Long.parseLong(skillUIDs[i])); + } + } + + // remove questions + if (questionsCSV != null && !questionsCSV.equals("")) { + String questionUIDs[] = questionsCSV.split(","); + for (int i = 0; i < questionUIDs.length; i++) { + qaService.deleteWizardQuestionByUID(Long.parseLong(questionUIDs[i])); + } + } + } + + /** + * Saves all the wizard items from the xml serialisation sent from the form + * + * @param xmlStr + */ + @SuppressWarnings("unchecked") + public void updateWizardFromXML(String xmlStr) { + //SortedSet currentCategories = getQaWizardCategories(); + SortedSet newCategories = new TreeSet(); + try { + DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); + DocumentBuilder db = dbf.newDocumentBuilder(); + Document document = db.parse(new InputSource(new StringReader(xmlStr))); + + // Get a list of category nodes + NodeList categoryNodeList = document.getElementsByTagName(ATTR_CATEGORY); + + for (int i = 0; i < categoryNodeList.getLength(); i++) { + + Element categoryElement = (Element) categoryNodeList.item(i); + + // Get the attributes for this category + NamedNodeMap categoryNamedNode = categoryNodeList.item(i).getAttributes(); + + QaWizardCategory category = new QaWizardCategory(); + category.setTitle(categoryNamedNode.getNamedItem(ATTR_TITLE).getNodeValue()); + category.setCognitiveSkills(new TreeSet()); + + if (categoryNamedNode.getNamedItem(ATTR_UID).getNodeValue() != null + && !categoryNamedNode.getNamedItem(ATTR_UID).getNodeValue().equals(NULL)) { + category.setUid(Long.parseLong(categoryNamedNode.getNamedItem(ATTR_UID).getNodeValue())); + } + + // Get a list of cognitive skill nodes + NodeList skillNodeList = categoryElement.getElementsByTagName(ATTR_SKILL); + for (int j = 0; j < skillNodeList.getLength(); j++) { + Element skillElement = (Element) skillNodeList.item(j); + + // Get the attributes for this skill + NamedNodeMap skillNamedNode = skillNodeList.item(j).getAttributes(); + + // Create the skill and add attributes from the node + QaWizardCognitiveSkill skill = new QaWizardCognitiveSkill(); + skill.setCategory(category); + skill.setTitle(skillNamedNode.getNamedItem(ATTR_TITLE).getNodeValue()); + skill.setQuestions(new TreeSet()); + + if (skillNamedNode.getNamedItem(ATTR_UID).getNodeValue() != null + && !skillNamedNode.getNamedItem(ATTR_UID).getNodeValue().equals(NULL)) { + skill.setUid(Long.parseLong(skillNamedNode.getNamedItem(ATTR_UID).getNodeValue())); + } + + // add the skill to the parent category + category.getCognitiveSkills().add(skill); + + // Get a list of questions for this skill + NodeList questionNodeList = skillElement.getElementsByTagName(ATTR_QUESTION); + for (int k = 0; k < questionNodeList.getLength(); k++) { + // Get the attributes for this question + NamedNodeMap questionNamedNode = questionNodeList.item(k).getAttributes(); + + // Create the question, and add attributes from the node + QaWizardQuestion question = new QaWizardQuestion(); + question.setQuestion(questionNamedNode.getNamedItem(ATTR_QUESTION).getNodeValue()); + + if (questionNamedNode.getNamedItem(ATTR_UID).getNodeValue() != null + && !questionNamedNode.getNamedItem(ATTR_UID).getNodeValue().equals(NULL)) { + question.setUid(Long.parseLong(questionNamedNode.getNamedItem(ATTR_UID).getNodeValue())); + } + + // add the question to the parent cognitive skill + skill.getQuestions().add(question); + } + } + newCategories.add(category); + } + + } catch (ParserConfigurationException e) { + logger.error("Could not parse wizard serialise xml", e); + } catch (SAXException e) { + logger.error("Could not parse wizard serialise xml", e); + } catch (IOException e) { + logger.error("Could not parse wizard serialise xml", e); + } + + qaService.saveOrUpdateQaWizardCategories(newCategories); + } + + /** + * Exports the wizard categories list so it can be imported elsewhere The + * export format is the same xml format used by the export ld servlet + * + * @param mapping + * @param form + * @param request + * @param response + * @return + */ + public ActionForward exportWizard(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) throws Exception { + + // set up mdlForumService + if (qaService == null) { + qaService = QaServiceProxy.getQaService(this.getServlet().getServletContext()); + } + + // now start the export + SortedSet exportCategories = new TreeSet(); + for (QaWizardCategory category : getQaWizardCategories()) { + exportCategories.add((QaWizardCategory) category.clone()); + } + + // exporting XML + XStream designXml = new XStream(new SunUnsafeReflectionProvider()); + designXml.addPermission(AnyTypePermission.ANY); + String exportXml = designXml.toXML(exportCategories); + + response.setContentType("application/x-download"); + response.setHeader("Content-Disposition", "attachment;filename=" + FILE_EXPORT); + OutputStream out = null; + try { + out = response.getOutputStream(); + out.write(exportXml.getBytes()); + response.setContentLength(exportXml.getBytes().length); + out.flush(); + } catch (Exception e) { + log.error("Exception occured writing out file:" + e.getMessage()); + throw new ExportToolContentException(e); + } finally { + try { + if (out != null) { + out.close(); + } + } catch (Exception e) { + log.error("Error Closing file. File already written out - no exception being thrown.", e); + } + } + + return null; + } + + /** + * Imports the wizard model from an xml file and replaces the current model + * First, saves the configurations, then performs the import using xstream + * + * @param mapping + * @param form + * @param request + * @param response + * @return + */ + @SuppressWarnings("unchecked") + public ActionForward importWizard(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) { + QaAdminForm adminForm = (QaAdminForm) form; + + if (qaService == null) { + qaService = QaServiceProxy.getQaService(this.getServlet().getServletContext()); + } + + // First save the config items + QaConfigItem enableQaWizard = qaService.getConfigItem(QaConfigItem.KEY_ENABLE_QAWIZARD); + + if (adminForm.getQaWizardEnabled() != null && adminForm.getQaWizardEnabled()) { + enableQaWizard.setConfigValue(QaAdminForm.TRUE); + + // get the wizard content and save + if (adminForm.getSerialiseXML() != null && !adminForm.getSerialiseXML().trim().equals("")) { + updateWizardFromXML(adminForm.getSerialiseXML().trim()); + } + + // remove any wizard items that were removed + removeWizardItems(adminForm.getDeleteCategoriesCSV(), adminForm.getDeleteSkillsCSV(), + adminForm.getDeleteQuestionsCSV()); + } else { + enableQaWizard.setConfigValue(QaAdminForm.FALSE); + } + qaService.saveOrUpdateConfigItem(enableQaWizard); + + // Now perform the import + try { + String xml = new String(adminForm.getImportFile().getFileData()); + XStream conversionXml = new XStream(new SunUnsafeReflectionProvider()); + conversionXml.addPermission(AnyTypePermission.ANY); + SortedSet exportCategories = (SortedSet) conversionXml.fromXML(xml); + + qaService.deleteAllWizardCategories(); + qaService.saveOrUpdateQaWizardCategories(exportCategories); + } catch (Exception e) { + logger.error("Failed to import wizard model", e); + request.setAttribute("error", true); + request.setAttribute("errorKey", "wizard.import.error"); + request.setAttribute(ATTR_CATEGORIES, getQaWizardCategories()); + return mapping.findForward("config"); + } + + request.setAttribute(ATTR_CATEGORIES, getQaWizardCategories()); + request.setAttribute("savedSuccess", true); + return mapping.findForward("config"); + + } + +} Index: lams_tool_laqa/src/java/org/lamsfoundation/lams/tool/qa/web/action/QaAuthoringConditionAction.java =================================================================== diff -u --- lams_tool_laqa/src/java/org/lamsfoundation/lams/tool/qa/web/action/QaAuthoringConditionAction.java (revision 0) +++ lams_tool_laqa/src/java/org/lamsfoundation/lams/tool/qa/web/action/QaAuthoringConditionAction.java (revision 32eb376c59d7c17cfa9d51cac14c00aae8cf44ff) @@ -0,0 +1,490 @@ +/**************************************************************** + * Copyright (C) 2005 LAMS Foundation (http://lamsfoundation.org) + * ============================================================= + * License Information: http://lamsfoundation.org/licensing/lams/2.0/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2.0 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 * USA + * + * http://www.gnu.org/licenses/gpl.txt + * **************************************************************** + */ + + +package org.lamsfoundation.lams.tool.qa.web.action; + +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.List; +import java.util.SortedSet; +import java.util.TreeSet; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang.math.NumberUtils; +import org.apache.struts.action.Action; +import org.apache.struts.action.ActionErrors; +import org.apache.struts.action.ActionForm; +import org.apache.struts.action.ActionForward; +import org.apache.struts.action.ActionMapping; +import org.apache.struts.action.ActionMessage; +import org.apache.struts.action.ActionMessages; +import org.apache.struts.util.LabelValueBean; +import org.lamsfoundation.lams.learningdesign.TextSearchConditionComparator; +import org.lamsfoundation.lams.tool.qa.QaAppConstants; +import org.lamsfoundation.lams.tool.qa.QaCondition; +import org.lamsfoundation.lams.tool.qa.dto.QaQuestionDTO; +import org.lamsfoundation.lams.tool.qa.service.IQaService; +import org.lamsfoundation.lams.tool.qa.service.QaServiceProxy; +import org.lamsfoundation.lams.tool.qa.web.form.QaConditionForm; +import org.lamsfoundation.lams.util.WebUtil; +import org.lamsfoundation.lams.web.util.SessionMap; +import org.springframework.web.context.WebApplicationContext; +import org.springframework.web.context.support.WebApplicationContextUtils; + +/** + * Auxiliary action in author mode. It contains operations with QaCondition. The + * rest of operations are located in QaAction action. + * + * @author Marcin Cieslak + * @see org.lamsfoundation.lams.tool.qa.web.action.QaAction + */ +public class QaAuthoringConditionAction extends Action { + + @Override + public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) throws Exception { + + String param = mapping.getParameter(); + + if (param.equals("newConditionInit")) { + return newConditionInit(mapping, form, request, response); + } + if (param.equals("editCondition")) { + return editCondition(mapping, form, request, response); + } + if (param.equals("saveOrUpdateCondition")) { + return saveOrUpdateCondition(mapping, form, request, response); + } + if (param.equals("removeCondition")) { + return removeCondition(mapping, form, request, response); + } + if (param.equals("upCondition")) { + return upCondition(mapping, form, request, response); + } + if (param.equals("downCondition")) { + return downCondition(mapping, form, request, response); + } + return null; + } + + /** + * Display empty page for a new condition. + * + * @param mapping + * @param form + * @param request + * @param response + * @return + */ + private ActionForward newConditionInit(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) { + + populateFormWithPossibleItems(form, request); + ((QaConditionForm) form).setOrderId(-1); + return mapping.findForward("addcondition"); + } + + /** + * Display edit page for an existing condition. + * + * @param mapping + * @param form + * @param request + * @param response + * @return + */ + private ActionForward editCondition(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) { + + QaConditionForm qaConditionForm = (QaConditionForm) form; + String sessionMapID = qaConditionForm.getSessionMapID(); + SessionMap sessionMap = (SessionMap) request.getSession().getAttribute(sessionMapID); + + int orderId = NumberUtils.stringToInt(request.getParameter(QaAppConstants.PARAM_ORDER_ID), -1); + QaCondition condition = null; + if (orderId != -1) { + SortedSet conditionSet = getQaConditionSet(sessionMap); + List conditionList = new ArrayList(conditionSet); + condition = conditionList.get(orderId); + if (condition != null) { + populateConditionToForm(orderId, condition, qaConditionForm, request); + } + } + + populateFormWithPossibleItems(form, request); + return condition == null ? null : mapping.findForward("addcondition"); + } + + /** + * This method will get necessary information from condition form and save + * or update into HttpSession condition list. Notice, this + * save is not persist them into database, just save + * HttpSession temporarily. Only they will be persist when + * the entire authoring page is being persisted. + * + * @param mapping + * @param form + * @param request + * @param response + * @return + * @throws ServletException + */ + private ActionForward saveOrUpdateCondition(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) { + + QaConditionForm conditionForm = (QaConditionForm) form; + ActionErrors errors = validateQaCondition(conditionForm, request); + + if (!errors.isEmpty()) { + populateFormWithPossibleItems(form, request); + this.addErrors(request, errors); + return mapping.findForward("addcondition"); + } + + try { + extractFormToQaCondition(request, conditionForm); + } catch (Exception e) { + + errors.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage("error.condition", e.getMessage())); + if (!errors.isEmpty()) { + populateFormWithPossibleItems(form, request); + this.addErrors(request, errors); + return mapping.findForward("addcondition"); + } + } + + request.setAttribute(QaAppConstants.ATTR_SESSION_MAP_ID, conditionForm.getSessionMapID()); + + return mapping.findForward(QaAppConstants.SUCCESS); + } + + /** + * Remove condition from HttpSession list and update page display. As + * authoring rule, all persist only happen when user submit whole page. So + * this remove is just impact HttpSession values. + * + * @param mapping + * @param form + * @param request + * @param response + * @return + */ + private ActionForward removeCondition(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) { + + // get back sessionMAP + String sessionMapID = WebUtil.readStrParam(request, QaAppConstants.ATTR_SESSION_MAP_ID); + SessionMap sessionMap = (SessionMap) request.getSession().getAttribute(sessionMapID); + + int orderId = NumberUtils.stringToInt(request.getParameter(QaAppConstants.PARAM_ORDER_ID), -1); + if (orderId != -1) { + SortedSet conditionSet = getQaConditionSet(sessionMap); + List conditionList = new ArrayList(conditionSet); + QaCondition condition = conditionList.remove(orderId); + for (QaCondition otherCondition : conditionSet) { + if (otherCondition.getOrderId() > orderId) { + otherCondition.setOrderId(otherCondition.getOrderId() - 1); + } + } + conditionSet.clear(); + conditionSet.addAll(conditionList); + // add to delList + List deletedList = getDeletedQaConditionList(sessionMap); + deletedList.add(condition); + } + + request.setAttribute(QaAppConstants.ATTR_SESSION_MAP_ID, sessionMapID); + return mapping.findForward(QaAppConstants.SUCCESS); + } + + /** + * Move up current item. + * + * @param mapping + * @param form + * @param request + * @param response + * @return + */ + private ActionForward upCondition(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) { + return switchItem(mapping, request, true); + } + + /** + * Move down current item. + * + * @param mapping + * @param form + * @param request + * @param response + * @return + */ + private ActionForward downCondition(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) { + return switchItem(mapping, request, false); + } + + private ActionForward switchItem(ActionMapping mapping, HttpServletRequest request, boolean up) { + // get back sessionMAP + String sessionMapID = WebUtil.readStrParam(request, QaAppConstants.ATTR_SESSION_MAP_ID); + SessionMap sessionMap = (SessionMap) request.getSession().getAttribute(sessionMapID); + + int orderId = NumberUtils.stringToInt(request.getParameter(QaAppConstants.PARAM_ORDER_ID), -1); + if (orderId != -1) { + SortedSet conditionSet = getQaConditionSet(sessionMap); + List conditionList = new ArrayList(conditionSet); + // get current and the target item, and switch their sequnece + QaCondition condition = conditionList.get(orderId); + QaCondition repCondition; + if (up) { + repCondition = conditionList.get(--orderId); + } else { + repCondition = conditionList.get(++orderId); + } + int upSeqId = repCondition.getOrderId(); + repCondition.setOrderId(condition.getOrderId()); + condition.setOrderId(upSeqId); + + // put back list, it will be sorted again + conditionSet.clear(); + conditionSet.addAll(conditionList); + } + + request.setAttribute(QaAppConstants.ATTR_SESSION_MAP_ID, sessionMapID); + return mapping.findForward(QaAppConstants.SUCCESS); + } + + // ************************************************************************************* + // Private methods for internal needs + // ************************************************************************************* + /** + * Return QaService bean. + */ + private IQaService getQaService() { + WebApplicationContext wac = WebApplicationContextUtils + .getRequiredWebApplicationContext(getServlet().getServletContext()); + return QaServiceProxy.getQaService(getServlet().getServletContext()); + } + + /** + * List save current taskList items. + * + * @param request + * @return + */ + private SortedSet getQaConditionSet(SessionMap sessionMap) { + SortedSet list = (SortedSet) sessionMap.get(QaAppConstants.ATTR_CONDITION_SET); + if (list == null) { + list = new TreeSet(new TextSearchConditionComparator()); + sessionMap.put(QaAppConstants.ATTR_CONDITION_SET, list); + } + return list; + } + + /** + * List save current taskList items. + * + * @param request + * @return + */ + private List getQuestionList(SessionMap sessionMap) { + List list = (List) sessionMap.get(QaAppConstants.LIST_QUESTION_DTOS); + if (list == null) { + list = new LinkedList(); + sessionMap.put(QaAppConstants.LIST_QUESTION_DTOS, list); + } + return list; + } + + /** + * Get the deleted condition list, which could be persisted or non-persisted + * items. + * + * @param request + * @return + */ + private List getDeletedQaConditionList(SessionMap sessionMap) { + return getListFromSession(sessionMap, QaAppConstants.ATTR_DELETED_CONDITION_LIST); + } + + /** + * Get java.util.List from HttpSession by given name. + * + * @param request + * @param name + * @return + */ + private List getListFromSession(SessionMap sessionMap, String name) { + List list = (List) sessionMap.get(name); + if (list == null) { + list = new ArrayList(); + sessionMap.put(name, list); + } + return list; + } + + /** + * This method will populate condition information to its form for edit use. + * + * @param orderId + * @param condition + * @param form + * @param request + */ + private void populateConditionToForm(int orderId, QaCondition condition, QaConditionForm form, + HttpServletRequest request) { + form.populateForm(condition); + if (orderId >= 0) { + form.setOrderId(orderId + 1); + } + } + + /** + * This method will populate questions to choose to the form for edit use. + * + * @param sequenceId + * @param condition + * @param form + * @param request + */ + private void populateFormWithPossibleItems(ActionForm form, HttpServletRequest request) { + QaConditionForm conditionForm = (QaConditionForm) form; + // get back sessionMAP + String sessionMapID = conditionForm.getSessionMapID(); + SessionMap sessionMap = (SessionMap) request.getSession().getAttribute(sessionMapID); + + List questions = getQuestionList(sessionMap); + + // Initialise the LabelValueBeans in the possibleOptions array. + LabelValueBean[] lvBeans = new LabelValueBean[questions.size()]; + + int i = 0; + for (QaQuestionDTO question : questions) { + String nonHTMLQuestion = question.getQuestion(); + if (nonHTMLQuestion != null) { + nonHTMLQuestion = WebUtil.removeHTMLtags(nonHTMLQuestion); + // we don't want to cite the whole question, so we just leave some first characters; it should be enough + // to recognise the question by a teacher + if (nonHTMLQuestion.length() > QaAppConstants.QUESTION_CUTOFF_INDEX) { + nonHTMLQuestion = nonHTMLQuestion.substring(0, QaAppConstants.QUESTION_CUTOFF_INDEX) + "..."; + } + } + lvBeans[i++] = new LabelValueBean(nonHTMLQuestion, new Integer(question.getDisplayOrder()).toString()); + } + conditionForm.setPossibleItems(lvBeans); + } + + /** + * Extract form content to QaCondition. + * + * @param request + * @param form + * @throws QaException + */ + private void extractFormToQaCondition(HttpServletRequest request, QaConditionForm form) throws Exception { + + SessionMap sessionMap = (SessionMap) request.getSession().getAttribute(form.getSessionMapID()); + // check whether it is "edit(old item)" or "add(new item)" + SortedSet conditionSet = getQaConditionSet(sessionMap); + int orderId = form.getOrderId(); + QaCondition condition = null; + + if (orderId == -1) { // add + String properConditionName = getQaService().createConditionName(conditionSet); + condition = form.extractCondition(); + condition.setName(properConditionName); + int maxOrderId = 1; + if (conditionSet != null && conditionSet.size() > 0) { + QaCondition last = conditionSet.last(); + maxOrderId = last.getOrderId() + 1; + } + condition.setOrderId(maxOrderId); + conditionSet.add(condition); + } else { // edit + List conditionList = new ArrayList(conditionSet); + condition = conditionList.get(orderId - 1); + form.extractCondition(condition); + } + + Integer[] selectedItems = form.getSelectedItems(); + List questions = getQuestionList(sessionMap); + + condition.temporaryQuestionDTOSet.clear(); + for (Integer selectedItem : selectedItems) { + for (QaQuestionDTO question : questions) { + if (selectedItem.equals(new Integer(question.getDisplayOrder()))) { + condition.temporaryQuestionDTOSet.add(question); + } + } + } + + } + + /** + * Validate QaCondition + * + * @param conditionForm + * @return + */ + private ActionErrors validateQaCondition(QaConditionForm conditionForm, HttpServletRequest request) { + ActionErrors errors = new ActionErrors(); + + String formConditionName = conditionForm.getDisplayName(); + if (StringUtils.isBlank(formConditionName)) { + + errors.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage("error.condition.name.blank")); + } else { + + Integer formConditionOrderId = conditionForm.getOrderId(); + + String sessionMapID = conditionForm.getSessionMapID(); + SessionMap sessionMap = (SessionMap) request.getSession().getAttribute(sessionMapID); + SortedSet conditionSet = getQaConditionSet(sessionMap); + for (QaCondition condition : conditionSet) { + if (formConditionName.equals(condition.getDisplayName()) + && !formConditionOrderId.equals(condition.getOrderId())) { + + errors.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage("error.condition.duplicated.name")); + break; + } + } + } + + // should be selected at least one question + Integer[] selectedItems = conditionForm.getSelectedItems(); + if (selectedItems == null || selectedItems.length == 0) { + errors.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage("error.condition.no.questions.selected")); + } + + return errors; + } + + private ActionMessages validate(QaConditionForm form, ActionMapping mapping, HttpServletRequest request) { + return new ActionMessages(); + } +} \ No newline at end of file Index: lams_tool_laqa/src/java/org/lamsfoundation/lams/tool/qa/web/action/QaLearningAction.java =================================================================== diff -u --- lams_tool_laqa/src/java/org/lamsfoundation/lams/tool/qa/web/action/QaLearningAction.java (revision 0) +++ lams_tool_laqa/src/java/org/lamsfoundation/lams/tool/qa/web/action/QaLearningAction.java (revision 32eb376c59d7c17cfa9d51cac14c00aae8cf44ff) @@ -0,0 +1,1202 @@ +/*************************************************************************** +Copyright (C) 2005 LAMS Foundation (http://lamsfoundation.org) +License Information: http://lamsfoundation.org/licensing/lams/2.0/ + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License version 2 as +published by the Free Software Foundation. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 +USA + +http://www.gnu.org/licenses/gpl.txt + * ***********************************************************************/ + + +package org.lamsfoundation.lams.tool.qa.web.action; + +import java.io.IOException; +import java.util.Date; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.TimeZone; +import java.util.TreeMap; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; + +import org.apache.commons.lang.StringEscapeUtils; +import org.apache.commons.lang.StringUtils; +import org.apache.log4j.Logger; +import org.apache.struts.Globals; +import org.apache.struts.action.ActionForm; +import org.apache.struts.action.ActionForward; +import org.apache.struts.action.ActionMapping; +import org.apache.struts.action.ActionMessage; +import org.apache.struts.action.ActionMessages; +import org.apache.struts.action.ActionRedirect; +import org.apache.tomcat.util.json.JSONArray; +import org.apache.tomcat.util.json.JSONException; +import org.apache.tomcat.util.json.JSONObject; +import org.lamsfoundation.lams.notebook.model.NotebookEntry; +import org.lamsfoundation.lams.notebook.service.CoreNotebookConstants; +import org.lamsfoundation.lams.rating.dto.ItemRatingCriteriaDTO; +import org.lamsfoundation.lams.rating.dto.ItemRatingDTO; +import org.lamsfoundation.lams.rating.dto.RatingCommentDTO; +import org.lamsfoundation.lams.rating.model.LearnerItemRatingCriteria; +import org.lamsfoundation.lams.tool.exception.ToolException; +import org.lamsfoundation.lams.tool.qa.QaAppConstants; +import org.lamsfoundation.lams.tool.qa.QaContent; +import org.lamsfoundation.lams.tool.qa.QaQueContent; +import org.lamsfoundation.lams.tool.qa.QaQueUsr; +import org.lamsfoundation.lams.tool.qa.QaSession; +import org.lamsfoundation.lams.tool.qa.QaUsrResp; +import org.lamsfoundation.lams.tool.qa.dto.GeneralLearnerFlowDTO; +import org.lamsfoundation.lams.tool.qa.dto.QaQuestionDTO; +import org.lamsfoundation.lams.tool.qa.service.IQaService; +import org.lamsfoundation.lams.tool.qa.service.QaServiceProxy; +import org.lamsfoundation.lams.tool.qa.util.LearningUtil; +import org.lamsfoundation.lams.tool.qa.util.QaComparator; +import org.lamsfoundation.lams.tool.qa.util.QaStringComparator; +import org.lamsfoundation.lams.tool.qa.web.form.QaLearningForm; +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; +import org.lamsfoundation.lams.web.util.AttributeNames; +import org.lamsfoundation.lams.web.util.SessionMap; + +/** + * @author Ozgur Demirtas + */ +public class QaLearningAction extends LamsDispatchAction implements QaAppConstants { + private static Logger logger = Logger.getLogger(QaLearningAction.class.getName()); + + private static IQaService qaService; + + @Override + public ActionForward unspecified(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) throws IOException, ServletException, ToolException { + QaLearningAction.logger.warn("dispatching unspecified..."); + return null; + } + + /** + * submits users responses + * + * @param mapping + * @param form + * @param request + * @param response + * @return + * @throws IOException + * @throws ServletException + */ + public ActionForward submitAnswersContent(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) throws IOException, ServletException { + initializeQAService(); + QaLearningForm qaLearningForm = (QaLearningForm) form; + + LearningUtil.saveFormRequestData(request, qaLearningForm); + String toolSessionID = request.getParameter(AttributeNames.PARAM_TOOL_SESSION_ID); + + QaSession qaSession = QaLearningAction.qaService.getSessionById(new Long(toolSessionID).longValue()); + QaContent qaContent = qaSession.getQaContent(); + + QaQueUsr qaQueUsr = getCurrentUser(toolSessionID); + //prohibit users from submitting answers after response is finalized but Resubmit button is not pressed (e.g. using 2 browsers) + if (qaQueUsr.isResponseFinalized()) { + ActionRedirect redirect = new ActionRedirect(mapping.findForwardConfig("learningStarter")); + redirect.addParameter(AttributeNames.PARAM_TOOL_SESSION_ID, toolSessionID); + redirect.addParameter(QaAppConstants.MODE, "learner"); + return redirect; + } + + GeneralLearnerFlowDTO generalLearnerFlowDTO = LearningUtil.buildGeneralLearnerFlowDTO(qaService, qaContent); + + String totalQuestionCount = generalLearnerFlowDTO.getTotalQuestionCount().toString(); + int intTotalQuestionCount = new Integer(totalQuestionCount).intValue(); + + String questionListingMode = generalLearnerFlowDTO.getQuestionListingMode(); + + Map mapAnswers = new TreeMap(new QaComparator()); + Map mapAnswersPresentable = new TreeMap(new QaComparator()); + + String forwardName = QaAppConstants.INDIVIDUAL_LEARNER_RESULTS; + ActionMessages errors = new ActionMessages(); + + String httpSessionID = qaLearningForm.getHttpSessionID(); + SessionMap sessionMap = (SessionMap) request.getSession() + .getAttribute(httpSessionID); + + /* if the listing mode is QUESTION_LISTING_MODE_COMBINED populate the answers here */ + if (questionListingMode.equalsIgnoreCase(QaAppConstants.QUESTION_LISTING_MODE_COMBINED)) { + + for (int questionIndex = QaAppConstants.INITIAL_QUESTION_COUNT + .intValue(); questionIndex <= intTotalQuestionCount; questionIndex++) { + // TestHarness can not send "answerX" fields, so stick to the original, unfiltered field + boolean isTestHarness = Boolean.valueOf(request.getParameter("testHarness")); + String answerParamName = "answer" + questionIndex + (isTestHarness ? "__textarea" : ""); + String answer = request.getParameter(answerParamName); + + 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); + + // store + if (errors.isEmpty()) { + QaLearningAction.qaService.updateResponseWithNewAnswer(answer, toolSessionID, + new Long(questionIndex), false); + } + } + + } else { + 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); + } + + //finalize response so user won't need to edit his answers again, if coming back to the activity after leaving activity at this point + if (errors.isEmpty()) { + qaQueUsr.setResponseFinalized(true); + QaLearningAction.qaService.updateUser(qaQueUsr); + + //in case of errors - prompt learner to enter answers again + } else { + saveErrors(request, errors); + forwardName = QaAppConstants.LOAD_LEARNER; + } + + generalLearnerFlowDTO.setMapAnswers(mapAnswers); + generalLearnerFlowDTO.setMapAnswersPresentable(mapAnswersPresentable); + + /* mapAnswers will be used in the viewAllAnswers screen */ + if (sessionMap == null) { + sessionMap = new SessionMap(); + } + + sessionMap.put(QaAppConstants.MAP_ALL_RESULTS_KEY, mapAnswers); + request.getSession().setAttribute(sessionMap.getSessionID(), sessionMap); + qaLearningForm.setHttpSessionID(sessionMap.getSessionID()); + qaLearningForm.resetAll(); + generalLearnerFlowDTO.setHttpSessionID(sessionMap.getSessionID()); + + boolean lockWhenFinished = qaContent.isLockWhenFinished(); + generalLearnerFlowDTO.setLockWhenFinished(new Boolean(lockWhenFinished).toString()); + generalLearnerFlowDTO.setNoReeditAllowed(qaContent.isNoReeditAllowed()); + generalLearnerFlowDTO.setReflection(new Boolean(qaContent.isReflect()).toString()); + + request.setAttribute(QaAppConstants.GENERAL_LEARNER_FLOW_DTO, generalLearnerFlowDTO); + + // notify teachers on response submit + if (errors.isEmpty() && qaContent.isNotifyTeachersOnResponseSubmit()) { + qaService.notifyTeachersOnResponseSubmit(new Long(toolSessionID)); + } + + return (mapping.findForward(forwardName)); + } + + public ActionForward checkLeaderProgress(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) throws JSONException, IOException { + + Long toolSessionId = WebUtil.readLongParam(request, AttributeNames.PARAM_TOOL_SESSION_ID); + + QaSession session = qaService.getSessionById(toolSessionId); + QaQueUsr leader = session.getGroupLeader(); + + boolean isLeaderResponseFinalized = leader.isResponseFinalized(); + + JSONObject JSONObject = new JSONObject(); + JSONObject.put("isLeaderResponseFinalized", isLeaderResponseFinalized); + response.setContentType("application/x-json;charset=utf-8"); + response.getWriter().print(JSONObject); + return null; + } + + /** + * auto saves responses + * + * @param mapping + * @param form + * @param request + * @param response + * @return + * @throws IOException + * @throws ServletException + */ + public ActionForward autoSaveAnswers(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) throws IOException, ServletException { + initializeQAService(); + QaLearningForm qaLearningForm = (QaLearningForm) form; + String toolSessionID = request.getParameter(AttributeNames.PARAM_TOOL_SESSION_ID); + + QaQueUsr qaQueUsr = getCurrentUser(toolSessionID); + //prohibit users from autosaving answers after response is finalized but Resubmit button is not pressed (e.g. using 2 browsers) + if (qaQueUsr.isResponseFinalized()) { + return null; + } + + LearningUtil.saveFormRequestData(request, qaLearningForm); + QaSession qaSession = QaLearningAction.qaService.getSessionById(new Long(toolSessionID).longValue()); + QaContent qaContent = qaSession.getQaContent(); + int intTotalQuestionCount = qaContent.getQaQueContents().size(); + + if (!qaContent.isQuestionsSequenced()) { + + for (int questionIndex = QaAppConstants.INITIAL_QUESTION_COUNT + .intValue(); questionIndex <= intTotalQuestionCount; questionIndex++) { + String newAnswer = request.getParameter("answer" + questionIndex); + QaLearningAction.qaService.updateResponseWithNewAnswer(newAnswer, toolSessionID, + new Long(questionIndex), true); + } + + } else { + String currentQuestionIndex = qaLearningForm.getCurrentQuestionIndex(); + String newAnswer = qaLearningForm.getAnswer(); + QaQueContent currentQuestion = QaLearningAction.qaService + .getQuestionByContentAndDisplayOrder(new Long(currentQuestionIndex), qaContent.getUid()); + + boolean isRequiredQuestionMissed = currentQuestion.isRequired() && isEmpty(newAnswer); + if (!isRequiredQuestionMissed) { + QaLearningAction.qaService.updateResponseWithNewAnswer(newAnswer, toolSessionID, + new Long(currentQuestionIndex), true); + } + } + return null; + } + + /** + * enables retaking the activity + * + * @param mapping + * @param form + * @param request + * @param response + * @return + * @throws IOException + * @throws ServletException + */ + public ActionForward redoQuestions(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) throws IOException, ServletException { + initializeQAService(); + QaLearningForm qaLearningForm = (QaLearningForm) form; + + LearningUtil.saveFormRequestData(request, qaLearningForm); + + String toolSessionID = request.getParameter(AttributeNames.PARAM_TOOL_SESSION_ID); + QaSession qaSession = QaLearningAction.qaService.getSessionById(new Long(toolSessionID).longValue()); + QaContent qaContent = qaSession.getQaContent(); + + GeneralLearnerFlowDTO generalLearnerFlowDTO = LearningUtil.buildGeneralLearnerFlowDTO(qaService, qaContent); + + qaLearningForm.setCurrentQuestionIndex(new Integer(1).toString()); + + String httpSessionID = qaLearningForm.getHttpSessionID(); + + SessionMap sessionMap = (SessionMap) request.getSession() + .getAttribute(httpSessionID); + request.getSession().setAttribute(sessionMap.getSessionID(), sessionMap); + qaLearningForm.setHttpSessionID(sessionMap.getSessionID()); + generalLearnerFlowDTO.setHttpSessionID(sessionMap.getSessionID()); + generalLearnerFlowDTO.setToolContentID(qaContent.getQaContentId().toString()); + + // create mapQuestions + Map mapQuestions = generalLearnerFlowDTO.getMapQuestionContentLearner(); + generalLearnerFlowDTO.setMapQuestions(mapQuestions); + generalLearnerFlowDTO.setTotalQuestionCount(new Integer(mapQuestions.size())); + generalLearnerFlowDTO.setRemainingQuestionCount(new Integer(mapQuestions.size()).toString()); + qaLearningForm.setTotalQuestionCount(new Integer(mapQuestions.size()).toString()); + + //in order to track whether redo button is pressed store this info + QaQueUsr qaQueUsr = getCurrentUser(toolSessionID); + qaQueUsr.setResponseFinalized(false); + QaLearningAction.qaService.updateUser(qaQueUsr); + + // populate answers + LearningUtil.populateAnswers(sessionMap, qaContent, qaQueUsr, mapQuestions, generalLearnerFlowDTO, + QaLearningAction.qaService); + + request.setAttribute(QaAppConstants.GENERAL_LEARNER_FLOW_DTO, generalLearnerFlowDTO); + qaLearningForm.resetAll(); + return (mapping.findForward(QaAppConstants.LOAD_LEARNER)); + } + + /** + * Stores all results and moves onto the next step. If view other users answers = true, then goes to the view all + * answers screen, otherwise goes straight to the reflection screen (if any). + * + * @return Learner Report for a session + * @throws IOException + * @throws ServletException + */ + public ActionForward storeAllResults(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) throws IOException, ServletException { + + initializeQAService(); + QaLearningForm qaLearningForm = (QaLearningForm) form; + LearningUtil.saveFormRequestData(request, qaLearningForm); + + String toolSessionID = request.getParameter(AttributeNames.PARAM_TOOL_SESSION_ID); + String userID = request.getParameter("userID"); + QaQueUsr user = qaService.getUserByIdAndSession(new Long(userID), new Long(toolSessionID)); + QaSession qaSession = QaLearningAction.qaService.getSessionById(new Long(toolSessionID).longValue()); + QaContent qaContent = qaSession.getQaContent(); + + // LearningUtil.storeResponses(mapAnswers, qaService, toolContentID, new Long(toolSessionID)); + + qaLearningForm.resetUserActions(); + qaLearningForm.setSubmitAnswersContent(null); + + if (qaContent.isShowOtherAnswers()) { + GeneralLearnerFlowDTO generalLearnerFlowDTO = LearningUtil.buildGeneralLearnerFlowDTO(qaService, qaContent); + String httpSessionID = qaLearningForm.getHttpSessionID(); + generalLearnerFlowDTO.setHttpSessionID(httpSessionID); + + /** Set up the data for the view all answers screen */ + QaLearningAction.refreshSummaryData(request, qaContent, qaSession, QaLearningAction.qaService, httpSessionID, user, + generalLearnerFlowDTO); + + generalLearnerFlowDTO.setRequestLearningReport(new Boolean(true).toString()); + generalLearnerFlowDTO.setRequestLearningReportProgress(new Boolean(false).toString()); + + generalLearnerFlowDTO.setReflection(new Boolean(qaContent.isReflect()).toString()); + + qaLearningForm.resetAll(); + + boolean lockWhenFinished = qaContent.isLockWhenFinished(); + generalLearnerFlowDTO.setLockWhenFinished(new Boolean(lockWhenFinished).toString()); + generalLearnerFlowDTO.setNoReeditAllowed(qaContent.isNoReeditAllowed()); + + boolean useSelectLeaderToolOuput = qaContent.isUseSelectLeaderToolOuput(); + generalLearnerFlowDTO.setUseSelectLeaderToolOuput(new Boolean(useSelectLeaderToolOuput).toString()); + + boolean allowRichEditor = qaContent.isAllowRichEditor(); + generalLearnerFlowDTO.setAllowRichEditor(new Boolean(allowRichEditor).toString()); + generalLearnerFlowDTO.setUserUid(user.getQueUsrId().toString()); + + boolean usernameVisible = qaContent.isUsernameVisible(); + generalLearnerFlowDTO.setUserNameVisible(new Boolean(usernameVisible).toString()); + + NotebookEntry notebookEntry = QaLearningAction.qaService.getEntry(new Long(toolSessionID), + CoreNotebookConstants.NOTEBOOK_TOOL, QaAppConstants.MY_SIGNATURE, new Integer(userID)); + + if (notebookEntry != null) { + // String notebookEntryPresentable=QaUtils.replaceNewLines(notebookEntry.getEntry()); + String notebookEntryPresentable = notebookEntry.getEntry(); + qaLearningForm.setEntryText(notebookEntryPresentable); + } + + request.setAttribute(QaAppConstants.GENERAL_LEARNER_FLOW_DTO, generalLearnerFlowDTO); + return (mapping.findForward(QaAppConstants.LEARNER_REP)); + + } else if (qaContent.isReflect()) { + return forwardtoReflection(mapping, request, qaContent, toolSessionID, userID, qaLearningForm); + + } else { + return endLearning(mapping, qaLearningForm, request, response); + } + } + + /** + * @param mapping + * @param form + * @param request + * @param response + * @return + * @throws IOException + * @throws ServletException + */ + public ActionForward refreshAllResults(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) throws IOException, ServletException { + initializeQAService(); + QaLearningForm qaLearningForm = (QaLearningForm) form; + + LearningUtil.saveFormRequestData(request, qaLearningForm); + + String toolSessionID = request.getParameter(AttributeNames.PARAM_TOOL_SESSION_ID); + qaLearningForm.setToolSessionID(toolSessionID); + + String userID = request.getParameter("userID"); + QaQueUsr user = qaService.getUserByIdAndSession(new Long(userID), new Long(toolSessionID)); + + QaSession qaSession = QaLearningAction.qaService.getSessionById(new Long(toolSessionID).longValue()); + + QaContent qaContent = qaSession.getQaContent(); + + GeneralLearnerFlowDTO generalLearnerFlowDTO = LearningUtil.buildGeneralLearnerFlowDTO(qaService, qaContent); + + String httpSessionID = qaLearningForm.getHttpSessionID(); + qaLearningForm.setHttpSessionID(httpSessionID); + generalLearnerFlowDTO.setHttpSessionID(httpSessionID); + SessionMap sessionMap = (SessionMap) request.getSession() + .getAttribute(httpSessionID); + + /* recreate the users and responses */ + qaLearningForm.resetUserActions(); + qaLearningForm.setSubmitAnswersContent(null); + + QaLearningAction.refreshSummaryData(request, qaContent, qaSession, QaLearningAction.qaService, httpSessionID, user, + generalLearnerFlowDTO); + + generalLearnerFlowDTO.setRequestLearningReport(new Boolean(true).toString()); + generalLearnerFlowDTO.setRequestLearningReportProgress(new Boolean(false).toString()); + + generalLearnerFlowDTO.setReflection(new Boolean(qaContent.isReflect()).toString()); + // generalLearnerFlowDTO.setNotebookEntriesVisible(new Boolean(false).toString()); + + qaLearningForm.resetAll(); + + boolean lockWhenFinished; + boolean noReeditAllowed; + if (sessionMap.get("noRefresh") != null && (boolean) sessionMap.get("noRefresh")) { + lockWhenFinished = true; + noReeditAllowed = true; + } else { + lockWhenFinished = qaContent.isLockWhenFinished(); + noReeditAllowed = qaContent.isNoReeditAllowed(); + } + generalLearnerFlowDTO.setLockWhenFinished(new Boolean(lockWhenFinished).toString()); + generalLearnerFlowDTO.setNoReeditAllowed(noReeditAllowed); + + boolean allowRichEditor = qaContent.isAllowRichEditor(); + generalLearnerFlowDTO.setAllowRichEditor(new Boolean(allowRichEditor).toString()); + + boolean useSelectLeaderToolOuput = qaContent.isUseSelectLeaderToolOuput(); + generalLearnerFlowDTO.setUseSelectLeaderToolOuput(new Boolean(useSelectLeaderToolOuput).toString()); + + QaQueUsr qaQueUsr = getCurrentUser(toolSessionID); + generalLearnerFlowDTO.setUserUid(qaQueUsr.getQueUsrId().toString()); + + boolean usernameVisible = qaContent.isUsernameVisible(); + generalLearnerFlowDTO.setUserNameVisible(new Boolean(usernameVisible).toString()); + + request.setAttribute(QaAppConstants.GENERAL_LEARNER_FLOW_DTO, generalLearnerFlowDTO); + + return (mapping.findForward(QaAppConstants.LEARNER_REP)); + } + + /** + * moves to the next question and modifies the map ActionForward + * + * @param mapping + * @param form + * @param request + * @param response + * @return + * @throws IOException + * @throws ServletException + * @throws ToolException + */ + public ActionForward getNextQuestion(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) throws IOException, ServletException, ToolException { + initializeQAService(); + QaLearningForm qaLearningForm = (QaLearningForm) form; + + LearningUtil.saveFormRequestData(request, qaLearningForm); + + String toolSessionID = request.getParameter(AttributeNames.PARAM_TOOL_SESSION_ID); + qaLearningForm.setToolSessionID(toolSessionID); + String httpSessionID = qaLearningForm.getHttpSessionID(); + qaLearningForm.setHttpSessionID(httpSessionID); + + QaSession qaSession = QaLearningAction.qaService.getSessionById(new Long(toolSessionID).longValue()); + QaContent qaContent = qaSession.getQaContent(); + + QaQueUsr qaQueUsr = getCurrentUser(toolSessionID); + //prohibit users from submitting answers after response is finalized but Resubmit button is not pressed (e.g. using 2 browsers) + if (qaQueUsr.isResponseFinalized()) { + ActionRedirect redirect = new ActionRedirect(mapping.findForwardConfig("learningStarter")); + redirect.addParameter(AttributeNames.PARAM_TOOL_SESSION_ID, toolSessionID); + redirect.addParameter(QaAppConstants.MODE, "learner"); + return redirect; + } + + GeneralLearnerFlowDTO generalLearnerFlowDTO = LearningUtil.buildGeneralLearnerFlowDTO(qaService, qaContent); + + storeSequentialAnswer(qaLearningForm, request, generalLearnerFlowDTO, true); + + qaLearningForm.resetAll(); + return (mapping.findForward(QaAppConstants.LOAD_LEARNER)); + } + + /** + * Get the answer from the form and copy into DTO. Set up the next question. If the current question is required and + * the answer is blank, then just persist the error and don't change questions. + * + * @param form + * @param request + * @param generalLearnerFlowDTO + * @param getNextQuestion + * @return + */ + 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); + if (mapAnswers == null) { + mapAnswers = new TreeMap(new QaComparator()); + } + + String newAnswer = qaLearningForm.getAnswer(); + Map mapSequentialAnswers = (Map) sessionMap + .get(QaAppConstants.MAP_SEQUENTIAL_ANSWERS_KEY); + if (mapSequentialAnswers.size() >= new Integer(currentQuestionIndex).intValue()) { + mapSequentialAnswers.remove(new Long(currentQuestionIndex).toString()); + } + mapSequentialAnswers.put(new Long(currentQuestionIndex).toString(), newAnswer); + mapAnswers.put(currentQuestionIndex, newAnswer); + + int nextQuestionOffset = getNextQuestion ? 1 : -1; + + // 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 (errors.isEmpty()) { + QaLearningAction.qaService.updateResponseWithNewAnswer(newAnswer, qaLearningForm.getToolSessionID(), + new Long(currentQuestionIndex), false); + } else { + saveErrors(request, errors); + nextQuestionOffset = 0; + } + + int intCurrentQuestionIndex = new Integer(currentQuestionIndex).intValue() + nextQuestionOffset; + String currentAnswer = ""; + if (mapAnswers.size() >= intCurrentQuestionIndex) { + currentAnswer = mapAnswers.get(new Long(intCurrentQuestionIndex).toString()); + } + generalLearnerFlowDTO.setCurrentAnswer(currentAnswer); + + // currentQuestionIndex will be: + generalLearnerFlowDTO.setCurrentQuestionIndex(new Integer(intCurrentQuestionIndex)); + + String totalQuestionCount = qaLearningForm.getTotalQuestionCount(); + + int remainingQuestionCount = new Long(totalQuestionCount).intValue() + - new Integer(currentQuestionIndex).intValue() + 1; + String userFeedback = ""; + if (remainingQuestionCount != 0) { + userFeedback = "Remaining question count: " + remainingQuestionCount; + } else { + userFeedback = "End of the questions."; + } + generalLearnerFlowDTO.setUserFeedback(userFeedback); + generalLearnerFlowDTO.setRemainingQuestionCount("" + remainingQuestionCount); + + qaLearningForm.resetUserActions(); /* resets all except submitAnswersContent */ + + sessionMap.put(QaAppConstants.MAP_ALL_RESULTS_KEY, mapAnswers); + sessionMap.put(QaAppConstants.MAP_SEQUENTIAL_ANSWERS_KEY, mapSequentialAnswers); + request.getSession().setAttribute(sessionMap.getSessionID(), sessionMap); + qaLearningForm.setHttpSessionID(sessionMap.getSessionID()); + generalLearnerFlowDTO.setHttpSessionID(sessionMap.getSessionID()); + + request.setAttribute(QaAppConstants.GENERAL_LEARNER_FLOW_DTO, generalLearnerFlowDTO); + + 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. + */ + private boolean isEmpty(String answer) { + if ((answer != null) && ((answer.indexOf(" -1) || (answer.indexOf(" -1))) { + return false; + } else { + return StringUtils.isBlank(WebUtil.removeHTMLtags(answer)); + } + } + + /** + * moves to the previous question and modifies the map ActionForward + * + * @param mapping + * @param form + * @param request + * @param response + * @return + * @throws IOException + * @throws ServletException + * @throws ToolException + */ + public ActionForward getPreviousQuestion(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) throws IOException, ServletException, ToolException { + + initializeQAService(); + QaLearningForm qaLearningForm = (QaLearningForm) form; + LearningUtil.saveFormRequestData(request, qaLearningForm); + + String httpSessionID = qaLearningForm.getHttpSessionID(); + qaLearningForm.setHttpSessionID(httpSessionID); + String toolSessionID = request.getParameter(AttributeNames.PARAM_TOOL_SESSION_ID); + qaLearningForm.setToolSessionID(toolSessionID); + QaSession qaSession = QaLearningAction.qaService.getSessionById(new Long(toolSessionID).longValue()); + QaContent qaContent = qaSession.getQaContent(); + + QaQueUsr qaQueUsr = getCurrentUser(toolSessionID); + //prohibit users from submitting answers after response is finalized but Resubmit button is not pressed (e.g. using 2 browsers) + if (qaQueUsr.isResponseFinalized()) { + ActionRedirect redirect = new ActionRedirect(mapping.findForwardConfig("learningStarter")); + redirect.addParameter(AttributeNames.PARAM_TOOL_SESSION_ID, toolSessionID); + redirect.addParameter(QaAppConstants.MODE, "learner"); + return redirect; + } + + GeneralLearnerFlowDTO generalLearnerFlowDTO = LearningUtil.buildGeneralLearnerFlowDTO(qaService, qaContent); + + storeSequentialAnswer(qaLearningForm, request, generalLearnerFlowDTO, false); + + qaLearningForm.resetAll(); + return (mapping.findForward(QaAppConstants.LOAD_LEARNER)); + } + + /** + * finishes the user's tool activity + * + * @param request + * @param qaService + * @param response + * @throws IOException + * @throws ToolException + */ + public ActionForward endLearning(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) throws IOException, ServletException, ToolException { + initializeQAService(); + QaLearningForm qaLearningForm = (QaLearningForm) form; + + LearningUtil.saveFormRequestData(request, qaLearningForm); + + String toolSessionID = request.getParameter(AttributeNames.PARAM_TOOL_SESSION_ID); + qaLearningForm.setToolSessionID(toolSessionID); + + String userID = request.getParameter("userID"); + qaLearningForm.setUserID(userID); + + QaSession qaSession = QaLearningAction.qaService.getSessionById(new Long(toolSessionID).longValue()); + + QaQueUsr qaQueUsr = QaLearningAction.qaService.getUserByIdAndSession(new Long(userID), + qaSession.getQaSessionId()); + qaQueUsr.setLearnerFinished(true); + QaLearningAction.qaService.updateUser(qaQueUsr); + + /* + * The learner is done with the tool session. The tool needs to clean-up. + */ + HttpSession ss = SessionManager.getSession(); + /* get back login user DTO */ + UserDTO user = (UserDTO) ss.getAttribute(AttributeNames.USER); + + qaSession.setSession_end_date(new Date(System.currentTimeMillis())); + qaSession.setSession_status(QaAppConstants.COMPLETED); + QaLearningAction.qaService.updateSession(qaSession); + + String httpSessionID = qaLearningForm.getHttpSessionID(); + // request.getSession().removeAttribute(httpSessionID); + qaLearningForm.setHttpSessionID(httpSessionID); + + qaLearningForm.resetAll(); + + String nextActivityUrl = QaLearningAction.qaService.leaveToolSession(new Long(toolSessionID), + new Long(user.getUserID().longValue())); + response.sendRedirect(nextActivityUrl); + + return null; + } + + public ActionForward updateReflection(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) throws IOException, ServletException, ToolException { + initializeQAService(); + QaLearningForm qaLearningForm = (QaLearningForm) form; + + LearningUtil.saveFormRequestData(request, qaLearningForm); + + String httpSessionID = qaLearningForm.getHttpSessionID(); + + qaLearningForm.setHttpSessionID(httpSessionID); + + String toolSessionID = request.getParameter(AttributeNames.PARAM_TOOL_SESSION_ID); + qaLearningForm.setToolSessionID(toolSessionID); + + String userID = request.getParameter("userID"); + qaLearningForm.setUserID(userID); + + QaSession qaSession = QaLearningAction.qaService.getSessionById(new Long(toolSessionID).longValue()); + + QaContent qaContent = qaSession.getQaContent(); + + QaQueUsr qaQueUsr = QaLearningAction.qaService.getUserByIdAndSession(new Long(userID), + qaSession.getQaSessionId()); + + String entryText = request.getParameter("entryText"); + qaLearningForm.setEntryText(entryText); + + NotebookEntry notebookEntryLocal = new NotebookEntry(); + notebookEntryLocal.setEntry(entryText); + // notebookEntry.setUser(qaQueUsr); + User user = new User(); + user.setUserId(new Integer(userID)); + notebookEntryLocal.setUser(user); + + QaLearningAction.qaService.updateEntry(notebookEntryLocal); + + GeneralLearnerFlowDTO generalLearnerFlowDTO = LearningUtil.buildGeneralLearnerFlowDTO(qaService, qaContent); + + generalLearnerFlowDTO.setNotebookEntry(entryText); + generalLearnerFlowDTO.setRequestLearningReportProgress(new Boolean(true).toString()); + + QaLearningAction.refreshSummaryData(request, qaContent, qaSession, QaLearningAction.qaService, httpSessionID, qaQueUsr, + generalLearnerFlowDTO); + + boolean isLearnerFinished = qaQueUsr.isLearnerFinished(); + generalLearnerFlowDTO.setRequestLearningReportViewOnly(new Boolean(isLearnerFinished).toString()); + + boolean lockWhenFinished = qaContent.isLockWhenFinished(); + generalLearnerFlowDTO.setLockWhenFinished(new Boolean(lockWhenFinished).toString()); + + boolean allowRichEditor = qaContent.isAllowRichEditor(); + generalLearnerFlowDTO.setAllowRichEditor(new Boolean(allowRichEditor).toString()); + + boolean useSelectLeaderToolOuput = qaContent.isUseSelectLeaderToolOuput(); + generalLearnerFlowDTO.setUseSelectLeaderToolOuput(new Boolean(useSelectLeaderToolOuput).toString()); + + NotebookEntry notebookEntry = QaLearningAction.qaService.getEntry(new Long(toolSessionID), + CoreNotebookConstants.NOTEBOOK_TOOL, QaAppConstants.MY_SIGNATURE, new Integer(userID)); + + if (notebookEntry != null) { + // String notebookEntryPresentable = QaUtils.replaceNewLines(notebookEntry.getEntry()); + qaLearningForm.setEntryText(notebookEntry.getEntry()); + } + + request.setAttribute(QaAppConstants.GENERAL_LEARNER_FLOW_DTO, generalLearnerFlowDTO); + + return (mapping.findForward(QaAppConstants.REVISITED_LEARNER_REP)); + } + + /** + * + * @param mapping + * @param form + * @param request + * @param response + * @return + * @throws IOException + * @throws ServletException + * @throws ToolException + */ + public ActionForward submitReflection(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) throws IOException, ServletException, ToolException { + initializeQAService(); + QaLearningForm qaLearningForm = (QaLearningForm) form; + + LearningUtil.saveFormRequestData(request, qaLearningForm); + + String httpSessionID = qaLearningForm.getHttpSessionID(); + + qaLearningForm.setHttpSessionID(httpSessionID); + + String toolSessionID = request.getParameter(AttributeNames.PARAM_TOOL_SESSION_ID); + qaLearningForm.setToolSessionID(toolSessionID); + + String userID = request.getParameter("userID"); + qaLearningForm.setUserID(userID); + + String reflectionEntry = request.getParameter(QaAppConstants.ENTRY_TEXT); + + QaLearningAction.qaService.createNotebookEntry(new Long(toolSessionID), CoreNotebookConstants.NOTEBOOK_TOOL, + QaAppConstants.MY_SIGNATURE, new Integer(userID), reflectionEntry); + + qaLearningForm.resetUserActions(); /* resets all except submitAnswersContent */ + return endLearning(mapping, form, request, response); + } + + /** + * + * @param mapping + * @param form + * @param request + * @param response + * @return + * @throws IOException + * @throws ServletException + * @throws ToolException + */ + public ActionForward forwardtoReflection(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) throws IOException, ServletException, ToolException { + initializeQAService(); + QaLearningForm qaLearningForm = (QaLearningForm) form; + + String httpSessionID = qaLearningForm.getHttpSessionID(); + + qaLearningForm.setHttpSessionID(httpSessionID); + + String toolSessionID = request.getParameter(AttributeNames.PARAM_TOOL_SESSION_ID); + + QaSession qaSession = QaLearningAction.qaService.getSessionById(new Long(toolSessionID).longValue()); + + QaContent qaContent = qaSession.getQaContent(); + + String userID = request.getParameter("userID"); + qaLearningForm.setUserID(userID); + + return forwardtoReflection(mapping, request, qaContent, toolSessionID, userID, qaLearningForm); + } + + private ActionForward forwardtoReflection(ActionMapping mapping, HttpServletRequest request, QaContent qaContent, + String toolSessionID, String userID, QaLearningForm qaLearningForm) { + + GeneralLearnerFlowDTO generalLearnerFlowDTO = new GeneralLearnerFlowDTO(); + generalLearnerFlowDTO.setActivityTitle(qaContent.getTitle()); + String reflectionSubject = qaContent.getReflectionSubject(); + // reflectionSubject = QaUtils.replaceNewLines(reflectionSubject); + generalLearnerFlowDTO.setReflectionSubject(reflectionSubject); + + // attempt getting notebookEntry + NotebookEntry notebookEntry = QaLearningAction.qaService.getEntry(new Long(toolSessionID), + CoreNotebookConstants.NOTEBOOK_TOOL, QaAppConstants.MY_SIGNATURE, new Integer(userID)); + + if (notebookEntry != null) { + // String notebookEntryPresentable=QaUtils.replaceNewLines(notebookEntry.getEntry()); + String notebookEntryPresentable = notebookEntry.getEntry(); + generalLearnerFlowDTO.setNotebookEntry(notebookEntryPresentable); + qaLearningForm.setEntryText(notebookEntryPresentable); + } + + request.setAttribute(QaAppConstants.GENERAL_LEARNER_FLOW_DTO, generalLearnerFlowDTO); + qaLearningForm.resetUserActions(); /* resets all except submitAnswersContent */ + + qaLearningForm.resetAll(); + return (mapping.findForward(QaAppConstants.NOTEBOOK)); + } + + /** + * populates data for summary screen, view all results screen. + * + * User id is needed if isUserNamesVisible is false && learnerRequest is true, as it is required to work out if the + * data being analysed is the current user. + */ + public static void refreshSummaryData(HttpServletRequest request, QaContent qaContent, QaSession qaSession, IQaService qaService, + String httpSessionID, QaQueUsr user, GeneralLearnerFlowDTO generalLearnerFlowDTO) { + + SessionMap sessionMap = (SessionMap) request.getSession() + .getAttribute(httpSessionID); + Long userId = user.getQueUsrId(); + Set questions = qaContent.getQaQueContents(); + generalLearnerFlowDTO.setQuestions(questions); + generalLearnerFlowDTO.setUserNameVisible(new Boolean(qaContent.isUsernameVisible()).toString()); + + // potentially empty list if the user starts the lesson after the time restriction has expired. + List userResponses = qaService.getResponsesByUserUid(user.getUid()); + + //handle rating criterias + int commentsMinWordsLimit = 0; + boolean isCommentsEnabled = false; + int countRatedQuestions = 0; + if (qaContent.isAllowRateAnswers() ) { + + if ( userResponses.isEmpty()) { + Set criterias = qaContent.getRatingCriterias(); + for ( LearnerItemRatingCriteria criteria : criterias ) { + if ( criteria.isCommentRating() ) { + isCommentsEnabled = true; + break; + } + } + + } else { + // create itemIds list + List itemIds = new LinkedList(); + for (QaUsrResp responseIter : userResponses) { + itemIds.add(responseIter.getResponseId()); + } + + List itemRatingDtos = qaService.getRatingCriteriaDtos(qaContent.getQaContentId(), qaSession.getQaSessionId(), itemIds, + true, userId); + sessionMap.put(AttributeNames.ATTR_ITEM_RATING_DTOS, itemRatingDtos); + + if (itemRatingDtos.size() > 0) { + commentsMinWordsLimit = itemRatingDtos.get(0).getCommentsMinWordsLimit(); + isCommentsEnabled = itemRatingDtos.get(0).isCommentsEnabled(); + } + + //map itemRatingDto to corresponding response + for (QaUsrResp response : userResponses) { + + //find corresponding itemRatingDto + ItemRatingDTO itemRatingDto = null; + for (ItemRatingDTO itemRatingDtoIter : itemRatingDtos) { + if (itemRatingDtoIter.getItemId().equals(response.getResponseId())) { + itemRatingDto = itemRatingDtoIter; + break; + } + } + + response.setItemRatingDto(itemRatingDto); + } + + // store how many items are rated + countRatedQuestions = qaService.getCountItemsRatedByUser(qaContent.getQaContentId(), userId.intValue()); + } + } + + request.setAttribute(TOOL_SESSION_ID, qaSession.getQaSessionId()); + + sessionMap.put("commentsMinWordsLimit", commentsMinWordsLimit); + sessionMap.put("isCommentsEnabled", isCommentsEnabled); + sessionMap.put(AttributeNames.ATTR_COUNT_RATED_ITEMS, countRatedQuestions); + + generalLearnerFlowDTO.setUserResponses(userResponses); + generalLearnerFlowDTO.setRequestLearningReportProgress(new Boolean(true).toString()); + } + + /** + * Refreshes user list. + */ + public ActionForward getResponses(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse res) throws IOException, ServletException, JSONException { + initializeQAService(); + + // teacher timezone + HttpSession ss = SessionManager.getSession(); + UserDTO userDto = (UserDTO) ss.getAttribute(AttributeNames.USER); + TimeZone userTimeZone = userDto.getTimeZone(); + + boolean isAllowRateAnswers = WebUtil.readBooleanParam(request, "isAllowRateAnswers"); + boolean isAllowRichEditor = WebUtil.readBooleanParam(request, "isAllowRichEditor"); + boolean isOnlyLeadersIncluded = WebUtil.readBooleanParam(request, "isOnlyLeadersIncluded", false); + Long qaContentId = WebUtil.readLongParam(request, "qaContentId"); + + Long questionUid = WebUtil.readLongParam(request, "questionUid"); + Long qaSessionId = WebUtil.readLongParam(request, "qaSessionId"); + + //in case of monitoring we show all results. in case of learning - don't show results from the current user + boolean isMonitoring = WebUtil.readBooleanParam(request, "isMonitoring", false); + Long userId = isMonitoring ? -1 : WebUtil.readLongParam(request, "userId"); + + //paging parameters of tablesorter + int size = WebUtil.readIntParam(request, "size"); + int page = WebUtil.readIntParam(request, "page"); + Integer sortByCol1 = WebUtil.readIntParam(request, "column[0]", true); + Integer sortByCol2 = WebUtil.readIntParam(request, "column[1]", true); + String searchString = request.getParameter("fcol[0]"); + + int sorting = QaAppConstants.SORT_BY_NO; + if (sortByCol1 != null) { + if (isMonitoring) { + sorting = sortByCol1.equals(0) ? QaAppConstants.SORT_BY_USERNAME_ASC + : QaAppConstants.SORT_BY_USERNAME_DESC; + } else { + sorting = sortByCol1.equals(0) ? QaAppConstants.SORT_BY_ANSWER_ASC : QaAppConstants.SORT_BY_ANSWER_DESC; + } + + } else if (sortByCol2 != null) { + sorting = sortByCol2.equals(0) ? QaAppConstants.SORT_BY_RATING_ASC : QaAppConstants.SORT_BY_RATING_DESC; + } + + List responses = QaLearningAction.qaService.getResponsesForTablesorter(qaContentId, qaSessionId, + questionUid, userId, isOnlyLeadersIncluded, page, size, sorting, searchString); + + JSONObject responcedata = new JSONObject(); + JSONArray rows = new JSONArray(); + + responcedata.put("total_rows", QaLearningAction.qaService.getCountResponsesBySessionAndQuestion(qaSessionId, + questionUid, userId, isOnlyLeadersIncluded, searchString)); + + // handle rating criterias - even though we may have searched on ratings earlier we can't use the average ratings + // calculated as they may have been averages over more than one criteria. + List itemRatingDtos = null; + if (isAllowRateAnswers && !responses.isEmpty()) { + //create itemIds list + List itemIds = new LinkedList(); + for (QaUsrResp response : responses) { + itemIds.add(response.getResponseId()); + } + + //all comments required only for monitoring + boolean isCommentsByOtherUsersRequired = isMonitoring; + itemRatingDtos = QaLearningAction.qaService.getRatingCriteriaDtos(qaContentId, qaSessionId, itemIds, + isCommentsByOtherUsersRequired, userId); + + // store how many items are rated + int countRatedQuestions = QaLearningAction.qaService.getCountItemsRatedByUser(qaContentId, + userId.intValue()); + responcedata.put(AttributeNames.ATTR_COUNT_RATED_ITEMS, countRatedQuestions); + } + + for (QaUsrResp response : responses) { + QaQueUsr user = response.getQaQueUser(); + + /* LDEV-3891: This code has been commented out, as the escapeCsv puts double quotes in the string, which goes through to the + * client and wrecks img src entries. It appears the browser cannot process the string with all the double quotes. + * This is the second time it is being fixed - the escapeCsv was removed in LDEV-3448 and then added back in + * when Peer Review was added (LDEV-3480). If escapeCsv needs to be added in again, make sure it does not break + * learner added images being seen in monitoring. + //remove leading and trailing quotes + String answer = StringEscapeUtils.escapeCsv(response.getAnswer()); + if (isAllowRichEditor && answer.startsWith("\"") && answer.length() >= 3) { + answer = answer.substring(1, answer.length() - 1); + } + */ + + JSONObject responseRow = new JSONObject(); + responseRow.put("responseUid", response.getResponseId().toString()); + responseRow.put("answer", response.getAnswer()); + responseRow.put("userName", StringEscapeUtils.escapeCsv(user.getFullname())); + responseRow.put("visible", new Boolean(response.isVisible()).toString()); + + // format attemptTime - got straight from server time to other timezones in formatter + // as trying to convert dates runs into tz issues - any Date object created is still + // in the server time zone. + Date attemptTime = response.getAttemptTime(); + responseRow.put("attemptTime", DateUtil.convertToStringForJSON(attemptTime, request.getLocale())); + responseRow.put("timeAgo", DateUtil.convertToStringForTimeagoJSON(attemptTime)); + + if (isAllowRateAnswers) { + + //find corresponding itemRatingDto + ItemRatingDTO itemRatingDto = null; + for (ItemRatingDTO itemRatingDtoIter : itemRatingDtos) { + if (response.getResponseId().equals(itemRatingDtoIter.getItemId())) { + itemRatingDto = itemRatingDtoIter; + break; + } + } + + boolean isItemAuthoredByUser = response.getQaQueUser().getQueUsrId().equals(userId); + responseRow.put("isItemAuthoredByUser", isItemAuthoredByUser); + + JSONArray criteriasRows = new JSONArray(); + for (ItemRatingCriteriaDTO criteriaDto : itemRatingDto.getCriteriaDtos()) { + JSONObject criteriasRow = new JSONObject(); + criteriasRow.put("ratingCriteriaId", criteriaDto.getRatingCriteria().getRatingCriteriaId()); + criteriasRow.put("title", criteriaDto.getRatingCriteria().getTitle()); + criteriasRow.put("averageRating", criteriaDto.getAverageRating()); + criteriasRow.put("numberOfVotes", criteriaDto.getNumberOfVotes()); + criteriasRow.put("userRating", criteriaDto.getUserRating()); + + criteriasRows.put(criteriasRow); + } + responseRow.put("criteriaDtos", criteriasRows); + + //handle comments + responseRow.put("commentsCriteriaId", itemRatingDto.getCommentsCriteriaId()); + String commentPostedByUser = itemRatingDto.getCommentPostedByUser() == null ? "" + : itemRatingDto.getCommentPostedByUser().getComment(); + responseRow.put("commentPostedByUser", commentPostedByUser); + if (itemRatingDto.getCommentDtos() != null) { + + JSONArray comments = new JSONArray(); + for (RatingCommentDTO commentDto : itemRatingDto.getCommentDtos()) { + JSONObject comment = new JSONObject(); + comment.put("comment", StringEscapeUtils.escapeCsv(commentDto.getComment())); + + if (isMonitoring) { + // format attemptTime + Date postedDate = commentDto.getPostedDate(); + postedDate = DateUtil.convertToTimeZoneFromDefault(userTimeZone, postedDate); + comment.put("postedDate", DateUtil.convertToStringForJSON(postedDate, request.getLocale())); + + comment.put("userFullName", StringEscapeUtils.escapeCsv(commentDto.getUserFullName())); + } + + comments.put(comment); + } + responseRow.put("comments", comments); + } + } + + rows.put(responseRow); + } + responcedata.put("rows", rows); + + res.setContentType("application/json;charset=utf-8"); + res.getWriter().print(new String(responcedata.toString())); + return null; + } + + private static Map removeNewLinesMap(Map map) { + Map newMap = new TreeMap(new QaStringComparator()); + + Iterator itMap = map.entrySet().iterator(); + while (itMap.hasNext()) { + Map.Entry pairs = (Map.Entry) itMap.next(); + String newText = ""; + if (pairs.getValue().toString() != null) { + newText = pairs.getValue().toString().replaceAll("\n", "
"); + } + newMap.put(pairs.getKey(), newText); + } + return newMap; + } + + private void initializeQAService() { + if (QaLearningAction.qaService == null) { + QaLearningAction.qaService = QaServiceProxy.getQaService(getServlet().getServletContext()); + } + } + + private QaQueUsr getCurrentUser(String toolSessionID) { + + // get back login user DTO + HttpSession ss = SessionManager.getSession(); + UserDTO toolUser = (UserDTO) ss.getAttribute(AttributeNames.USER); + Long userId = new Long(toolUser.getUserID().longValue()); + + return QaLearningAction.qaService.getUserByIdAndSession(userId, new Long(toolSessionID)); + } + +} Index: lams_tool_laqa/src/java/org/lamsfoundation/lams/tool/qa/web/action/QaLearningStarterAction.java =================================================================== diff -u --- lams_tool_laqa/src/java/org/lamsfoundation/lams/tool/qa/web/action/QaLearningStarterAction.java (revision 0) +++ lams_tool_laqa/src/java/org/lamsfoundation/lams/tool/qa/web/action/QaLearningStarterAction.java (revision 32eb376c59d7c17cfa9d51cac14c00aae8cf44ff) @@ -0,0 +1,445 @@ +/**************************************************************** + * Copyright (C) 2005 LAMS Foundation (http://lamsfoundation.org) + * ============================================================= + * License Information: http://lamsfoundation.org/licensing/lams/2.0/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + * USA + * + * http://www.gnu.org/licenses/gpl.txt + * **************************************************************** + */ + + +package org.lamsfoundation.lams.tool.qa.web.action; + +import java.io.IOException; +import java.util.Date; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.TimeZone; +import java.util.TreeMap; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; + +import org.apache.log4j.Logger; +import org.apache.struts.Globals; +import org.apache.struts.action.Action; +import org.apache.struts.action.ActionForm; +import org.apache.struts.action.ActionForward; +import org.apache.struts.action.ActionMapping; +import org.apache.struts.action.ActionMessage; +import org.apache.struts.action.ActionMessages; +import org.lamsfoundation.lams.learning.web.bean.ActivityPositionDTO; +import org.lamsfoundation.lams.learning.web.util.LearningWebUtil; +import org.lamsfoundation.lams.notebook.model.NotebookEntry; +import org.lamsfoundation.lams.notebook.service.CoreNotebookConstants; +import org.lamsfoundation.lams.tool.ToolAccessMode; +import org.lamsfoundation.lams.tool.qa.QaAppConstants; +import org.lamsfoundation.lams.tool.qa.QaContent; +import org.lamsfoundation.lams.tool.qa.QaQueContent; +import org.lamsfoundation.lams.tool.qa.QaQueUsr; +import org.lamsfoundation.lams.tool.qa.QaSession; +import org.lamsfoundation.lams.tool.qa.dto.GeneralLearnerFlowDTO; +import org.lamsfoundation.lams.tool.qa.dto.QaQuestionDTO; +import org.lamsfoundation.lams.tool.qa.service.IQaService; +import org.lamsfoundation.lams.tool.qa.service.QaServiceProxy; +import org.lamsfoundation.lams.tool.qa.util.LearningUtil; +import org.lamsfoundation.lams.tool.qa.util.QaApplicationException; +import org.lamsfoundation.lams.tool.qa.util.QaComparator; +import org.lamsfoundation.lams.tool.qa.util.QaUtils; +import org.lamsfoundation.lams.tool.qa.web.form.QaLearningForm; +import org.lamsfoundation.lams.usermanagement.dto.UserDTO; +import org.lamsfoundation.lams.util.DateUtil; +import org.lamsfoundation.lams.util.WebUtil; +import org.lamsfoundation.lams.web.session.SessionManager; +import org.lamsfoundation.lams.web.util.AttributeNames; +import org.lamsfoundation.lams.web.util.SessionMap; + +/** + * This class is used to load the default content and initialize the presentation Map for Learner mode. + * It is important that ALL the session attributes created in this action gets removed by: + * QaUtils.cleanupSession(request) + * + * @author Ozgur Demirtas + * + */ +public class QaLearningStarterAction extends Action implements QaAppConstants { + private static Logger logger = Logger.getLogger(QaLearningStarterAction.class.getName()); + + private static IQaService qaService; + + @Override + public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) throws IOException, ServletException, QaApplicationException { + + QaUtils.cleanUpSessionAbsolute(request); + if (qaService == null) { + qaService = QaServiceProxy.getQaService(getServlet().getServletContext()); + } + + QaLearningForm qaLearningForm = (QaLearningForm) form; + /* validate learning mode parameters */ + validateParameters(request, mapping, qaLearningForm); + String mode = qaLearningForm.getMode(); + String toolSessionID = qaLearningForm.getToolSessionID(); + + /* + * By now, the passed tool session id MUST exist in the db by calling: + * public void createToolSession(Long toolSessionId, Long toolContentId) by the core. + * + * make sure this session exists in tool's session table by now. + */ + QaSession qaSession = qaService.getSessionById(new Long(toolSessionID).longValue()); + if (qaSession == null) { + QaUtils.cleanUpSessionAbsolute(request); + throw new ServletException("No session found"); + } + + QaContent qaContent = qaSession.getQaContent(); + if (qaContent == null) { + QaUtils.cleanUpSessionAbsolute(request); + throw new ServletException("No QA content found"); + } + + QaQueUsr user = null; + if ((mode != null) && mode.equals(ToolAccessMode.TEACHER.toString())) { + // monitoring mode - user is specified in URL + // assessmentUser may be null if the user was force completed. + user = getSpecifiedUser(toolSessionID, WebUtil.readIntParam(request, AttributeNames.PARAM_USER_ID, false)); + } else { + user = getCurrentUser(toolSessionID); + } + Long userId = user.getQueUsrId(); + qaLearningForm.setUserID(user.getQueUsrId().toString()); + + QaQueUsr groupLeader = null; + if (qaContent.isUseSelectLeaderToolOuput()) { + groupLeader = qaService.checkLeaderSelectToolForSessionLeader(user, new Long(toolSessionID).longValue()); + + // forwards to the leaderSelection page + if (groupLeader == null && !mode.equals(ToolAccessMode.TEACHER.toString())) { + + List groupUsers = qaService.getUsersBySessionId(new Long(toolSessionID).longValue()); + request.setAttribute(ATTR_GROUP_USERS, groupUsers); + request.setAttribute(TOOL_SESSION_ID, toolSessionID); + request.setAttribute(ATTR_CONTENT, qaContent); + + return mapping.findForward(WAIT_FOR_LEADER); + } + + // check if leader has submitted all answers + if (groupLeader.isResponseFinalized() && !mode.equals(ToolAccessMode.TEACHER.toString())) { + + // in case user joins the lesson after leader has answers some answers already - we need to make sure + // he has the same scratches as leader + qaService.copyAnswersFromLeader(user, groupLeader); + + user.setResponseFinalized(true); + qaService.updateUser(user); + } + } + + /* holds the question contents for a given tool session and relevant content */ + Map mapQuestionStrings = new TreeMap(new QaComparator()); + Map mapQuestions = new TreeMap(); + + String httpSessionID = qaLearningForm.getHttpSessionID(); + SessionMap sessionMap = httpSessionID == null ? null + : (SessionMap) request.getSession().getAttribute(httpSessionID); + if (sessionMap == null) { + sessionMap = new SessionMap(); + Map mapSequentialAnswers = new HashMap(); + sessionMap.put(MAP_SEQUENTIAL_ANSWERS_KEY, mapSequentialAnswers); + request.getSession().setAttribute(sessionMap.getSessionID(), sessionMap); + qaLearningForm.setHttpSessionID(sessionMap.getSessionID()); + + sessionMap.put(AttributeNames.ATTR_LEARNER_CONTENT_FOLDER, + qaService.getLearnerContentFolder(new Long(toolSessionID), user.getQueUsrId())); + } + String sessionMapId = sessionMap.getSessionID(); + sessionMap.put(IS_DISABLED, qaContent.isLockWhenFinished() && user.isLearnerFinished() + || (mode != null) && mode.equals(ToolAccessMode.TEACHER.toString())); + + sessionMap.put(ATTR_GROUP_LEADER, groupLeader); + boolean isUserLeader = qaService.isUserGroupLeader(user, new Long(toolSessionID)); + boolean lockWhenFinished = qaContent.isLockWhenFinished(); + sessionMap.put(ATTR_IS_USER_LEADER, isUserLeader); + sessionMap.put(AttributeNames.ATTR_MODE, mode); + sessionMap.put(ATTR_CONTENT, qaContent); + sessionMap.put(AttributeNames.USER, user); + + GeneralLearnerFlowDTO generalLearnerFlowDTO = LearningUtil.buildGeneralLearnerFlowDTO(qaService, qaContent); + generalLearnerFlowDTO.setUserUid(user.getQueUsrId().toString()); + generalLearnerFlowDTO.setHttpSessionID(sessionMapId); + generalLearnerFlowDTO.setToolSessionID(toolSessionID); + generalLearnerFlowDTO.setToolContentID(qaContent.getQaContentId().toString()); + generalLearnerFlowDTO.setReportTitleLearner(qaContent.getReportTitle()); + + generalLearnerFlowDTO.setLockWhenFinished(new Boolean(lockWhenFinished).toString()); + generalLearnerFlowDTO.setNoReeditAllowed(qaContent.isNoReeditAllowed()); + generalLearnerFlowDTO.setReflection(new Boolean(qaContent.isReflect()).toString()); + generalLearnerFlowDTO.setReflectionSubject(qaContent.getReflectionSubject()); + + NotebookEntry notebookEntry = qaService.getEntry(new Long(toolSessionID), CoreNotebookConstants.NOTEBOOK_TOOL, + MY_SIGNATURE, userId.intValue()); + if (notebookEntry != null) { + //String notebookEntryPresentable = QaUtils.replaceNewLines(notebookEntry.getEntry()); + qaLearningForm.setEntryText(notebookEntry.getEntry()); + generalLearnerFlowDTO.setNotebookEntry(notebookEntry.getEntry()); + } + + /* + * Is the tool activity been checked as Define Later in the property inspector? + */ + if (qaContent.isDefineLater()) { + QaUtils.cleanUpSessionAbsolute(request); + return (mapping.findForward(DEFINE_LATER)); + } + + ActivityPositionDTO activityPosition = LearningWebUtil.putActivityPositionInRequestByToolSessionId( + new Long(toolSessionID), request, getServlet().getServletContext()); + sessionMap.put(AttributeNames.ATTR_ACTIVITY_POSITION, activityPosition); + + /* + * fetch question content from content + */ + Iterator contentIterator = qaContent.getQaQueContents().iterator(); + while (contentIterator.hasNext()) { + QaQueContent qaQuestion = (QaQueContent) contentIterator.next(); + if (qaQuestion != null) { + int displayOrder = qaQuestion.getDisplayOrder(); + + if (displayOrder != 0) { + /* + * add the question to the questions Map in the displayOrder + */ + QaQuestionDTO questionDTO = new QaQuestionDTO(qaQuestion); + mapQuestions.put(displayOrder, questionDTO); + + mapQuestionStrings.put(new Integer(displayOrder).toString(), qaQuestion.getQuestion()); + + } + } + } + generalLearnerFlowDTO.setMapQuestions(mapQuestionStrings); + generalLearnerFlowDTO.setMapQuestionContentLearner(mapQuestions); + generalLearnerFlowDTO.setTotalQuestionCount(new Integer(mapQuestions.size())); + qaLearningForm.setTotalQuestionCount(new Integer(mapQuestions.size()).toString()); + + String feedBackType = ""; + if (qaContent.isQuestionsSequenced()) { + feedBackType = FEEDBACK_TYPE_SEQUENTIAL; + } else { + feedBackType = FEEDBACK_TYPE_COMBINED; + } + String userFeedback = feedBackType + generalLearnerFlowDTO.getTotalQuestionCount() + QUESTIONS; + generalLearnerFlowDTO.setUserFeedback(userFeedback); + + generalLearnerFlowDTO.setRemainingQuestionCount(generalLearnerFlowDTO.getTotalQuestionCount().toString()); + generalLearnerFlowDTO.setInitialScreen(new Boolean(true).toString()); + + request.setAttribute(GENERAL_LEARNER_FLOW_DTO, generalLearnerFlowDTO); + + /* + * by now, we know that the mode is either teacher or learner + * check if the mode is teacher and request is for Learner Progress + */ + if (mode.equals("teacher")) { + //start generating learner progress report for toolSessionID + + /* + * the report should have the all entries for the users in this tool session, + * and display under the "my answers" section the answers for the user id in the url + */ +// Long learnerProgressUserId = WebUtil.readLongParam(request, AttributeNames.PARAM_USER_ID, false); + generalLearnerFlowDTO.setRequestLearningReport(new Boolean(true).toString()); + generalLearnerFlowDTO.setRequestLearningReportProgress(new Boolean(true).toString()); + generalLearnerFlowDTO.setTeacherViewOnly(new Boolean(true).toString()); + + QaLearningAction.refreshSummaryData(request, qaContent, qaSession, qaService, sessionMapId, user, + generalLearnerFlowDTO); + request.setAttribute(QaAppConstants.GENERAL_LEARNER_FLOW_DTO, generalLearnerFlowDTO); + + return (mapping.findForward(LEARNER_REP)); + } + + //check if there is submission deadline + Date submissionDeadline = qaContent.getSubmissionDeadline(); + if (submissionDeadline != null) { + // store submission deadline to sessionMap + sessionMap.put(QaAppConstants.ATTR_SUBMISSION_DEADLINE, submissionDeadline); + + HttpSession ss = SessionManager.getSession(); + UserDTO learnerDto = (UserDTO) ss.getAttribute(AttributeNames.USER); + TimeZone learnerTimeZone = learnerDto.getTimeZone(); + Date tzSubmissionDeadline = DateUtil.convertToTimeZoneFromDefault(learnerTimeZone, submissionDeadline); + Date currentLearnerDate = DateUtil.convertToTimeZoneFromDefault(learnerTimeZone, new Date()); + + // calculate whether submission deadline has passed, and if so forward to "submissionDeadline" + if (currentLearnerDate.after(tzSubmissionDeadline)) { + + //if ShowOtherAnswersAfterDeadline is enabled - show others answers + if (qaContent.isShowOtherAnswersAfterDeadline()) { + generalLearnerFlowDTO.setLockWhenFinished(Boolean.TRUE.toString()); + generalLearnerFlowDTO.setNoReeditAllowed(true); + //only for ActionForward refreshAllResults(..) method + sessionMap.put("noRefresh", true); + /* + * the report should have all the users' entries OR the report should have only the current + * session's entries + */ + generalLearnerFlowDTO.setRequestLearningReport(new Boolean(true).toString()); + + QaLearningAction.refreshSummaryData(request, qaContent, qaSession, qaService, sessionMapId, user, + generalLearnerFlowDTO); + + if (user.isLearnerFinished()) { + generalLearnerFlowDTO.setRequestLearningReportViewOnly(new Boolean(true).toString()); + return (mapping.findForward(REVISITED_LEARNER_REP)); + } else { + generalLearnerFlowDTO.setRequestLearningReportViewOnly(new Boolean(false).toString()); + return (mapping.findForward(LEARNER_REP)); + } + + // show submissionDeadline page otherwise + } else { + return mapping.findForward("submissionDeadline"); + } + } + } + + /* + * Verify that userId does not already exist in the db. + * If it does exist and the passed tool session id exists in the db, that means the user already responded to + * the content and + * his answers must be displayed read-only + * + * if the user's tool session id AND user id exists in the tool tables go to learner's report. + */ + /* + * if the 'All Responses' has been clicked no more user entry is accepted, and isResponseFinalized() returns + * true + */ + Long currentToolSessionID = new Long(qaLearningForm.getToolSessionID()); + + //if Response is Finalized + if (user.isResponseFinalized()) { + QaSession checkSession = user.getQaSession(); + + if (checkSession != null) { + Long checkQaSessionId = checkSession.getQaSessionId(); + + if (checkQaSessionId.toString().equals(currentToolSessionID.toString())) { + + // the learner is in the same session and has already responsed to this content + + generalLearnerFlowDTO.setLockWhenFinished(new Boolean(qaContent.isLockWhenFinished()).toString()); + generalLearnerFlowDTO.setNoReeditAllowed(qaContent.isNoReeditAllowed()); + /* + * the report should have all the users' entries OR the report should have only the current + * session's entries + */ + generalLearnerFlowDTO.setRequestLearningReport(new Boolean(true).toString()); + + QaLearningAction.refreshSummaryData(request, qaContent, qaSession, qaService, sessionMapId, user, + generalLearnerFlowDTO); + + if (user.isLearnerFinished()) { + generalLearnerFlowDTO.setRequestLearningReportViewOnly(new Boolean(true).toString()); + return (mapping.findForward(REVISITED_LEARNER_REP)); + } else { + generalLearnerFlowDTO.setRequestLearningReportViewOnly(new Boolean(false).toString()); + return (mapping.findForward(LEARNER_REP)); + } + } + } + } + + //**---- showing AnswersContent.jsp ----** + LearningUtil.populateAnswers(sessionMap, qaContent, user, mapQuestions, generalLearnerFlowDTO, qaService); + + return (mapping.findForward(LOAD_LEARNER)); + } + + /** + * validates the learning mode parameters + * + * @param request + * @param mapping + * @return ActionForward + */ + protected void validateParameters(HttpServletRequest request, ActionMapping mapping, + QaLearningForm qaLearningForm) { + /* + * process incoming tool session id and later derive toolContentId from it. + */ + String strToolSessionId = request.getParameter(AttributeNames.PARAM_TOOL_SESSION_ID); + long toolSessionId = 0; + if ((strToolSessionId == null) || (strToolSessionId.length() == 0)) { + ActionMessages errors = new ActionMessages(); + errors.add(Globals.ERROR_KEY, new ActionMessage("error.toolSessionId.required")); + logger.error("error.toolSessionId.required"); + saveErrors(request, errors); + return; + } else { + try { + toolSessionId = new Long(strToolSessionId).longValue(); + qaLearningForm.setToolSessionID(new Long(toolSessionId).toString()); + } catch (NumberFormatException e) { + logger.error("add error.sessionId.numberFormatException to ActionMessages."); + return; + } + } + + /* mode can be learner, teacher or author */ + String mode = request.getParameter(MODE); + if ((mode == null) || (mode.length() == 0)) { + logger.error("Mode is empty"); + return; + } + if ((!mode.equals("learner")) && (!mode.equals("teacher")) && (!mode.equals("author"))) { + logger.error("Wrong mode"); + return; + } + qaLearningForm.setMode(mode); + } + + private QaQueUsr getCurrentUser(String toolSessionId) { + // get back login user DTO + HttpSession ss = SessionManager.getSession(); + UserDTO toolUser = (UserDTO) ss.getAttribute(AttributeNames.USER); + Integer userId = toolUser.getUserID(); + + QaQueUsr qaUser = qaService.getUserByIdAndSession(userId.longValue(), new Long(toolSessionId)); + if (qaUser == null) { + qaUser = qaService.createUser(new Long(toolSessionId), userId); + } + + return qaUser; + } + + private QaQueUsr getSpecifiedUser(String toolSessionId, Integer userId) { + QaQueUsr qaUser = qaService.getUserByIdAndSession(userId.longValue(), new Long(toolSessionId)); + if (qaUser == null) { + qaUser = qaService.createUser(new Long(toolSessionId), userId); + } + return qaUser; + } +} \ No newline at end of file Index: lams_tool_laqa/src/java/org/lamsfoundation/lams/tool/qa/web/action/QaMonitoringAction.java =================================================================== diff -u --- lams_tool_laqa/src/java/org/lamsfoundation/lams/tool/qa/web/action/QaMonitoringAction.java (revision 0) +++ lams_tool_laqa/src/java/org/lamsfoundation/lams/tool/qa/web/action/QaMonitoringAction.java (revision 32eb376c59d7c17cfa9d51cac14c00aae8cf44ff) @@ -0,0 +1,218 @@ +/*************************************************************************** +Copyright (C) 2005 LAMS Foundation (http://lamsfoundation.org) +License Information: http://lamsfoundation.org/licensing/lams/2.0/ + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License version 2 as +published by the Free Software Foundation. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 +USA + +http://www.gnu.org/licenses/gpl.txt + * ***********************************************************************/ + + + +package org.lamsfoundation.lams.tool.qa.web.action; + +import java.io.IOException; +import java.util.Date; +import java.util.List; +import java.util.TimeZone; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; + +import org.apache.commons.lang.StringEscapeUtils; +import org.apache.log4j.Logger; +import org.apache.struts.action.ActionForm; +import org.apache.struts.action.ActionForward; +import org.apache.struts.action.ActionMapping; +import org.apache.tomcat.util.json.JSONArray; +import org.apache.tomcat.util.json.JSONException; +import org.apache.tomcat.util.json.JSONObject; +import org.lamsfoundation.lams.tool.exception.ToolException; +import org.lamsfoundation.lams.tool.qa.QaAppConstants; +import org.lamsfoundation.lams.tool.qa.QaContent; +import org.lamsfoundation.lams.tool.qa.QaUsrResp; +import org.lamsfoundation.lams.tool.qa.service.IQaService; +import org.lamsfoundation.lams.tool.qa.service.QaServiceProxy; +import org.lamsfoundation.lams.usermanagement.dto.UserDTO; +import org.lamsfoundation.lams.util.DateUtil; +import org.lamsfoundation.lams.util.WebUtil; +import org.lamsfoundation.lams.web.action.LamsDispatchAction; +import org.lamsfoundation.lams.web.session.SessionManager; +import org.lamsfoundation.lams.web.util.AttributeNames; + +/** + * @author Ozgur Demirtas + */ +public class QaMonitoringAction extends LamsDispatchAction implements QaAppConstants { + private static Logger logger = Logger.getLogger(QaMonitoringAction.class.getName()); + + @Override + public ActionForward unspecified(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) throws IOException, ServletException, ToolException { + return null; + } + + public ActionForward updateResponse(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) throws IOException, ServletException { + + IQaService qaService = QaServiceProxy.getQaService(getServlet().getServletContext()); + + Long responseUid = WebUtil.readLongParam(request, QaAppConstants.RESPONSE_UID); + String updatedResponse = request.getParameter("updatedResponse"); + QaUsrResp qaUsrResp = qaService.getResponseById(responseUid); + + /* + * write out the audit log entry. If you move this after the update of the response, then make sure you update + * the audit call to use a copy of the original answer + */ + qaService.getAuditService().logChange(QaAppConstants.MY_SIGNATURE, qaUsrResp.getQaQueUser().getQueUsrId(), + qaUsrResp.getQaQueUser().getUsername(), qaUsrResp.getAnswer(), updatedResponse); + + qaUsrResp.setAnswer(updatedResponse); + qaService.updateUserResponse(qaUsrResp); + + return null; + } + + public ActionForward updateResponseVisibility(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) throws IOException, ServletException, ToolException { + IQaService qaService = QaServiceProxy.getQaService(getServlet().getServletContext()); + + Long responseUid = WebUtil.readLongParam(request, QaAppConstants.RESPONSE_UID); + boolean isHideItem = WebUtil.readBooleanParam(request, QaAppConstants.IS_HIDE_ITEM); + qaService.updateResponseVisibility(responseUid, isHideItem); + + return null; + } + + /** + * Set Submission Deadline + * + * @param mapping + * @param form + * @param request + * @param response + * @return + * @throws IOException + */ + public ActionForward setSubmissionDeadline(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) throws IOException { + IQaService qaService = getQAService(); + + Long contentID = WebUtil.readLongParam(request, AttributeNames.PARAM_TOOL_CONTENT_ID); + QaContent content = qaService.getQaContent(contentID); + + Long dateParameter = WebUtil.readLongParam(request, QaAppConstants.ATTR_SUBMISSION_DEADLINE, true); + Date tzSubmissionDeadline = null; + String formattedDate = ""; + if (dateParameter != null) { + Date submissionDeadline = new Date(dateParameter); + HttpSession ss = SessionManager.getSession(); + UserDTO teacher = (UserDTO) ss.getAttribute(AttributeNames.USER); + TimeZone teacherTimeZone = teacher.getTimeZone(); + tzSubmissionDeadline = DateUtil.convertFromTimeZoneToDefault(teacherTimeZone, submissionDeadline); + formattedDate = DateUtil.convertToStringForJSON(tzSubmissionDeadline, request.getLocale()); + } else { + //set showOtherAnswersAfterDeadline to false + content.setShowOtherAnswersAfterDeadline(false); + } + content.setSubmissionDeadline(tzSubmissionDeadline); + qaService.saveOrUpdateQaContent(content); + + response.setContentType("text/plain;charset=utf-8"); + response.getWriter().print(formattedDate); + return null; + } + + /** + * Set Submission Deadline + * + * @param mapping + * @param form + * @param request + * @param response + * @return + */ + public ActionForward setShowOtherAnswersAfterDeadline(ActionMapping mapping, ActionForm form, + HttpServletRequest request, HttpServletResponse response) { + IQaService qaService = getQAService(); + + Long contentID = WebUtil.readLongParam(request, AttributeNames.PARAM_TOOL_CONTENT_ID); + QaContent content = qaService.getQaContent(contentID); + + boolean showOtherAnswersAfterDeadline = WebUtil.readBooleanParam(request, + QaAppConstants.PARAM_SHOW_OTHER_ANSWERS_AFTER_DEADLINE); + content.setShowOtherAnswersAfterDeadline(showOtherAnswersAfterDeadline); + qaService.saveOrUpdateQaContent(content); + + return null; + } + + private IQaService getQAService() { + return QaServiceProxy.getQaService(getServlet().getServletContext()); + } + + /** + * Get Paged Reflections + * + * @param mapping + * @param form + * @param request + * @param response + * @return + */ + public ActionForward getReflectionsJSON(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) throws IOException, ServletException, ToolException, JSONException { + + Long toolSessionId = WebUtil.readLongParam(request, QaAppConstants.TOOL_SESSION_ID); + + // paging parameters of tablesorter + int size = WebUtil.readIntParam(request, "size"); + int page = WebUtil.readIntParam(request, "page"); + Integer sortByName = WebUtil.readIntParam(request, "column[0]", true); + String searchString = request.getParameter("fcol[0]"); + + int sorting = QaAppConstants.SORT_BY_NO; + if (sortByName != null) { + sorting = sortByName.equals(0) ? QaAppConstants.SORT_BY_USERNAME_ASC : QaAppConstants.SORT_BY_USERNAME_DESC; + } + + //return user list according to the given sessionID + IQaService qaService = getQAService(); + List users = qaService.getUserReflectionsForTablesorter(toolSessionId, page, size, sorting, + searchString); + + JSONArray rows = new JSONArray(); + JSONObject responsedata = new JSONObject(); + responsedata.put("total_rows", qaService.getCountUsersBySessionWithSearch(toolSessionId, searchString)); + + for (Object[] userAndReflection : users) { + JSONObject responseRow = new JSONObject(); + responseRow.put("username", StringEscapeUtils.escapeHtml((String) userAndReflection[1])); + if (userAndReflection.length > 2 && userAndReflection[2] != null) { + String reflection = StringEscapeUtils.escapeHtml((String) userAndReflection[2]); + responseRow.put(QaAppConstants.NOTEBOOK, reflection.replaceAll("\n", "
")); + } + rows.put(responseRow); + } + responsedata.put("rows", rows); + response.setContentType("application/json;charset=utf-8"); + response.getWriter().print(new String(responsedata.toString())); + return null; + } + +} \ No newline at end of file Index: lams_tool_laqa/src/java/org/lamsfoundation/lams/tool/qa/web/action/QaMonitoringStarterAction.java =================================================================== diff -u --- lams_tool_laqa/src/java/org/lamsfoundation/lams/tool/qa/web/action/QaMonitoringStarterAction.java (revision 0) +++ lams_tool_laqa/src/java/org/lamsfoundation/lams/tool/qa/web/action/QaMonitoringStarterAction.java (revision 32eb376c59d7c17cfa9d51cac14c00aae8cf44ff) @@ -0,0 +1,220 @@ +/**************************************************************** + * Copyright (C) 2005 LAMS Foundation (http://lamsfoundation.org) + * ============================================================= + * License Information: http://lamsfoundation.org/licensing/lams/2.0/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + * USA + * + * http://www.gnu.org/licenses/gpl.txt + * **************************************************************** + */ + + +package org.lamsfoundation.lams.tool.qa.web.action; + +import java.io.IOException; +import java.util.Date; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.Set; +import java.util.TimeZone; +import java.util.TreeSet; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; + +import org.apache.log4j.Logger; +import org.apache.struts.action.Action; +import org.apache.struts.action.ActionForm; +import org.apache.struts.action.ActionForward; +import org.apache.struts.action.ActionMapping; +import org.lamsfoundation.lams.tool.qa.QaAppConstants; +import org.lamsfoundation.lams.tool.qa.QaContent; +import org.lamsfoundation.lams.tool.qa.QaQueContent; +import org.lamsfoundation.lams.tool.qa.QaQueUsr; +import org.lamsfoundation.lams.tool.qa.QaSession; +import org.lamsfoundation.lams.tool.qa.dto.GroupDTO; +import org.lamsfoundation.lams.tool.qa.dto.QaQuestionDTO; +import org.lamsfoundation.lams.tool.qa.dto.QaStatsDTO; +import org.lamsfoundation.lams.tool.qa.service.IQaService; +import org.lamsfoundation.lams.tool.qa.service.QaServiceProxy; +import org.lamsfoundation.lams.tool.qa.util.QaApplicationException; +import org.lamsfoundation.lams.tool.qa.util.QaSessionComparator; +import org.lamsfoundation.lams.tool.qa.util.QaUtils; +import org.lamsfoundation.lams.tool.qa.web.form.QaMonitoringForm; +import org.lamsfoundation.lams.usermanagement.dto.UserDTO; +import org.lamsfoundation.lams.util.DateUtil; +import org.lamsfoundation.lams.util.WebUtil; +import org.lamsfoundation.lams.web.session.SessionManager; +import org.lamsfoundation.lams.web.util.AttributeNames; + +/** + * Starts up the monitoring module + * + * @author Ozgur Demirtas + */ +public class QaMonitoringStarterAction extends Action implements QaAppConstants { + private static Logger logger = Logger.getLogger(QaMonitoringStarterAction.class.getName()); + + @Override + public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) throws IOException, ServletException, QaApplicationException { + QaUtils.cleanUpSessionAbsolute(request); + + QaMonitoringForm qaMonitoringForm = (QaMonitoringForm) form; + + IQaService qaService = QaServiceProxy.getQaService(getServlet().getServletContext()); + + String contentFolderID = WebUtil.readStrParam(request, AttributeNames.PARAM_CONTENT_FOLDER_ID); + qaMonitoringForm.setContentFolderID(contentFolderID); + + ActionForward validateParameters = validateParameters(request, mapping, qaMonitoringForm); + if (validateParameters != null) { + return validateParameters; + } + + String toolContentID = qaMonitoringForm.getToolContentID(); + QaContent qaContent = qaService.getQaContent(new Long(toolContentID).longValue()); + if (qaContent == null) { + QaUtils.cleanUpSessionAbsolute(request); + throw new ServletException("Data not initialised in Monitoring"); + } + + qaMonitoringForm.setCurrentTab("1"); + + String strToolContentID = request.getParameter(AttributeNames.PARAM_TOOL_CONTENT_ID); + qaMonitoringForm.setToolContentID(strToolContentID); + + /* this section is related to summary tab. Starts here. */ +// SessionMap sessionMap = new SessionMap(); +// sessionMap.put(ACTIVITY_TITLE_KEY, qaContent.getTitle()); +// sessionMap.put(ACTIVITY_INSTRUCTIONS_KEY, qaContent.getInstructions()); +// +// qaMonitoringForm.setHttpSessionID(sessionMap.getSessionID()); +// request.getSession().setAttribute(sessionMap.getSessionID(), sessionMap); + + List questionDTOs = new LinkedList(); + for (QaQueContent question : qaContent.getQaQueContents()) { + QaQuestionDTO questionDTO = new QaQuestionDTO(question); + questionDTOs.add(questionDTO); + } + request.setAttribute(LIST_QUESTION_DTOS, questionDTOs); +// sessionMap.put(LIST_QUESTION_DTOS, questionDTOs); +// request.setAttribute(TOTAL_QUESTION_COUNT, new Integer(questionDTOs.size())); + + //session dto list + List groupDTOs = new LinkedList(); + Set sessions = new TreeSet(new QaSessionComparator()); + sessions.addAll(qaContent.getQaSessions()); + for (QaSession session : sessions) { + String sessionId = session.getQaSessionId().toString(); + String sessionName = session.getSession_name(); + + GroupDTO groupDTO = new GroupDTO(); + groupDTO.setSessionName(sessionName); + groupDTO.setSessionId(sessionId); + groupDTOs.add(groupDTO); + } + request.setAttribute(LIST_ALL_GROUPS_DTO, groupDTOs); + + // setting up the advanced summary for LDEV-1662 + request.setAttribute(QaAppConstants.ATTR_CONTENT, qaContent); + + boolean isGroupedActivity = qaService.isGroupedActivity(qaContent.getQaContentId()); + request.setAttribute("isGroupedActivity", isGroupedActivity); + + //ratings stuff + boolean isRatingsEnabled = qaService.isRatingsEnabled(qaContent); + request.setAttribute("isRatingsEnabled", isRatingsEnabled); + + //comments stuff + boolean isCommentsEnabled = qaService.isCommentsEnabled(qaContent.getQaContentId()); + request.setAttribute("isCommentsEnabled", isCommentsEnabled); + + //buildQaStatsDTO + QaStatsDTO qaStatsDTO = new QaStatsDTO(); + int countSessionComplete = 0; + int countAllUsers = 0; + Iterator iteratorSession = qaContent.getQaSessions().iterator(); + while (iteratorSession.hasNext()) { + QaSession qaSession = (QaSession) iteratorSession.next(); + + if (qaSession != null) { + + if (qaSession.getSession_status().equals(COMPLETED)) { + ++countSessionComplete; + } + + Iterator iteratorUser = qaSession.getQaQueUsers().iterator(); + while (iteratorUser.hasNext()) { + QaQueUsr qaQueUsr = (QaQueUsr) iteratorUser.next(); + + if (qaQueUsr != null) { + ++countAllUsers; + } + } + } + } + qaStatsDTO.setCountAllUsers(new Integer(countAllUsers).toString()); + qaStatsDTO.setCountSessionComplete(new Integer(countSessionComplete).toString()); + request.setAttribute(QA_STATS_DTO, qaStatsDTO); + + // set SubmissionDeadline, if any + if (qaContent.getSubmissionDeadline() != null) { + Date submissionDeadline = qaContent.getSubmissionDeadline(); + HttpSession ss = SessionManager.getSession(); + UserDTO teacher = (UserDTO) ss.getAttribute(AttributeNames.USER); + TimeZone teacherTimeZone = teacher.getTimeZone(); + Date tzSubmissionDeadline = DateUtil.convertToTimeZoneFromDefault(teacherTimeZone, submissionDeadline); + request.setAttribute(QaAppConstants.ATTR_SUBMISSION_DEADLINE, tzSubmissionDeadline.getTime()); + // use the unconverted time, as convertToStringForJSON() does the timezone conversion if needed + request.setAttribute(QaAppConstants.ATTR_SUBMISSION_DEADLINE_DATESTRING, DateUtil.convertToStringForJSON(submissionDeadline, request.getLocale())); + } + + return (mapping.findForward(LOAD_MONITORING)); + } + + /** + * validates request paramaters based on tool contract + * + * @param request + * @param mapping + * @return ActionForward + * @throws ServletException + */ + protected ActionForward validateParameters(HttpServletRequest request, ActionMapping mapping, + QaMonitoringForm qaMonitoringForm) throws ServletException { + + String strToolContentId = request.getParameter(AttributeNames.PARAM_TOOL_CONTENT_ID); + + if ((strToolContentId == null) || (strToolContentId.length() == 0)) { + QaUtils.cleanUpSessionAbsolute(request); + throw new ServletException("No Tool Content ID found"); + } else { + try { + long toolContentId = new Long(strToolContentId).longValue(); + + qaMonitoringForm.setToolContentID(new Long(toolContentId).toString()); + } catch (NumberFormatException e) { + QaUtils.cleanUpSessionAbsolute(request); + throw e; + } + } + return null; + } +} Index: lams_tool_laqa/src/java/org/lamsfoundation/lams/tool/qa/web/action/QaPedagogicalPlannerAction.java =================================================================== diff -u --- lams_tool_laqa/src/java/org/lamsfoundation/lams/tool/qa/web/action/QaPedagogicalPlannerAction.java (revision 0) +++ lams_tool_laqa/src/java/org/lamsfoundation/lams/tool/qa/web/action/QaPedagogicalPlannerAction.java (revision 32eb376c59d7c17cfa9d51cac14c00aae8cf44ff) @@ -0,0 +1,128 @@ +/**************************************************************** + * Copyright (C) 2005 LAMS Foundation (http://lamsfoundation.org) + * ============================================================= + * License Information: http://lamsfoundation.org/licensing/lams/2.0/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + * USA + * + * http://www.gnu.org/licenses/gpl.txt + * **************************************************************** + */ + + +package org.lamsfoundation.lams.tool.qa.web.action; + +import java.io.IOException; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.lang.StringUtils; +import org.apache.struts.action.ActionForm; +import org.apache.struts.action.ActionForward; +import org.apache.struts.action.ActionMapping; +import org.apache.struts.action.ActionMessages; +import org.lamsfoundation.lams.tool.qa.QaAppConstants; +import org.lamsfoundation.lams.tool.qa.QaContent; +import org.lamsfoundation.lams.tool.qa.QaQueContent; +import org.lamsfoundation.lams.tool.qa.service.IQaService; +import org.lamsfoundation.lams.tool.qa.service.QaServiceProxy; +import org.lamsfoundation.lams.tool.qa.web.form.QaPedagogicalPlannerForm; +import org.lamsfoundation.lams.util.WebUtil; +import org.lamsfoundation.lams.web.action.LamsDispatchAction; +import org.lamsfoundation.lams.web.util.AttributeNames; +import org.springframework.web.context.WebApplicationContext; +import org.springframework.web.context.support.WebApplicationContextUtils; + +public class QaPedagogicalPlannerAction extends LamsDispatchAction { + + @Override + protected ActionForward unspecified(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) { + return initPedagogicalPlannerForm(mapping, form, request, response); + } + + public ActionForward initPedagogicalPlannerForm(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) { + QaPedagogicalPlannerForm plannerForm = (QaPedagogicalPlannerForm) form; + Long toolContentID = WebUtil.readLongParam(request, AttributeNames.PARAM_TOOL_CONTENT_ID); + QaContent qaContent = getQaService().getQaContent(toolContentID); + plannerForm.fillForm(qaContent); + String contentFolderId = WebUtil.readStrParam(request, AttributeNames.PARAM_CONTENT_FOLDER_ID); + plannerForm.setContentFolderID(contentFolderId); + return mapping.findForward(QaAppConstants.SUCCESS); + } + + public ActionForward saveOrUpdatePedagogicalPlannerForm(ActionMapping mapping, ActionForm form, + HttpServletRequest request, HttpServletResponse response) throws IOException { + QaPedagogicalPlannerForm plannerForm = (QaPedagogicalPlannerForm) form; + ActionMessages errors = plannerForm.validate(); + if (errors.isEmpty()) { + + QaContent qaContent = getQaService().getQaContent(plannerForm.getToolContentID()); + + int questionIndex = 0; + String question = null; + + do { + question = plannerForm.getQuestion(questionIndex); + if (StringUtils.isEmpty(question)) { + plannerForm.removeQuestion(questionIndex); + } else { + if (questionIndex < qaContent.getQaQueContents().size()) { + QaQueContent qaQuestion = getQaService() + .getQuestionByContentAndDisplayOrder((long) questionIndex + 1, qaContent.getUid()); + qaQuestion.setQuestion(question); + getQaService().saveOrUpdateQuestion(qaQuestion); + + } else { + QaQueContent qaQuestion = new QaQueContent(); + qaQuestion.setDisplayOrder(questionIndex + 1); + qaQuestion.setRequired(false); + qaQuestion.setQaContent(qaContent); + qaQuestion.setQuestion(question); + getQaService().saveOrUpdateQuestion(qaQuestion); + } + questionIndex++; + } + } while (question != null); + if (questionIndex < qaContent.getQaQueContents().size()) { + getQaService().removeQuestionsFromCache(qaContent); + getQaService().removeQaContentFromCache(qaContent); + for (; questionIndex < qaContent.getQaQueContents().size(); questionIndex++) { + QaQueContent qaQuestion = getQaService() + .getQuestionByContentAndDisplayOrder((long) questionIndex + 1, qaContent.getUid()); + getQaService().removeQuestion(qaQuestion); + } + } + } else { + saveErrors(request, errors); + } + return mapping.findForward(QaAppConstants.SUCCESS); + } + + public ActionForward createPedagogicalPlannerQuestion(ActionMapping mapping, ActionForm form, + HttpServletRequest request, HttpServletResponse response) { + QaPedagogicalPlannerForm plannerForm = (QaPedagogicalPlannerForm) form; + plannerForm.setQuestion(plannerForm.getQuestionCount().intValue(), ""); + return mapping.findForward(QaAppConstants.SUCCESS); + } + + private IQaService getQaService() { + WebApplicationContext wac = WebApplicationContextUtils + .getRequiredWebApplicationContext(getServlet().getServletContext()); + return QaServiceProxy.getQaService(getServlet().getServletContext()); + } +} \ No newline at end of file Index: lams_tool_laqa/src/java/org/lamsfoundation/lams/tool/qa/web/action/QaStarterAction.java =================================================================== diff -u --- lams_tool_laqa/src/java/org/lamsfoundation/lams/tool/qa/web/action/QaStarterAction.java (revision 0) +++ lams_tool_laqa/src/java/org/lamsfoundation/lams/tool/qa/web/action/QaStarterAction.java (revision 32eb376c59d7c17cfa9d51cac14c00aae8cf44ff) @@ -0,0 +1,284 @@ +/**************************************************************** + * Copyright (C) 2005 LAMS Foundation (http://lamsfoundation.org) + * ============================================================= + * License Information: http://lamsfoundation.org/licensing/lams/2.0/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + * USA + * + * http://www.gnu.org/licenses/gpl.txt + * **************************************************************** + */ + + +package org.lamsfoundation.lams.tool.qa.web.action; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.SortedSet; +import java.util.TreeSet; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.lang.StringUtils; +import org.apache.log4j.Logger; +import org.apache.struts.Globals; +import org.apache.struts.action.Action; +import org.apache.struts.action.ActionForm; +import org.apache.struts.action.ActionForward; +import org.apache.struts.action.ActionMapping; +import org.apache.struts.action.ActionMessage; +import org.apache.struts.action.ActionMessages; +import org.lamsfoundation.lams.learningdesign.TextSearchConditionComparator; +import org.lamsfoundation.lams.rating.model.RatingCriteria; +import org.lamsfoundation.lams.tool.ToolAccessMode; +import org.lamsfoundation.lams.tool.qa.QaAppConstants; +import org.lamsfoundation.lams.tool.qa.QaCondition; +import org.lamsfoundation.lams.tool.qa.QaContent; +import org.lamsfoundation.lams.tool.qa.QaQueContent; +import org.lamsfoundation.lams.tool.qa.dto.QaQuestionDTO; +import org.lamsfoundation.lams.tool.qa.service.IQaService; +import org.lamsfoundation.lams.tool.qa.service.QaServiceProxy; +import org.lamsfoundation.lams.tool.qa.util.QaApplicationException; +import org.lamsfoundation.lams.tool.qa.util.QaUtils; +import org.lamsfoundation.lams.tool.qa.web.form.QaAuthoringForm; +import org.lamsfoundation.lams.util.WebUtil; +import org.lamsfoundation.lams.web.util.AttributeNames; +import org.lamsfoundation.lams.web.util.SessionMap; + +/** + * Initializes the tool's authoring mode + * + * @author Ozgur Demirtas + */ +public class QaStarterAction extends Action implements QaAppConstants { + private static Logger logger = Logger.getLogger(QaStarterAction.class.getName()); + + @Override + public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) throws IOException, ServletException, QaApplicationException { + + QaUtils.cleanUpSessionAbsolute(request); + QaAuthoringForm qaAuthoringForm = (QaAuthoringForm) form; + + String contentFolderID = WebUtil.readStrParam(request, AttributeNames.PARAM_CONTENT_FOLDER_ID); + qaAuthoringForm.setContentFolderID(contentFolderID); + + qaAuthoringForm.resetRadioBoxes(); + + IQaService qaService = null; + if (getServlet() == null || getServlet().getServletContext() == null) { + qaService = qaAuthoringForm.getQaService(); + } else { + qaService = QaServiceProxy.getQaService(getServlet().getServletContext()); + } + + validateDefaultContent(request, mapping, qaService, qaAuthoringForm); + + //no problems getting the default content, will render authoring screen + String strToolContentID = ""; + /* the authoring url must be passed a tool content id */ + strToolContentID = request.getParameter(AttributeNames.PARAM_TOOL_CONTENT_ID); + qaAuthoringForm.setToolContentID(strToolContentID); + + SessionMap sessionMap = new SessionMap(); + sessionMap.put(QaAppConstants.ACTIVITY_TITLE_KEY, ""); + sessionMap.put(QaAppConstants.ACTIVITY_INSTRUCTIONS_KEY, ""); + sessionMap.put(AttributeNames.PARAM_CONTENT_FOLDER_ID, contentFolderID); + qaAuthoringForm.setHttpSessionID(sessionMap.getSessionID()); + + if (strToolContentID == null || strToolContentID.equals("")) { + QaUtils.cleanUpSessionAbsolute(request); + throw new ServletException("No Tool Content ID found"); + } + + QaContent qaContent = qaService.getQaContent(new Long(strToolContentID).longValue()); + if (qaContent == null) { + /* fetch default content */ + long defaultContentID = qaService.getToolDefaultContentIdBySignature(QaAppConstants.MY_SIGNATURE); + qaContent = qaService.getQaContent(defaultContentID); + qaContent = QaContent.newInstance(qaContent, new Long(strToolContentID)); + } + + prepareDTOandForm(request, qaAuthoringForm, qaContent, qaService, sessionMap); + + ToolAccessMode mode = WebUtil.readToolAccessModeAuthorDefaulted(request); + // request is from monitoring module + if (mode.isTeacher()) { + qaService.setDefineLater(strToolContentID, true); + } + request.setAttribute(AttributeNames.ATTR_MODE, mode.toString()); + + SortedSet conditionList = getQaConditionList(sessionMap); + conditionList.clear(); + conditionList.addAll(qaContent.getConditions()); + + qaAuthoringForm.setAllowRichEditor(qaContent.isAllowRichEditor()); + qaAuthoringForm.setUseSelectLeaderToolOuput(qaContent.isUseSelectLeaderToolOuput()); + + sessionMap.put(QaAppConstants.ATTR_QA_AUTHORING_FORM, qaAuthoringForm); + request.getSession().setAttribute(sessionMap.getSessionID(), sessionMap); + + // get rating criterias from DB + List ratingCriterias = qaService.getRatingCriterias(qaContent.getQaContentId()); + sessionMap.put(AttributeNames.ATTR_RATING_CRITERIAS, ratingCriterias); + + return mapping.findForward(LOAD_QUESTIONS); + } + + /** + * retrives the existing content information from the db and prepares the data for presentation purposes. + * + * @param request + * @param mapping + * @param qaAuthoringForm + * @param mapQuestionContent + * @param toolContentID + * @return ActionForward + */ + protected QaContent prepareDTOandForm(HttpServletRequest request, QaAuthoringForm qaAuthoringForm, + QaContent qaContent, IQaService qaService, SessionMap sessionMap) { + + qaAuthoringForm.setUsernameVisible(qaContent.isUsernameVisible() ? "1" : "0"); + qaAuthoringForm.setAllowRateAnswers(qaContent.isAllowRateAnswers() ? "1" : "0"); + qaAuthoringForm.setNotifyTeachersOnResponseSubmit(qaContent.isNotifyTeachersOnResponseSubmit() ? "1" : "0"); + qaAuthoringForm.setShowOtherAnswers(qaContent.isShowOtherAnswers() ? "1" : "0"); + qaAuthoringForm.setQuestionsSequenced(qaContent.isQuestionsSequenced() ? "1" : "0"); + qaAuthoringForm.setLockWhenFinished(qaContent.isLockWhenFinished() ? "1" : "0"); + qaAuthoringForm.setNoReeditAllowed(qaContent.isNoReeditAllowed() ? "1" : "0"); + qaAuthoringForm.setMaximumRates(qaContent.getMaximumRates()); + qaAuthoringForm.setMinimumRates(qaContent.getMinimumRates()); + qaAuthoringForm.setReflect(qaContent.isReflect() ? "1" : "0"); + qaAuthoringForm.setReflectionSubject(qaContent.getReflectionSubject()); + qaAuthoringForm.setTitle(qaContent.getTitle()); + qaAuthoringForm.setInstructions(qaContent.getInstructions()); + sessionMap.put(QaAppConstants.ACTIVITY_TITLE_KEY, qaContent.getTitle()); + sessionMap.put(QaAppConstants.ACTIVITY_INSTRUCTIONS_KEY, qaContent.getInstructions()); + + List questionDTOs = new LinkedList(); + + /* + * get the existing question content + */ + Iterator queIterator = qaContent.getQaQueContents().iterator(); + while (queIterator.hasNext()) { + + QaQueContent qaQuestion = (QaQueContent) queIterator.next(); + if (qaQuestion != null) { + QaQuestionDTO qaQuestionDTO = new QaQuestionDTO(qaQuestion); + questionDTOs.add(qaQuestionDTO); + } + } + + request.setAttribute(QaAppConstants.TOTAL_QUESTION_COUNT, new Integer(questionDTOs.size())); + request.setAttribute(QaAppConstants.LIST_QUESTION_DTOS, questionDTOs); + sessionMap.put(QaAppConstants.LIST_QUESTION_DTOS, questionDTOs); + + SortedSet conditionSet = new TreeSet(new TextSearchConditionComparator()); + for (QaCondition condition : qaContent.getConditions()) { + conditionSet.add(condition); + for (QaQuestionDTO dto : questionDTOs) { + for (QaQueContent question : condition.getQuestions()) { + if (dto.getDisplayOrder().equals(String.valueOf(question.getDisplayOrder()))) { + condition.temporaryQuestionDTOSet.add(dto); + } + } + } + } + sessionMap.put(QaAppConstants.ATTR_CONDITION_SET, conditionSet); + + List listDeletedQuestionDTOs = new ArrayList(); + sessionMap.put(QaAppConstants.LIST_DELETED_QUESTION_DTOS, listDeletedQuestionDTOs); + + qaAuthoringForm.resetUserAction(); + + return qaContent; + } + + /** + * each tool has a signature. QA tool's signature is stored in MY_SIGNATURE. + * The default tool content id and other depending content ids are obtained + * in this method. if all the default content has been setup properly the + * method persists DEFAULT_CONTENT_ID in the session. + * + * @param request + * @param mapping + * @return ActionForward + */ + public boolean validateDefaultContent(HttpServletRequest request, ActionMapping mapping, IQaService qaService, + QaAuthoringForm qaAuthoringForm) { + + /* + * retrieve the default content id based on tool signature + */ + long defaultContentID = 0; + try { + defaultContentID = qaService.getToolDefaultContentIdBySignature(QaAppConstants.MY_SIGNATURE); + if (defaultContentID == 0) { + QaStarterAction.logger.debug("default content id has not been setup"); + return false; + } + } catch (Exception e) { + QaStarterAction.logger.error("error getting the default content id: " + e.getMessage()); + persistError(request, "error.defaultContent.notSetup"); + return false; + } + + /* + * retrieve uid of the content based on default content id determined above + */ + try { + //retrieve uid of the content based on default content id determined above + QaContent qaContent = qaService.getQaContent(defaultContentID); + if (qaContent == null) { + QaStarterAction.logger.error("Exception occured: No default content"); + persistError(request, "error.defaultContent.notSetup"); + return false; + } + + } catch (Exception e) { + QaStarterAction.logger.error("Exception occured: No default question content"); + persistError(request, "error.defaultContent.notSetup"); + return false; + } + + return true; + } + + /** + * persists error messages to request scope + * + * @param request + * @param message + */ + public void persistError(HttpServletRequest request, String message) { + ActionMessages errors = new ActionMessages(); + errors.add(Globals.ERROR_KEY, new ActionMessage(message)); + saveErrors(request, errors); + } + + private SortedSet getQaConditionList(SessionMap sessionMap) { + SortedSet list = (SortedSet) sessionMap.get(QaAppConstants.ATTR_CONDITION_SET); + if (list == null) { + list = new TreeSet(new TextSearchConditionComparator()); + sessionMap.put(QaAppConstants.ATTR_CONDITION_SET, list); + } + return list; + } +} Index: lams_tool_laqa/web/WEB-INF/struts-config.xml =================================================================== diff -u -r320934945c495ab0832be6fb547d83812ac3152a -r32eb376c59d7c17cfa9d51cac14c00aae8cf44ff --- lams_tool_laqa/web/WEB-INF/struts-config.xml (.../struts-config.xml) (revision 320934945c495ab0832be6fb547d83812ac3152a) +++ lams_tool_laqa/web/WEB-INF/struts-config.xml (.../struts-config.xml) (revision 32eb376c59d7c17cfa9d51cac14c00aae8cf44ff) @@ -45,7 +45,7 @@ - +