Index: lams_tool_daco/.externalToolBuilders/SASS_lams_tool_daco.launch =================================================================== diff -u -r7475d08afc280b5e2e5ddf04e8bf35e3166aaf80 -r085d47fc4191f2cb614a5a7c8fe3ff6c5abcef0f --- lams_tool_daco/.externalToolBuilders/SASS_lams_tool_daco.launch (.../SASS_lams_tool_daco.launch) (revision 7475d08afc280b5e2e5ddf04e8bf35e3166aaf80) +++ lams_tool_daco/.externalToolBuilders/SASS_lams_tool_daco.launch (.../SASS_lams_tool_daco.launch) (revision 085d47fc4191f2cb614a5a7c8fe3ff6c5abcef0f) @@ -5,6 +5,12 @@ + + + + + + Fisheye: Tag 085d47fc4191f2cb614a5a7c8fe3ff6c5abcef0f refers to a dead (removed) revision in file `lams_tool_daco/src/java/org/lamsfoundation/lams/tool/daco/web/action/AuthoringAction.java'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 085d47fc4191f2cb614a5a7c8fe3ff6c5abcef0f refers to a dead (removed) revision in file `lams_tool_daco/src/java/org/lamsfoundation/lams/tool/daco/web/action/ClearSessionAction.java'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 085d47fc4191f2cb614a5a7c8fe3ff6c5abcef0f refers to a dead (removed) revision in file `lams_tool_daco/src/java/org/lamsfoundation/lams/tool/daco/web/action/LearningAction.java'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 085d47fc4191f2cb614a5a7c8fe3ff6c5abcef0f refers to a dead (removed) revision in file `lams_tool_daco/src/java/org/lamsfoundation/lams/tool/daco/web/action/MonitoringAction.java'. Fisheye: No comparison available. Pass `N' to diff? Index: lams_tool_daco/src/java/org/lamsfoundation/lams/tool/daco/web/controller/AuthoringController.java =================================================================== diff -u --- lams_tool_daco/src/java/org/lamsfoundation/lams/tool/daco/web/controller/AuthoringController.java (revision 0) +++ lams_tool_daco/src/java/org/lamsfoundation/lams/tool/daco/web/controller/AuthoringController.java (revision 085d47fc4191f2cb614a5a7c8fe3ff6c5abcef0f) @@ -0,0 +1,944 @@ +///**************************************************************** +// * 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.daco.web.controller; +// +//import java.io.UnsupportedEncodingException; +//import java.net.URLDecoder; +//import java.sql.Timestamp; +//import java.util.ArrayList; +//import java.util.Date; +//import java.util.HashMap; +//import java.util.Iterator; +//import java.util.LinkedHashSet; +//import java.util.List; +//import java.util.Map; +//import java.util.Set; +//import java.util.SortedSet; +//import java.util.TreeSet; +// +//import javax.servlet.ServletException; +//import javax.servlet.http.HttpServletRequest; +//import javax.servlet.http.HttpServletResponse; +//import javax.servlet.http.HttpSession; +// +//import org.apache.commons.beanutils.PropertyUtils; +//import org.apache.commons.lang.StringUtils; +//import org.apache.commons.lang.math.NumberUtils; +//import org.apache.log4j.Logger; +//import org.apache.struts.action.Action; +//import org.apache.struts.action.ActionErrors; +//import org.apache.struts.action.ActionForm; +//import org.apache.struts.action.ActionForward; +//import org.apache.struts.action.ActionMapping; +//import org.apache.struts.action.ActionMessage; +//import org.apache.struts.action.ActionMessages; +//import org.lamsfoundation.lams.authoring.web.AuthoringConstants; +//import org.lamsfoundation.lams.tool.ToolAccessMode; +//import org.lamsfoundation.lams.tool.daco.DacoConstants; +//import org.lamsfoundation.lams.tool.daco.model.Daco; +//import org.lamsfoundation.lams.tool.daco.model.DacoAnswerOption; +//import org.lamsfoundation.lams.tool.daco.model.DacoQuestion; +//import org.lamsfoundation.lams.tool.daco.model.DacoUser; +//import org.lamsfoundation.lams.tool.daco.service.DacoApplicationException; +//import org.lamsfoundation.lams.tool.daco.service.IDacoService; +//import org.lamsfoundation.lams.tool.daco.util.DacoQuestionComparator; +//import org.lamsfoundation.lams.tool.daco.web.form.DacoForm; +//import org.lamsfoundation.lams.tool.daco.web.form.DacoQuestionForm; +//import org.lamsfoundation.lams.usermanagement.dto.UserDTO; +//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; +//import org.springframework.stereotype.Controller; +//import org.springframework.web.bind.annotation.ModelAttribute; +//import org.springframework.web.bind.annotation.RequestMapping; +//import org.springframework.web.context.WebApplicationContext; +//import org.springframework.web.context.support.WebApplicationContextUtils; +// +///** +// * @author Marcin Cieslak +// */ +//@Controller +//@RequestMapping("/authoring") +//public class AuthoringController { +// +// private static Logger log = Logger.getLogger(AuthoringController.class); +// +// /** +// * Display edit page for existed daco question. +// * +// * @param mapping +// * @param form +// * @param request +// * @param response +// * @return +// */ +// @RequestMapping("/editQuestion") +// protected String editQuestion(@ModelAttribute("questionForm")DacoQuestionForm questionForm, HttpServletRequest request) { +// +// // get back sessionMAP +// String sessionMapID = WebUtil.readStrParam(request, DacoConstants.ATTR_SESSION_MAP_ID); +// SessionMap sessionMap = (SessionMap) request.getSession() +// .getAttribute(sessionMapID); +// int questionIndex = NumberUtils.stringToInt(request.getParameter(DacoConstants.PARAM_QUESTION_INDEX), -1); +// DacoQuestion question = null; +// if (questionIndex != -1) { +// SortedSet questionSet = getQuestionList(sessionMap); +// List questionList = new ArrayList<>(questionSet); +// question = questionList.get(questionIndex); +// if (question != null) { +// populateQuestionToForm(questionIndex, question, questionForm, request); +// } +// } +// return findForward(question == null ? -1 : question.getType(), mapping); +// } +// +// /** +// * Extract web from content to daco question. +// * +// * @param request +// * @param questionForm +// * @param answerOptionList +// * @throws DacoApplicationException +// */ +// protected void extractFormToDacoQuestion(HttpServletRequest request, List answerOptionList, +// DacoQuestionForm questionForm) throws Exception { +// /* +// * BE CAREFUL: This method will copy nessary info from request form to a old or new DacoQuestion instance. It +// * gets all +// * info EXCEPT DacoQuestion.createDate and DacoQuestion.createBy, which need be set when persisting this daco +// * question. +// */ +// +// SessionMap sessionMap = (SessionMap) request.getSession() +// .getAttribute(questionForm.getSessionMapID()); +// // check whether it is "edit(old question)" or "add(new question)" +// SortedSet questionSet = getQuestionList(sessionMap); +// int questionIndex = NumberUtils.stringToInt(questionForm.getQuestionIndex(), -1); +// DacoQuestion question = null; +// if (questionIndex == -1) { // add +// question = new DacoQuestion(); +// question.setCreateDate(new Timestamp(new Date().getTime())); +// questionSet.add(question); +// +// } else { // edit +// List questionList = new ArrayList<>(questionSet); +// question = questionList.get(questionIndex); +// } +// +// question.setType(questionForm.getQuestionType()); +// +// String constraint = questionForm.getMax(); +// if (!StringUtils.isBlank(constraint)) { +// question.setMax(Float.parseFloat(constraint)); +// } else { +// question.setMax(null); +// } +// constraint = questionForm.getMin(); +// if (!StringUtils.isBlank(constraint)) { +// question.setMin(Float.parseFloat(constraint)); +// } else { +// question.setMin(null); +// } +// constraint = questionForm.getDigitsDecimal(); +// if (!StringUtils.isBlank(constraint)) { +// question.setDigitsDecimal(Short.parseShort(constraint)); +// } +// +// Set answerOptions = new LinkedHashSet<>(); +// if (answerOptionList != null) { +// int index = 1; +// for (String ins : answerOptionList) { +// DacoAnswerOption answerOption = new DacoAnswerOption(); +// answerOption.setAnswerOption(ins.trim()); +// answerOption.setSequenceNumber(index++); +// answerOptions.add(answerOption); +// } +// } +// question.setRequired(questionForm.isQuestionRequired()); +// question.setAnswerOptions(answerOptions); +// +// Short summary = questionForm.getSummary(); +// if (summary != null && summary > 0) { +// question.setSummary(questionForm.getSummary()); +// } else { +// question.setSummary(null); +// } +// +// question.setDescription( +// StringUtils.isBlank(questionForm.getDescription()) ? null : questionForm.getDescription().trim()); +// +// } +// +// /** +// * Get back relative ActionForward from request. +// * +// * @param type +// * @param mapping +// * @return +// */ +// protected ActionForward findForward(short type, ActionMapping mapping) { +// ActionForward forward; +// switch (type) { +// case DacoConstants.QUESTION_TYPE_TEXTFIELD: +// forward = mapping.findForward("textfield"); +// break; +// case DacoConstants.QUESTION_TYPE_TEXTAREA: +// forward = mapping.findForward("textarea"); +// break; +// case DacoConstants.QUESTION_TYPE_NUMBER: +// forward = mapping.findForward("number"); +// break; +// case DacoConstants.QUESTION_TYPE_DATE: +// forward = mapping.findForward("date"); +// break; +// case DacoConstants.QUESTION_TYPE_FILE: +// forward = mapping.findForward("file"); +// break; +// case DacoConstants.QUESTION_TYPE_IMAGE: +// forward = mapping.findForward("image"); +// break; +// case DacoConstants.QUESTION_TYPE_RADIO: +// forward = mapping.findForward("radio"); +// break; +// case DacoConstants.QUESTION_TYPE_DROPDOWN: +// forward = mapping.findForward("dropdown"); +// break; +// case DacoConstants.QUESTION_TYPE_CHECKBOX: +// forward = mapping.findForward("checkbox"); +// break; +// case DacoConstants.QUESTION_TYPE_LONGLAT: +// forward = mapping.findForward("longlat"); +// break; +// default: +// forward = null; +// break; +// } +// return forward; +// } +// +// /** +// * Get answer options from HttpRequest +// * +// * @param request +// */ +// protected List getAnswerOptionsFromRequest(HttpServletRequest request) { +// String list = request.getParameter(DacoConstants.ATTR_ANSWER_OPTION_LIST); +// if (list == null) { +// return null; +// } +// String[] params = list.split("&"); +// Map paramMap = new HashMap<>(); +// String[] pair; +// for (String item : params) { +// pair = item.split("="); +// if (pair == null || pair.length != 2) { +// continue; +// } +// try { +// paramMap.put(pair[0], URLDecoder.decode(pair[1], "UTF-8")); +// } catch (UnsupportedEncodingException e) { +// AuthoringController.log.error("Error occurs when decode answer options string:" + e.toString()); +// } +// } +// +// int count = NumberUtils.stringToInt(paramMap.get(DacoConstants.ANSWER_OPTION_COUNT)); +// List answerOptionList = new ArrayList<>(); +// for (int index = 1; index <= count; index++) { +// String item = paramMap.get(DacoConstants.ANSWER_OPTION_DESC_PREFIX + index); +// if (item != null) { +// answerOptionList.add(item); +// } +// } +// return answerOptionList; +// } +// +// // ************************************************************************************* +// // Private method +// // ************************************************************************************* +// /** +// * Return DacoService bean. +// */ +// protected IDacoService getDacoService() { +// WebApplicationContext wac = WebApplicationContextUtils +// .getRequiredWebApplicationContext(getServlet().getServletContext()); +// return (IDacoService) wac.getBean(DacoConstants.DACO_SERVICE); +// } +// +// /** +// * List save deleted daco questions, which could be persisted or non-persisted questions. +// * +// * @param request +// * @return +// */ +// protected List getDeletedDacoQuestionList(SessionMap sessionMap) { +// return getListFromSession(sessionMap, DacoConstants.ATTR_DELETED_QUESTION_LIST); +// } +// +// /** +// * Get java.util.List from HttpSession by given name. +// * +// * @param request +// * @param name +// * @return +// */ +// protected List getListFromSession(SessionMap sessionMap, String name) { +// List list = (List) sessionMap.get(name); +// if (list == null) { +// list = new ArrayList(); +// sessionMap.put(name, list); +// } +// return list; +// } +// +// /** +// * Get longitude/latitude maps from HttpRequest +// * +// * @param request +// */ +// protected List geSelectedMapsFromRequest(HttpServletRequest request) { +// String list = request.getParameter(DacoConstants.PARAM_LONGLAT_MAPS_SELECTED); +// if (list == null) { +// return null; +// } +// String[] params = list.split("&"); +// List longlatMaps = new ArrayList<>(); +// for (String item : params) { +// longlatMaps.add(item); +// } +// return longlatMaps; +// } +// +// /** +// * List save current daco questions. +// * +// * @param request +// * @return +// */ +// protected SortedSet getQuestionList(SessionMap sessionMap) { +// +// SortedSet list = (SortedSet) sessionMap.get(DacoConstants.ATTR_QUESTION_LIST); +// if (list == null) { +// list = new TreeSet<>(new DacoQuestionComparator()); +// sessionMap.put(DacoConstants.ATTR_QUESTION_LIST, list); +// } +// return list; +// } +// +// /** +// * Display same entire authoring page content from HttpSession variable. +// * +// * @param mapping +// * @param form +// * @param request +// * @param response +// * @return +// * @throws ServletException +// */ +// protected ActionForward initPage(ActionMapping mapping, ActionForm form, HttpServletRequest request, +// HttpServletResponse response) throws ServletException { +// String sessionMapID = WebUtil.readStrParam(request, DacoConstants.ATTR_SESSION_MAP_ID); +// SessionMap sessionMap = (SessionMap) request.getSession() +// .getAttribute(sessionMapID); +// DacoForm existForm = (DacoForm) sessionMap.get(DacoConstants.ATTR_DACO_FORM); +// +// DacoForm dacoForm = (DacoForm) form; +// try { +// PropertyUtils.copyProperties(dacoForm, existForm); +// } catch (Exception e) { +// throw new ServletException(e); +// } +// +// ToolAccessMode mode = WebUtil.readToolAccessModeAuthorDefaulted(request); +// request.setAttribute(AttributeNames.ATTR_MODE, mode.toString()); +// +// return mapping.findForward(DacoConstants.SUCCESS); +// } +// +// /** +// * Ajax call, will add one more input line for new answer option. +// * +// * @param mapping +// * @param form +// * @param request +// * @param response +// * @return +// */ +// protected ActionForward newAnswerOption(ActionMapping mapping, ActionForm form, HttpServletRequest request) { +// int count = NumberUtils.stringToInt(request.getParameter(DacoConstants.ANSWER_OPTION_COUNT), 0); +// +// List answerOptionList = new ArrayList(++count); +// for (int index = 1; index <= count; index++) { +// String answerOption = request.getParameter(DacoConstants.ANSWER_OPTION_DESC_PREFIX + index); +// answerOptionList.add(answerOption == null ? "" : answerOption); +// } +// request.setAttribute(DacoConstants.ATTR_ANSWER_OPTION_LIST, answerOptionList); +// return mapping.findForward(DacoConstants.SUCCESS); +// } +// +// /** +// * Display empty page for new daco question. +// * +// * @param mapping +// * @param form +// * @param request +// * @param response +// * @return +// */ +// protected ActionForward newQuestion(ActionMapping mapping, ActionForm form, HttpServletRequest request) { +// +// String sessionMapID = WebUtil.readStrParam(request, DacoConstants.ATTR_SESSION_MAP_ID); +// DacoQuestionForm questionForm = (DacoQuestionForm) form; +// questionForm.setSessionMapID(sessionMapID); +// +// short type = (short) NumberUtils.stringToInt(request.getParameter(DacoConstants.QUESTION_TYPE)); +// if (type == DacoConstants.QUESTION_TYPE_RADIO || type == DacoConstants.QUESTION_TYPE_DROPDOWN +// || type == DacoConstants.QUESTION_TYPE_CHECKBOX) { +// List answerOptionList = new ArrayList(DacoConstants.INIT_ANSWER_OPTION_COUNT); +// for (int index = 0; index < DacoConstants.INIT_ANSWER_OPTION_COUNT; index++) { +// answerOptionList.add(""); +// } +// request.setAttribute(DacoConstants.ATTR_ANSWER_OPTION_LIST, answerOptionList); +// } +// return findForward(type, mapping); +// } +// +// /** +// * This method will populate daco question information to its form for edit use. +// * +// * @param questionIndex +// * @param question +// * @param form +// * @param request +// */ +// protected void populateQuestionToForm(int questionIndex, DacoQuestion question, DacoQuestionForm form, +// HttpServletRequest request) { +// form.setDescription(question.getDescription()); +// form.setQuestionRequired(question.isRequired()); +// form.setSummary(question.getSummary()); +// if (questionIndex >= 0) { +// form.setQuestionIndex(new Integer(questionIndex).toString()); +// } +// +// Float min = question.getMin(); +// Float max = question.getMax(); +// short questionType = question.getType(); +// +// if (questionType == DacoConstants.QUESTION_TYPE_NUMBER) { +// Short digitsDecimal = question.getDigitsDecimal(); +// if (digitsDecimal != null) { +// form.setDigitsDecimal(digitsDecimal.toString()); +// if (digitsDecimal == 0) { +// form.setMin(min == null ? null : String.valueOf(Math.round(min))); +// form.setMax(max == null ? null : String.valueOf(Math.round(max))); +// } else { +// form.setMin(min == null ? null : String.valueOf(round(min, digitsDecimal))); +// form.setMax(max == null ? null : String.valueOf(round(max, digitsDecimal))); +// } +// } else { +// form.setMin(min == null ? null : String.valueOf(min)); +// form.setMax(max == null ? null : String.valueOf(max)); +// form.setDigitsDecimal(null); +// } +// } else { +// form.setMin(min == null ? null : String.valueOf(min.intValue())); +// form.setMax(max == null ? null : String.valueOf(max.intValue())); +// } +// +// if (questionType == DacoConstants.QUESTION_TYPE_RADIO || questionType == DacoConstants.QUESTION_TYPE_DROPDOWN +// || questionType == DacoConstants.QUESTION_TYPE_CHECKBOX) { +// Set answerOptionList = question.getAnswerOptions(); +// List answerOptions = new ArrayList(); +// for (DacoAnswerOption in : answerOptionList) { +// answerOptions.add(in.getAnswerOption()); +// } +// request.setAttribute(DacoConstants.ATTR_ANSWER_OPTION_LIST, answerOptions); +// } else if (questionType == DacoConstants.QUESTION_TYPE_LONGLAT) { +// +// Set answerOptionList = question.getAnswerOptions(); +// List selectedMaps = new ArrayList(); +// for (DacoAnswerOption in : answerOptionList) { +// selectedMaps.add(in.getAnswerOption()); +// } +// request.setAttribute(DacoConstants.PARAM_LONGLAT_MAPS_SELECTED, selectedMaps); +// } +// } +// +// /** +// * Ajax call, remove the given line of instruction of resource item. +// * +// * @param mapping +// * @param form +// * @param request +// * @param response +// * @return +// */ +// protected ActionForward removeAnswerOption(ActionMapping mapping, ActionForm form, HttpServletRequest request) { +// int count = NumberUtils.stringToInt(request.getParameter(DacoConstants.ANSWER_OPTION_COUNT), 0); +// int removeIndex = NumberUtils.stringToInt(request.getParameter(DacoConstants.PARAM_ANSWER_OPTION_INDEX), -1); +// List answerOptionList = new ArrayList(count - 1); +// for (int index = 1; index <= count; index++) { +// if (index != removeIndex) { +// String answerOption = request.getParameter(DacoConstants.ANSWER_OPTION_DESC_PREFIX + index); +// answerOptionList.add(answerOption == null ? "" : answerOption); +// } +// } +// request.setAttribute(DacoConstants.ATTR_ANSWER_OPTION_LIST, answerOptionList); +// return mapping.findForward(DacoConstants.SUCCESS); +// } +// +// /** +// * Remove daco question from HttpSession list and update page display. As authoring rule, all persist only happen +// * when user +// * submit whole page. So this remove is just impact HttpSession values. +// * +// * @param mapping +// * @param form +// * @param request +// * @param response +// * @return +// */ +// protected ActionForward removeQuestion(ActionMapping mapping, ActionForm form, HttpServletRequest request) { +// +// // get back sessionMAP +// String sessionMapID = WebUtil.readStrParam(request, DacoConstants.ATTR_SESSION_MAP_ID); +// SessionMap sessionMap = (SessionMap) request.getSession() +// .getAttribute(sessionMapID); +// +// int questionIndex = NumberUtils.stringToInt(request.getParameter(DacoConstants.PARAM_QUESTION_INDEX), -1); +// if (questionIndex != -1) { +// SortedSet questionSet = getQuestionList(sessionMap); +// List questionList = new ArrayList<>(questionSet); +// DacoQuestion question = questionList.remove(questionIndex); +// questionSet.clear(); +// questionSet.addAll(questionList); +// // add to delList +// List deletedList = getDeletedDacoQuestionList(sessionMap); +// deletedList.add(question); +// } +// +// request.setAttribute(DacoConstants.ATTR_SESSION_MAP_ID, sessionMapID); +// return mapping.findForward(DacoConstants.SUCCESS); +// } +// +// /** +// * This method will get necessary information from daco question form and save or update into +// * HttpSession +// * DacoQuestionList. Notice, this save is not persist them into database, just save HttpSession +// * temporarily. +// * Only they will be persist when the entire authoring page is being persisted. +// * +// * @param mapping +// * @param form +// * @param request +// * @param response +// * @return +// * @throws ServletException +// */ +// protected ActionForward saveOrUpdateQuestion(ActionMapping mapping, ActionForm form, HttpServletRequest request) { +// List answerOptionList = getAnswerOptionsFromRequest(request); +// List longlatMaps = geSelectedMapsFromRequest(request); +// DacoQuestionForm questionForm = (DacoQuestionForm) form; +// ActionErrors errors = validateDacoQuestionForm(questionForm, answerOptionList); +// +// if (!errors.isEmpty()) { +// this.addErrors(request, errors); +// ensureMinimumAnswerOptions(answerOptionList); +// request.setAttribute(DacoConstants.ATTR_ANSWER_OPTION_LIST, answerOptionList); +// request.setAttribute(DacoConstants.PARAM_LONGLAT_MAPS_SELECTED, longlatMaps); +// return findForward(questionForm.getQuestionType(), mapping); +// } +// +// try { +// List listToSave = answerOptionList == null ? longlatMaps : answerOptionList; +// extractFormToDacoQuestion(request, listToSave, questionForm); +// } catch (Exception e) { +// e.printStackTrace(); +// // any upload exception will display as normal error message rather +// // then throw exception directly +// errors.add(ActionMessages.GLOBAL_MESSAGE, +// new ActionMessage(DacoConstants.ERROR_MSG_UPLOAD_FAILED, e.getMessage())); +// if (!errors.isEmpty()) { +// this.addErrors(request, errors); +// request.setAttribute(DacoConstants.ATTR_ANSWER_OPTION_LIST, answerOptionList); +// request.setAttribute(DacoConstants.PARAM_LONGLAT_MAPS_SELECTED, longlatMaps); +// return findForward(questionForm.getQuestionType(), mapping); +// } +// } +// // set session map ID so that questionlist.jsp can get sessionMAP +// request.setAttribute(DacoConstants.ATTR_SESSION_MAP_ID, questionForm.getSessionMapID()); +// // return null to close this window +// return mapping.findForward(DacoConstants.SUCCESS); +// } +// +// /** +// * Read daco data from database and put them into HttpSession. It will redirect to init.do directly after this +// * method run +// * successfully. +// * +// * This method will avoid read database again and lost un-saved resouce question lost when user "refresh page", +// * +// * @throws ServletException +// * +// */ +// @RequestMapping("/start") +// protected String start(@ModelAttribute("dacoForm")DacoForm dacoForm , HttpServletRequest request) throws ServletException { +// ToolAccessMode mode = WebUtil.readToolAccessModeAuthorDefaulted(request); +// request.setAttribute(AttributeNames.ATTR_MODE, mode.toString()); +// return starting(dacoForm, request); +// } +// +// @RequestMapping("/definelater") +// protected String defineLater(@ModelAttribute("dacoForm")DacoForm dacoForm , HttpServletRequest request) throws ServletException { +// // update define later flag to true +// Long contentId = new Long(WebUtil.readLongParam(request, AttributeNames.PARAM_TOOL_CONTENT_ID)); +// IDacoService service = getDacoService(); +// Daco daco = service.getDacoByContentId(contentId); +// +// daco.setDefineLater(true); +// service.saveOrUpdateDaco(daco); +// +// //audit log the teacher has started editing activity in monitor +// service.auditLogStartEditingActivityInMonitor(contentId); +// +// request.setAttribute(AttributeNames.ATTR_MODE, ToolAccessMode.TEACHER.toString()); +// return starting(dacoForm, request); +// } +// protected String starting(@ModelAttribute("dacoForm")DacoForm dacoForm , HttpServletRequest request) +// throws ServletException { +// +// // save toolContentID into HTTPSession +// Long contentId = new Long(WebUtil.readLongParam(request, AttributeNames.PARAM_TOOL_CONTENT_ID)); +// +// // get back the daco and question list and display them on page +// IDacoService service = getDacoService(); +// +// List questions = null; +// Daco daco = null; +// +// // initial Session Map +// SessionMap sessionMap = new SessionMap<>(); +// request.getSession().setAttribute(sessionMap.getSessionID(), sessionMap); +// dacoForm.setSessionMapID(sessionMap.getSessionID()); +// +// // Get contentFolderID and save to form. +// String contentFolderID = WebUtil.readStrParam(request, AttributeNames.PARAM_CONTENT_FOLDER_ID); +// dacoForm.setContentFolderID(contentFolderID); +// sessionMap.put(AttributeNames.PARAM_CONTENT_FOLDER_ID, contentFolderID); +// +// try { +// daco = service.getDacoByContentId(contentId); +// // if daco does not exist, try to use default content instead. +// if (daco == null) { +// daco = service.getDefaultContent(contentId); +// if (daco.getDacoQuestions() == null) { +// questions = null; +// } else { +// +// questions = new ArrayList<>(daco.getDacoQuestions()); +// } +// } else { +// +// questions = new ArrayList<>(daco.getDacoQuestions()); +// } +// +// dacoForm.setDaco(daco); +// } catch (Exception e) { +// AuthoringController.log.error(e); +// throw new ServletException(e); +// } +// +// // init it to avoid null exception in following handling +// if (questions == null) { +// questions = new ArrayList<>(); +// } else { +// DacoUser dacoUser = null; +// // handle system default question: createBy is null, now set it to +// // current user +// for (DacoQuestion question : questions) { +// if (question.getCreateBy() == null) { +// if (dacoUser == null) { +// // get back login user DTO +// HttpSession ss = SessionManager.getSession(); +// UserDTO user = (UserDTO) ss.getAttribute(AttributeNames.USER); +// dacoUser = new DacoUser(user, daco); +// } +// question.setCreateBy(dacoUser); +// } +// } +// } +// +// // init daco question list +// SortedSet dacoQuestionList = getQuestionList(sessionMap); +// dacoQuestionList.clear(); +// dacoQuestionList.addAll(questions); +// +// sessionMap.put(DacoConstants.ATTR_DACO_FORM, dacoForm); +// request.getSession().setAttribute(AttributeNames.PARAM_NOTIFY_CLOSE_URL, +// request.getParameter(AttributeNames.PARAM_NOTIFY_CLOSE_URL)); +// +// return "pages/authoring/start"; +// } +// +// /** +// * This method will persist all inforamtion in this authoring page, include all daco question, information etc. +// * +// * @param mapping +// * @param form +// * @param request +// * @param response +// * @return +// * @throws ServletException +// */ +// protected ActionForward updateContent(ActionMapping mapping, ActionForm form, HttpServletRequest request, +// HttpServletResponse response) throws Exception { +// DacoForm dacoForm = (DacoForm) form; +// +// // get back sessionMAP +// SessionMap sessionMap = (SessionMap) request.getSession() +// .getAttribute(dacoForm.getSessionMapID()); +// +// ToolAccessMode toolAccessMode = WebUtil.readToolAccessModeAuthorDefaulted(request); +// request.setAttribute(AttributeNames.ATTR_MODE, toolAccessMode.toString()); +// +// ActionMessages errors = validateDacoForm(dacoForm, mapping, request); +// if (!errors.isEmpty()) { +// saveErrors(request, errors); +// return mapping.findForward(DacoConstants.SUCCESS); +// } +// +// Daco daco = dacoForm.getDaco(); +// IDacoService service = getDacoService(); +// +// // **********************************Get Daco PO********************* +// Daco dacoPO = service.getDacoByContentId(dacoForm.getDaco().getContentId()); +// if (dacoPO == null) { +// // new Daco, create it. +// dacoPO = daco; +// dacoPO.setCreated(new Timestamp(new Date().getTime())); +// dacoPO.setUpdated(new Timestamp(new Date().getTime())); +// +// } else { +// service.releaseDacoFromCache(dacoPO); +// +// Long uid = dacoPO.getUid(); +// PropertyUtils.copyProperties(dacoPO, daco); +// // get back UID +// dacoPO.setUid(uid); +// +// // if it's a teacher - change define later status +// if (toolAccessMode.isTeacher()) { +// dacoPO.setDefineLater(false); +// } +// dacoPO.setUpdated(new Timestamp(new Date().getTime())); +// } +// +// // *******************************Handle user******************* +// // try to get form system session +// HttpSession ss = SessionManager.getSession(); +// // get back login user DTO +// UserDTO user = (UserDTO) ss.getAttribute(AttributeNames.USER); +// DacoUser dacoUser = service.getUserByUserIdAndContentId(new Long(user.getUserID().intValue()), +// dacoForm.getDaco().getContentId()); +// if (dacoUser == null) { +// dacoUser = new DacoUser(user, dacoPO); +// } +// +// dacoPO.setCreatedBy(dacoUser); +// +// // ************************* Handle daco questions ******************* +// // Handle daco questions +// SortedSet formQuestionSet = getQuestionList(sessionMap); +// Set questionSet = new LinkedHashSet<>(formQuestionSet.size()); +// +// for (DacoQuestion question : formQuestionSet) { +// // This flushs user UID info to message if this user is a new +// // user. +// question.setCreateBy(dacoUser); +// question.setDaco(dacoPO); +// questionSet.add(question); +// } +// +// dacoPO.setDacoQuestions(questionSet); +// service.saveOrUpdateDaco(dacoPO); +// +// // delete questions from database +// List deletedQuestionList = getDeletedDacoQuestionList(sessionMap); +// Iterator iter = deletedQuestionList.iterator(); +// while (iter.hasNext()) { +// DacoQuestion question = iter.next(); +// iter.remove(); +// if (question.getUid() != null) { +// service.deleteDacoQuestion(question.getUid()); +// } +// } +// dacoForm.setDaco(dacoPO); +// +// request.setAttribute(AuthoringConstants.LAMS_AUTHORING_SUCCESS_FLAG, Boolean.TRUE); +// +// return mapping.findForward(DacoConstants.SUCCESS); +// } +// +// protected ActionMessages validateDacoForm(DacoForm dacoForm, ActionMapping mapping, HttpServletRequest request) { +// ActionMessages errors = new ActionMessages(); +// Short min = dacoForm.getDaco().getMinRecords(); +// Short max = dacoForm.getDaco().getMaxRecords(); +// if (min != null && max != null && min > 0 && max > 0 && min > max) { +// errors.add(ActionMessages.GLOBAL_MESSAGE, +// new ActionMessage(DacoConstants.ERROR_MSG_RECORDLIMIT_MIN_TOOHIGH_MAX)); +// } +// +// return errors; +// } +// +// /** +// * Vaidate daco question regards to their type +// * (textfield/textarea/number/date/file/image/radio/dropdown/checkbox/longlat) +// * +// * @param questionForm +// * @return +// */ +// protected ActionErrors validateDacoQuestionForm(DacoQuestionForm questionForm, List answerOptionList) { +// ActionErrors errors = new ActionErrors(); +// if (StringUtils.isBlank(questionForm.getDescription())) { +// errors.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage(DacoConstants.ERROR_MSG_DESC_BLANK)); +// } +// +// String constraint = questionForm.getMax(); +// Float max = null; +// if (!StringUtils.isBlank(constraint)) { +// if (questionForm.getQuestionType() == DacoConstants.QUESTION_TYPE_TEXTFIELD +// || questionForm.getQuestionType() == DacoConstants.QUESTION_TYPE_TEXTAREA +// || questionForm.getQuestionType() == DacoConstants.QUESTION_TYPE_CHECKBOX) { +// try { +// max = (float) Integer.parseInt(constraint); +// if (max < 0) { +// errors.add(ActionMessages.GLOBAL_MESSAGE, +// new ActionMessage(DacoConstants.ERROR_MSG_MAX_NEGATIVE)); +// } else if (questionForm.getQuestionType() == DacoConstants.QUESTION_TYPE_CHECKBOX +// && max > answerOptionList.size()) { +// errors.add(ActionMessages.GLOBAL_MESSAGE, +// new ActionMessage(DacoConstants.ERROR_MSG_MAX_TOOHIGH_ANSWEROPTION)); +// } +// } catch (NumberFormatException e) { +// errors.add(ActionMessages.GLOBAL_MESSAGE, +// new ActionMessage(DacoConstants.ERROR_MSG_MAX_NUMBER_INT)); +// } +// } else if (questionForm.getQuestionType() == DacoConstants.QUESTION_TYPE_NUMBER) { +// try { +// max = Float.parseFloat(constraint); +// +// } catch (NumberFormatException e) { +// errors.add(ActionMessages.GLOBAL_MESSAGE, +// new ActionMessage(DacoConstants.ERROR_MSG_MAX_NUMBER_FLOAT)); +// } +// } +// } +// +// constraint = questionForm.getMin(); +// if (!StringUtils.isBlank(constraint)) { +// Float min = null; +// if (questionForm.getQuestionType() == DacoConstants.QUESTION_TYPE_TEXTFIELD +// || questionForm.getQuestionType() == DacoConstants.QUESTION_TYPE_TEXTAREA +// || questionForm.getQuestionType() == DacoConstants.QUESTION_TYPE_CHECKBOX) { +// try { +// min = (float) Integer.parseInt(constraint); +// if (min < 0) { +// errors.add(ActionMessages.GLOBAL_MESSAGE, +// new ActionMessage(DacoConstants.ERROR_MSG_MIN_NEGATIVE)); +// } else if (questionForm.getQuestionType() == DacoConstants.QUESTION_TYPE_CHECKBOX +// && min > answerOptionList.size()) { +// errors.add(ActionMessages.GLOBAL_MESSAGE, +// new ActionMessage(DacoConstants.ERROR_MSG_MIN_TOOHIGH_ANSWEROPTION)); +// } +// } catch (NumberFormatException e) { +// errors.add(ActionMessages.GLOBAL_MESSAGE, +// new ActionMessage(DacoConstants.ERROR_MSG_MIN_NUMBER_INT)); +// } +// } +// if (questionForm.getQuestionType() == DacoConstants.QUESTION_TYPE_NUMBER) { +// try { +// min = Float.parseFloat(constraint); +// +// } catch (NumberFormatException e) { +// errors.add(ActionMessages.GLOBAL_MESSAGE, +// new ActionMessage(DacoConstants.ERROR_MSG_MIN_NUMBER_FLOAT)); +// } +// } +// if (min != null && max != null && min > max) { +// errors.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage(DacoConstants.ERROR_MSG_MIN_TOOHIGH_MAX)); +// } +// } +// +// constraint = questionForm.getDigitsDecimal(); +// if (!StringUtils.isBlank(constraint)) { +// try { +// Short digitsDecimal = Short.parseShort(constraint); +// if (digitsDecimal < 0) { +// errors.add(ActionMessages.GLOBAL_MESSAGE, +// new ActionMessage(DacoConstants.ERROR_MSG_DIGITSDECIMAL_NONNEGATIVE)); +// } +// } catch (NumberFormatException e) { +// errors.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage(DacoConstants.ERROR_MSG_DIGITSDECIMAL_INT)); +// } +// } +// +// if (answerOptionList != null) { +// if (answerOptionList.size() < DacoConstants.ANSWER_OPTION_MINIMUM_COUNT) { +// errors.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage( +// DacoConstants.ERROR_MSG_ANSWEROPTION_NOTENOUGH, DacoConstants.ANSWER_OPTION_MINIMUM_COUNT)); +// } +// String ordinal = getDacoService().getLocalisedMessage("label.authoring.basic.answeroption.ordinal", null); +// for (int firstOptionNumber = 0; firstOptionNumber < answerOptionList.size(); firstOptionNumber++) { +// String firstOption = answerOptionList.get(firstOptionNumber); +// for (int secondOptionNumber = firstOptionNumber + 1; secondOptionNumber < answerOptionList +// .size(); secondOptionNumber++) { +// String secondOption = answerOptionList.get(secondOptionNumber); +// if (firstOption.trim().equals(secondOption.trim())) { +// errors.add(ActionMessages.GLOBAL_MESSAGE, +// new ActionMessage(DacoConstants.ERROR_MSG_ANSWEROPTION_REPEAT, +// ordinal.charAt(firstOptionNumber) + ")", +// ordinal.charAt(secondOptionNumber) + ")")); +// } +// } +// } +// } +// +// return errors; +// } +// +// protected void ensureMinimumAnswerOptions(List answerOptionList) { +// if (answerOptionList != null) { +// while (answerOptionList.size() < DacoConstants.ANSWER_OPTION_MINIMUM_COUNT) { +// answerOptionList.add(""); +// } +// } +// } +// +// public final double round(double number, int positions) { +// double shift = Math.pow(10, positions); +// shift = Math.round(number * shift) / shift; +// return shift; +// } +//} \ No newline at end of file Index: lams_tool_daco/src/java/org/lamsfoundation/lams/tool/daco/web/controller/ClearSessionAction.java =================================================================== diff -u --- lams_tool_daco/src/java/org/lamsfoundation/lams/tool/daco/web/controller/ClearSessionAction.java (revision 0) +++ lams_tool_daco/src/java/org/lamsfoundation/lams/tool/daco/web/controller/ClearSessionAction.java (revision 085d47fc4191f2cb614a5a7c8fe3ff6c5abcef0f) @@ -0,0 +1,46 @@ +/**************************************************************** + * 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.daco.web.controller; + +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. + * + * @author Steve.Ni + */ +public class ClearSessionAction extends LamsAuthoringFinishAction { + + @Override + public void clearSession(String customiseSessionID, HttpSession session, ToolAccessMode mode) { + if (mode.isAuthor()) { + session.removeAttribute(customiseSessionID); + } + } + +} Index: lams_tool_daco/src/java/org/lamsfoundation/lams/tool/daco/web/controller/LearningAction.java =================================================================== diff -u --- lams_tool_daco/src/java/org/lamsfoundation/lams/tool/daco/web/controller/LearningAction.java (revision 0) +++ lams_tool_daco/src/java/org/lamsfoundation/lams/tool/daco/web/controller/LearningAction.java (revision 085d47fc4191f2cb614a5a7c8fe3ff6c5abcef0f) @@ -0,0 +1,1093 @@ +/**************************************************************** + * 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.daco.web.controller; + +import java.io.IOException; +import java.text.ParseException; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.Date; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.Locale; +import java.util.Set; +import java.util.SortedSet; +import java.util.TreeSet; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; + +import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang.math.NumberUtils; +import org.apache.log4j.Logger; +import org.apache.struts.action.Action; +import org.apache.struts.action.ActionErrors; +import org.apache.struts.action.ActionForm; +import org.apache.struts.action.ActionForward; +import org.apache.struts.action.ActionMapping; +import org.apache.struts.action.ActionMessage; +import org.apache.struts.action.ActionMessages; +import org.apache.struts.upload.FormFile; +import org.lamsfoundation.lams.learning.web.bean.ActivityPositionDTO; +import org.lamsfoundation.lams.learning.web.util.LearningWebUtil; +import org.lamsfoundation.lams.notebook.model.NotebookEntry; +import org.lamsfoundation.lams.notebook.service.CoreNotebookConstants; +import org.lamsfoundation.lams.tool.ToolAccessMode; +import org.lamsfoundation.lams.tool.daco.DacoConstants; +import org.lamsfoundation.lams.tool.daco.dto.QuestionSummaryDTO; +import org.lamsfoundation.lams.tool.daco.model.Daco; +import org.lamsfoundation.lams.tool.daco.model.DacoAnswer; +import org.lamsfoundation.lams.tool.daco.model.DacoQuestion; +import org.lamsfoundation.lams.tool.daco.model.DacoSession; +import org.lamsfoundation.lams.tool.daco.model.DacoUser; +import org.lamsfoundation.lams.tool.daco.service.DacoApplicationException; +import org.lamsfoundation.lams.tool.daco.service.IDacoService; +import org.lamsfoundation.lams.tool.daco.service.UploadDacoFileException; +import org.lamsfoundation.lams.tool.daco.util.DacoQuestionComparator; +import org.lamsfoundation.lams.tool.daco.web.form.RecordForm; +import org.lamsfoundation.lams.tool.daco.web.form.ReflectionForm; +import org.lamsfoundation.lams.usermanagement.dto.UserDTO; +import org.lamsfoundation.lams.util.FileValidatorUtil; +import org.lamsfoundation.lams.util.NumberUtil; +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; +import org.springframework.web.context.WebApplicationContext; +import org.springframework.web.context.support.WebApplicationContextUtils; + +/** + * + * @author Marcin Cieslak + * + * @version $Revision$ + */ +public class LearningAction extends Action { + + private static Logger log = Logger.getLogger(LearningAction.class); + + @Override + public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) throws IOException, ServletException { + String param = mapping.getParameter(); + // -----------------------Daco Learner function + // --------------------------- + if (param.equals("start")) { + return start(mapping, request); + } + + if (param.equals("finish")) { + return finish(mapping, request); + } + + if (param.equals("saveOrUpdateRecord")) { + return saveOrUpdateRecord(mapping, form, request); + } + + if (param.equals("editRecord")) { + return editRecord(mapping, form, request); + } + + if (param.equals("removeRecord")) { + return removeRecord(mapping, request); + } + + if (param.equals("diplayHorizontalRecordList")) { + return diplayHorizontalRecordList(mapping, request); + } + + if (param.equals("changeView")) { + return changeView(mapping, request); + } + + if (param.equals("refreshQuestionSummaries")) { + return refreshQuestionSummaries(mapping, request); + } + + // ================ Reflection ======================= + if (param.equals("startReflection")) { + return startReflection(mapping, form, request); + } + if (param.equals("submitReflection")) { + return submitReflection(mapping, form, request); + } + + return mapping.findForward(DacoConstants.ERROR); + } + + /** + * @param mapping + * @param request + * @return + */ + protected ActionForward diplayHorizontalRecordList(ActionMapping mapping, HttpServletRequest request) { + request.setAttribute(DacoConstants.ATTR_SESSION_MAP_ID, + request.getParameter(DacoConstants.ATTR_SESSION_MAP_ID)); + Long userUid = WebUtil.readLongParam(request, DacoConstants.USER_UID, true); + if (userUid != null) { + request.setAttribute(DacoConstants.USER_UID, userUid); + } + return mapping.findForward(DacoConstants.SUCCESS); + } + + /** + * Read daco data from database and put them into HttpSession. It will redirect to init.do directly after this + * method run successfully. + * + * This method will avoid read database again and lost un-saved resouce question lost when user "refresh page", + * + */ + protected ActionForward start(ActionMapping mapping, HttpServletRequest request) { + + // initial Session Map + SessionMap sessionMap = new SessionMap(); + request.getSession().setAttribute(sessionMap.getSessionID(), sessionMap); + + // save toolContentID into HTTPSession + ToolAccessMode mode = WebUtil.readToolAccessModeParam(request, AttributeNames.PARAM_MODE, true); + + Long sessionId = new Long(request.getParameter(AttributeNames.PARAM_TOOL_SESSION_ID)); + + request.setAttribute(DacoConstants.ATTR_SESSION_MAP_ID, sessionMap.getSessionID()); + + // get back the daco and question list and display them on page + IDacoService service = getDacoService(); + DacoUser dacoUser = null; + Daco daco = service.getDacoBySessionId(sessionId); + + if (mode != null && mode.isTeacher()) { + // monitoring mode - user is specified in URL + // dacoUser may be null if the user was force completed. + dacoUser = getSpecifiedUser(service, sessionId, + WebUtil.readIntParam(request, AttributeNames.PARAM_USER_ID, false)); + } else { + dacoUser = getCurrentUser(service, sessionId, daco); + } + + // check whehter finish lock is on/off + boolean lock = daco.getLockOnFinished() && dacoUser != null && dacoUser.isSessionFinished(); + + // get notebook entry + String entryText = null; + if (dacoUser != null) { + NotebookEntry notebookEntry = service.getEntry(sessionId, CoreNotebookConstants.NOTEBOOK_TOOL, + DacoConstants.TOOL_SIGNATURE, dacoUser.getUserId().intValue()); + if (notebookEntry != null) { + entryText = notebookEntry.getEntry(); + } + } + + sessionMap.put(DacoConstants.ATTR_FINISH_LOCK, lock); + sessionMap.put(DacoConstants.ATTR_USER_FINISHED, dacoUser != null && dacoUser.isSessionFinished()); + sessionMap.put(AttributeNames.PARAM_TOOL_SESSION_ID, sessionId); + sessionMap.put(AttributeNames.ATTR_MODE, mode); + sessionMap.put(DacoConstants.ATTR_REFLECTION_ENTRY, entryText); + sessionMap.put(DacoConstants.ATTR_DACO, daco); + sessionMap.put(DacoConstants.ATTR_LEARNING_VIEW, DacoConstants.LEARNING_VIEW_VERTICAL); + + List> records = service.getDacoAnswersByUser(dacoUser); + sessionMap.put(DacoConstants.ATTR_RECORD_LIST, records); + request.setAttribute(DacoConstants.ATTR_DISPLAYED_RECORD_NUMBER, records.size() + 1); + + List summaries = service.getQuestionSummaries(dacoUser.getUid()); + sessionMap.put(DacoConstants.ATTR_QUESTION_SUMMARIES, summaries); + + Integer totalRecordCount = service.getGroupRecordCount(dacoUser.getSession().getSessionId()); + sessionMap.put(DacoConstants.ATTR_TOTAL_RECORD_COUNT, totalRecordCount); + + ActivityPositionDTO activityPosition = LearningWebUtil.putActivityPositionInRequestByToolSessionId(sessionId, + request, getServlet().getServletContext()); + sessionMap.put(AttributeNames.ATTR_ACTIVITY_POSITION, activityPosition); + + // add define later support + if (daco.isDefineLater()) { + return mapping.findForward(DacoConstants.DEFINE_LATER); + } + + // set contentInUse flag to true! + daco.setContentInUse(true); + daco.setDefineLater(false); + service.saveOrUpdateDaco(daco); + + sessionMap.put(DacoConstants.ATTR_DACO, daco); + + if (daco.isNotifyTeachersOnLearnerEntry()) { + service.notifyTeachersOnLearnerEntry(sessionId, dacoUser); + } + + return mapping.findForward(DacoConstants.SUCCESS); + } + + /** + * Finish learning session. + * + * @param mapping + * @param form + * @param request + * @param response + * @return + */ + protected ActionForward finish(ActionMapping mapping, HttpServletRequest request) { + + // get back SessionMap + String sessionMapID = request.getParameter(DacoConstants.ATTR_SESSION_MAP_ID); + SessionMap sessionMap = (SessionMap) request.getSession().getAttribute(sessionMapID); + + // get mode and ToolSessionID from sessionMAP + ToolAccessMode mode = (ToolAccessMode) sessionMap.get(AttributeNames.ATTR_MODE); + Long sessionId = (Long) sessionMap.get(AttributeNames.PARAM_TOOL_SESSION_ID); + + ActionErrors errors = validateBeforeFinish(request, sessionMapID); + if (!errors.isEmpty()) { + this.addErrors(request, errors); + request.setAttribute(DacoConstants.ATTR_DISPLAYED_RECORD_NUMBER, + request.getParameter(DacoConstants.ATTR_DISPLAYED_RECORD_NUMBER)); + return mapping.getInputForward(); + } + + IDacoService service = getDacoService(); + // get sessionId from HttpServletRequest + String nextActivityUrl = null; + try { + HttpSession httpSession = SessionManager.getSession(); + UserDTO user = (UserDTO) httpSession.getAttribute(AttributeNames.USER); + Long userUid = new Long(user.getUserID().longValue()); + + nextActivityUrl = service.finishToolSession(sessionId, userUid); + request.setAttribute(DacoConstants.ATTR_NEXT_ACTIVITY_URL, nextActivityUrl); + } catch (DacoApplicationException e) { + + LearningAction.log.error("Failed get next activity url:" + e.getMessage()); + } + + return mapping.findForward(DacoConstants.SUCCESS); + } + + /** + * Save file or textfield daco question into database. + * + * @param mapping + * @param form + * @param request + * @param response + * @return + */ + protected ActionForward saveOrUpdateRecord(ActionMapping mapping, ActionForm form, HttpServletRequest request) { + RecordForm recordForm = (RecordForm) form; + String sessionMapID = request.getParameter(DacoConstants.ATTR_SESSION_MAP_ID); + SessionMap sessionMap = (SessionMap) request.getSession().getAttribute(sessionMapID); + Daco daco = (Daco) sessionMap.get(DacoConstants.ATTR_DACO); + Set questionList = daco.getDacoQuestions(); + Long sessionId = (Long) sessionMap.get(AttributeNames.PARAM_TOOL_SESSION_ID); + IDacoService service = getDacoService(); + DacoUser user = getCurrentUser(service, sessionId, daco); + + service.releaseAnswersFromCache(user.getAnswers()); + + request.setAttribute(DacoConstants.ATTR_SESSION_MAP_ID, sessionMapID); + sessionMap.put(DacoConstants.ATTR_LEARNING_CURRENT_TAB, 1); + + /* + * design decision - assume users will not have a lot of records each. If very large record sets + * we should go to the db and just get the size & the next id, and the record to be updated, + * rather than manipulating the full list of records. + */ + List record = null; + List> records = (List>) sessionMap.get(DacoConstants.ATTR_RECORD_LIST); + int recordCount = records.size(); + int displayedRecordNumber = recordForm.getDisplayedRecordNumber(); + + /* + * Cannot use the displayRecordNumber as the new record id as records may be deleted and there will + * be missing numbers in the recordId sequence. Just using displayRecordNumber will add entries to + * existing records. + */ + int nextRecordId = 1; + if (recordCount > 0) { + // records should be in recordId order, so find the next record id based on the last record + List lastRecord = records.get(recordCount - 1); + DacoAnswer lastRecordAnswer = lastRecord.get(0); + if (lastRecordAnswer.getRecordId() >= nextRecordId) { + nextRecordId = lastRecordAnswer.getRecordId() + 1; + } + } + + boolean isEdit = false; + if (displayedRecordNumber <= recordCount) { + record = records.get(displayedRecordNumber - 1); + isEdit = true; + } else { + record = new LinkedList(); + recordCount++; + } + + ActionErrors errors = validateRecordForm(daco, recordForm, questionList, recordCount); + if (!errors.isEmpty()) { + this.addErrors(request, errors); + refreshQuestionSummaries(mapping, request); + request.setAttribute(DacoConstants.ATTR_DISPLAYED_RECORD_NUMBER, recordForm.getDisplayedRecordNumber()); + return mapping.findForward(DacoConstants.SUCCESS); + } + + Iterator questionIterator = questionList.iterator(); + DacoQuestion question = null; + int formAnswerNumber = 0; + int answerNumber = 0; + int fileNumber = 0; + DacoAnswer answer = null; + + while (questionIterator.hasNext()) { + + question = questionIterator.next(); + if (isEdit) { + answer = record.get(answerNumber++); + } else { + answer = new DacoAnswer(); + answer.setQuestion(question); + answer.setRecordId(nextRecordId); + answer.setUser(user); + } + answer.setCreateDate(new Date()); + + switch (question.getType()) { + case DacoConstants.QUESTION_TYPE_NUMBER: { + String formAnswer = recordForm.getAnswer(formAnswerNumber); + if (StringUtils.isBlank(formAnswer)) { + answer.setAnswer(null); + } else { + if (question.getDigitsDecimal() != null) { + formAnswer = NumberUtil.formatLocalisedNumber(Double.parseDouble(formAnswer), (Locale) null, + question.getDigitsDecimal()); + } + answer.setAnswer(formAnswer); + } + formAnswerNumber++; + } + break; + case DacoConstants.QUESTION_TYPE_DATE: { + String[] dateParts = new String[] { recordForm.getAnswer(formAnswerNumber++), + recordForm.getAnswer(formAnswerNumber++), recordForm.getAnswer(formAnswerNumber) }; + if (!(StringUtils.isBlank(dateParts[0]) || StringUtils.isBlank(dateParts[1]) + || StringUtils.isBlank(dateParts[2]))) { + + Calendar calendar = Calendar.getInstance(); + calendar.clear(); + calendar.set(Integer.parseInt(dateParts[2]), Integer.parseInt(dateParts[1]) - 1, + Integer.parseInt(dateParts[0])); + answer.setAnswer(DacoConstants.DEFAULT_DATE_FORMAT.format(calendar.getTime())); + } else { + answer.setAnswer(null); + } + } + formAnswerNumber++; + break; + case DacoConstants.QUESTION_TYPE_CHECKBOX: { + String formAnswer = recordForm.getAnswer(formAnswerNumber); + String[] checkboxes = formAnswer.split("&"); + if (isEdit) { + DacoAnswer localAnswer = answer; + answerNumber--; + do { + service.deleteDacoAnswer(localAnswer.getUid()); + record.remove(answerNumber); + if (answerNumber < record.size()) { + localAnswer = record.get(answerNumber); + if (localAnswer.getQuestion().getType() != DacoConstants.QUESTION_TYPE_CHECKBOX) { + localAnswer = null; + } + } else { + localAnswer = null; + } + } while (localAnswer != null); + answer = (DacoAnswer) answer.clone(); + + } + if (StringUtils.isBlank(formAnswer)) { + answer.setAnswer(null); + } else { + for (int checkboxNumber = 0; checkboxNumber < checkboxes.length; checkboxNumber++) { + answer.setAnswer(checkboxes[checkboxNumber]); + if (checkboxNumber < checkboxes.length - 1) { + service.saveOrUpdateAnswer(answer); + if (isEdit) { + record.add(answerNumber++, answer); + } else { + record.add(answer); + } + + answer = (DacoAnswer) answer.clone(); + } + } + } + if (isEdit) { + record.add(answerNumber++, answer); + } + } + formAnswerNumber++; + break; + case DacoConstants.QUESTION_TYPE_LONGLAT: { + answer.setAnswer(recordForm.getAnswer(formAnswerNumber++)); + service.saveOrUpdateAnswer(answer); + if (isEdit) { + answer = record.get(answerNumber++); + } else { + record.add(answer); + answer = (DacoAnswer) answer.clone(); + } + answer.setAnswer(recordForm.getAnswer(formAnswerNumber)); + } + formAnswerNumber++; + break; + case DacoConstants.QUESTION_TYPE_FILE: + case DacoConstants.QUESTION_TYPE_IMAGE: { + FormFile file = recordForm.getFile(fileNumber); + if (file != null) { + try { + service.uploadDacoAnswerFile(answer, file); + } catch (UploadDacoFileException e) { + LearningAction.log.error("Failed upload Resource File " + e.toString()); + e.printStackTrace(); + } + } + } + fileNumber++; + break; + case DacoConstants.QUESTION_TYPE_DROPDOWN: { + String formAnswer = recordForm.getAnswer(formAnswerNumber); + answer.setAnswer("0".equals(formAnswer) ? null : formAnswer); + } + formAnswerNumber++; + break; + default: + answer.setAnswer(recordForm.getAnswer(formAnswerNumber)); + formAnswerNumber++; + break; + } + + service.saveOrUpdateAnswer(answer); + if (!isEdit) { + record.add(answer); + } + } + + form.reset(mapping, request); + if (isEdit) { + request.setAttribute(DacoConstants.ATTR_RECORD_OPERATION_SUCCESS, DacoConstants.RECORD_OPERATION_EDIT); + } else { + + records.add(record); + request.setAttribute(DacoConstants.ATTR_RECORD_OPERATION_SUCCESS, DacoConstants.RECORD_OPERATION_ADD); + + // notify teachers + if (daco.isNotifyTeachersOnRecordSumbit()) { + service.notifyTeachersOnRecordSumbit(sessionId, user); + } + } + + request.setAttribute(DacoConstants.ATTR_DISPLAYED_RECORD_NUMBER, records.size() + 1); + refreshQuestionSummaries(mapping, request); + + return mapping.findForward(DacoConstants.SUCCESS); + } + + /** + * Display empty reflection form. + * + * @param mapping + * @param form + * @param request + * @param response + * @return + */ + protected ActionForward startReflection(ActionMapping mapping, ActionForm form, HttpServletRequest request) { + + // get session value + String sessionMapID = WebUtil.readStrParam(request, DacoConstants.ATTR_SESSION_MAP_ID); + + ActionErrors errors = validateBeforeFinish(request, sessionMapID); + if (!errors.isEmpty()) { + this.addErrors(request, errors); + refreshQuestionSummaries(mapping, request); + request.setAttribute(DacoConstants.ATTR_DISPLAYED_RECORD_NUMBER, + request.getParameter(DacoConstants.ATTR_DISPLAYED_RECORD_NUMBER)); + return mapping.getInputForward(); + } + SessionMap sessionMap = (SessionMap) request.getSession().getAttribute(sessionMapID); + + Long toolSessionID = (Long) sessionMap.get(AttributeNames.PARAM_TOOL_SESSION_ID); + IDacoService service = getDacoService(); + ReflectionForm reflectionForm = (ReflectionForm) form; + HttpSession httpSession = SessionManager.getSession(); + UserDTO userDTO = (UserDTO) httpSession.getAttribute(AttributeNames.USER); + DacoUser user = service.getUserByUserIdAndSessionId(userDTO.getUserID().longValue(), toolSessionID); + + reflectionForm.setUserId(userDTO.getUserID()); + reflectionForm.setSessionId(toolSessionID); + + // get the existing reflection entry + + NotebookEntry entry = service.getEntry(toolSessionID, CoreNotebookConstants.NOTEBOOK_TOOL, + DacoConstants.TOOL_SIGNATURE, userDTO.getUserID()); + + if (entry != null) { + reflectionForm.setEntryText(entry.getEntry()); + } + request.setAttribute(DacoConstants.ATTR_SESSION_MAP_ID, sessionMapID); + reflectionForm.setSessionMapID(sessionMapID); + return mapping.findForward(DacoConstants.SUCCESS); + } + + /** + * Submit reflection form input database. + * + * @param mapping + * @param form + * @param request + * @param response + * @return + */ + protected ActionForward submitReflection(ActionMapping mapping, ActionForm form, HttpServletRequest request) { + ReflectionForm reflectionForm = (ReflectionForm) form; + Integer userId = reflectionForm.getUserId(); + Long sessionId = reflectionForm.getSessionId(); + IDacoService service = getDacoService(); + // check for existing notebook entry + NotebookEntry entry = service.getEntry(sessionId, CoreNotebookConstants.NOTEBOOK_TOOL, + DacoConstants.TOOL_SIGNATURE, userId); + + if (entry == null) { + // create new entry + service.createNotebookEntry(sessionId, CoreNotebookConstants.NOTEBOOK_TOOL, DacoConstants.TOOL_SIGNATURE, + userId, reflectionForm.getEntryText()); + } else { + // update existing entry + entry.setEntry(reflectionForm.getEntryText()); + entry.setLastModified(new Date()); + service.updateEntry(entry); + } + + return finish(mapping, request); + } + + // ************************************************************************************* + // Private method + // ************************************************************************************* + protected ActionErrors validateBeforeFinish(HttpServletRequest request, String sessionMapID) { + ActionErrors errors = new ActionErrors(); + SessionMap sessionMap = (SessionMap) request.getSession().getAttribute(sessionMapID); + int recordCount = ((List) sessionMap.get(DacoConstants.ATTR_RECORD_LIST)).size(); + Daco daco = (Daco) sessionMap.get(DacoConstants.ATTR_DACO); + Short min = daco.getMinRecords(); + if (min != null && min > 0 && recordCount < min) { + errors.add(ActionMessages.GLOBAL_MESSAGE, + new ActionMessage(DacoConstants.ERROR_MSG_RECORD_NOTENOUGH, daco.getMinRecords())); + } + return errors; + } + + protected IDacoService getDacoService() { + WebApplicationContext wac = WebApplicationContextUtils + .getRequiredWebApplicationContext(getServlet().getServletContext()); + return (IDacoService) wac.getBean(DacoConstants.DACO_SERVICE); + } + + /** + * List save current daco questions. + * + * @param request + * @return + */ + protected SortedSet getDacoQuestionList(SessionMap sessionMap) { + SortedSet list = (SortedSet) sessionMap.get(DacoConstants.ATTR_QUESTION_LIST); + if (list == null) { + list = new TreeSet(new DacoQuestionComparator()); + sessionMap.put(DacoConstants.ATTR_QUESTION_LIST, list); + } + return list; + } + + /** + * Get java.util.List from HttpSession by given name. + * + * @param request + * @param name + * @return + */ + protected List getListFromSession(SessionMap sessionMap, String name) { + List list = (List) sessionMap.get(name); + if (list == null) { + list = new ArrayList(); + sessionMap.put(name, list); + } + return list; + } + + protected DacoUser getCurrentUser(IDacoService service, Long sessionId, Daco daco) { + // try to get form system session + HttpSession ss = SessionManager.getSession(); + // get back login user DTO + UserDTO user = (UserDTO) ss.getAttribute(AttributeNames.USER); + DacoUser dacoUser = service.getUserByUserIdAndSessionId(new Long(user.getUserID().intValue()), sessionId); + + if (dacoUser == null) { + DacoSession session = service.getSessionBySessionId(sessionId); + dacoUser = new DacoUser(user, session); + dacoUser.setDaco(daco); + service.createUser(dacoUser); + } + return dacoUser; + } + + protected DacoUser getSpecifiedUser(IDacoService service, Long sessionId, Integer userId) { + DacoUser dacoUser = service.getUserByUserIdAndSessionId(new Long(userId.intValue()), sessionId); + if (dacoUser == null) { + LearningAction.log + .error("Unable to find specified user for daco activity. Screens are likely to fail. SessionId=" + + sessionId + " UserId=" + userId); + } + return dacoUser; + } + + protected ActionErrors validateRecordForm(Daco daco, RecordForm recordForm, Set questionList, + int recordCount) { + ActionErrors errors = new ActionErrors(); + Short maxRecords = daco.getMaxRecords(); + if (maxRecords != null && maxRecords > 0 && recordCount > maxRecords) { + errors.add(ActionMessages.GLOBAL_MESSAGE, + new ActionMessage(DacoConstants.ERROR_MSG_RECORD_TOOMUCH, daco.getMaxRecords())); + } + + Iterator questionIterator = questionList.iterator(); + DacoQuestion question = null; + int answerNumber = 0; + int fileNumber = 0; + int questionNumber = 1; + + while (questionIterator.hasNext()) { + question = questionIterator.next(); + switch (question.getType()) { + case DacoConstants.QUESTION_TYPE_TEXTFIELD: + case DacoConstants.QUESTION_TYPE_RADIO: + if (question.isRequired() && StringUtils.isBlank(recordForm.getAnswer(answerNumber))) { + errors.add(ActionMessages.GLOBAL_MESSAGE, + new ActionMessage(DacoConstants.ERROR_MSG_RECORD_BLANK, questionNumber)); + + } + answerNumber++; + break; + case DacoConstants.QUESTION_TYPE_TEXTAREA: { + if (StringUtils.isBlank(recordForm.getAnswer(answerNumber))) { + if (question.isRequired()) { + errors.add(ActionMessages.GLOBAL_MESSAGE, + new ActionMessage(DacoConstants.ERROR_MSG_RECORD_BLANK, questionNumber)); + } + } else if (question.getMax() != null) { + long words = 0; + int index = 0; + boolean prevWhiteSpace = true; + while (index < recordForm.getAnswer(answerNumber).length()) { + char c = recordForm.getAnswer(answerNumber).charAt(index++); + boolean currWhiteSpace = Character.isWhitespace(c); + if (prevWhiteSpace && !currWhiteSpace) { + words++; + } + prevWhiteSpace = currWhiteSpace; + } + int max = question.getMax().intValue(); + if (words > max) { + errors.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage( + DacoConstants.ERROR_MSG_RECORD_TEXTAREA_LONG, questionNumber, max)); + } + } + } + answerNumber++; + break; + case DacoConstants.QUESTION_TYPE_NUMBER: { + if (StringUtils.isBlank(recordForm.getAnswer(answerNumber))) { + if (question.isRequired()) { + errors.add(ActionMessages.GLOBAL_MESSAGE, + new ActionMessage(DacoConstants.ERROR_MSG_RECORD_BLANK, questionNumber)); + } + } else { + try { + float number = Float.parseFloat(recordForm.getAnswer(answerNumber)); + Float min = question.getMin(); + Float max = question.getMax(); + if (min != null && number < min) { + errors.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage( + DacoConstants.ERROR_MSG_RECORD_NUMBER_MIN, questionNumber, min)); + } else if (max != null && number > max) { + errors.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage( + DacoConstants.ERROR_MSG_RECORD_NUMBER_MAX, questionNumber, max)); + } + } catch (NumberFormatException e) { + errors.add(ActionMessages.GLOBAL_MESSAGE, + new ActionMessage(DacoConstants.ERROR_MSG_RECORD_NUMBER_FLOAT, questionNumber)); + } + } + } + answerNumber++; + break; + case DacoConstants.QUESTION_TYPE_DATE: { + String day = recordForm.getAnswer(answerNumber++); + String month = recordForm.getAnswer(answerNumber++); + String year = recordForm.getAnswer(answerNumber); + if (StringUtils.isBlank(day) && StringUtils.isBlank(month) && StringUtils.isBlank(year)) { + if (question.isRequired()) { + errors.add(ActionMessages.GLOBAL_MESSAGE, + new ActionMessage(DacoConstants.ERROR_MSG_RECORD_BLANK, questionNumber)); + } + } else { + Integer yearNum = null; + Integer monthNum = null; + if (StringUtils.isBlank(year)) { + errors.add(ActionMessages.GLOBAL_MESSAGE, + new ActionMessage(DacoConstants.ERROR_MSG_RECORD_DATE_YEAR_BLANK, questionNumber)); + } else { + try { + yearNum = Integer.parseInt(year); + } catch (NumberFormatException e) { + errors.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage( + DacoConstants.ERROR_MSG_RECORD_DATE_YEAR_INT, questionNumber)); + } + } + boolean monthValid = false; + if (StringUtils.isBlank(month)) { + errors.add(ActionMessages.GLOBAL_MESSAGE, + new ActionMessage(DacoConstants.ERROR_MSG_RECORD_DATE_MONTH_BLANK, questionNumber)); + } else { + try { + monthNum = Integer.parseInt(month); + if (monthNum < 1 || monthNum > 12) { + errors.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage( + DacoConstants.ERROR_MSG_RECORD_DATE_MONTH_LIMIT, questionNumber)); + } else { + monthValid = true; + } + } catch (NumberFormatException e) { + errors.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage( + DacoConstants.ERROR_MSG_RECORD_DATE_MONTH_INT, questionNumber)); + } + } + + if (StringUtils.isBlank(day)) { + errors.add(ActionMessages.GLOBAL_MESSAGE, + new ActionMessage(DacoConstants.ERROR_MSG_RECORD_DATE_DAY_BLANK, questionNumber)); + } else if (monthValid) { + try { + + int dayNum = Integer.parseInt(day); + Integer maxDays = yearNum == null || monthNum == null ? null + : getMaxDays(monthNum, yearNum); + if (dayNum < 1 || maxDays != null && dayNum > maxDays) { + errors.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage( + DacoConstants.ERROR_MSG_RECORD_DATE_DAY_LIMIT, questionNumber, maxDays)); + } + } catch (NumberFormatException e) { + errors.add(ActionMessages.GLOBAL_MESSAGE, + new ActionMessage(DacoConstants.ERROR_MSG_RECORD_DATE_DAY_INT, questionNumber)); + } + } + } + } + answerNumber++; + break; + case DacoConstants.QUESTION_TYPE_FILE: { + FormFile file = recordForm.getFile(fileNumber); + if (file == null || file.getFileSize() == 0) { + if (question.isRequired()) { + errors.add(ActionMessages.GLOBAL_MESSAGE, + new ActionMessage(DacoConstants.ERROR_MSG_RECORD_BLANK, questionNumber)); + } + } else { + FileValidatorUtil.validateFileSize(file, true, errors); + } + fileNumber++; + } + break; + case DacoConstants.QUESTION_TYPE_IMAGE: { + FormFile file = recordForm.getFile(fileNumber); + if (file == null || file.getFileSize() == 0) { + if (question.isRequired()) { + errors.add(ActionMessages.GLOBAL_MESSAGE, + new ActionMessage(DacoConstants.ERROR_MSG_RECORD_BLANK, questionNumber)); + } + } else { + String fileName = file.getFileName(); + boolean isImage = false; + if (fileName.length() > 5) { + + String extension = fileName.substring(fileName.length() - 3); + for (String acceptedExtension : DacoConstants.IMAGE_EXTENSIONS) { + if (extension.equalsIgnoreCase(acceptedExtension)) { + isImage = true; + break; + } + } + } + if (!isImage) { + errors.add(ActionMessages.GLOBAL_MESSAGE, + new ActionMessage(DacoConstants.ERROR_MSG_RECORD_IMAGE_FORMAT, questionNumber)); + } else { + FileValidatorUtil.validateFileSize(file, true, errors); + } + } + fileNumber++; + } + break; + case DacoConstants.QUESTION_TYPE_DROPDOWN: { + if (question.isRequired() && "0".equals(recordForm.getAnswer(answerNumber))) { + errors.add(ActionMessages.GLOBAL_MESSAGE, + new ActionMessage(DacoConstants.ERROR_MSG_RECORD_BLANK, questionNumber)); + + } + } + answerNumber++; + break; + case DacoConstants.QUESTION_TYPE_CHECKBOX: { + if (StringUtils.isBlank(recordForm.getAnswer(answerNumber))) { + if (question.isRequired()) { + errors.add(ActionMessages.GLOBAL_MESSAGE, + new ActionMessage(DacoConstants.ERROR_MSG_RECORD_BLANK, questionNumber)); + } + } else { + int count = recordForm.getAnswer(answerNumber).split("&").length; + Float min = question.getMin(); + Float max = question.getMax(); + if (min != null && count < min) { + errors.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage( + DacoConstants.ERROR_MSG_RECORD_CHECKBOX_MIN, questionNumber, min.intValue())); + } else if (max != null && count > max) { + errors.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage( + DacoConstants.ERROR_MSG_RECORD_CHECKBOX_MAX, questionNumber, max.intValue())); + } + } + } + answerNumber++; + break; + case DacoConstants.QUESTION_TYPE_LONGLAT: { + String longitude = recordForm.getAnswer(answerNumber++); + String latitude = recordForm.getAnswer(answerNumber); + if (StringUtils.isBlank(longitude)) { + if (StringUtils.isBlank(latitude)) { + if (question.isRequired()) { + errors.add(ActionMessages.GLOBAL_MESSAGE, + new ActionMessage(DacoConstants.ERROR_MSG_RECORD_BLANK, questionNumber)); + } + } else { + errors.add(ActionMessages.GLOBAL_MESSAGE, + new ActionMessage(DacoConstants.ERROR_MSG_RECORD_LONGITUDE_BLANK, questionNumber)); + } + + } else if (StringUtils.isBlank(latitude)) { + errors.add(ActionMessages.GLOBAL_MESSAGE, + new ActionMessage(DacoConstants.ERROR_MSG_RECORD_LATITUDE_BLANK, questionNumber)); + } else { + try { + Float.parseFloat(longitude); + } catch (NumberFormatException e) { + errors.add(ActionMessages.GLOBAL_MESSAGE, + new ActionMessage(DacoConstants.ERROR_MSG_RECORD_LONGITUDE_FLOAT, questionNumber)); + } + try { + Float.parseFloat(latitude); + } catch (NumberFormatException e) { + errors.add(ActionMessages.GLOBAL_MESSAGE, + new ActionMessage(DacoConstants.ERROR_MSG_RECORD_LATITUDE_FLOAT, questionNumber)); + } + } + } + answerNumber++; + break; + } + questionNumber++; + } + return errors; + } + + protected final int getMaxDays(int month, int year) { + if (month == 1 || month == 3 || month == 5 || month == 7 || month == 8 || month == 10 || month == 12) { + return 31; + } + if (month == 2) { + return isLeapYear(year) ? 29 : 28; + } + return 30; + } + + protected final boolean isLeapYear(int year) { + if (year % 4 == 0) { + + if (year % 100 != 0) { + return true; + } else if (year % 400 == 0) { + return false; + } else { + return false; + } + } else { + return false; + } + } + + protected ActionForward editRecord(ActionMapping mapping, ActionForm form, HttpServletRequest request) { + String sessionMapID = WebUtil.readStrParam(request, DacoConstants.ATTR_SESSION_MAP_ID); + SessionMap sessionMap = (SessionMap) request.getSession().getAttribute(sessionMapID); + int recordIndex = NumberUtils.stringToInt(request.getParameter(DacoConstants.PARAM_RECORD_INDEX), -1); + List> records = (List>) sessionMap.get(DacoConstants.ATTR_RECORD_LIST); + if (recordIndex != -1 && records != null && records.size() >= recordIndex) { + List record = records.get(recordIndex - 1); + RecordForm recordForm = (RecordForm) form; + recordForm.setDisplayedRecordNumber(recordIndex); + recordForm.setSessionMapID(sessionMapID); + StringBuilder checkboxes = null; + int checkboxQuestionNumber = 0; + int formAnswerNumber = 0; + for (int answerNumber = 0; answerNumber < record.size(); answerNumber++) { + DacoAnswer answer = record.get(answerNumber); + short questionType = answer.getQuestion().getType(); + + if (questionType == DacoConstants.QUESTION_TYPE_CHECKBOX) { + if (checkboxes == null) { + checkboxes = new StringBuilder(record.size() * 3); + checkboxQuestionNumber = formAnswerNumber++; + } + checkboxes.append(answer.getAnswer()).append('&'); + } else { + if (checkboxes != null) { + recordForm.setAnswer(checkboxQuestionNumber, checkboxes.toString()); + checkboxes = null; + } + if (questionType == DacoConstants.QUESTION_TYPE_DATE) { + String[] dateParts = new String[3]; + if (answer.getAnswer() != null) { + Calendar calendar = Calendar.getInstance(); + calendar.clear(); + + try { + calendar.setTime(DacoConstants.DEFAULT_DATE_FORMAT.parse(answer.getAnswer())); + } catch (ParseException e) { + LearningAction.log.error(e.getMessage()); + e.printStackTrace(); + } + + dateParts[0] = String.valueOf(calendar.get(Calendar.DAY_OF_MONTH)); + dateParts[1] = String.valueOf(calendar.get(Calendar.MONTH) + 1); + dateParts[2] = String.valueOf(calendar.get(Calendar.YEAR)); + } + recordForm.setAnswer(formAnswerNumber++, dateParts[0]); + recordForm.setAnswer(formAnswerNumber++, dateParts[1]); + recordForm.setAnswer(formAnswerNumber++, dateParts[2]); + } else if (!(questionType == DacoConstants.QUESTION_TYPE_FILE + || questionType == DacoConstants.QUESTION_TYPE_IMAGE)) { + recordForm.setAnswer(formAnswerNumber++, answer.getAnswer()); + } + } + } + if (checkboxes != null) { + recordForm.setAnswer(checkboxQuestionNumber, checkboxes.toString()); + } + + request.setAttribute(DacoConstants.ATTR_SESSION_MAP_ID, sessionMapID); + sessionMap.put(DacoConstants.ATTR_LEARNING_CURRENT_TAB, 1); + request.setAttribute(DacoConstants.ATTR_DISPLAYED_RECORD_NUMBER, recordIndex); + return mapping.findForward(DacoConstants.SUCCESS); + } else { + return null; + } + } + + protected ActionForward removeRecord(ActionMapping mapping, HttpServletRequest request) { + String sessionMapID = WebUtil.readStrParam(request, DacoConstants.ATTR_SESSION_MAP_ID); + SessionMap sessionMap = (SessionMap) request.getSession().getAttribute(sessionMapID); + int recordIndex = NumberUtils.stringToInt(request.getParameter(DacoConstants.PARAM_RECORD_INDEX), -1); + List> records = (List>) sessionMap.get(DacoConstants.ATTR_RECORD_LIST); + IDacoService service = getDacoService(); + if (recordIndex != -1 && records != null && records.size() >= recordIndex) { + List record = records.get(recordIndex - 1); + service.deleteDacoRecord(record); + records.remove(record); + sessionMap.put(DacoConstants.ATTR_RECORD_LIST, records); + request.setAttribute(DacoConstants.ATTR_SESSION_MAP_ID, sessionMapID); + return mapping.findForward(DacoConstants.SUCCESS); + } else { + return null; + } + } + + protected ActionForward changeView(ActionMapping mapping, HttpServletRequest request) { + String sessionMapID = WebUtil.readStrParam(request, DacoConstants.ATTR_SESSION_MAP_ID); + SessionMap sessionMap = (SessionMap) request.getSession().getAttribute(sessionMapID); + request.setAttribute(DacoConstants.ATTR_SESSION_MAP_ID, sessionMapID); + request.setAttribute(DacoConstants.ATTR_DISPLAYED_RECORD_NUMBER, + WebUtil.readIntParam(request, DacoConstants.ATTR_DISPLAYED_RECORD_NUMBER)); + request.setAttribute(DacoConstants.ATTR_LEARNING_CURRENT_TAB, + WebUtil.readIntParam(request, DacoConstants.ATTR_LEARNING_CURRENT_TAB)); + String currentView = (String) sessionMap.get(DacoConstants.ATTR_LEARNING_VIEW); + if (DacoConstants.LEARNING_VIEW_HORIZONTAL.equals(currentView)) { + sessionMap.put(DacoConstants.ATTR_LEARNING_VIEW, DacoConstants.LEARNING_VIEW_VERTICAL); + } else { + sessionMap.put(DacoConstants.ATTR_LEARNING_VIEW, DacoConstants.LEARNING_VIEW_HORIZONTAL); + } + return mapping.findForward(DacoConstants.SUCCESS); + } + + protected ActionForward refreshQuestionSummaries(ActionMapping mapping, HttpServletRequest request) { + String sessionMapID = WebUtil.readStrParam(request, DacoConstants.ATTR_SESSION_MAP_ID); + SessionMap sessionMap = (SessionMap) request.getSession().getAttribute(sessionMapID); + Daco daco = (Daco) sessionMap.get(DacoConstants.ATTR_DACO); + Long sessionId = (Long) sessionMap.get(AttributeNames.PARAM_TOOL_SESSION_ID); + IDacoService service = getDacoService(); + DacoUser user = getCurrentUser(service, sessionId, daco); + + // get mode - monitoring vs learner + ToolAccessMode mode = (ToolAccessMode) sessionMap.get(AttributeNames.ATTR_MODE); + if (mode != null && mode.isTeacher()) { + // monitoring mode - user is specified in URL + // user may be null if the user was force completed. + user = getSpecifiedUser(service, sessionId, + WebUtil.readIntParam(request, AttributeNames.PARAM_USER_ID, false)); + } else { + user = getCurrentUser(service, sessionId, daco); + } + + if (user != null) { + List summaries = service.getQuestionSummaries(user.getUid()); + sessionMap.put(DacoConstants.ATTR_QUESTION_SUMMARIES, summaries); + Integer totalRecordCount = service.getGroupRecordCount(user.getSession().getSessionId()); + sessionMap.put(DacoConstants.ATTR_TOTAL_RECORD_COUNT, totalRecordCount); + } else { + sessionMap.put(DacoConstants.ATTR_QUESTION_SUMMARIES, new LinkedList()); + sessionMap.put(DacoConstants.ATTR_TOTAL_RECORD_COUNT, 0); + } + + request.setAttribute(DacoConstants.ATTR_SESSION_MAP_ID, sessionMapID); + return mapping.findForward(DacoConstants.SUCCESS); + } + +} \ No newline at end of file Index: lams_tool_daco/src/java/org/lamsfoundation/lams/tool/daco/web/controller/MonitoringAction.java =================================================================== diff -u --- lams_tool_daco/src/java/org/lamsfoundation/lams/tool/daco/web/controller/MonitoringAction.java (revision 0) +++ lams_tool_daco/src/java/org/lamsfoundation/lams/tool/daco/web/controller/MonitoringAction.java (revision 085d47fc4191f2cb614a5a7c8fe3ff6c5abcef0f) @@ -0,0 +1,555 @@ +/**************************************************************** + * 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.daco.web.controller; + +import java.io.IOException; +import java.text.ParseException; +import java.util.Date; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Locale; +import java.util.Set; + +import javax.servlet.ServletException; +import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; + +import org.apache.commons.lang.StringUtils; +import org.apache.log4j.Logger; +import org.apache.struts.action.Action; +import org.apache.struts.action.ActionForm; +import org.apache.struts.action.ActionForward; +import org.apache.struts.action.ActionMapping; +import org.lamsfoundation.lams.notebook.model.NotebookEntry; +import org.lamsfoundation.lams.notebook.service.CoreNotebookConstants; +import org.lamsfoundation.lams.tool.daco.DacoConstants; +import org.lamsfoundation.lams.tool.daco.dto.MonitoringSummarySessionDTO; +import org.lamsfoundation.lams.tool.daco.dto.MonitoringSummaryUserDTO; +import org.lamsfoundation.lams.tool.daco.dto.QuestionSummaryDTO; +import org.lamsfoundation.lams.tool.daco.model.Daco; +import org.lamsfoundation.lams.tool.daco.model.DacoAnswer; +import org.lamsfoundation.lams.tool.daco.model.DacoAnswerOption; +import org.lamsfoundation.lams.tool.daco.model.DacoQuestion; +import org.lamsfoundation.lams.tool.daco.model.DacoUser; +import org.lamsfoundation.lams.tool.daco.service.IDacoService; +import org.lamsfoundation.lams.tool.daco.util.DacoExcelUtil; +import org.lamsfoundation.lams.usermanagement.dto.UserDTO; +import org.lamsfoundation.lams.util.CentralConstants; +import org.lamsfoundation.lams.util.FileUtil; +import org.lamsfoundation.lams.util.NumberUtil; +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; +import org.springframework.web.context.WebApplicationContext; +import org.springframework.web.context.support.WebApplicationContextUtils; +import org.springframework.web.util.HtmlUtils; + +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.JsonNodeFactory; +import com.fasterxml.jackson.databind.node.ObjectNode; + +public class MonitoringAction extends Action { + public static Logger log = Logger.getLogger(MonitoringAction.class); + + @Override + public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) throws IOException, ServletException, ParseException { + String param = mapping.getParameter(); + + if (param.equals("summary")) { + return summary(mapping, request); + } + if (param.equals("getUsers")) { + return getUsers(mapping, form, request, response); + } + if (param.equals("viewReflection")) { + return viewReflection(mapping, request); + } + + if (param.equals("listRecords")) { + return listRecords(mapping, request); + } + if (param.equals("changeView")) { + return changeView(mapping, request); + } + if (param.equals("getQuestionSummaries")) { + return getQuestionSummaries(mapping, request); + } + if (param.equals("statistic")) { + return statistic(mapping, request); + } + if (param.equals("exportToSpreadsheet")) { + return exportToSpreadsheet(request, response); + } + + return mapping.findForward(DacoConstants.ERROR); + } + + protected ActionForward listRecords(ActionMapping mapping, HttpServletRequest request) { + return listRecords(mapping, request, false); + } + + protected ActionForward changeView(ActionMapping mapping, HttpServletRequest request) { + return listRecords(mapping, request, true); + } + + private ActionForward listRecords(ActionMapping mapping, HttpServletRequest request, boolean changeView) { + + String sessionMapID = request.getParameter(DacoConstants.ATTR_SESSION_MAP_ID); + SessionMap sessionMap = (SessionMap) request.getSession().getAttribute(sessionMapID); + Long toolSessionId = WebUtil.readLongParam(request, AttributeNames.PARAM_TOOL_SESSION_ID, true); + Long userId = WebUtil.readLongParam(request, DacoConstants.USER_ID, true); + Integer sortOrder = WebUtil.readIntParam(request, DacoConstants.ATTR_SORT, true); + if (sortOrder == null) { + sortOrder = DacoConstants.SORT_BY_NO; + } + + sessionMap.put(DacoConstants.ATTR_MONITORING_SUMMARY, + getDacoService().getAnswersAsRecords(toolSessionId, userId, sortOrder)); + request.setAttribute(DacoConstants.ATTR_SESSION_MAP_ID, sessionMapID); + request.setAttribute(AttributeNames.PARAM_TOOL_SESSION_ID, toolSessionId); + request.setAttribute(DacoConstants.ATTR_SORT, sortOrder); + request.setAttribute(DacoConstants.USER_ID, userId); + + if (changeView) { + String currentView = (String) sessionMap.get(DacoConstants.ATTR_LEARNING_VIEW); + if (DacoConstants.LEARNING_VIEW_HORIZONTAL.equals(currentView)) { + sessionMap.put(DacoConstants.ATTR_LEARNING_VIEW, DacoConstants.LEARNING_VIEW_VERTICAL); + } else { + sessionMap.put(DacoConstants.ATTR_LEARNING_VIEW, DacoConstants.LEARNING_VIEW_HORIZONTAL); + } + } + + return mapping.findForward(DacoConstants.SUCCESS); + } + + protected ActionForward summary(ActionMapping mapping, HttpServletRequest request) { + // initial Session Map + IDacoService service = getDacoService(); + String sessionMapID = WebUtil.readStrParam(request, DacoConstants.ATTR_SESSION_MAP_ID, true); + + boolean newSession = sessionMapID == null || request.getSession().getAttribute(sessionMapID) == null; + SessionMap sessionMap = null; + if (newSession) { + sessionMap = new SessionMap(); + sessionMapID = sessionMap.getSessionID(); + request.getSession().setAttribute(sessionMapID, sessionMap); + sessionMap.put(DacoConstants.ATTR_LEARNING_VIEW, DacoConstants.LEARNING_VIEW_VERTICAL); + } else { + sessionMap = (SessionMap) request.getSession().getAttribute(sessionMapID); + } + + Long contentId = sessionMap.get(AttributeNames.PARAM_TOOL_CONTENT_ID) == null + ? WebUtil.readLongParam(request, AttributeNames.PARAM_TOOL_CONTENT_ID) + : (Long) sessionMap.get(AttributeNames.PARAM_TOOL_CONTENT_ID); + Daco daco = service.getDacoByContentId(contentId); + + List monitoringSummaryList = service.getMonitoringSummary(contentId, + DacoConstants.MONITORING_SUMMARY_MATCH_NONE); + + Long userUid = WebUtil.readLongParam(request, DacoConstants.USER_UID, true); + if (userUid == null) { + userUid = (Long) sessionMap.get(DacoConstants.USER_UID); + request.setAttribute(DacoConstants.ATTR_MONITORING_CURRENT_TAB, 1); + } else { + request.setAttribute(DacoConstants.ATTR_MONITORING_CURRENT_TAB, 3); + } + + request.setAttribute(DacoConstants.ATTR_SESSION_MAP_ID, sessionMapID); + sessionMap.put(DacoConstants.USER_UID, userUid); + sessionMap.put(DacoConstants.PAGE_EDITABLE, !daco.isContentInUse()); + sessionMap.put(DacoConstants.ATTR_MONITORING_SUMMARY, monitoringSummaryList); + + if (newSession) { + boolean isGroupedActivity = service.isGroupedActivity(contentId); + sessionMap.put(DacoConstants.ATTR_IS_GROUPED_ACTIVITY, isGroupedActivity); + sessionMap.put(DacoConstants.ATTR_DACO, daco); + sessionMap.put(AttributeNames.PARAM_TOOL_CONTENT_ID, contentId); + sessionMap.put(AttributeNames.PARAM_CONTENT_FOLDER_ID, + WebUtil.readStrParam(request, AttributeNames.PARAM_CONTENT_FOLDER_ID)); + + HttpSession ss = SessionManager.getSession(); + UserDTO user = (UserDTO) ss.getAttribute(AttributeNames.USER); + } + return mapping.findForward(DacoConstants.SUCCESS); + } + + protected ActionForward getUsers(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse res) throws IOException, ServletException { + + IDacoService service = getDacoService(); + String sessionMapID = WebUtil.readStrParam(request, DacoConstants.ATTR_SESSION_MAP_ID, true); + SessionMap sessionMap = (SessionMap) request.getSession().getAttribute(sessionMapID); + + Long sessionId = WebUtil.readLongParam(request, AttributeNames.PARAM_TOOL_SESSION_ID); + + Long contentId = sessionMap.get(AttributeNames.PARAM_TOOL_CONTENT_ID) == null + ? WebUtil.readLongParam(request, AttributeNames.PARAM_TOOL_CONTENT_ID) + : (Long) sessionMap.get(AttributeNames.PARAM_TOOL_CONTENT_ID); + + // paging parameters of tablesorter + int size = WebUtil.readIntParam(request, "size"); + int page = WebUtil.readIntParam(request, "page"); + Integer isSort1 = WebUtil.readIntParam(request, "column[0]", true); + Integer isSort2 = WebUtil.readIntParam(request, "column[1]", true); + String searchString = request.getParameter("fcol[0]"); + + int sorting = DacoConstants.SORT_BY_NO; + if ((isSort1 != null) && isSort1.equals(0)) { + sorting = DacoConstants.SORT_BY_USER_NAME_ASC; + + } else if ((isSort1 != null) && isSort1.equals(1)) { + sorting = DacoConstants.SORT_BY_USER_NAME_DESC; + + } else if ((isSort2 != null) && isSort2.equals(0)) { + sorting = DacoConstants.SORT_BY_NUM_RECORDS_ASC; + + } else if ((isSort2 != null) && isSort2.equals(1)) { + sorting = DacoConstants.SORT_BY_NUM_RECORDS_DESC; + } + + Daco daco = service.getDacoByContentId(contentId); + + List users = service.getUsersForTablesorter(sessionId, page, size, sorting, searchString, + daco.isReflectOnActivity()); + + ArrayNode rows = JsonNodeFactory.instance.arrayNode(); + + ObjectNode responsedata = JsonNodeFactory.instance.objectNode(); + responsedata.put("total_rows", service.getCountUsersBySession(sessionId, searchString)); + + for (Object[] userAndReflection : users) { + + ObjectNode responseRow = JsonNodeFactory.instance.objectNode(); + + DacoUser user = (DacoUser) userAndReflection[0]; + + responseRow.put(DacoConstants.USER_ID, user.getUserId()); + responseRow.put(DacoConstants.USER_FULL_NAME, HtmlUtils.htmlEscape(user.getFullName())); + + if (userAndReflection.length > 1 && userAndReflection[1] != null) { + responseRow.put(DacoConstants.RECORD_COUNT, (Integer) userAndReflection[1]); + } else { + responseRow.put(DacoConstants.RECORD_COUNT, 0); + } + + if (userAndReflection.length > 2 && userAndReflection[2] != null) { + responseRow.put(DacoConstants.NOTEBOOK_ENTRY, + HtmlUtils.htmlEscape((String) userAndReflection[2])); + } + if (userAndReflection.length > 3 && userAndReflection[3] != null) { + responseRow.put(DacoConstants.PORTRAIT_ID, (String) userAndReflection[3]); + } + rows.add(responseRow); + } + responsedata.set("rows", rows); + res.setContentType("application/json;charset=utf-8"); + res.getWriter().print(new String(responsedata.toString())); + return null; + } + + protected ActionForward viewReflection(ActionMapping mapping, HttpServletRequest request) { + String sessionMapID = request.getParameter(DacoConstants.ATTR_SESSION_MAP_ID); + SessionMap sessionMap = (SessionMap) request.getSession().getAttribute(sessionMapID); + Integer userId = WebUtil.readIntParam(request, DacoConstants.USER_ID); + Long sessionId = WebUtil.readLongParam(request, AttributeNames.PARAM_TOOL_SESSION_ID); + + IDacoService service = getDacoService(); + DacoUser user = service.getUserByUserIdAndSessionId(userId.longValue(), sessionId); + NotebookEntry notebookEntry = service.getEntry(sessionId, CoreNotebookConstants.NOTEBOOK_TOOL, + DacoConstants.TOOL_SIGNATURE, userId); + + MonitoringSummaryUserDTO userDTO = new MonitoringSummaryUserDTO(null, userId, user.getFullName(), null); + userDTO.setReflectionEntry(notebookEntry.getEntry()); + sessionMap.put(DacoConstants.ATTR_USER, userDTO); + request.setAttribute(DacoConstants.ATTR_SESSION_MAP_ID, sessionMapID); + return mapping.findForward(DacoConstants.SUCCESS); + } + + private IDacoService getDacoService() { + WebApplicationContext wac = WebApplicationContextUtils + .getRequiredWebApplicationContext(getServlet().getServletContext()); + return (IDacoService) wac.getBean(DacoConstants.DACO_SERVICE); + } + + /** + * Exports all learners' data to an Excel or CSV file. + * + * @param request + * @param response + * @return + * @throws IOException + * @throws JXLException + * @throws ParseException + */ + protected ActionForward exportToSpreadsheet(HttpServletRequest request, HttpServletResponse response) + throws IOException, ParseException { + // Get required parameters + String sessionMapID = request.getParameter(DacoConstants.ATTR_SESSION_MAP_ID); + SessionMap sessionMap = (SessionMap) request.getSession().getAttribute(sessionMapID); + Daco daco = (Daco) sessionMap.get(DacoConstants.ATTR_DACO); + IDacoService service = getDacoService(); + + // Prepare headers and column names + String title = service.getLocalisedMessage(DacoConstants.KEY_LABEL_EXPORT_FILE_TITLE, null); + String dateHeader = service.getLocalisedMessage(DacoConstants.KEY_LABEL_EXPORT_FILE_DATE, null); + + Set questions = daco.getDacoQuestions(); + HashMap questionUidToSpreadsheetColumnIndex = new HashMap<>(); + // First two columns are "user" and date when was the answer added + int columnIndex = 2; + String[] columnNames = new String[questions.size() + 2]; + columnNames[0] = service.getLocalisedMessage(DacoConstants.KEY_LABEL_EXPORT_FILE_USER, null); + columnNames[1] = service.getLocalisedMessage(DacoConstants.KEY_LABEL_EXPORT_FILE_ANSWER_DATE, null); + for (DacoQuestion question : questions) { + questionUidToSpreadsheetColumnIndex.put(question.getUid(), columnIndex); + columnNames[columnIndex] = WebUtil.removeHTMLtags(question.getDescription()); + columnIndex++; + } + + // Some strings used in building cell values + String longitudeHeader = service.getLocalisedMessage(DacoConstants.KEY_LABEL_LEARNING_LONGLAT_LONGITUDE, null); + String longitudeUnit = service.getLocalisedMessage(DacoConstants.KEY_LABEL_LEARNING_LONGLAT_LONGITUDE_UNIT, + null); + String latitudeHeader = service.getLocalisedMessage(DacoConstants.KEY_LABEL_LEARNING_LONGLAT_LATITUDE, null); + String latitudeUnit = service.getLocalisedMessage(DacoConstants.KEY_LABEL_LEARNING_LONGLAT_LATITUDE_UNIT, null); + + List rows = new LinkedList<>(); + // We get all sessions with all users with all their records from the given Daco content + List monitoringSummary = service.getSummaryForExport(daco.getContentId(), null); + // Get current user's locale to format numbers properly + Locale monitoringUserLocale = null; + HttpSession ss = SessionManager.getSession(); + if (ss != null) { + UserDTO systemUser = (UserDTO) ss.getAttribute(AttributeNames.USER); + if (systemUser != null) { + monitoringUserLocale = new Locale(systemUser.getLocaleLanguage(), systemUser.getLocaleCountry()); + } + } + + for (MonitoringSummarySessionDTO summarySession : monitoringSummary) { + // Maybe we'll need delimiter between sessions one day - here is the place to add an empty row + for (MonitoringSummaryUserDTO user : summarySession.getUsers()) { + List> records = user.getRecords(); + for (int rowIndex = 0; rowIndex < records.size(); rowIndex++) { + Object[] row = new Object[questions.size() + 2]; + row[0] = user.getFullName(); + + List record = records.get(rowIndex); + for (int answerIndex = 0; answerIndex < record.size(); answerIndex++) { + DacoAnswer answer = record.get(answerIndex); + // we set the date of the whole row to the latest from all the participating answers + if (row[1] == null) { + row[1] = answer.getCreateDate(); + } else { + Date currentDate = (Date) row[1]; + Date newDate = answer.getCreateDate(); + if (currentDate.compareTo(newDate) < 0) { + row[1] = newDate; + } + } + Object cell = null; + String answerString = answer.getAnswer(); + columnIndex = questionUidToSpreadsheetColumnIndex.get(answer.getQuestion().getUid()); + // we extract answers and add them to "data" array in readable form + switch (answer.getQuestion().getType()) { + case DacoConstants.QUESTION_TYPE_NUMBER: + if (!StringUtils.isBlank(answerString)) { + Short fractionDigits = answer.getQuestion().getDigitsDecimal(); + if (fractionDigits == null) { + fractionDigits = Short.MAX_VALUE; + } + cell = NumberUtil.formatLocalisedNumber(Double.parseDouble(answerString), + monitoringUserLocale, fractionDigits); + } + break; + case DacoConstants.QUESTION_TYPE_DATE: + if (!StringUtils.isBlank(answerString)) { + cell = DacoConstants.DEFAULT_DATE_FORMAT.parse(answerString); + } + break; + case DacoConstants.QUESTION_TYPE_CHECKBOX: + if (!StringUtils.isBlank(answerString)) { + DacoQuestion question = answer.getQuestion(); + DacoQuestion currentQuestion = question; + List answerOptions = new LinkedList<>( + question.getAnswerOptions()); + StringBuilder cellStringBuilder = new StringBuilder(); + // instead of number, we create a comma-separated string of chosen options + do { + try { + int chosenAnswer = Integer.parseInt(answerString) - 1; + String chosenAnswerOption = answerOptions.get(chosenAnswer) + .getAnswerOption(); + cellStringBuilder.append(chosenAnswerOption).append(", "); + } catch (Exception e) { + log.error("exportToSpreadsheet encountered '" + e + + "' while parsing checkbox answer; answer was " + answerString); + } + answerIndex++; + // LDEV-3648 If the checkbox is the last entry, then there won't be any more answers so don't trigger an out of bounds exception! + if (answerIndex < record.size()) { + answer = record.get(answerIndex); + currentQuestion = answer.getQuestion(); + answerString = answer.getAnswer(); + } + } while (answerIndex < record.size() && currentQuestion.equals(question)); + // we went one answer too far, so we go back + answerIndex--; + cell = (cellStringBuilder.length() > 1 ? cellStringBuilder + .delete(cellStringBuilder.length() - 2, cellStringBuilder.length()) + .toString() : cellStringBuilder.toString()); + } + break; + case DacoConstants.QUESTION_TYPE_LONGLAT: + // Both longitude and latitude go in the same cell + if (StringUtils.isBlank(answerString)) { + // If longitude was not entered, then latitude also is blank, so skip the next answer + answerIndex++; + } else { + StringBuilder cellStringBuilder = new StringBuilder(longitudeHeader).append(' ') + .append(answerString).append(' ').append(longitudeUnit).append("; "); + answerIndex++; + answer = record.get(answerIndex); + cellStringBuilder.append(latitudeHeader).append(' ').append(answer.getAnswer()) + .append(' ').append(latitudeUnit); + cell = cellStringBuilder.toString(); + } + break; + case DacoConstants.QUESTION_TYPE_FILE: + case DacoConstants.QUESTION_TYPE_IMAGE: + if (!StringUtils.isBlank(answer.getFileName())) { + // Just get the file name, instead of the real file + cell = answer.getFileName(); + } + break; + case DacoConstants.QUESTION_TYPE_RADIO: + case DacoConstants.QUESTION_TYPE_DROPDOWN: + if (!StringUtils.isBlank(answerString)) { + List answerOptions = new LinkedList<>( + answer.getQuestion().getAnswerOptions()); + try { + int chosenAnswer = Integer.parseInt(answerString) - 1; + cell = answerOptions.get(chosenAnswer).getAnswerOption(); + } catch (Exception e) { + log.error("exportToSpreadsheet encountered '" + e + + "' while parsing dropdown or radio answer; answer was " + + answerString); + } + } + break; + default: + cell = answer.getAnswer(); + break; + } + row[columnIndex] = cell; + } + rows.add(row); + } + + } + } + // Convert from Collection to array + Object[][] data = rows.toArray(new Object[][] {}); + + // Prepare response headers + String fileName = DacoConstants.EXPORT_TO_SPREADSHEET_FILE_NAME; + fileName = FileUtil.encodeFilenameForDownload(request, fileName); + response.setContentType(CentralConstants.RESPONSE_CONTENT_TYPE_DOWNLOAD); + response.setHeader(CentralConstants.HEADER_CONTENT_DISPOSITION, + CentralConstants.HEADER_CONTENT_ATTACHMENT + fileName); + MonitoringAction.log.debug("Exporting to a spreadsheet tool content with UID: " + daco.getUid()); + ServletOutputStream out = response.getOutputStream(); + + // Export to XLS + String sheetName = service.getLocalisedMessage(DacoConstants.KEY_LABEL_EXPORT_FILE_SHEET, null); + DacoExcelUtil.exportToExcel(out, sheetName, title, dateHeader, columnNames, data); + + // Return the file inside response, but not any JSP page + return null; + } + + @SuppressWarnings({ "rawtypes", "unchecked" }) + protected ActionForward getQuestionSummaries(ActionMapping mapping, HttpServletRequest request) { + String sessionMapID = WebUtil.readStrParam(request, DacoConstants.ATTR_SESSION_MAP_ID); + SessionMap sessionMap = (SessionMap) request.getSession().getAttribute(sessionMapID); + + Long sessionId = WebUtil.readLongParam(request, AttributeNames.PARAM_TOOL_SESSION_ID); + IDacoService service = getDacoService(); + + DacoUser user; + Long userId = WebUtil.readLongParam(request, DacoConstants.USER_ID, true); + user = userId != null ? service.getUserByUserIdAndSessionId(userId, sessionId) : null; + + if (user != null) { + List summaries = service.getQuestionSummaries(user.getUid()); + sessionMap.put(DacoConstants.ATTR_QUESTION_SUMMARIES, summaries); + Integer totalRecordCount = service.getGroupRecordCount(sessionId); + sessionMap.put(DacoConstants.ATTR_TOTAL_RECORD_COUNT, totalRecordCount); + Integer userRecordCount = service.getRecordNum(userId, sessionId); + sessionMap.put(DacoConstants.RECORD_COUNT, userRecordCount); + sessionMap.put(DacoConstants.USER_FULL_NAME, user.getFullName()); + } else { + sessionMap.put(DacoConstants.ATTR_QUESTION_SUMMARIES, new LinkedList()); + sessionMap.put(DacoConstants.ATTR_TOTAL_RECORD_COUNT, 0); + sessionMap.put(DacoConstants.RECORD_COUNT, 0); + sessionMap.put(DacoConstants.USER_FULL_NAME, ""); + } + + request.setAttribute(DacoConstants.ATTR_SESSION_MAP_ID, sessionMapID); + return mapping.findForward(DacoConstants.SUCCESS); + } + + /** + * Show statistics page. + * + * @param mapping + * @param form + * @param request + * @param response + * @return + */ + private ActionForward statistic(ActionMapping mapping, HttpServletRequest request) { + + String sessionMapID = WebUtil.readStrParam(request, DacoConstants.ATTR_SESSION_MAP_ID); + SessionMap sessionMap = (SessionMap) request.getSession().getAttribute(sessionMapID); + + IDacoService service = getDacoService(); + + Long contentId = sessionMap.get(AttributeNames.PARAM_TOOL_CONTENT_ID) == null + ? WebUtil.readLongParam(request, AttributeNames.PARAM_TOOL_CONTENT_ID) + : (Long) sessionMap.get(AttributeNames.PARAM_TOOL_CONTENT_ID); + Daco daco = service.getDacoByContentId(contentId); + List sessList = service.getSessionStatistics(daco.getUid()); + + request.setAttribute(DacoConstants.ATTR_SESSION_SUMMARIES, sessList); + request.setAttribute(DacoConstants.ATTR_SESSION_MAP_ID, sessionMapID); + return mapping.findForward(DacoConstants.SUCCESS); + } + +} Index: lams_tool_daco/web/WEB-INF/spring-servlet.xml =================================================================== diff -u --- lams_tool_daco/web/WEB-INF/spring-servlet.xml (revision 0) +++ lams_tool_daco/web/WEB-INF/spring-servlet.xml (revision 085d47fc4191f2cb614a5a7c8fe3ff6c5abcef0f) @@ -0,0 +1,17 @@ + + + + + + + + + + + \ No newline at end of file Index: lams_tool_daco/web/WEB-INF/web.xml =================================================================== diff -u -r7475d08afc280b5e2e5ddf04e8bf35e3166aaf80 -r085d47fc4191f2cb614a5a7c8fe3ff6c5abcef0f --- lams_tool_daco/web/WEB-INF/web.xml (.../web.xml) (revision 7475d08afc280b5e2e5ddf04e8bf35e3166aaf80) +++ lams_tool_daco/web/WEB-INF/web.xml (.../web.xml) (revision 085d47fc4191f2cb614a5a7c8fe3ff6c5abcef0f) @@ -74,27 +74,13 @@ - action - org.apache.struts.action.ActionServlet - - config - /WEB-INF/struts-config.xml - - - debug - 999 - - - detail - 1 - - - validate - true - - 2 + spring + + org.springframework.web.servlet.DispatcherServlet + + 1 - + Connector net.fckeditor.connector.ConnectorServlet @@ -123,7 +109,7 @@ - action + spring *.do Index: lams_tool_scratchie/src/java/org/lamsfoundation/lams/tool/scratchie/web/controller/AuthoringController.java =================================================================== diff -u -r60b108064c4a844e3f153a849ab51a14bc3a8488 -r085d47fc4191f2cb614a5a7c8fe3ff6c5abcef0f --- lams_tool_scratchie/src/java/org/lamsfoundation/lams/tool/scratchie/web/controller/AuthoringController.java (.../AuthoringController.java) (revision 60b108064c4a844e3f153a849ab51a14bc3a8488) +++ lams_tool_scratchie/src/java/org/lamsfoundation/lams/tool/scratchie/web/controller/AuthoringController.java (.../AuthoringController.java) (revision 085d47fc4191f2cb614a5a7c8fe3ff6c5abcef0f) @@ -229,7 +229,7 @@ } ToolAccessMode mode = WebUtil.readToolAccessModeAuthorDefaulted(request); - request.setAttribute(AttributeNames.ATTR_MODE, mode.toString()); + authoringForm.setMode(mode.toString()); return "pages/authoring/authoring"; } Index: lams_tool_scratchie/src/java/org/lamsfoundation/lams/tool/scratchie/web/form/ScratchieForm.java =================================================================== diff -u -r60b108064c4a844e3f153a849ab51a14bc3a8488 -r085d47fc4191f2cb614a5a7c8fe3ff6c5abcef0f --- lams_tool_scratchie/src/java/org/lamsfoundation/lams/tool/scratchie/web/form/ScratchieForm.java (.../ScratchieForm.java) (revision 60b108064c4a844e3f153a849ab51a14bc3a8488) +++ lams_tool_scratchie/src/java/org/lamsfoundation/lams/tool/scratchie/web/form/ScratchieForm.java (.../ScratchieForm.java) (revision 085d47fc4191f2cb614a5a7c8fe3ff6c5abcef0f) @@ -41,16 +41,7 @@ private String sessionMapID; private String contentFolderID; - private SortedSet itemList; - public SortedSet getItemList() { - return itemList; - } - - public void setItemList(SortedSet itemList) { - this.itemList = itemList; - } - //tool access mode; private String mode; Index: lams_tool_scratchie/src/java/org/lamsfoundation/lams/tool/scratchie/web/form/ScratchieItemForm.java =================================================================== diff -u -r60b108064c4a844e3f153a849ab51a14bc3a8488 -r085d47fc4191f2cb614a5a7c8fe3ff6c5abcef0f --- lams_tool_scratchie/src/java/org/lamsfoundation/lams/tool/scratchie/web/form/ScratchieItemForm.java (.../ScratchieItemForm.java) (revision 60b108064c4a844e3f153a849ab51a14bc3a8488) +++ lams_tool_scratchie/src/java/org/lamsfoundation/lams/tool/scratchie/web/form/ScratchieItemForm.java (.../ScratchieItemForm.java) (revision 085d47fc4191f2cb614a5a7c8fe3ff6c5abcef0f) @@ -38,7 +38,6 @@ private String itemIndex; private String sessionMapID; private String contentFolderID; - private List answerList; // tool access mode; private String mode; @@ -94,13 +93,5 @@ this.description = description; } - public List getAnswerList() { - return answerList; - } - - public void setAnswerList(List answerList) { - this.answerList = answerList; - } - } Index: lams_tool_scratchie/web/pages/authoring/authoring.jsp =================================================================== diff -u -r60b108064c4a844e3f153a849ab51a14bc3a8488 -r085d47fc4191f2cb614a5a7c8fe3ff6c5abcef0f --- lams_tool_scratchie/web/pages/authoring/authoring.jsp (.../authoring.jsp) (revision 60b108064c4a844e3f153a849ab51a14bc3a8488) +++ lams_tool_scratchie/web/pages/authoring/authoring.jsp (.../authoring.jsp) (revision 085d47fc4191f2cb614a5a7c8fe3ff6c5abcef0f) @@ -40,9 +40,8 @@ - + - Index: lams_tool_scribe/web/pages/monitoring/notebook.jsp =================================================================== diff -u -r770fb82629331ca1c70c47845ab63b9528b7bc9e -r085d47fc4191f2cb614a5a7c8fe3ff6c5abcef0f --- lams_tool_scribe/web/pages/monitoring/notebook.jsp (.../notebook.jsp) (revision 770fb82629331ca1c70c47845ab63b9528b7bc9e) +++ lams_tool_scribe/web/pages/monitoring/notebook.jsp (.../notebook.jsp) (revision 085d47fc4191f2cb614a5a7c8fe3ff6c5abcef0f) @@ -18,7 +18,8 @@ - + +