Index: lams_tool_lamc/src/java/org/lamsfoundation/lams/tool/mc/util/AuthoringUtil.java =================================================================== diff -u --- lams_tool_lamc/src/java/org/lamsfoundation/lams/tool/mc/util/AuthoringUtil.java (revision 0) +++ lams_tool_lamc/src/java/org/lamsfoundation/lams/tool/mc/util/AuthoringUtil.java (revision 4170df8bc66e658ef4dcd47e99eceddec3c2673a) @@ -0,0 +1,253 @@ +/*************************************************************************** + * 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.mc.util; + +import java.util.Date; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; +import java.util.TreeMap; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpSession; + +import org.apache.commons.lang.StringUtils; +import org.apache.log4j.Logger; +import org.lamsfoundation.lams.tool.mc.McAppConstants; +import org.lamsfoundation.lams.tool.mc.dto.McOptionDTO; +import org.lamsfoundation.lams.tool.mc.dto.McQuestionDTO; +import org.lamsfoundation.lams.tool.mc.pojos.McContent; +import org.lamsfoundation.lams.tool.mc.pojos.McOptsContent; +import org.lamsfoundation.lams.tool.mc.pojos.McQueContent; +import org.lamsfoundation.lams.tool.mc.service.IMcService; +import org.lamsfoundation.lams.usermanagement.dto.UserDTO; +import org.lamsfoundation.lams.web.session.SessionManager; +import org.lamsfoundation.lams.web.util.AttributeNames; + +/** + * Keeps all operations needed for Authoring mode. + * + * @author Ozgur Demirtas + */ +public class AuthoringUtil { + private static Logger logger = Logger.getLogger(AuthoringUtil.class.getName()); + + /** + * extractCandidateAtOrder + */ + public static McOptionDTO getOptionAtDisplayOrder(List options, int intOriginalCandidateIndex) { + int counter = 0; + Iterator iter = options.iterator(); + while (iter.hasNext()) { + ++counter; + McOptionDTO optionDto = (McOptionDTO) iter.next(); + + if (new Integer(intOriginalCandidateIndex).toString().equals(new Integer(counter).toString())) { + return optionDto; + } + } + return null; + } + + /** + * persisting content + */ + public static McContent saveOrUpdateMcContent(IMcService mcService, HttpServletRequest request, McContent mcContent, + String strToolContentID, List questionDTOs) { + UserDTO toolUser = (UserDTO) SessionManager.getSession().getAttribute(AttributeNames.USER); + + String richTextTitle = request.getParameter(McAppConstants.TITLE); + String richTextInstructions = request.getParameter(McAppConstants.INSTRUCTIONS); + String sln = request.getParameter("sln"); + String useSelectLeaderToolOuput = request.getParameter("useSelectLeaderToolOuput"); + String prefixAnswersWithLetters = request.getParameter("prefixAnswersWithLetters"); + String questionsSequenced = request.getParameter("questionsSequenced"); + String randomize = request.getParameter("randomize"); + String displayAnswers = request.getParameter("displayAnswers"); + String showMarks = request.getParameter("showMarks"); + String retries = request.getParameter("retries"); + String reflect = request.getParameter(McAppConstants.REFLECT); + String reflectionSubject = request.getParameter(McAppConstants.REFLECTION_SUBJECT); + + boolean questionsSequencedBoolean = false; + boolean randomizeBoolean = false; + boolean displayAnswersBoolean = false; + boolean showMarksBoolean = false; + boolean slnBoolean = false; + boolean useSelectLeaderToolOuputBoolean = false; + boolean prefixAnswersWithLettersBoolean = false; + boolean retriesBoolean = false; + boolean reflectBoolean = false; + + if ((questionsSequenced != null) && (questionsSequenced.equalsIgnoreCase("1"))) { + questionsSequencedBoolean = true; + } + + if ((randomize != null) && (randomize.equalsIgnoreCase("1"))) { + randomizeBoolean = true; + } + + if ((displayAnswers != null) && (displayAnswers.equalsIgnoreCase("1"))) { + displayAnswersBoolean = true; + } + + if ((showMarks != null) && (showMarks.equalsIgnoreCase("1"))) { + showMarksBoolean = true; + } + + if ((sln != null) && (sln.equalsIgnoreCase("1"))) { + slnBoolean = true; + } + + if ((useSelectLeaderToolOuput != null) && (useSelectLeaderToolOuput.equalsIgnoreCase("1"))) { + useSelectLeaderToolOuputBoolean = true; + } + + if ((prefixAnswersWithLetters != null) && (prefixAnswersWithLetters.equalsIgnoreCase("1"))) { + prefixAnswersWithLettersBoolean = true; + } + + if ((retries != null) && (retries.equalsIgnoreCase("1"))) { + retriesBoolean = 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 { + // should not reach here + userId = 0; + } + } + + boolean newContent = false; + if (mcContent == null) { + mcContent = new McContent(); + newContent = true; + } + + mcContent.setMcContentId(new Long(strToolContentID)); + mcContent.setTitle(richTextTitle); + mcContent.setInstructions(richTextInstructions); + mcContent.setUpdateDate(new Date(System.currentTimeMillis())); + /** keep updating this one */ + mcContent.setCreatedBy(userId); + /** make sure we are setting the userId from the User object above */ + + mcContent.setQuestionsSequenced(questionsSequencedBoolean); + mcContent.setRandomize(randomizeBoolean); + mcContent.setDisplayAnswers(displayAnswersBoolean); + mcContent.setShowMarks(showMarksBoolean); + mcContent.setRetries(retriesBoolean); + mcContent.setShowReport(slnBoolean); + mcContent.setUseSelectLeaderToolOuput(useSelectLeaderToolOuputBoolean); + mcContent.setPrefixAnswersWithLetters(prefixAnswersWithLettersBoolean); + + mcContent.setReflect(reflectBoolean); + mcContent.setReflectionSubject(reflectionSubject); + + //calculate total mark + int totalMark = 0; + for (McQuestionDTO questionDto: questionDTOs) { + String mark = questionDto.getMark(); + if (StringUtils.isNotBlank(mark)) { + int intMark = new Integer(mark).intValue(); + totalMark += intMark; + } + } + + String passmarkStr = request.getParameter("passmark"); + //nullify passmark in case 'retries' option is OFF + if (StringUtils.isBlank(passmarkStr) || !retriesBoolean) { + passmarkStr = "0"; + } + //passmark can't be more than total mark + Integer passmark = new Integer(passmarkStr); + if (totalMark < passmark) { + passmark = totalMark; + } + mcContent.setPassMark(passmark); + + if (newContent) { + mcService.createMc(mcContent); + } else { + mcService.updateMc(mcContent); + } + + mcContent = mcService.getMcContent(new Long(strToolContentID)); + + return mcContent; + } + + /** + * generates a list for holding default questions and their candidate answers + */ + public static List buildDefaultQuestions(McContent mcContent) { + List questionDtos = new LinkedList(); + + Long mapIndex = new Long(1); + + for (McQueContent question : (Set) mcContent.getMcQueContents()) { + McQuestionDTO questionDto = new McQuestionDTO(); + + String feedback = ""; + if (question.getFeedback() != null) { + feedback = question.getFeedback(); + } + + String questionText = question.getQuestion(); + + questionDto.setUid(question.getUid()); + questionDto.setQuestion(questionText); + questionDto.setDisplayOrder(question.getDisplayOrder()); + questionDto.setFeedback(feedback); + questionDto.setMark(question.getMark().toString()); + + // build candidate dtos + List optionDtos = new LinkedList(); + for (McOptsContent option : (Set) question.getMcOptionsContents()) { + McOptionDTO optionDTO = new McOptionDTO(option); + optionDtos.add(optionDTO); + } + + questionDto.setOptionDtos(optionDtos); + questionDtos.add(questionDto); + + mapIndex = new Long(mapIndex.longValue() + 1); + } + + return questionDtos; + } +} Index: lams_tool_lamc/src/java/org/lamsfoundation/lams/tool/mc/util/LearningUtil.java =================================================================== diff -u --- lams_tool_lamc/src/java/org/lamsfoundation/lams/tool/mc/util/LearningUtil.java (revision 0) +++ lams_tool_lamc/src/java/org/lamsfoundation/lams/tool/mc/util/LearningUtil.java (revision 4170df8bc66e658ef4dcd47e99eceddec3c2673a) @@ -0,0 +1,86 @@ +/*************************************************************************** + * 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.mc.util; + +import java.util.Iterator; +import java.util.List; + +import javax.servlet.http.HttpServletRequest; + +import org.apache.log4j.Logger; +import org.lamsfoundation.lams.tool.mc.dto.AnswerDTO; +import org.lamsfoundation.lams.tool.mc.dto.McGeneralLearnerFlowDTO; +import org.lamsfoundation.lams.tool.mc.pojos.McContent; +import org.lamsfoundation.lams.tool.mc.web.form.McLearningForm; + +/** + * + * Keeps all operations needed for Authoring mode. + * + * @author Ozgur Demirtas + */ +public class LearningUtil { + static Logger logger = Logger.getLogger(LearningUtil.class.getName()); + + public static void saveFormRequestData(HttpServletRequest request, McLearningForm mcLearningForm) { + + String httpSessionID = request.getParameter("httpSessionID"); + mcLearningForm.setHttpSessionID(httpSessionID); + + String passMarkApplicable = request.getParameter("passMarkApplicable"); + mcLearningForm.setPassMarkApplicable(passMarkApplicable); + + String userOverPassMark = request.getParameter("userOverPassMark"); + mcLearningForm.setUserOverPassMark(userOverPassMark); + } + + /** + * buildMcGeneralLearnerFlowDTO + */ + public static McGeneralLearnerFlowDTO buildMcGeneralLearnerFlowDTO(McContent mcContent) { + McGeneralLearnerFlowDTO mcGeneralLearnerFlowDTO = new McGeneralLearnerFlowDTO(); + mcGeneralLearnerFlowDTO.setRetries(new Boolean(mcContent.isRetries()).toString()); + mcGeneralLearnerFlowDTO.setActivityTitle(mcContent.getTitle()); + mcGeneralLearnerFlowDTO.setActivityInstructions(mcContent.getInstructions()); + mcGeneralLearnerFlowDTO.setPassMark(mcContent.getPassMark()); + mcGeneralLearnerFlowDTO.setReportTitleLearner("Report"); + + mcGeneralLearnerFlowDTO.setTotalQuestionCount(new Integer(mcContent.getMcQueContents().size())); + return mcGeneralLearnerFlowDTO; + } + + /** + * Should we show the marks for each question - we show the marks if any of the questions have a mark > 1. + */ + public static Boolean isShowMarksOnQuestion(List listQuestionAndCandidateAnswersDTO) { + Iterator iter = listQuestionAndCandidateAnswersDTO.iterator(); + while (iter.hasNext()) { + AnswerDTO elem = (AnswerDTO) iter.next(); + if (elem.getMark().intValue() > 1) { + return Boolean.TRUE; + } + } + return Boolean.FALSE; + } + +} Fisheye: Tag 4170df8bc66e658ef4dcd47e99eceddec3c2673a refers to a dead (removed) revision in file `lams_tool_lamc/src/java/org/lamsfoundation/lams/tool/mc/web/AuthoringUtil.java'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 4170df8bc66e658ef4dcd47e99eceddec3c2673a refers to a dead (removed) revision in file `lams_tool_lamc/src/java/org/lamsfoundation/lams/tool/mc/web/ClearSessionAction.java'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 4170df8bc66e658ef4dcd47e99eceddec3c2673a refers to a dead (removed) revision in file `lams_tool_lamc/src/java/org/lamsfoundation/lams/tool/mc/web/LearningUtil.java'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 4170df8bc66e658ef4dcd47e99eceddec3c2673a refers to a dead (removed) revision in file `lams_tool_lamc/src/java/org/lamsfoundation/lams/tool/mc/web/McAction.java'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 4170df8bc66e658ef4dcd47e99eceddec3c2673a refers to a dead (removed) revision in file `lams_tool_lamc/src/java/org/lamsfoundation/lams/tool/mc/web/McLearningAction.java'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 4170df8bc66e658ef4dcd47e99eceddec3c2673a refers to a dead (removed) revision in file `lams_tool_lamc/src/java/org/lamsfoundation/lams/tool/mc/web/McLearningStarterAction.java'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 4170df8bc66e658ef4dcd47e99eceddec3c2673a refers to a dead (removed) revision in file `lams_tool_lamc/src/java/org/lamsfoundation/lams/tool/mc/web/McMonitoringAction.java'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 4170df8bc66e658ef4dcd47e99eceddec3c2673a refers to a dead (removed) revision in file `lams_tool_lamc/src/java/org/lamsfoundation/lams/tool/mc/web/McMonitoringStarterAction.java'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 4170df8bc66e658ef4dcd47e99eceddec3c2673a refers to a dead (removed) revision in file `lams_tool_lamc/src/java/org/lamsfoundation/lams/tool/mc/web/McPedagogicalPlannerAction.java'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 4170df8bc66e658ef4dcd47e99eceddec3c2673a refers to a dead (removed) revision in file `lams_tool_lamc/src/java/org/lamsfoundation/lams/tool/mc/web/McStarterAction.java'. Fisheye: No comparison available. Pass `N' to diff? Index: lams_tool_lamc/src/java/org/lamsfoundation/lams/tool/mc/web/action/ClearSessionAction.java =================================================================== diff -u --- lams_tool_lamc/src/java/org/lamsfoundation/lams/tool/mc/web/action/ClearSessionAction.java (revision 0) +++ lams_tool_lamc/src/java/org/lamsfoundation/lams/tool/mc/web/action/ClearSessionAction.java (revision 4170df8bc66e658ef4dcd47e99eceddec3c2673a) @@ -0,0 +1,44 @@ +/**************************************************************** + * 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.mc.web.action; + +import javax.servlet.http.HttpSession; + +import org.lamsfoundation.lams.authoring.web.LamsAuthoringFinishAction; +import org.lamsfoundation.lams.tool.ToolAccessMode; + +/** + * This class give a chance to clear HttpSession when user save/close authoring page. + */ +public class ClearSessionAction extends LamsAuthoringFinishAction { + + @Override + public void clearSession(String customiseSessionID, HttpSession session, ToolAccessMode mode) { + if (mode.isAuthor()) { + session.removeAttribute(customiseSessionID); + } + } + +} Index: lams_tool_lamc/src/java/org/lamsfoundation/lams/tool/mc/web/action/McAction.java =================================================================== diff -u --- lams_tool_lamc/src/java/org/lamsfoundation/lams/tool/mc/web/action/McAction.java (revision 0) +++ lams_tool_lamc/src/java/org/lamsfoundation/lams/tool/mc/web/action/McAction.java (revision 4170df8bc66e658ef4dcd47e99eceddec3c2673a) @@ -0,0 +1,766 @@ +/**************************************************************** + * 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.mc.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.Set; + +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.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.questions.Answer; +import org.lamsfoundation.lams.questions.Question; +import org.lamsfoundation.lams.questions.QuestionExporter; +import org.lamsfoundation.lams.questions.QuestionParser; +import org.lamsfoundation.lams.tool.ToolAccessMode; +import org.lamsfoundation.lams.tool.mc.McAppConstants; +import org.lamsfoundation.lams.tool.mc.dto.McOptionDTO; +import org.lamsfoundation.lams.tool.mc.dto.McQuestionDTO; +import org.lamsfoundation.lams.tool.mc.pojos.McContent; +import org.lamsfoundation.lams.tool.mc.pojos.McQueContent; +import org.lamsfoundation.lams.tool.mc.service.IMcService; +import org.lamsfoundation.lams.tool.mc.service.McServiceProxy; +import org.lamsfoundation.lams.tool.mc.util.AuthoringUtil; +import org.lamsfoundation.lams.tool.mc.web.form.McAuthoringForm; +import org.lamsfoundation.lams.util.WebUtil; +import org.lamsfoundation.lams.web.action.LamsDispatchAction; +import org.lamsfoundation.lams.web.util.AttributeNames; +import org.lamsfoundation.lams.web.util.SessionMap; + +/** + * Action class that controls the logic of tool behavior. + * + * @author Ozgur Demirtas + */ +public class McAction extends LamsDispatchAction { + private static Logger logger = Logger.getLogger(McAction.class.getName()); + + /** + * submits content into the tool database + */ + public ActionForward submitAllContent(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) throws IOException, ServletException { + + McAuthoringForm mcAuthoringForm = (McAuthoringForm) form; + IMcService mcService = McServiceProxy.getMcService(getServlet().getServletContext()); + String sessionMapId = mcAuthoringForm.getHttpSessionID(); + SessionMap sessionMap = (SessionMap) request.getSession() + .getAttribute(sessionMapId); + request.setAttribute(McAppConstants.ATTR_SESSION_MAP_ID, sessionMapId); + + String strToolContentID = (String) sessionMap.get(AttributeNames.PARAM_TOOL_CONTENT_ID); + List questionDTOs = (List) sessionMap.get(McAppConstants.QUESTION_DTOS); + McContent mcContent = mcService.getMcContent(new Long(strToolContentID)); + ToolAccessMode mode = (ToolAccessMode) sessionMap.get(AttributeNames.ATTR_MODE); + List deletedQuestionDTOs = (List) sessionMap + .get(McAppConstants.LIST_DELETED_QUESTION_DTOS); + + if (questionDTOs.isEmpty()) { + ActionMessages errors = new ActionMessages(); + ActionMessage error = new ActionMessage("questions.none.submitted"); + errors.add(ActionMessages.GLOBAL_MESSAGE, error); + saveErrors(request, errors); + McAction.logger.debug("errors saved: " + errors); + return mapping.findForward(McAppConstants.LOAD_AUTHORING); + } + + // in case request is from monitoring module - prepare for recalculate User Answers + if (mode.isTeacher()) { + Set oldQuestions = mcContent.getMcQueContents(); + mcService.releaseQuestionsFromCache(mcContent); + mcService.setDefineLater(strToolContentID, false); + + // audit log the teacher has started editing activity in monitor + mcService.auditLogStartEditingActivityInMonitor(new Long(strToolContentID)); + + // recalculate User Answers + mcService.recalculateUserAnswers(mcContent, oldQuestions, questionDTOs, deletedQuestionDTOs); + } + + // remove deleted questions + for (McQuestionDTO deletedQuestionDTO : deletedQuestionDTOs) { + McQueContent removeableQuestion = mcService.getQuestionByUid(deletedQuestionDTO.getUid()); + if (removeableQuestion != null) { + // Set attempts = removeableQuestion.getMcUsrAttempts(); + // Iterator iter = attempts.iterator(); + // while (iter.hasNext()) { + // McUsrAttempt attempt = iter.next(); + // iter.remove(); + // } + // mcService.updateQuestion(removeableQuestion); + mcContent.getMcQueContents().remove(removeableQuestion); + mcService.removeMcQueContent(removeableQuestion); + } + } + + // store content + mcContent = AuthoringUtil.saveOrUpdateMcContent(mcService, request, mcContent, strToolContentID, questionDTOs); + + // store questions + mcContent = mcService.createQuestions(questionDTOs, mcContent); + + if (mcContent != null) { + // sorts the questions by the display order + List sortedQuestions = mcService.getAllQuestionsSorted(mcContent.getUid().longValue()); + int displayOrder = 1; + for (McQueContent question : sortedQuestions) { + McQueContent existingQuestion = mcService.getQuestionByUid(question.getUid()); + existingQuestion.setDisplayOrder(new Integer(displayOrder)); + mcService.updateQuestion(existingQuestion); + displayOrder++; + } + } + + request.setAttribute(AuthoringConstants.LAMS_AUTHORING_SUCCESS_FLAG, Boolean.TRUE); + return mapping.findForward(McAppConstants.LOAD_AUTHORING); + } + + /** + * opens up an new screen within the current page for editing a question + */ + public ActionForward editQuestionBox(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) throws IOException, ServletException { + McAuthoringForm mcAuthoringForm = (McAuthoringForm) form; + String sessionMapId = request.getParameter(McAppConstants.ATTR_SESSION_MAP_ID); + SessionMap sessionMap = (SessionMap) request.getSession() + .getAttribute(sessionMapId); + request.setAttribute(McAppConstants.ATTR_SESSION_MAP_ID, sessionMapId); + List questionDtos = (List) sessionMap.get(McAppConstants.QUESTION_DTOS); + + Integer questionIndex = WebUtil.readIntParam(request, "questionIndex", true); + + McQuestionDTO questionDto = null; + //editing existing question + if (questionIndex != null) { + mcAuthoringForm.setQuestionIndex(questionIndex); + + //find according questionDto + for (McQuestionDTO questionDtoIter : questionDtos) { + Integer displayOrder = questionDtoIter.getDisplayOrder(); + + if ((displayOrder != null) && displayOrder.equals(questionIndex)) { + questionDto = questionDtoIter; + break; + } + } + + //adding new question + } else { + // prepare question for adding new question page + questionDto = new McQuestionDTO(); + List newOptions = new ArrayList<>(); + McOptionDTO newOption1 = new McOptionDTO(); + newOption1.setCorrect("Correct"); + McOptionDTO newOption2 = new McOptionDTO(); + newOptions.add(newOption1); + newOptions.add(newOption2); + questionDto.setOptionDtos(newOptions); + } + sessionMap.put(McAppConstants.QUESTION_DTO, questionDto); + + 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 { + McAuthoringForm mcAuthoringForm = (McAuthoringForm) form; + + String sessionMapId = request.getParameter(McAppConstants.ATTR_SESSION_MAP_ID); + SessionMap sessionMap = (SessionMap) request.getSession() + .getAttribute(sessionMapId); + request.setAttribute(McAppConstants.ATTR_SESSION_MAP_ID, sessionMapId); + + Integer questionIndexToDelete = WebUtil.readIntParam(request, "questionIndex"); + mcAuthoringForm.setQuestionIndex(questionIndexToDelete); + + List questionDTOs = (List) sessionMap.get(McAppConstants.QUESTION_DTOS); + + //exclude Question with questionIndex From List + List tempQuestionDtos = new LinkedList<>(); + int queIndex = 0; + for (McQuestionDTO questionDTO : questionDTOs) { + + String questionText = questionDTO.getQuestion(); + Integer displayOrder = questionDTO.getDisplayOrder(); + if ((questionText != null) && !questionText.isEmpty()) { + + if (!displayOrder.equals(questionIndexToDelete)) { + ++queIndex; + questionDTO.setDisplayOrder(queIndex); + tempQuestionDtos.add(questionDTO); + + } else { + List deletedQuestionDTOs = (List) sessionMap + .get(McAppConstants.LIST_DELETED_QUESTION_DTOS); + deletedQuestionDTOs.add(questionDTO); + sessionMap.put(McAppConstants.LIST_DELETED_QUESTION_DTOS, deletedQuestionDTOs); + } + } + } + questionDTOs = tempQuestionDtos; + sessionMap.put(McAppConstants.QUESTION_DTOS, questionDTOs); + + return (mapping.findForward("itemList")); + } + + /** + * moves a question down in the list + * + * @param mapping + * @param form + * @param request + * @param response + * @return + * @throws IOException + * @throws ServletException + */ + public ActionForward moveQuestionDown(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) throws IOException, ServletException { + McAuthoringForm mcAuthoringForm = (McAuthoringForm) form; + + String sessionMapId = request.getParameter(McAppConstants.ATTR_SESSION_MAP_ID); + SessionMap sessionMap = (SessionMap) request.getSession() + .getAttribute(sessionMapId); + request.setAttribute(McAppConstants.ATTR_SESSION_MAP_ID, sessionMapId); + + Integer questionIndex = WebUtil.readIntParam(request, "questionIndex"); + mcAuthoringForm.setQuestionIndex(questionIndex); + + List questionDTOs = (List) sessionMap.get(McAppConstants.QUESTION_DTOS); + questionDTOs = McAction.swapQuestions(questionDTOs, questionIndex, "down"); + questionDTOs = McAction.reorderQuestionDtos(questionDTOs); + sessionMap.put(McAppConstants.QUESTION_DTOS, questionDTOs); + + return (mapping.findForward("itemList")); + } + + public ActionForward moveQuestionUp(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) throws IOException, ServletException { + McAuthoringForm mcAuthoringForm = (McAuthoringForm) form; + String sessionMapId = request.getParameter(McAppConstants.ATTR_SESSION_MAP_ID); + SessionMap sessionMap = (SessionMap) request.getSession() + .getAttribute(sessionMapId); + request.setAttribute(McAppConstants.ATTR_SESSION_MAP_ID, sessionMapId); + + Integer questionIndex = WebUtil.readIntParam(request, "questionIndex"); + mcAuthoringForm.setQuestionIndex(questionIndex); + + List questionDTOs = (List) sessionMap.get(McAppConstants.QUESTION_DTOS); + questionDTOs = McAction.swapQuestions(questionDTOs, questionIndex, "up"); + questionDTOs = McAction.reorderQuestionDtos(questionDTOs); + sessionMap.put(McAppConstants.QUESTION_DTOS, questionDTOs); + + return (mapping.findForward("itemList")); + } + + /* + * swappes McQuestionDTO questions in the list. Auxiliary method for moveQuestionDown() and moveQuestionUp() + */ + private static List swapQuestions(List questionDTOs, Integer originalQuestionIndex, + String direction) { + + int replacedQuestionIndex = direction.equals("down") ? originalQuestionIndex + 1 : originalQuestionIndex - 1; + + McQuestionDTO mainQuestion = questionDTOs.get(originalQuestionIndex - 1); + McQuestionDTO replacedQuestion = questionDTOs.get(replacedQuestionIndex - 1); + if ((mainQuestion == null) || (replacedQuestion == null)) { + return questionDTOs; + } + + List questionDtos = new LinkedList<>(); + + Iterator iter = questionDTOs.iterator(); + while (iter.hasNext()) { + McQuestionDTO questionDto = iter.next(); + McQuestionDTO tempQuestion = new McQuestionDTO(); + + if ((!questionDto.getDisplayOrder().equals(originalQuestionIndex)) + && !questionDto.getDisplayOrder().equals(replacedQuestionIndex)) { + // normal copy + tempQuestion = questionDto; + + } else if (questionDto.getDisplayOrder().equals(originalQuestionIndex)) { + // move type 1 + tempQuestion = replacedQuestion; + + } else if (questionDto.getDisplayOrder().equals(replacedQuestionIndex)) { + // move type 2 + tempQuestion = mainQuestion; + } + + questionDtos.add(tempQuestion); + } + + return questionDtos; + } + + /* + * Auxiliary method for moveQuestionDown() and moveQuestionUp() + */ + private static List reorderQuestionDtos(List questionDTOs) { + List tempQuestionDtos = new LinkedList<>(); + + int queIndex = 0; + Iterator iter = questionDTOs.iterator(); + while (iter.hasNext()) { + McQuestionDTO questionDto = iter.next(); + + String question = questionDto.getQuestion(); + String feedback = questionDto.getFeedback(); + String mark = questionDto.getMark(); + + List optionDtos = questionDto.getOptionDtos(); + if ((question != null) && (!question.equals(""))) { + ++queIndex; + + questionDto.setQuestion(question); + questionDto.setDisplayOrder(queIndex); + questionDto.setFeedback(feedback); + questionDto.setOptionDtos(optionDtos); + questionDto.setMark(mark); + tempQuestionDtos.add(questionDto); + } + } + + return tempQuestionDtos; + } + + public ActionForward saveQuestion(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) throws IOException, ServletException { + + McAuthoringForm mcAuthoringForm = (McAuthoringForm) form; + + String sessionMapId = request.getParameter(McAppConstants.ATTR_SESSION_MAP_ID); + SessionMap sessionMap = (SessionMap) request.getSession() + .getAttribute(sessionMapId); + request.setAttribute(McAppConstants.ATTR_SESSION_MAP_ID, sessionMapId); + + String mark = request.getParameter("mark"); + + List options = McAction.repopulateOptionDTOs(request, false); + + //remove blank options + List optionsWithoutEmptyOnes = new LinkedList<>(); + for (McOptionDTO optionDTO : options) { + String optionText = optionDTO.getCandidateAnswer(); + if ((optionText != null) && (optionText.length() > 0)) { + optionsWithoutEmptyOnes.add(optionDTO); + } + } + options = optionsWithoutEmptyOnes; + + List questionDTOs = (List) sessionMap.get(McAppConstants.QUESTION_DTOS); + + String newQuestion = request.getParameter("newQuestion"); + String feedback = request.getParameter("feedback"); + Integer questionIndex = WebUtil.readIntParam(request, "questionIndex", true); + mcAuthoringForm.setQuestionIndex(questionIndex); + + if ((newQuestion != null) && (newQuestion.length() > 0)) { + // adding new question + if (questionIndex == null) { + + //finding max displayOrder + int maxDisplayOrder = 0; + for (McQuestionDTO questionDTO : questionDTOs) { + int displayOrder = new Integer(questionDTO.getDisplayOrder()); + if (displayOrder > maxDisplayOrder) { + maxDisplayOrder = displayOrder; + } + } + + McQuestionDTO questionDTO = new McQuestionDTO(); + questionDTO.setQuestion(newQuestion); + questionDTO.setFeedback(feedback); + questionDTO.setDisplayOrder(maxDisplayOrder + 1); + questionDTO.setOptionDtos(options); + questionDTO.setMark(mark); + + questionDTOs.add(questionDTO); + + // updating existing question + } else { + McQuestionDTO questionDto = null; + for (McQuestionDTO questionDtoIter : questionDTOs) { + Integer displayOrder = questionDtoIter.getDisplayOrder(); + + if ((displayOrder != null) && displayOrder.equals(questionIndex)) { + questionDto = questionDtoIter; + break; + } + } + + questionDto.setQuestion(newQuestion); + questionDto.setFeedback(feedback); + questionDto.setDisplayOrder(questionIndex); + questionDto.setOptionDtos(options); + questionDto.setMark(mark); + } + } else { + // entry blank, not adding + } + + request.setAttribute(McAppConstants.QUESTION_DTOS, questionDTOs); + sessionMap.put(McAppConstants.QUESTION_DTOS, questionDTOs); + + return (mapping.findForward("itemList")); + } + + /** + * Parses questions extracted from IMS QTI file and adds them to currently edited question. + */ + @SuppressWarnings({ "unchecked", "rawtypes" }) + public ActionForward saveQTI(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) throws IOException, ServletException { + // big part of code was taken from addSingleQuestion() and saveQuestion() methods + String sessionMapId = request.getParameter(McAppConstants.ATTR_SESSION_MAP_ID); + SessionMap sessionMap = (SessionMap) request.getSession() + .getAttribute(sessionMapId); + request.setAttribute(McAppConstants.ATTR_SESSION_MAP_ID, sessionMapId); + String contentFolderID = (String) sessionMap.get(AttributeNames.PARAM_CONTENT_FOLDER_ID); + + List questionDtos = (List) sessionMap.get(McAppConstants.QUESTION_DTOS); + // proper parsing + Question[] questions = QuestionParser.parseQuestionChoiceForm(request); + + for (Question question : questions) { + // quietly do same verification as in other question-adding methods + String questionText = question.getText(); + if (StringUtils.isBlank(questionText)) { + logger.warn("Skipping a blank question."); + continue; + } + + questionText = QuestionParser.processHTMLField(questionText, false, contentFolderID, + question.getResourcesFolderPath()); + + List optionDtos = new ArrayList<>(); + String correctAnswer = null; + Integer correctAnswerScore = 1; + + if (question.getAnswers() != null) { + for (Answer answer : question.getAnswers()) { + McOptionDTO optionDto = new McOptionDTO(); + String answerText = QuestionParser.processHTMLField(answer.getText(), false, contentFolderID, + question.getResourcesFolderPath()); + if (answerText == null) { + logger.warn("Skipping a blank answer"); + continue; + } + if ((correctAnswer != null) && correctAnswer.equals(answerText)) { + logger.warn("Skipping an answer with same text as the correct answer: " + answerText); + + continue; + } + + optionDto.setCandidateAnswer(answerText); + + if ((answer.getScore() != null) && (answer.getScore() > 0)) { + if (correctAnswer == null) { + optionDto.setCorrect("Correct"); + correctAnswer = optionDto.getCandidateAnswer(); + // marks are integer numbers + correctAnswerScore = Math.min(new Double(Math.ceil(answer.getScore())).intValue(), 10); + } else { + // there can be only one correct answer in a MCQ question + logger.warn( + "Choosing only first correct answer, despite another one was found: " + answerText); + optionDto.setCorrect("Incorrect"); + } + } else { + optionDto.setCorrect("Incorrect"); + } + + optionDtos.add(optionDto); + } + } + + if (correctAnswer == null) { + logger.warn("No correct answer found for question: " + questionText); + continue; + } + + McQuestionDTO questionDto = new McQuestionDTO(); + questionDto.setDisplayOrder(questionDtos.size() + 1); + questionDto.setQuestion(questionText); + questionDto.setFeedback(QuestionParser.processHTMLField(question.getFeedback(), true, null, null)); + questionDto.setOptionDtos(optionDtos); + questionDto.setMark(correctAnswerScore.toString()); + + questionDtos.add(questionDto); + + if (logger.isDebugEnabled()) { + logger.debug("Added question: " + questionText); + } + } + + sessionMap.put(McAppConstants.QUESTION_DTOS, questionDtos); + + return mapping.findForward("itemList"); + } + + /** + * Prepares MC questions for QTI packing + */ + @SuppressWarnings({ "unchecked", "rawtypes" }) + public ActionForward exportQTI(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) throws IOException { + String sessionMapId = request.getParameter(McAppConstants.ATTR_SESSION_MAP_ID); + SessionMap sessionMap = (SessionMap) request.getSession() + .getAttribute(sessionMapId); + request.setAttribute(McAppConstants.ATTR_SESSION_MAP_ID, sessionMapId); + + List questionDtos = (List) sessionMap.get(McAppConstants.QUESTION_DTOS); + List questions = new LinkedList<>(); + + for (McQuestionDTO mcQuestion : questionDtos) { + Question question = new Question(); + + question.setType(Question.QUESTION_TYPE_MULTIPLE_CHOICE); + question.setTitle("Question " + mcQuestion.getDisplayOrder()); + question.setText(mcQuestion.getQuestion()); + question.setFeedback(mcQuestion.getFeedback()); + List answers = new ArrayList<>(); + + for (McOptionDTO mcAnswer : mcQuestion.getOptionDtos()) { + Answer answer = new Answer(); + answer.setText(mcAnswer.getCandidateAnswer()); + answer.setScore( + "Correct".equalsIgnoreCase(mcAnswer.getCorrect()) ? Float.parseFloat(mcQuestion.getMark()) : 0); + + answers.add(answer); + question.setAnswers(answers); + } + + // put the question in the right place + questions.add(mcQuestion.getDisplayOrder() - 1, question); + } + + String title = request.getParameter("title"); + QuestionExporter exporter = new QuestionExporter(title, questions.toArray(Question.QUESTION_ARRAY_TYPE)); + exporter.exportQTIPackage(request, response); + + return null; + } + + public ActionForward moveCandidateUp(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) throws IOException, ServletException { + String sessionMapId = request.getParameter(McAppConstants.ATTR_SESSION_MAP_ID); + SessionMap sessionMap = (SessionMap) request.getSession() + .getAttribute(sessionMapId); + request.setAttribute(McAppConstants.ATTR_SESSION_MAP_ID, sessionMapId); + + String candidateIndex = request.getParameter("candidateIndex"); + request.setAttribute("candidateIndex", candidateIndex); + + List optionDtos = McAction.repopulateOptionDTOs(request, false); + + //moveAddedCandidateUp + McQuestionDTO questionDto = (McQuestionDTO) sessionMap.get(McAppConstants.QUESTION_DTO); + List listCandidates = new LinkedList<>(); + listCandidates = McAction.swapOptions(optionDtos, candidateIndex, "up"); + questionDto.setOptionDtos(listCandidates); + sessionMap.put(McAppConstants.QUESTION_DTO, questionDto); + + return (mapping.findForward("candidateAnswersList")); + } + + public ActionForward moveCandidateDown(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) throws IOException, ServletException { + String sessionMapId = request.getParameter(McAppConstants.ATTR_SESSION_MAP_ID); + SessionMap sessionMap = (SessionMap) request.getSession() + .getAttribute(sessionMapId); + request.setAttribute(McAppConstants.ATTR_SESSION_MAP_ID, sessionMapId); + + String candidateIndex = request.getParameter("candidateIndex"); + request.setAttribute("candidateIndex", candidateIndex); + + List optionDtos = McAction.repopulateOptionDTOs(request, false); + + //moveAddedCandidateDown + McQuestionDTO questionDto = (McQuestionDTO) sessionMap.get(McAppConstants.QUESTION_DTO); + List swapedOptions = new LinkedList<>(); + swapedOptions = McAction.swapOptions(optionDtos, candidateIndex, "down"); + questionDto.setOptionDtos(swapedOptions); + sessionMap.put(McAppConstants.QUESTION_DTO, questionDto); + + return (mapping.findForward("candidateAnswersList")); + } + + /* + * swaps options in the list + */ + private static List swapOptions(List optionDtos, String optionIndex, String direction) { + + int intOptionIndex = new Integer(optionIndex).intValue(); + int intOriginalOptionIndex = intOptionIndex; + + int replacedOptionIndex = 0; + if (direction.equals("down")) { + replacedOptionIndex = ++intOptionIndex; + } else { + replacedOptionIndex = --intOptionIndex; + } + + McOptionDTO mainOption = AuthoringUtil.getOptionAtDisplayOrder(optionDtos, intOriginalOptionIndex); + McOptionDTO replacedOption = AuthoringUtil.getOptionAtDisplayOrder(optionDtos, replacedOptionIndex); + if ((mainOption == null) || (replacedOption == null)) { + return optionDtos; + } + + List newOptionDtos = new LinkedList<>(); + + int queIndex = 1; + for (McOptionDTO option : optionDtos) { + + McOptionDTO tempOption = new McOptionDTO(); + if ((!new Integer(queIndex).toString().equals(new Integer(intOriginalOptionIndex).toString())) + && !new Integer(queIndex).toString().equals(new Integer(replacedOptionIndex).toString())) { + // normal copy + tempOption = option; + } else if (new Integer(queIndex).toString().equals(new Integer(intOriginalOptionIndex).toString())) { + // move type 1 + tempOption = replacedOption; + } else if (new Integer(queIndex).toString().equals(new Integer(replacedOptionIndex).toString())) { + // move type 2 + tempOption = mainOption; + } + + newOptionDtos.add(tempOption); + queIndex++; + } + + return newOptionDtos; + } + + public ActionForward removeCandidate(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) throws IOException, ServletException { + String sessionMapId = request.getParameter(McAppConstants.ATTR_SESSION_MAP_ID); + SessionMap sessionMap = (SessionMap) request.getSession() + .getAttribute(sessionMapId); + request.setAttribute(McAppConstants.ATTR_SESSION_MAP_ID, sessionMapId); + + String candidateIndexToRemove = request.getParameter("candidateIndex"); + request.setAttribute("candidateIndex", candidateIndexToRemove); + + // removeAddedCandidate + McQuestionDTO questionDto = (McQuestionDTO) sessionMap.get(McAppConstants.QUESTION_DTO); + + List optionDtos = McAction.repopulateOptionDTOs(request, false); + List listFinalCandidatesDTO = new LinkedList<>(); + int caIndex = 0; + for (McOptionDTO mcOptionDTO : optionDtos) { + caIndex++; + + if (caIndex != new Integer(candidateIndexToRemove).intValue()) { + listFinalCandidatesDTO.add(mcOptionDTO); + } + } + + questionDto.setOptionDtos(listFinalCandidatesDTO); + sessionMap.put(McAppConstants.QUESTION_DTO, questionDto); + + return (mapping.findForward("candidateAnswersList")); + } + + public ActionForward newCandidateBox(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) throws IOException, ServletException { + String sessionMapId = request.getParameter(McAppConstants.ATTR_SESSION_MAP_ID); + SessionMap sessionMap = (SessionMap) request.getSession() + .getAttribute(sessionMapId); + request.setAttribute(McAppConstants.ATTR_SESSION_MAP_ID, sessionMapId); + + String candidateIndex = request.getParameter("candidateIndex"); + request.setAttribute("candidateIndex", candidateIndex); + + List optionDtos = McAction.repopulateOptionDTOs(request, true); + + //newAddedCandidateBox + McQuestionDTO questionDto = (McQuestionDTO) sessionMap.get(McAppConstants.QUESTION_DTO); + questionDto.setOptionDtos(optionDtos); + sessionMap.put(McAppConstants.QUESTION_DTO, questionDto); + + return (mapping.findForward("candidateAnswersList")); + } + + /** + * repopulateOptionsBox + */ + private static List repopulateOptionDTOs(HttpServletRequest request, boolean isAddBlankOptions) { + + String correct = request.getParameter("correct"); + + /* check this logic again */ + int intCorrect = 0; + if (correct != null) { + intCorrect = new Integer(correct).intValue(); + } + + List optionDtos = new LinkedList<>(); + for (int i = 0; i < McAppConstants.MAX_OPTION_COUNT; i++) { + String optionText = request.getParameter("ca" + i); + Long optionUid = WebUtil.readLongParam(request, "caUid" + i, true); + + String isCorrect = "Incorrect"; + + if (i == intCorrect) { + isCorrect = "Correct"; + } + + if (optionText != null) { + McOptionDTO optionDTO = new McOptionDTO(); + optionDTO.setUid(optionUid); + optionDTO.setCandidateAnswer(optionText); + optionDTO.setCorrect(isCorrect); + optionDtos.add(optionDTO); + } + } + + if (isAddBlankOptions) { + McOptionDTO optionDTO = new McOptionDTO(); + optionDTO.setCandidateAnswer(""); + optionDTO.setCorrect("Incorrect"); + optionDtos.add(optionDTO); + } + + return optionDtos; + } + +} Index: lams_tool_lamc/src/java/org/lamsfoundation/lams/tool/mc/web/action/McLearningAction.java =================================================================== diff -u --- lams_tool_lamc/src/java/org/lamsfoundation/lams/tool/mc/web/action/McLearningAction.java (revision 0) +++ lams_tool_lamc/src/java/org/lamsfoundation/lams/tool/mc/web/action/McLearningAction.java (revision 4170df8bc66e658ef4dcd47e99eceddec3c2673a) @@ -0,0 +1,760 @@ +/*************************************************************************** + * 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.mc.web.action; + +import java.io.IOException; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Set; +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.action.ActionForm; +import org.apache.struts.action.ActionForward; +import org.apache.struts.action.ActionMapping; +import org.apache.tomcat.util.json.JSONException; +import org.apache.tomcat.util.json.JSONObject; +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.exception.DataMissingException; +import org.lamsfoundation.lams.tool.exception.ToolException; +import org.lamsfoundation.lams.tool.mc.McAppConstants; +import org.lamsfoundation.lams.tool.mc.dto.AnswerDTO; +import org.lamsfoundation.lams.tool.mc.dto.McGeneralLearnerFlowDTO; +import org.lamsfoundation.lams.tool.mc.pojos.McContent; +import org.lamsfoundation.lams.tool.mc.pojos.McOptsContent; +import org.lamsfoundation.lams.tool.mc.pojos.McQueContent; +import org.lamsfoundation.lams.tool.mc.pojos.McQueUsr; +import org.lamsfoundation.lams.tool.mc.pojos.McSession; +import org.lamsfoundation.lams.tool.mc.pojos.McUsrAttempt; +import org.lamsfoundation.lams.tool.mc.service.IMcService; +import org.lamsfoundation.lams.tool.mc.service.McServiceProxy; +import org.lamsfoundation.lams.tool.mc.util.LearningUtil; +import org.lamsfoundation.lams.tool.mc.util.McComparator; +import org.lamsfoundation.lams.tool.mc.web.form.McLearningForm; +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; + +/** + * @author Ozgur Demirtas + */ +public class McLearningAction extends LamsDispatchAction { + private static Logger logger = Logger.getLogger(McLearningAction.class.getName()); + + private static IMcService mcService; + + /** + * main content/question content management and workflow logic + * + * if the passed toolContentId exists in the db, we need to get the relevant data into the Map if not, create the + * default Map + */ + @Override + public ActionForward unspecified(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) throws IOException, ServletException { + McLearningForm mcLearningForm = (McLearningForm) form; + LearningUtil.saveFormRequestData(request, mcLearningForm); + return null; + } + + /** + * responds to learner activity in learner mode. + * + * @param mapping + * @param form + * @param request + * @param response + * @return + * @throws IOException + * @throws ServletException + */ + public ActionForward displayMc(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) throws IOException, ServletException { + McLearningForm mcLearningForm = (McLearningForm) form; + if (mcService == null) { + mcService = McServiceProxy.getMcService(getServlet().getServletContext()); + } + + String toolSessionID = request.getParameter(AttributeNames.PARAM_TOOL_SESSION_ID); + mcLearningForm.setToolSessionID(toolSessionID); + + McSession mcSession = mcService.getMcSessionById(new Long(toolSessionID)); + + String toolContentId = mcSession.getMcContent().getMcContentId().toString(); + mcLearningForm.setToolContentID(toolContentId); + + LearningUtil.saveFormRequestData(request, mcLearningForm); + + if (mcLearningForm.getNextQuestionSelected() != null && !mcLearningForm.getNextQuestionSelected().equals("")) { + mcLearningForm.resetParameters(); + return getNextOptions(mapping, form, request, response); + } + if (mcLearningForm.getContinueOptionsCombined() != null) { + return continueOptionsCombined(mapping, form, request, response); + } else if (mcLearningForm.getNextOptions() != null) { + return getNextOptions(mapping, form, request, response); + } else if (mcLearningForm.getRedoQuestions() != null) { + return redoQuestions(request, mcLearningForm, mapping); + } else if (mcLearningForm.getViewAnswers() != null) { + return viewAnswers(mapping, mcLearningForm, request, response); + } else if (mcLearningForm.getSubmitReflection() != null) { + return submitReflection(mapping, form, request, response); + } else if (mcLearningForm.getForwardtoReflection() != null) { + return forwardtoReflection(mapping, form, request, response); + } else if (mcLearningForm.getLearnerFinished() != null) { + return endLearning(mapping, form, request, response); + } + + return mapping.findForward(McAppConstants.LOAD_LEARNER); + } + + /** + * ActionForward endLearning(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse + * response) + * + * + * @param mapping + * @param form + * @param request + * @param response + * @return + * @throws IOException + * @throws ServletException + */ + public ActionForward endLearning(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) throws IOException, ServletException { + McLearningForm mcLearningForm = (McLearningForm) form; + if (mcService == null) { + mcService = McServiceProxy.getMcService(getServlet().getServletContext()); + } + + String toolSessionID = request.getParameter(AttributeNames.PARAM_TOOL_SESSION_ID); + mcLearningForm.setToolSessionID(toolSessionID); + + McSession mcSession = mcService.getMcSessionById(new Long(toolSessionID)); + + String toolContentId = mcSession.getMcContent().getMcContentId().toString(); + mcLearningForm.setToolContentID(toolContentId); + + LearningUtil.saveFormRequestData(request, mcLearningForm); + // requested learner finished, the learner should be directed to next activity + + HttpSession ss = SessionManager.getSession(); + UserDTO userDto = (UserDTO) ss.getAttribute(AttributeNames.USER); + + String nextUrl = null; + try { + nextUrl = mcService.leaveToolSession(new Long(toolSessionID), userDto.getUserID().longValue()); + } catch (DataMissingException e) { + McLearningAction.logger.error("failure getting nextUrl: " + e); + return mapping.findForward(McAppConstants.LEARNING_STARTER); + } catch (ToolException e) { + McLearningAction.logger.error("failure getting nextUrl: " + e); + return mapping.findForward(McAppConstants.LEARNING_STARTER); + } catch (Exception e) { + McLearningAction.logger.error("unknown exception getting nextUrl: " + e); + return mapping.findForward(McAppConstants.LEARNING_STARTER); + } + + response.sendRedirect(nextUrl); + + return null; + } + + /** + * + */ + protected List buildAnswerDtos(List answers, McContent content) { + + List answerDtos = new LinkedList(); + + for (McQueContent question : (Set) content.getMcQueContents()) { + String questionUid = question.getUid().toString(); + int questionMark = question.getMark().intValue(); + + AnswerDTO answerDto = new AnswerDTO(); + answerDto.setQuestion(question.getQuestion()); + answerDto.setDisplayOrder(question.getDisplayOrder().toString()); + answerDto.setQuestionUid(question.getUid()); + answerDto.setFeedback(question.getFeedback() != null ? question.getFeedback() : ""); + + //search for according answer + McOptsContent answerOption = null; + for (String answer : answers) { + int hyphenPosition = answer.indexOf("-"); + String answeredQuestionUid = answer.substring(0, hyphenPosition); + + if (questionUid.equals(answeredQuestionUid)) { + String answeredOptionUid = answer.substring(hyphenPosition + 1); + answerOption = question.getOptionsContentByUID(new Long(answeredOptionUid)); + answerDto.setAnswerOption(answerOption); + break; + } + } + + boolean isCorrect = (answerOption != null) && answerOption.isCorrectOption(); + answerDto.setAttemptCorrect(isCorrect); + if (isCorrect) { + answerDto.setFeedbackCorrect(question.getFeedback()); + answerDto.setMark(questionMark); + } else { + answerDto.setFeedbackIncorrect(question.getFeedback()); + answerDto.setMark(0); + } + + answerDtos.add(answerDto); + + } + + return answerDtos; + } + + /** + * responses to learner when they answer all the questions on a single page + */ + public ActionForward continueOptionsCombined(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) throws IOException, ServletException { + McLearningForm mcLearningForm = (McLearningForm) form; + if (mcService == null) { + mcService = McServiceProxy.getMcService(getServlet().getServletContext()); + } + + String httpSessionID = mcLearningForm.getHttpSessionID(); + SessionMap sessionMap = (SessionMap) request.getSession().getAttribute(httpSessionID); + request.getSession().setAttribute(httpSessionID, sessionMap); + + String toolSessionID = request.getParameter(AttributeNames.PARAM_TOOL_SESSION_ID); + McSession session = mcService.getMcSessionById(new Long(toolSessionID)); + String toolContentId = session.getMcContent().getMcContentId().toString(); + McContent mcContent = mcService.getMcContent(new Long(toolContentId)); + + List answers = McLearningAction.parseLearnerAnswers(mcLearningForm, request, mcContent.isQuestionsSequenced()); + if (mcContent.isQuestionsSequenced()) { + sessionMap.put(McAppConstants.QUESTION_AND_CANDIDATE_ANSWERS_KEY, answers); + } + + mcLearningForm.resetCa(mapping, request); + + McQueUsr user = getCurrentUser(toolSessionID); + + //prohibit users from submitting answers after response is finalized but Resubmit button is not pressed (e.g. using 2 browsers) + if (user.isResponseFinalised()) { + return viewAnswers(mapping, mcLearningForm, request, response); + } + + /* process the answers */ + List answerDtos = buildAnswerDtos(answers, mcContent); + mcService.saveUserAttempt(user, answerDtos); + + //calculate total learner mark + int learnerMark = 0; + for (AnswerDTO answerDto : answerDtos) { + learnerMark += answerDto.getMark(); + } + + Integer numberOfAttempts = user.getNumberOfAttempts() + 1; + user.setNumberOfAttempts(numberOfAttempts); + user.setLastAttemptTotalMark(learnerMark); + user.setResponseFinalised(true); + mcService.updateMcQueUsr(user); + + return viewAnswers(mapping, mcLearningForm, request, response); + } + + /** + * takes the learner to the next set of questions + * + * @param request + * @param form + * @param mapping + * @return ActionForward + */ + public ActionForward getNextOptions(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) throws IOException, ServletException { + McLearningForm mcLearningForm = (McLearningForm) form; + if (mcService == null) { + mcService = McServiceProxy.getMcService(getServlet().getServletContext()); + } + String toolSessionID = request.getParameter(AttributeNames.PARAM_TOOL_SESSION_ID); + McSession mcSession = mcService.getMcSessionById(new Long(toolSessionID)); + String toolContentId = mcSession.getMcContent().getMcContentId().toString(); + McContent mcContent = mcService.getMcContent(new Long(toolContentId)); + + McQueUsr user = getCurrentUser(toolSessionID); + + String httpSessionID = mcLearningForm.getHttpSessionID(); + SessionMap sessionMap = (SessionMap) request.getSession() + .getAttribute(httpSessionID); + + //prohibit users from submitting answers after response is finalized but Resubmit button is not pressed (e.g. using 2 browsers) + if (user.isResponseFinalised()) { + return viewAnswers(mapping, mcLearningForm, request, response); + } + + //parse learner input + List answers = McLearningAction.parseLearnerAnswers(mcLearningForm, request, mcContent.isQuestionsSequenced()); + sessionMap.put(McAppConstants.QUESTION_AND_CANDIDATE_ANSWERS_KEY, answers); + + //save user attempt + List answerDtos = buildAnswerDtos(answers, mcContent); + mcService.saveUserAttempt(user, answerDtos); + + List learnerAnswersDTOList = mcService.getAnswersFromDatabase(mcContent, user); + request.setAttribute(McAppConstants.LEARNER_ANSWERS_DTO_LIST, learnerAnswersDTOList); + + McGeneralLearnerFlowDTO mcGeneralLearnerFlowDTO = LearningUtil.buildMcGeneralLearnerFlowDTO(mcContent); + + Integer totalQuestionCount = mcGeneralLearnerFlowDTO.getTotalQuestionCount(); + Integer questionIndex = mcLearningForm.getQuestionIndex(); + if (totalQuestionCount.equals(questionIndex)) { + mcGeneralLearnerFlowDTO.setTotalCountReached(new Boolean(true).toString()); + } + + mcGeneralLearnerFlowDTO.setReflection(new Boolean(mcContent.isReflect()).toString()); + mcGeneralLearnerFlowDTO.setReflectionSubject(mcContent.getReflectionSubject()); + mcGeneralLearnerFlowDTO.setRetries(new Boolean(mcContent.isRetries()).toString()); + mcGeneralLearnerFlowDTO.setTotalMarksPossible(mcContent.getTotalMarksPossible()); + mcGeneralLearnerFlowDTO.setQuestionIndex(questionIndex); + request.setAttribute(McAppConstants.MC_GENERAL_LEARNER_FLOW_DTO, mcGeneralLearnerFlowDTO); + + LearningWebUtil.putActivityPositionInRequestByToolSessionId(new Long(toolSessionID), request, + getServlet().getServletContext()); + + request.setAttribute("sessionMapID", sessionMap.getSessionID()); + + return mapping.findForward(McAppConstants.LOAD_LEARNER); + } + + /** + * allows the learner to view their answer history + * + * @param request + * @param form + * @param mapping + * @return ActionForward + */ + public ActionForward viewAnswers(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) throws IOException, ServletException { + McLearningForm mcLearningForm = (McLearningForm) form; + + // may have to get service from the form - if class has been created by starter action, rather than by struts + if (mcService == null) { + if (getServlet() != null) { + mcService = McServiceProxy.getMcService(getServlet().getServletContext()); + } else { + mcService = mcLearningForm.getMcService(); + } + } + + String toolSessionID = request.getParameter(AttributeNames.PARAM_TOOL_SESSION_ID); + McSession mcSession = mcService.getMcSessionById(new Long(toolSessionID)); + + String toolContentId = mcSession.getMcContent().getMcContentId().toString(); + McContent mcContent = mcService.getMcContent(new Long(toolContentId)); + + String sessionMapID = mcLearningForm.getHttpSessionID(); + request.setAttribute("sessionMapID", sessionMapID); + + McGeneralLearnerFlowDTO mcGeneralLearnerFlowDTO = LearningUtil.buildMcGeneralLearnerFlowDTO(mcContent); + + Map mapQuestionsUidContent = new TreeMap(new McComparator()); + if (mcContent != null) { + List list = mcService.refreshQuestionContent(mcContent.getUid()); + + Iterator listIterator = list.iterator(); + Long mapIndex = new Long(1); + while (listIterator.hasNext()) { + McQueContent mcQueContent = (McQueContent) listIterator.next(); + mapQuestionsUidContent.put(mapIndex.toString(), mcQueContent.getUid()); + mapIndex = new Long(mapIndex.longValue() + 1); + } + } + + //builds a map to hold all the candidate answers for all the questions by accessing the db + Map mapStartupGeneralOptionsContent = new TreeMap(new McComparator()); + Iterator itMap = mapQuestionsUidContent.entrySet().iterator(); + Long mapIndex = new Long(1); + while (itMap.hasNext()) { + Map.Entry pairs = (Map.Entry) itMap.next(); + String currentQuestionUid = pairs.getValue().toString(); + List listQuestionOptions = mcService.findOptionsByQuestionUid(new Long(currentQuestionUid)); + + //builds a questions map from questions list + Map mapOptsContent = new TreeMap(new McComparator()); + Iterator iter = listQuestionOptions.iterator(); + Long mapIndex2 = new Long(1); + while (iter.hasNext()) { + McOptsContent option = iter.next(); + mapOptsContent.put(mapIndex2.toString(), option.getMcQueOptionText()); + mapIndex2 = new Long(mapIndex2.longValue() + 1); + } + + mapStartupGeneralOptionsContent.put(mapIndex.toString(), mapOptsContent); + mapIndex = new Long(mapIndex.longValue() + 1); + } + mcGeneralLearnerFlowDTO.setMapGeneralOptionsContent(mapStartupGeneralOptionsContent); + + //builds a map to hold question texts + Map mapQuestionsContent = new TreeMap(new McComparator()); + List list = mcService.refreshQuestionContent(mcContent.getUid()); + Iterator iter = list.iterator(); + Long mapIndex3 = new Long(1); + while (iter.hasNext()) { + McQueContent question = (McQueContent) iter.next(); + mapQuestionsContent.put(mapIndex3.toString(), question.getQuestion()); + mapIndex3 = new Long(mapIndex3.longValue() + 1); + } + mcGeneralLearnerFlowDTO.setMapQuestionsContent(mapQuestionsContent); + + //rebuildFeedbackMapfromDB + Map mapFeedbackContent = new TreeMap(new McComparator()); + List list2 = mcService.refreshQuestionContent(mcContent.getUid()); + Iterator iter2 = list2.iterator(); + Long mapIndex4 = new Long(1); + while (iter2.hasNext()) { + McQueContent question = (McQueContent) iter2.next(); + + String feedback = question.getFeedback(); + + mapFeedbackContent.put(mapIndex4.toString(), feedback); + mapIndex4 = new Long(mapIndex4.longValue() + 1); + } + mcGeneralLearnerFlowDTO.setMapFeedbackContent(mapFeedbackContent); + + McQueUsr user = getCurrentUser(toolSessionID); + + Long toolContentUID = mcContent.getUid(); + + //create attemptMap for displaying on jsp + Map attemptMap = new TreeMap(new McComparator()); + for (int i = 1; i <= mcContent.getMcQueContents().size(); i++) { + McQueContent question = mcService.getQuestionByDisplayOrder(new Long(i), toolContentUID); + + McUsrAttempt userAttempt = mcService.getUserAttemptByQuestion(user.getUid(), question.getUid()); + + if (userAttempt != null) { + attemptMap.put(new Integer(i).toString(), userAttempt); + } + } + mcGeneralLearnerFlowDTO.setAttemptMap(attemptMap); + mcGeneralLearnerFlowDTO.setReflection(new Boolean(mcContent.isReflect()).toString()); + mcGeneralLearnerFlowDTO.setReflectionSubject(mcContent.getReflectionSubject()); + + NotebookEntry notebookEntry = mcService.getEntry(new Long(toolSessionID), CoreNotebookConstants.NOTEBOOK_TOOL, + McAppConstants.TOOL_SIGNATURE, new Integer(user.getQueUsrId().intValue())); + request.setAttribute("notebookEntry", notebookEntry); + if (notebookEntry != null) { + mcGeneralLearnerFlowDTO.setNotebookEntry(notebookEntry.getEntry()); + } + + mcGeneralLearnerFlowDTO.setRetries(new Boolean(mcContent.isRetries()).toString()); + mcGeneralLearnerFlowDTO.setPassMarkApplicable(new Boolean(mcContent.isPassMarkApplicable()).toString()); + mcGeneralLearnerFlowDTO.setUserOverPassMark(new Boolean(user.isLastAttemptMarkPassed()).toString()); + mcGeneralLearnerFlowDTO.setTotalMarksPossible(mcContent.getTotalMarksPossible()); + mcGeneralLearnerFlowDTO.setShowMarks(new Boolean(mcContent.isShowMarks()).toString()); + mcGeneralLearnerFlowDTO.setDisplayAnswers(new Boolean(mcContent.isDisplayAnswers()).toString()); + mcGeneralLearnerFlowDTO.setLearnerMark(user.getLastAttemptTotalMark()); + + Object[] markStatistics = null; + if (mcContent.isShowMarks()) { + markStatistics = mcService.getMarkStatistics(mcSession); + } + if (markStatistics != null) { + mcGeneralLearnerFlowDTO.setLowestMark(markStatistics[0] != null ? ((Float)markStatistics[0]).intValue() : 0); + mcGeneralLearnerFlowDTO.setAverageMark(markStatistics[1] != null ? ((Float)markStatistics[1]).intValue() : 0); + mcGeneralLearnerFlowDTO.setTopMark(markStatistics[2] != null ? ((Float)markStatistics[2]).intValue() : 0); + } else { + mcGeneralLearnerFlowDTO.setLowestMark(0); + mcGeneralLearnerFlowDTO.setAverageMark(0); + mcGeneralLearnerFlowDTO.setTopMark(0); + } + + request.setAttribute(McAppConstants.MC_GENERAL_LEARNER_FLOW_DTO, mcGeneralLearnerFlowDTO); + + LearningWebUtil.putActivityPositionInRequestByToolSessionId(new Long(toolSessionID), request, + getServlet().getServletContext()); + + return mapping.findForward(McAppConstants.VIEW_ANSWERS); + } + + /** + * + */ + public ActionForward redoQuestions(HttpServletRequest request, McLearningForm mcLearningForm, + ActionMapping mapping) { + if (mcService == null) { + mcService = McServiceProxy.getMcService(getServlet().getServletContext()); + } + String toolSessionID = request.getParameter(AttributeNames.PARAM_TOOL_SESSION_ID); + McSession mcSession = mcService.getMcSessionById(new Long(toolSessionID)); + String toolContentId = mcSession.getMcContent().getMcContentId().toString(); + McContent mcContent = mcService.getMcContent(new Long(toolContentId)); + McQueUsr mcQueUsr = getCurrentUser(toolSessionID); + + //in order to track whether redo button is pressed store this info + mcQueUsr.setResponseFinalised(false); + mcService.updateMcQueUsr(mcQueUsr); + + //clear sessionMap + String httpSessionID = mcLearningForm.getHttpSessionID(); + SessionMap sessionMap = (SessionMap) request.getSession().getAttribute(httpSessionID); + List sequentialCheckedCa = new LinkedList(); + sessionMap.put(McAppConstants.QUESTION_AND_CANDIDATE_ANSWERS_KEY, sequentialCheckedCa); + + List learnerAnswersDTOList = mcService.getAnswersFromDatabase(mcContent, mcQueUsr); + request.setAttribute(McAppConstants.LEARNER_ANSWERS_DTO_LIST, learnerAnswersDTOList); + + McGeneralLearnerFlowDTO mcGeneralLearnerFlowDTO = LearningUtil.buildMcGeneralLearnerFlowDTO(mcContent); + mcGeneralLearnerFlowDTO.setQuestionIndex(new Integer(1)); + mcGeneralLearnerFlowDTO.setReflection(new Boolean(mcContent.isReflect()).toString()); + mcGeneralLearnerFlowDTO.setReflectionSubject(mcContent.getReflectionSubject()); + mcGeneralLearnerFlowDTO.setRetries(new Boolean(mcContent.isRetries()).toString()); + + String passMarkApplicable = new Boolean(mcContent.isPassMarkApplicable()).toString(); + mcGeneralLearnerFlowDTO.setPassMarkApplicable(passMarkApplicable); + mcLearningForm.setPassMarkApplicable(passMarkApplicable); + + String userOverPassMark = Boolean.FALSE.toString(); + mcGeneralLearnerFlowDTO.setUserOverPassMark(userOverPassMark); + mcLearningForm.setUserOverPassMark(userOverPassMark); + + mcGeneralLearnerFlowDTO.setTotalMarksPossible(mcContent.getTotalMarksPossible()); + + // should we show the marks for each question - we show the marks if any of the questions + // have a mark > 1. + Boolean showMarks = LearningUtil.isShowMarksOnQuestion(learnerAnswersDTOList); + mcGeneralLearnerFlowDTO.setShowMarks(showMarks.toString()); + + request.setAttribute("sessionMapID", mcLearningForm.getHttpSessionID()); + + request.setAttribute(McAppConstants.MC_GENERAL_LEARNER_FLOW_DTO, mcGeneralLearnerFlowDTO); + return mapping.findForward(McAppConstants.LOAD_LEARNER); + } + + /** + * checks Leader Progress + */ + public ActionForward checkLeaderProgress(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) throws JSONException, IOException { + + if (mcService == null) { + mcService = McServiceProxy.getMcService(getServlet().getServletContext()); + } + Long toolSessionId = WebUtil.readLongParam(request, AttributeNames.PARAM_TOOL_SESSION_ID); + + McSession session = mcService.getMcSessionById(toolSessionId); + McQueUsr leader = session.getGroupLeader(); + + boolean isLeaderResponseFinalized = leader.isResponseFinalised(); + + JSONObject JSONObject = new JSONObject(); + JSONObject.put("isLeaderResponseFinalized", isLeaderResponseFinalized); + response.setContentType("application/x-json;charset=utf-8"); + response.getWriter().print(JSONObject); + return null; + } + + /** + * + * @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 { + McLearningForm mcLearningForm = (McLearningForm) form; + + if (mcService == null) { + mcService = McServiceProxy.getMcService(getServlet().getServletContext()); + } + + String toolSessionID = request.getParameter(AttributeNames.PARAM_TOOL_SESSION_ID); + mcLearningForm.setToolSessionID(toolSessionID); + + Long userID = mcLearningForm.getUserID(); + + String reflectionEntry = request.getParameter(McAppConstants.ENTRY_TEXT); + NotebookEntry notebookEntry = mcService.getEntry(new Long(toolSessionID), CoreNotebookConstants.NOTEBOOK_TOOL, + McAppConstants.TOOL_SIGNATURE, userID.intValue()); + + if (notebookEntry != null) { + notebookEntry.setEntry(reflectionEntry); + mcService.updateEntry(notebookEntry); + } else { + mcService.createNotebookEntry(new Long(toolSessionID), CoreNotebookConstants.NOTEBOOK_TOOL, + McAppConstants.TOOL_SIGNATURE, userID.intValue(), reflectionEntry); + } + + 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 { + McLearningForm mcLearningForm = (McLearningForm) form; + if (mcService == null) { + mcService = McServiceProxy.getMcService(getServlet().getServletContext()); + } + + String toolSessionID = request.getParameter(AttributeNames.PARAM_TOOL_SESSION_ID); + + McSession mcSession = mcService.getMcSessionById(new Long(toolSessionID)); + + McContent mcContent = mcSession.getMcContent(); + + McGeneralLearnerFlowDTO mcGeneralLearnerFlowDTO = new McGeneralLearnerFlowDTO(); + mcGeneralLearnerFlowDTO.setActivityTitle(mcContent.getTitle()); + mcGeneralLearnerFlowDTO.setReflectionSubject(mcContent.getReflectionSubject()); + + Long userID = mcLearningForm.getUserID(); + + // attempt getting notebookEntry + NotebookEntry notebookEntry = mcService.getEntry(new Long(toolSessionID), CoreNotebookConstants.NOTEBOOK_TOOL, + McAppConstants.TOOL_SIGNATURE, userID.intValue()); + + if (notebookEntry != null) { + String notebookEntryPresentable = notebookEntry.getEntry(); + mcLearningForm.setEntryText(notebookEntryPresentable); + + } + + request.setAttribute(McAppConstants.MC_GENERAL_LEARNER_FLOW_DTO, mcGeneralLearnerFlowDTO); + + return mapping.findForward(McAppConstants.NOTEBOOK); + } + + /** + * 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 { + if (mcService == null) { + mcService = McServiceProxy.getMcService(getServlet().getServletContext()); + } + McLearningForm mcLearningForm = (McLearningForm) form; + String toolSessionID = request.getParameter(AttributeNames.PARAM_TOOL_SESSION_ID); + McSession mcSession = mcService.getMcSessionById(new Long(toolSessionID)); + McContent mcContent = mcSession.getMcContent(); + + Long userID = mcLearningForm.getUserID(); + McQueUsr user = mcService.getMcUserBySession(userID, mcSession.getUid()); + + //prohibit users from autosaving answers after response is finalized but Resubmit button is not pressed (e.g. using 2 browsers) + if (user.isResponseFinalised()) { + return null; + } + + List answers = McLearningAction.parseLearnerAnswers(mcLearningForm, request, mcContent.isQuestionsSequenced()); + + List answerDtos = buildAnswerDtos(answers, mcContent); + mcService.saveUserAttempt(user, answerDtos); + + return null; + } + + private static List parseLearnerAnswers(McLearningForm mcLearningForm, HttpServletRequest request, boolean isQuestionsSequenced) { + String httpSessionID = mcLearningForm.getHttpSessionID(); + SessionMap sessionMap = (SessionMap) request.getSession().getAttribute(httpSessionID); + + List answers = new LinkedList(); + if (isQuestionsSequenced) { + + List previousAnswers = (List) sessionMap + .get(McAppConstants.QUESTION_AND_CANDIDATE_ANSWERS_KEY); + answers.addAll(previousAnswers); + + /* checkedCa refers to candidate answers */ + String[] checkedCa = mcLearningForm.getCheckedCa(); + + if (checkedCa != null) { + for (int i = 0; i < checkedCa.length; i++) { + String currentCa = checkedCa[i]; + answers.add(currentCa); + } + } + + } else { + Map parameters = request.getParameterMap(); + Iterator iter = parameters.keySet().iterator(); + while (iter.hasNext()) { + String key = iter.next(); + if (key.startsWith("checkedCa")) { + String currentCheckedCa = request.getParameter(key); + if (currentCheckedCa != null) { + answers.add(currentCheckedCa); + } + } + } + } + + return answers; + } + + private McQueUsr getCurrentUser(String toolSessionId) { + McSession mcSession = mcService.getMcSessionById(new Long(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 mcService.getMcUserBySession(userId, mcSession.getUid()); + } + +} Index: lams_tool_lamc/src/java/org/lamsfoundation/lams/tool/mc/web/action/McLearningStarterAction.java =================================================================== diff -u --- lams_tool_lamc/src/java/org/lamsfoundation/lams/tool/mc/web/action/McLearningStarterAction.java (revision 0) +++ lams_tool_lamc/src/java/org/lamsfoundation/lams/tool/mc/web/action/McLearningStarterAction.java (revision 4170df8bc66e658ef4dcd47e99eceddec3c2673a) @@ -0,0 +1,261 @@ +/*************************************************************************** + * 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.mc.web.action; + +import java.io.IOException; +import java.util.Date; +import java.util.LinkedList; +import java.util.List; +import java.util.Set; +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.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.apache.struts.action.ActionRedirect; +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.mc.McAppConstants; +import org.lamsfoundation.lams.tool.mc.dto.AnswerDTO; +import org.lamsfoundation.lams.tool.mc.dto.McGeneralLearnerFlowDTO; +import org.lamsfoundation.lams.tool.mc.pojos.McContent; +import org.lamsfoundation.lams.tool.mc.pojos.McQueUsr; +import org.lamsfoundation.lams.tool.mc.pojos.McSession; +import org.lamsfoundation.lams.tool.mc.service.IMcService; +import org.lamsfoundation.lams.tool.mc.service.McApplicationException; +import org.lamsfoundation.lams.tool.mc.service.McServiceProxy; +import org.lamsfoundation.lams.tool.mc.util.LearningUtil; +import org.lamsfoundation.lams.tool.mc.web.form.McLearningForm; +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; + +/** + * Note: Because of MCQ's learning reporting structure, Show Learner Report is always ON even if in authoring it is set + * to false. + * + * @author Ozgur Demirtas + */ +public class McLearningStarterAction extends Action { + + private static Logger logger = Logger.getLogger(McLearningStarterAction.class.getName()); + + private static IMcService mcService; + + @Override + public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) throws IOException, ServletException, McApplicationException { + + if (mcService == null) { + mcService = McServiceProxy.getMcService(getServlet().getServletContext()); + } + + McLearningForm mcLearningForm = (McLearningForm) form; + mcLearningForm.setMcService(mcService); + mcLearningForm.setPassMarkApplicable(new Boolean(false).toString()); + mcLearningForm.setUserOverPassMark(new Boolean(false).toString()); + + SessionMap sessionMap = new SessionMap(); + List sequentialCheckedCa = new LinkedList(); + sessionMap.put(McAppConstants.QUESTION_AND_CANDIDATE_ANSWERS_KEY, sequentialCheckedCa); + request.getSession().setAttribute(sessionMap.getSessionID(), sessionMap); + mcLearningForm.setHttpSessionID(sessionMap.getSessionID()); + + String toolSessionID = request.getParameter(AttributeNames.PARAM_TOOL_SESSION_ID); + mcLearningForm.setToolSessionID(new Long(toolSessionID).toString()); + + /* + * by now, we made sure that the passed tool session id exists in the db as a new record Make sure we can + * retrieve it and the relavent content + */ + McSession mcSession = mcService.getMcSessionById(new Long(toolSessionID)); + if (mcSession == null) { + return (mapping.findForward(McAppConstants.ERROR_LIST)); + } + + /* + * find out what content this tool session is referring to get the content for this tool session Each passed + * tool session id points to a particular content. Many to one mapping. + */ + McContent mcContent = mcSession.getMcContent(); + if (mcContent == null) { + ActionMessages errors = new ActionMessages(); + errors.add(Globals.ERROR_KEY, new ActionMessage("error.content.doesNotExist")); + saveErrors(request, errors); + return (mapping.findForward(McAppConstants.ERROR_LIST)); + } + + String mode = request.getParameter(McAppConstants.MODE); + McQueUsr user = null; + if ((mode != null) && mode.equals(ToolAccessMode.TEACHER.toString())) { + // monitoring mode - user is specified in URL + // user 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(); + mcLearningForm.setUserID(userID); + + /* + * Is there a deadline set? + */ + Date submissionDeadline = mcContent.getSubmissionDeadline(); + if (submissionDeadline != null) { + + 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()); + request.setAttribute("submissionDeadline", submissionDeadline); + + // calculate whether submission deadline has passed, and if so forward to "submissionDeadline" + if (currentLearnerDate.after(tzSubmissionDeadline)) { + return mapping.findForward("submissionDeadline"); + } + } + + mcLearningForm.setToolContentID(mcContent.getMcContentId().toString()); + + McGeneralLearnerFlowDTO mcGeneralLearnerFlowDTO = LearningUtil.buildMcGeneralLearnerFlowDTO(mcContent); + mcGeneralLearnerFlowDTO.setTotalCountReached(new Boolean(false).toString()); + mcGeneralLearnerFlowDTO.setQuestionIndex(new Integer(1)); + + Boolean displayAnswers = mcContent.isDisplayAnswers(); + mcGeneralLearnerFlowDTO.setDisplayAnswers(displayAnswers.toString()); + mcGeneralLearnerFlowDTO.setReflection(new Boolean(mcContent.isReflect()).toString()); + // String reflectionSubject = McUtils.replaceNewLines(mcContent.getReflectionSubject()); + mcGeneralLearnerFlowDTO.setReflectionSubject(mcContent.getReflectionSubject()); + + NotebookEntry notebookEntry = mcService.getEntry(new Long(toolSessionID), CoreNotebookConstants.NOTEBOOK_TOOL, + McAppConstants.TOOL_SIGNATURE, userID.intValue()); + + if (notebookEntry != null) { + // String notebookEntryPresentable = McUtils.replaceNewLines(notebookEntry.getEntry()); + mcGeneralLearnerFlowDTO.setNotebookEntry(notebookEntry.getEntry()); + } + request.setAttribute(McAppConstants.MC_GENERAL_LEARNER_FLOW_DTO, mcGeneralLearnerFlowDTO); + + List learnerAnswersDTOList = mcService.getAnswersFromDatabase(mcContent, user); + request.setAttribute(McAppConstants.LEARNER_ANSWERS_DTO_LIST, learnerAnswersDTOList); + // should we show the marks for each question - we show the marks if any of the questions + // have a mark > 1. + Boolean showMarks = LearningUtil.isShowMarksOnQuestion(learnerAnswersDTOList); + mcGeneralLearnerFlowDTO.setShowMarks(showMarks.toString()); + + /* find out if the content is being modified at the moment. */ + boolean isDefineLater = mcContent.isDefineLater(); + if (isDefineLater == true) { + return (mapping.findForward("defineLater")); + } + + McQueUsr groupLeader = null; + if (mcContent.isUseSelectLeaderToolOuput()) { + groupLeader = mcService.checkLeaderSelectToolForSessionLeader(user, new Long(toolSessionID)); + + // forwards to the leaderSelection page + if (groupLeader == null && !mode.equals(ToolAccessMode.TEACHER.toString())) { + + Set groupUsers = mcSession.getMcQueUsers();// mcService.getUsersBySession(new + // Long(toolSessionID).longValue()); + request.setAttribute(McAppConstants.ATTR_GROUP_USERS, groupUsers); + request.setAttribute(McAppConstants.TOOL_SESSION_ID, toolSessionID); + request.setAttribute(McAppConstants.ATTR_CONTENT, mcContent); + + return mapping.findForward(McAppConstants.WAIT_FOR_LEADER); + } + + // check if leader has submitted all answers + if (groupLeader.isResponseFinalised() && !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 + mcService.copyAnswersFromLeader(user, groupLeader); + + user.setResponseFinalised(true); + mcService.updateMcQueUsr(user); + } + } + + sessionMap.put(McAppConstants.ATTR_GROUP_LEADER, groupLeader); + boolean isUserLeader = mcSession.isUserGroupLeader(user); + sessionMap.put(McAppConstants.ATTR_IS_USER_LEADER, isUserLeader); + sessionMap.put(AttributeNames.ATTR_MODE, mode); + sessionMap.put(McAppConstants.ATTR_CONTENT, mcContent); + request.setAttribute("sessionMapID", sessionMap.getSessionID()); + + /* user has already submitted response once OR it's a monitor - go to viewAnswers page. */ + if (user.isResponseFinalised() || mode.equals("teacher")) { + + ActionRedirect redirect = new ActionRedirect(mapping.findForwardConfig("viewAnswersRedirect")); + redirect.addParameter(AttributeNames.PARAM_TOOL_SESSION_ID, toolSessionID); + redirect.addParameter("userID", userID); + redirect.addParameter(McAppConstants.MODE, mode); + redirect.addParameter("httpSessionID", sessionMap.getSessionID()); + return redirect; + } + + return (mapping.findForward(McAppConstants.LOAD_LEARNER)); + } + + private McQueUsr 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()); + + McSession mcSession = mcService.getMcSessionById(new Long(toolSessionId)); + McQueUsr qaUser = mcService.getMcUserBySession(userId, mcSession.getUid()); + if (qaUser == null) { + qaUser = mcService.createMcUser(new Long(toolSessionId)); + } + + return qaUser; + } + + private McQueUsr getSpecifiedUser(String toolSessionId, Integer userId) { + McSession mcSession = mcService.getMcSessionById(new Long(toolSessionId)); + McQueUsr qaUser = mcService.getMcUserBySession(new Long(userId.intValue()), mcSession.getUid()); + if (qaUser == null) { + logger.error("Unable to find specified user for Q&A activity. Screens are likely to fail. SessionId=" + + new Long(toolSessionId) + " UserId=" + userId); + } + return qaUser; + } +} Index: lams_tool_lamc/src/java/org/lamsfoundation/lams/tool/mc/web/action/McMonitoringAction.java =================================================================== diff -u --- lams_tool_lamc/src/java/org/lamsfoundation/lams/tool/mc/web/action/McMonitoringAction.java (revision 0) +++ lams_tool_lamc/src/java/org/lamsfoundation/lams/tool/mc/web/action/McMonitoringAction.java (revision 4170df8bc66e658ef4dcd47e99eceddec3c2673a) @@ -0,0 +1,409 @@ +/*************************************************************************** + * 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.mc.web.action; + +import java.io.IOException; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.TimeZone; + +import javax.servlet.ServletException; +import javax.servlet.http.Cookie; +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.action.ActionForm; +import org.apache.struts.action.ActionForward; +import org.apache.struts.action.ActionMapping; +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.tool.exception.ToolException; +import org.lamsfoundation.lams.tool.mc.McAppConstants; +import org.lamsfoundation.lams.tool.mc.dto.LeaderResultsDTO; +import org.lamsfoundation.lams.tool.mc.dto.McGeneralLearnerFlowDTO; +import org.lamsfoundation.lams.tool.mc.dto.McUserMarkDTO; +import org.lamsfoundation.lams.tool.mc.dto.SessionDTO; +import org.lamsfoundation.lams.tool.mc.pojos.McContent; +import org.lamsfoundation.lams.tool.mc.pojos.McOptsContent; +import org.lamsfoundation.lams.tool.mc.pojos.McQueContent; +import org.lamsfoundation.lams.tool.mc.pojos.McQueUsr; +import org.lamsfoundation.lams.tool.mc.pojos.McSession; +import org.lamsfoundation.lams.tool.mc.pojos.McUsrAttempt; +import org.lamsfoundation.lams.tool.mc.service.IMcService; +import org.lamsfoundation.lams.tool.mc.service.McServiceProxy; +import org.lamsfoundation.lams.util.DateUtil; +import org.lamsfoundation.lams.util.MessageService; +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 McMonitoringAction extends LamsDispatchAction { + private static Logger logger = Logger.getLogger(McMonitoringAction.class.getName()); + + /** + * displayAnswers + */ + public ActionForward displayAnswers(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) throws IOException, ServletException { + IMcService mcService = McServiceProxy.getMcService(getServlet().getServletContext()); + String strToolContentID = request.getParameter(AttributeNames.PARAM_TOOL_CONTENT_ID); + String contentFolderID = WebUtil.readStrParam(request, AttributeNames.PARAM_CONTENT_FOLDER_ID); + + McContent mcContent = mcService.getMcContent(new Long(strToolContentID)); + mcContent.setDisplayAnswers(new Boolean(true)); + mcService.updateMc(mcContent); + + // use redirect to prevent resubmition of the same request + ActionRedirect redirect = new ActionRedirect(mapping.findForwardConfig("monitoringStarterRedirect")); + redirect.addParameter(McAppConstants.TOOL_CONTENT_ID, strToolContentID); + redirect.addParameter(AttributeNames.PARAM_CONTENT_FOLDER_ID, contentFolderID); + return redirect; + } + + /** + * allows viewing users reflection data + */ + public ActionForward openNotebook(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) throws IOException, ServletException, ToolException { + IMcService mcService = McServiceProxy.getMcService(getServlet().getServletContext()); + String userId = request.getParameter("userId"); + String userName = request.getParameter("userName"); + String sessionId = request.getParameter("sessionId"); + NotebookEntry notebookEntry = mcService.getEntry(new Long(sessionId), CoreNotebookConstants.NOTEBOOK_TOOL, + McAppConstants.TOOL_SIGNATURE, new Integer(userId)); + + McGeneralLearnerFlowDTO mcGeneralLearnerFlowDTO = new McGeneralLearnerFlowDTO(); + if (notebookEntry != null) { + // String notebookEntryPresentable = McUtils.replaceNewLines(notebookEntry.getEntry()); + mcGeneralLearnerFlowDTO.setNotebookEntry(notebookEntry.getEntry()); + mcGeneralLearnerFlowDTO.setUserName(userName); + } + + request.setAttribute(McAppConstants.MC_GENERAL_LEARNER_FLOW_DTO, mcGeneralLearnerFlowDTO); + + return mapping.findForward(McAppConstants.LEARNER_NOTEBOOK); + } + + /** + * downloadMarks + */ + public ActionForward downloadMarks(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) throws IOException, ServletException { + MessageService messageService = McServiceProxy.getMessageService(getServlet().getServletContext()); + + IMcService mcService = McServiceProxy.getMcService(getServlet().getServletContext()); + Long toolContentID = WebUtil.readLongParam(request, AttributeNames.PARAM_TOOL_CONTENT_ID, false); + + McContent mcContent = mcService.getMcContent(new Long(toolContentID)); + + byte[] spreadsheet = null; + + try { + spreadsheet = mcService.prepareSessionDataSpreadsheet(mcContent); + } catch (Exception e) { + log.error("Error preparing spreadsheet: ", e); + request.setAttribute("errorName", messageService.getMessage("error.monitoring.spreadsheet.download")); + request.setAttribute("errorMessage", e); + return mapping.findForward("error"); + } + + // set cookie that will tell JS script that export has been finished + String downloadTokenValue = WebUtil.readStrParam(request, "downloadTokenValue"); + Cookie fileDownloadTokenCookie = new Cookie("fileDownloadToken", downloadTokenValue); + fileDownloadTokenCookie.setPath("/"); + response.addCookie(fileDownloadTokenCookie); + + // construct download file response header + OutputStream out = response.getOutputStream(); + String fileName = "lams_mcq.xls"; + String mineType = "application/vnd.ms-excel"; + String header = "attachment; filename=\"" + fileName + "\";"; + response.setContentType(mineType); + response.setHeader("Content-Disposition", header); + + // write response + try { + out.write(spreadsheet); + out.flush(); + } finally { + try { + if (out != null) { + out.close(); + } + } catch (IOException e) { + } + } + + return null; + } + + /** + * Set Submission Deadline + * @throws IOException + */ + public ActionForward setSubmissionDeadline(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) throws IOException { + + IMcService service = McServiceProxy.getMcService(getServlet().getServletContext()); + + Long contentID = WebUtil.readLongParam(request, AttributeNames.PARAM_TOOL_CONTENT_ID); + McContent mcContent = service.getMcContent(contentID); + + Long dateParameter = WebUtil.readLongParam(request, McAppConstants.ATTR_SUBMISSION_DEADLINE, true); + Date tzSubmissionDeadline = null; + String formattedDate = ""; + if (dateParameter != null) { + Date submissionDeadline = new Date(dateParameter); + HttpSession ss = SessionManager.getSession(); + org.lamsfoundation.lams.usermanagement.dto.UserDTO teacher = (org.lamsfoundation.lams.usermanagement.dto.UserDTO) ss + .getAttribute(AttributeNames.USER); + TimeZone teacherTimeZone = teacher.getTimeZone(); + tzSubmissionDeadline = DateUtil.convertFromTimeZoneToDefault(teacherTimeZone, submissionDeadline); + formattedDate = DateUtil.convertToStringForJSON(tzSubmissionDeadline, request.getLocale()); + } + mcContent.setSubmissionDeadline(tzSubmissionDeadline); + service.updateMc(mcContent); + response.setContentType("text/plain;charset=utf-8"); + response.getWriter().print(formattedDate); + return null; + } + + /** + * Set tool's activityEvaluation + * + * @param mapping + * @param form + * @param request + * @param response + * @return + * @throws JSONException + * @throws IOException + */ + public ActionForward setActivityEvaluation(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) throws JSONException, IOException { + IMcService service = McServiceProxy.getMcService(getServlet().getServletContext()); + + Long contentID = WebUtil.readLongParam(request, AttributeNames.PARAM_TOOL_CONTENT_ID); + String activityEvaluation = WebUtil.readStrParam(request, McAppConstants.ATTR_ACTIVITY_EVALUATION); + service.setActivityEvaluation(contentID, activityEvaluation); + + JSONObject responseJSON = new JSONObject(); + responseJSON.put("success", "true"); + response.setContentType("application/json;charset=utf-8"); + response.getWriter().print(new String(responseJSON.toString())); + return null; + } + + /** + * Populate user jqgrid table on summary page. + */ + public ActionForward userMasterDetail(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) { + IMcService mcService = McServiceProxy.getMcService(getServlet().getServletContext()); + + Long userUid = WebUtil.readLongParam(request, McAppConstants.USER_UID); + McQueUsr user = mcService.getMcUserByUID(userUid); + List userAttempts = mcService.getFinalizedUserAttempts(user); + + // Escapes all characters that may brake JS code on assigning Java value to JS String variable (particularly + // escapes all quotes in the following way \"). + if (userAttempts != null) { + for (McUsrAttempt userAttempt : userAttempts) { + McQueContent question = userAttempt.getMcQueContent(); + McOptsContent option = userAttempt.getMcOptionsContent(); + + String questionText = question.getQuestion(); + if (questionText != null) { + String escapedQuestion = StringEscapeUtils.escapeJavaScript(questionText); + question.setEscapedQuestion(escapedQuestion); + } + + String optionText = option.getMcQueOptionText(); + if (optionText != null) { + String escapedOptionText = StringEscapeUtils.escapeJavaScript(optionText); + option.setEscapedOptionText(escapedOptionText); + } + } + } + + request.setAttribute(McAppConstants.USER_ATTEMPTS, userAttempts); + request.setAttribute(McAppConstants.TOOL_SESSION_ID, user.getMcSession().getMcSessionId()); + return (userAttempts == null || userAttempts.isEmpty()) ? null + : mapping.findForward(McAppConstants.USER_MASTER_DETAIL); + } + + /** + * Return paged users for jqGrid. + */ + public ActionForward getPagedUsers(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) throws JSONException, IOException { + IMcService mcService = McServiceProxy.getMcService(getServlet().getServletContext()); + + Long sessionId = WebUtil.readLongParam(request, AttributeNames.PARAM_TOOL_SESSION_ID); + McSession session = mcService.getMcSessionById(sessionId); + //find group leader, if any + McQueUsr groupLeader = session.getGroupLeader(); + + // Getting the params passed in from the jqGrid + int page = WebUtil.readIntParam(request, AttributeNames.PARAM_PAGE); + int rowLimit = WebUtil.readIntParam(request, AttributeNames.PARAM_ROWS); + String sortOrder = WebUtil.readStrParam(request, AttributeNames.PARAM_SORD); + String sortBy = WebUtil.readStrParam(request, AttributeNames.PARAM_SIDX, true); + if (StringUtils.isEmpty(sortBy)) { + sortBy = "userName"; + } + String searchString = WebUtil.readStrParam(request, "userName", true); + + List userDtos = mcService.getPagedUsersBySession(sessionId, page - 1, rowLimit, sortBy, + sortOrder, searchString); + int countVisitLogs = mcService.getCountPagedUsersBySession(sessionId, searchString); + + int totalPages = new Double( + Math.ceil(new Integer(countVisitLogs).doubleValue() / new Integer(rowLimit).doubleValue())).intValue(); + + JSONArray rows = new JSONArray(); + int i = 1; + for (McUserMarkDTO userDto : userDtos) { + + JSONArray visitLogData = new JSONArray(); + Long userUid = Long.parseLong(userDto.getQueUsrId()); + visitLogData.put(userUid); + String fullName = StringEscapeUtils.escapeHtml(userDto.getFullName()); + if (groupLeader != null && groupLeader.getUid().equals(userUid)) { + fullName += " (" + mcService.getLocalizedMessage("label.monitoring.group.leader") + ")"; + } + + visitLogData.put(fullName); + Long totalMark = (userDto.getTotalMark() == null) ? 0 : userDto.getTotalMark(); + visitLogData.put(totalMark); + + JSONObject userRow = new JSONObject(); + userRow.put("id", i++); + userRow.put("cell", visitLogData); + + rows.put(userRow); + } + + JSONObject responseJSON = new JSONObject(); + responseJSON.put("total", totalPages); + responseJSON.put("page", page); + responseJSON.put("records", countVisitLogs); + responseJSON.put("rows", rows); + + response.setContentType("application/json;charset=utf-8"); + response.getWriter().write(responseJSON.toString()); + return null; + } + + public ActionForward saveUserMark(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) { + + if ((request.getParameter(McAppConstants.PARAM_NOT_A_NUMBER) == null) + && !StringUtils.isEmpty(request.getParameter(McAppConstants.PARAM_USER_ATTEMPT_UID))) { + IMcService mcService = McServiceProxy.getMcService(getServlet().getServletContext()); + + Long userAttemptUid = WebUtil.readLongParam(request, McAppConstants.PARAM_USER_ATTEMPT_UID); + Integer newGrade = Integer.valueOf(request.getParameter(McAppConstants.PARAM_GRADE)); + mcService.changeUserAttemptMark(userAttemptUid, newGrade); + } + + return null; + } + + /** + * Get the mark summary with data arranged in bands. Can be displayed graphically or in a table. + */ + public ActionForward getMarkChartData(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse res) throws IOException, ServletException, JSONException { + + IMcService mcService = McServiceProxy.getMcService(getServlet().getServletContext()); + Long contentID = WebUtil.readLongParam(request, AttributeNames.PARAM_TOOL_CONTENT_ID); + McContent mcContent = mcService.getMcContent(contentID); + List results = null; + + if ( mcContent != null ) { + if ( mcContent.isUseSelectLeaderToolOuput() ) { + results = mcService.getMarksArrayForLeaders(contentID); + } else { + Long sessionID = WebUtil.readLongParam(request, AttributeNames.PARAM_TOOL_SESSION_ID); + results = mcService.getMarksArray(sessionID); + } + } + + JSONObject responseJSON = new JSONObject(); + if ( results != null ) + responseJSON.put("data", results); + else + responseJSON.put("data", new Float[0]); + + res.setContentType("application/json;charset=utf-8"); + res.getWriter().write(responseJSON.toString()); + return null; + + } + + public ActionForward statistic(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) { + + IMcService mcService = McServiceProxy.getMcService(getServlet().getServletContext()); + Long contentID = WebUtil.readLongParam(request, AttributeNames.PARAM_TOOL_CONTENT_ID); + request.setAttribute(AttributeNames.PARAM_TOOL_CONTENT_ID, contentID); + McContent mcContent = mcService.getMcContent(contentID); + if ( mcContent != null ) { + if ( mcContent.isUseSelectLeaderToolOuput() ) { + LeaderResultsDTO leaderDto = mcService.getLeaderResultsDTOForLeaders(contentID); + request.setAttribute("leaderDto", leaderDto); + } else { + List sessionDtos = mcService.getSessionDtos(contentID, true); + request.setAttribute("sessionDtos", sessionDtos); + } + request.setAttribute("useSelectLeaderToolOutput", mcContent.isUseSelectLeaderToolOuput()); + } + + // prepare toolOutputDefinitions and activityEvaluation + List toolOutputDefinitions = new ArrayList(); + toolOutputDefinitions.add(McAppConstants.OUTPUT_NAME_LEARNER_MARK); + toolOutputDefinitions.add(McAppConstants.OUTPUT_NAME_LEARNER_ALL_CORRECT); + String activityEvaluation = mcService.getActivityEvaluation(contentID); + request.setAttribute(McAppConstants.ATTR_TOOL_OUTPUT_DEFINITIONS, toolOutputDefinitions); + request.setAttribute(McAppConstants.ATTR_ACTIVITY_EVALUATION, activityEvaluation); + + return mapping.findForward(McAppConstants.STATISTICS); + } + + +} Index: lams_tool_lamc/src/java/org/lamsfoundation/lams/tool/mc/web/action/McMonitoringStarterAction.java =================================================================== diff -u --- lams_tool_lamc/src/java/org/lamsfoundation/lams/tool/mc/web/action/McMonitoringStarterAction.java (revision 0) +++ lams_tool_lamc/src/java/org/lamsfoundation/lams/tool/mc/web/action/McMonitoringStarterAction.java (revision 4170df8bc66e658ef4dcd47e99eceddec3c2673a) @@ -0,0 +1,176 @@ +/*************************************************************************** + * 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.mc.web.action; + +import java.io.IOException; +import java.util.ArrayList; +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.mc.McAppConstants; +import org.lamsfoundation.lams.tool.mc.dto.McGeneralMonitoringDTO; +import org.lamsfoundation.lams.tool.mc.dto.ReflectionDTO; +import org.lamsfoundation.lams.tool.mc.dto.SessionDTO; +import org.lamsfoundation.lams.tool.mc.pojos.McContent; +import org.lamsfoundation.lams.tool.mc.pojos.McSession; +import org.lamsfoundation.lams.tool.mc.service.IMcService; +import org.lamsfoundation.lams.tool.mc.service.McApplicationException; +import org.lamsfoundation.lams.tool.mc.service.McServiceProxy; +import org.lamsfoundation.lams.tool.mc.util.McSessionComparator; +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 McMonitoringStarterAction extends Action { + private static Logger logger = Logger.getLogger(McMonitoringStarterAction.class.getName()); + private static IMcService service; + + @Override + @SuppressWarnings("unchecked") + public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) throws IOException, ServletException, McApplicationException { + initializeMcService(); + + McGeneralMonitoringDTO mcGeneralMonitoringDTO = new McGeneralMonitoringDTO(); + + String toolContentID = null; + try { + Long toolContentIDLong = WebUtil.readLongParam(request, AttributeNames.PARAM_TOOL_CONTENT_ID, false); + toolContentID = toolContentIDLong.toString(); + } catch (IllegalArgumentException e) { + logger.error("Unable to start monitoring as tool content id is missing"); + throw (e); + } + + McContent mcContent = service.getMcContent(new Long(toolContentID)); + mcGeneralMonitoringDTO.setToolContentID(toolContentID); + mcGeneralMonitoringDTO.setActivityTitle(mcContent.getTitle()); + mcGeneralMonitoringDTO.setActivityInstructions(mcContent.getInstructions()); + + //set up sessionDTOs list + Set sessions = new TreeSet(new McSessionComparator()); + sessions.addAll(mcContent.getMcSessions()); + List sessionDtos = new LinkedList(); + for (McSession session : sessions) { + SessionDTO sessionDto = new SessionDTO(); + sessionDto.setSessionId(session.getMcSessionId()); + sessionDto.setSessionName(session.getSession_name()); + + sessionDtos.add(sessionDto); + } + request.setAttribute(McAppConstants.SESSION_DTOS, sessionDtos); + + // setting up the advanced summary + + request.setAttribute(McAppConstants.ATTR_CONTENT, mcContent); + request.setAttribute("questionsSequenced", mcContent.isQuestionsSequenced()); + request.setAttribute("showMarks", mcContent.isShowMarks()); + request.setAttribute("useSelectLeaderToolOuput", mcContent.isUseSelectLeaderToolOuput()); + request.setAttribute("prefixAnswersWithLetters", mcContent.isPrefixAnswersWithLetters()); + request.setAttribute("randomize", mcContent.isRandomize()); + request.setAttribute("displayAnswers", mcContent.isDisplayAnswers()); + request.setAttribute("retries", mcContent.isRetries()); + request.setAttribute("reflect", mcContent.isReflect()); + request.setAttribute("reflectionSubject", mcContent.getReflectionSubject()); + request.setAttribute("passMark", mcContent.getPassMark()); + request.setAttribute("toolContentID", mcContent.getMcContentId()); + request.setAttribute(AttributeNames.PARAM_CONTENT_FOLDER_ID, + WebUtil.readStrParam(request, AttributeNames.PARAM_CONTENT_FOLDER_ID)); + + // setting up Date and time restriction in activities + HttpSession ss = SessionManager.getSession(); + Date submissionDeadline = mcContent.getSubmissionDeadline(); + if (submissionDeadline != null) { + UserDTO learnerDto = (UserDTO) ss.getAttribute(AttributeNames.USER); + TimeZone learnerTimeZone = learnerDto.getTimeZone(); + Date tzSubmissionDeadline = DateUtil.convertToTimeZoneFromDefault(learnerTimeZone, submissionDeadline); + request.setAttribute(McAppConstants.ATTR_SUBMISSION_DEADLINE, tzSubmissionDeadline.getTime()); + // use the unconverted time, as convertToStringForJSON() does the timezone conversion if needed + request.setAttribute(McAppConstants.ATTR_SUBMISSION_DEADLINE_DATESTRING, + DateUtil.convertToStringForJSON(submissionDeadline, request.getLocale())); + } + + boolean isGroupedActivity = service.isGroupedActivity(new Long(mcContent.getMcContentId())); + request.setAttribute("isGroupedActivity", isGroupedActivity); + + /* this section is needed for Edit Activity screen, from here... */ + + mcGeneralMonitoringDTO.setDisplayAnswers(new Boolean(mcContent.isDisplayAnswers()).toString()); + + List reflectionsContainerDTO = service.getReflectionList(mcContent, null); + request.setAttribute(McAppConstants.REFLECTIONS_CONTAINER_DTO, reflectionsContainerDTO); + + request.setAttribute(McAppConstants.MC_GENERAL_MONITORING_DTO, mcGeneralMonitoringDTO); + + //count users + int countSessionComplete = 0; + int countAllUsers = 0; + Iterator iteratorSession = mcContent.getMcSessions().iterator(); + while (iteratorSession.hasNext()) { + McSession mcSession = (McSession) iteratorSession.next(); + + if (mcSession != null) { + + if (mcSession.getSessionStatus().equals(McAppConstants.COMPLETED)) { + countSessionComplete++; + } + countAllUsers += mcSession.getMcQueUsers().size(); + } + } + mcGeneralMonitoringDTO.setCountAllUsers(new Integer(countAllUsers)); + mcGeneralMonitoringDTO.setCountSessionComplete(new Integer(countSessionComplete)); + + return (mapping.findForward(McAppConstants.LOAD_MONITORING_CONTENT)); + } + + // ************************************************************************************* + // Private method + // ************************************************************************************* + private void initializeMcService() { + if (service == null) { + service = McServiceProxy.getMcService(getServlet().getServletContext()); + } + } +} Index: lams_tool_lamc/src/java/org/lamsfoundation/lams/tool/mc/web/action/McPedagogicalPlannerAction.java =================================================================== diff -u --- lams_tool_lamc/src/java/org/lamsfoundation/lams/tool/mc/web/action/McPedagogicalPlannerAction.java (revision 0) +++ lams_tool_lamc/src/java/org/lamsfoundation/lams/tool/mc/web/action/McPedagogicalPlannerAction.java (revision 4170df8bc66e658ef4dcd47e99eceddec3c2673a) @@ -0,0 +1,181 @@ +/**************************************************************** + * 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.mc.web.action; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; + +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.ActionForm; +import org.apache.struts.action.ActionForward; +import org.apache.struts.action.ActionMapping; +import org.apache.struts.action.ActionMessages; +import org.lamsfoundation.lams.tool.mc.McAppConstants; +import org.lamsfoundation.lams.tool.mc.dto.McOptionDTO; +import org.lamsfoundation.lams.tool.mc.pojos.McContent; +import org.lamsfoundation.lams.tool.mc.pojos.McOptsContent; +import org.lamsfoundation.lams.tool.mc.pojos.McQueContent; +import org.lamsfoundation.lams.tool.mc.service.IMcService; +import org.lamsfoundation.lams.tool.mc.service.McServiceProxy; +import org.lamsfoundation.lams.tool.mc.web.form.McPedagogicalPlannerForm; +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 McPedagogicalPlannerAction 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) { + McPedagogicalPlannerForm plannerForm = (McPedagogicalPlannerForm) form; + Long toolContentID = WebUtil.readLongParam(request, AttributeNames.PARAM_TOOL_CONTENT_ID); + McContent mcContent = getMcService().getMcContent(toolContentID); + plannerForm.fillForm(mcContent, getMcService()); + return mapping.findForward(McAppConstants.SUCCESS); + } + + public ActionForward saveOrUpdatePedagogicalPlannerForm(ActionMapping mapping, ActionForm form, + HttpServletRequest request, HttpServletResponse response) throws IOException { + + McPedagogicalPlannerForm plannerForm = (McPedagogicalPlannerForm) form; + ActionMessages errors = plannerForm.validate(request); + + if (errors.isEmpty()) { + McContent mcContent = getMcService().getMcContent(plannerForm.getToolContentID()); + int questionIndex = 1; + String question = null; + + do { + question = plannerForm.getQuestion(questionIndex - 1); + List candidateAnswerDTOList = plannerForm.extractCandidateAnswers(request, questionIndex); + boolean removeQuestion = true; + if (!StringUtils.isEmpty(question)) { + if (candidateAnswerDTOList != null) { + for (McOptionDTO answer : candidateAnswerDTOList) { + if (answer != null && !StringUtils.isEmpty(answer.getCandidateAnswer())) { + removeQuestion = false; + break; + } + } + } + } + if (removeQuestion) { + plannerForm.removeQuestion(questionIndex - 1); + } else { + if (questionIndex <= mcContent.getMcQueContents().size()) { + McQueContent mcQueContent = getMcService().getQuestionByDisplayOrder((long) questionIndex, + mcContent.getUid()); + mcQueContent.setQuestion(question); + int candidateAnswerDTOIndex = 0; + Set candidateAnswers = mcQueContent.getMcOptionsContents(); + Iterator candidateAnswerIter = candidateAnswers.iterator(); + while (candidateAnswerIter.hasNext()) { + McOptsContent candidateAnswer = candidateAnswerIter.next(); + if (candidateAnswerDTOIndex >= candidateAnswerDTOList.size()) { + candidateAnswerIter.remove(); + } else { + McOptionDTO answerDTO = candidateAnswerDTOList.get(candidateAnswerDTOIndex); + candidateAnswer.setCorrectOption(McAppConstants.CORRECT.equals(answerDTO.getCorrect())); + candidateAnswer.setMcQueOptionText(answerDTO.getCandidateAnswer()); + getMcService().updateMcOptionsContent(candidateAnswer); + } + candidateAnswerDTOIndex++; + } + getMcService().saveOrUpdateMcQueContent(mcQueContent); + } else { + McQueContent mcQueContent = new McQueContent(); + mcQueContent.setDisplayOrder(questionIndex); + mcQueContent.setMcContent(mcContent); + mcQueContent.setMcContentId(mcContent.getMcContentId()); + mcQueContent.setQuestion(question); + mcQueContent.setMark(McAppConstants.QUESTION_DEFAULT_MARK); + Set candidateAnswers = mcQueContent.getMcOptionsContents(); + for (int candidateAnswerDTOIndex = 0; candidateAnswerDTOIndex < candidateAnswerDTOList + .size(); candidateAnswerDTOIndex++) { + McOptionDTO answerDTO = candidateAnswerDTOList.get(candidateAnswerDTOIndex); + McOptsContent candidateAnswer = new McOptsContent(candidateAnswerDTOIndex + 1, + McAppConstants.CORRECT.equals(answerDTO.getCorrect()), + answerDTO.getCandidateAnswer(), mcQueContent); + candidateAnswer.setMcQueContentId(mcQueContent.getMcContentId()); + candidateAnswers.add(candidateAnswer); + } + getMcService().saveOrUpdateMcQueContent(mcQueContent); + mcContent.getMcQueContents().add(mcQueContent); + } + questionIndex++; + } + } while (questionIndex <= plannerForm.getQuestionCount()); + for (; questionIndex <= mcContent.getMcQueContents().size(); questionIndex++) { + McQueContent mcQueContent = getMcService().getQuestionByDisplayOrder((long) questionIndex, + mcContent.getUid()); + mcContent.getMcQueContents().remove(mcQueContent); + getMcService().removeMcQueContent(mcQueContent); + } + plannerForm.fillForm(mcContent, getMcService()); + } else { + saveErrors(request, errors); + } + return mapping.findForward(McAppConstants.SUCCESS); + } + + public ActionForward createPedagogicalPlannerQuestion(ActionMapping mapping, ActionForm form, + HttpServletRequest request, HttpServletResponse response) { + McPedagogicalPlannerForm plannerForm = (McPedagogicalPlannerForm) form; + int questionDisplayOrder = plannerForm.getQuestionCount().intValue() + 1; + plannerForm.setCandidateAnswerCount(new ArrayList(plannerForm.getQuestionCount())); + Map paramMap = request.getParameterMap(); + for (int questionIndex = 1; questionIndex < questionDisplayOrder; questionIndex++) { + String[] param = paramMap.get(McAppConstants.CANDIDATE_ANSWER_COUNT + questionIndex); + int count = NumberUtils.toInt(param[0]); + plannerForm.getCandidateAnswerCount().add(count); + } + plannerForm.setQuestion(questionDisplayOrder - 1, ""); + plannerForm.getCandidateAnswerCount().add(McAppConstants.CANDIDATE_ANSWER_DEFAULT_COUNT); + plannerForm.setCorrect(questionDisplayOrder - 1, "1"); + return mapping.findForward(McAppConstants.SUCCESS); + } + + private IMcService getMcService() { + WebApplicationContext wac = WebApplicationContextUtils + .getRequiredWebApplicationContext(getServlet().getServletContext()); + return McServiceProxy.getMcService(getServlet().getServletContext()); + } + +} \ No newline at end of file Index: lams_tool_lamc/src/java/org/lamsfoundation/lams/tool/mc/web/action/McStarterAction.java =================================================================== diff -u --- lams_tool_lamc/src/java/org/lamsfoundation/lams/tool/mc/web/action/McStarterAction.java (revision 0) +++ lams_tool_lamc/src/java/org/lamsfoundation/lams/tool/mc/web/action/McStarterAction.java (revision 4170df8bc66e658ef4dcd47e99eceddec3c2673a) @@ -0,0 +1,122 @@ +/**************************************************************** + * 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.mc.web.action; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +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.ToolAccessMode; +import org.lamsfoundation.lams.tool.mc.McAppConstants; +import org.lamsfoundation.lams.tool.mc.dto.McQuestionDTO; +import org.lamsfoundation.lams.tool.mc.pojos.McContent; +import org.lamsfoundation.lams.tool.mc.service.IMcService; +import org.lamsfoundation.lams.tool.mc.service.McApplicationException; +import org.lamsfoundation.lams.tool.mc.service.McServiceProxy; +import org.lamsfoundation.lams.tool.mc.util.AuthoringUtil; +import org.lamsfoundation.lams.tool.mc.web.form.McAuthoringForm; +import org.lamsfoundation.lams.util.WebUtil; +import org.lamsfoundation.lams.web.util.AttributeNames; +import org.lamsfoundation.lams.web.util.SessionMap; + +/** + * A Map data structure is used to present the UI. + * + * @author Ozgur Demirtas + */ +public class McStarterAction extends Action { + private static Logger logger = Logger.getLogger(McStarterAction.class.getName()); + + @Override + public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) throws IOException, ServletException, McApplicationException { + + McAuthoringForm mcAuthoringForm = (McAuthoringForm) form; + + SessionMap sessionMap = new SessionMap(); + request.getSession().setAttribute(sessionMap.getSessionID(), sessionMap); + String sessionMapId = sessionMap.getSessionID(); + request.setAttribute(McAppConstants.ATTR_SESSION_MAP_ID, sessionMapId); + + String contentFolderID = WebUtil.readStrParam(request, AttributeNames.PARAM_CONTENT_FOLDER_ID); + sessionMap.put(AttributeNames.PARAM_CONTENT_FOLDER_ID, contentFolderID); + String strToolContentID = request.getParameter(AttributeNames.PARAM_TOOL_CONTENT_ID); + sessionMap.put(AttributeNames.PARAM_TOOL_CONTENT_ID, strToolContentID); + ToolAccessMode mode = WebUtil.readToolAccessModeAuthorDefaulted(request); + sessionMap.put(AttributeNames.ATTR_MODE, mode); + + IMcService mcService = McServiceProxy.getMcService(getServlet().getServletContext()); + + // request is from monitoring module + if (mode.isTeacher()) { + mcService.setDefineLater(strToolContentID, true); + } + + if ((strToolContentID == null) || (strToolContentID.equals(""))) { + return (mapping.findForward(McAppConstants.ERROR_LIST)); + } + + McContent mcContent = mcService.getMcContent(new Long(strToolContentID)); + + // if mcContent does not exist, try to use default content instead. + if (mcContent == null) { + long defaultContentID = mcService.getToolDefaultContentIdBySignature(McAppConstants.TOOL_SIGNATURE); + mcContent = mcService.getMcContent(new Long(defaultContentID)); + mcContent = McContent.newInstance(mcContent, new Long(strToolContentID)); + } + + // prepare form + mcAuthoringForm.setSln(mcContent.isShowReport() ? "1" : "0"); + mcAuthoringForm.setQuestionsSequenced(mcContent.isQuestionsSequenced() ? "1" : "0"); + mcAuthoringForm.setRandomize(mcContent.isRandomize() ? "1" : "0"); + mcAuthoringForm.setDisplayAnswers(mcContent.isDisplayAnswers() ? "1" : "0"); + mcAuthoringForm.setShowMarks(mcContent.isShowMarks() ? "1" : "0"); + mcAuthoringForm.setUseSelectLeaderToolOuput(mcContent.isUseSelectLeaderToolOuput() ? "1" : "0"); + mcAuthoringForm.setPrefixAnswersWithLetters(mcContent.isPrefixAnswersWithLetters() ? "1" : "0"); + mcAuthoringForm.setRetries(mcContent.isRetries() ? "1" : "0"); + mcAuthoringForm.setPassmark("" + mcContent.getPassMark()); + mcAuthoringForm.setReflect(mcContent.isReflect() ? "1" : "0"); + mcAuthoringForm.setReflectionSubject(mcContent.getReflectionSubject()); + mcAuthoringForm.setTitle(mcContent.getTitle()); + mcAuthoringForm.setInstructions(mcContent.getInstructions()); + + List questionDtos = AuthoringUtil.buildDefaultQuestions(mcContent); + sessionMap.put(McAppConstants.QUESTION_DTOS, questionDtos); + + List listDeletedQuestionDTOs = new ArrayList(); + sessionMap.put(McAppConstants.LIST_DELETED_QUESTION_DTOS, listDeletedQuestionDTOs); + + return (mapping.findForward(McAppConstants.LOAD_AUTHORING)); + } +} Index: lams_tool_lamc/src/java/org/lamsfoundation/lams/tool/mc/web/form/McPedagogicalPlannerForm.java =================================================================== diff -u -r289926a27bdbc9bd2519e3064a85f489fc1845ec -r4170df8bc66e658ef4dcd47e99eceddec3c2673a --- lams_tool_lamc/src/java/org/lamsfoundation/lams/tool/mc/web/form/McPedagogicalPlannerForm.java (.../McPedagogicalPlannerForm.java) (revision 289926a27bdbc9bd2519e3064a85f489fc1845ec) +++ lams_tool_lamc/src/java/org/lamsfoundation/lams/tool/mc/web/form/McPedagogicalPlannerForm.java (.../McPedagogicalPlannerForm.java) (revision 4170df8bc66e658ef4dcd47e99eceddec3c2673a) @@ -40,7 +40,7 @@ import org.lamsfoundation.lams.tool.mc.dto.McQuestionDTO; import org.lamsfoundation.lams.tool.mc.pojos.McContent; import org.lamsfoundation.lams.tool.mc.service.IMcService; -import org.lamsfoundation.lams.tool.mc.web.AuthoringUtil; +import org.lamsfoundation.lams.tool.mc.util.AuthoringUtil; import org.lamsfoundation.lams.web.planner.PedagogicalPlannerActivityForm; public class McPedagogicalPlannerForm extends PedagogicalPlannerActivityForm { Index: lams_tool_lamc/web/WEB-INF/struts-config.xml =================================================================== diff -u -rec381d32c228f460e0fd3ce3857aab14d4f6fd87 -r4170df8bc66e658ef4dcd47e99eceddec3c2673a --- lams_tool_lamc/web/WEB-INF/struts-config.xml (.../struts-config.xml) (revision ec381d32c228f460e0fd3ce3857aab14d4f6fd87) +++ lams_tool_lamc/web/WEB-INF/struts-config.xml (.../struts-config.xml) (revision 4170df8bc66e658ef4dcd47e99eceddec3c2673a) @@ -30,7 +30,7 @@ + type="org.lamsfoundation.lams.tool.mc.web.action.ClearSessionAction">