Index: lams_tool_laqa/.externalToolBuilders/SASS_lams_tool_laqa.launch =================================================================== diff -u -ra83b0eec89979dce7415b02afdda324b14018dbb -r6d9587c552af599d4fc4e68399d218f5f4ca7cf4 --- lams_tool_laqa/.externalToolBuilders/SASS_lams_tool_laqa.launch (.../SASS_lams_tool_laqa.launch) (revision a83b0eec89979dce7415b02afdda324b14018dbb) +++ lams_tool_laqa/.externalToolBuilders/SASS_lams_tool_laqa.launch (.../SASS_lams_tool_laqa.launch) (revision 6d9587c552af599d4fc4e68399d218f5f4ca7cf4) @@ -5,6 +5,12 @@ + + + + + + Fisheye: Tag 6d9587c552af599d4fc4e68399d218f5f4ca7cf4 refers to a dead (removed) revision in file `lams_tool_laqa/src/java/org/lamsfoundation/lams/tool/qa/web/action/ClearSessionAction.java'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 6d9587c552af599d4fc4e68399d218f5f4ca7cf4 refers to a dead (removed) revision in file `lams_tool_laqa/src/java/org/lamsfoundation/lams/tool/qa/web/action/QaAction.java'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 6d9587c552af599d4fc4e68399d218f5f4ca7cf4 refers to a dead (removed) revision in file `lams_tool_laqa/src/java/org/lamsfoundation/lams/tool/qa/web/action/QaAdminAction.java'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 6d9587c552af599d4fc4e68399d218f5f4ca7cf4 refers to a dead (removed) revision in file `lams_tool_laqa/src/java/org/lamsfoundation/lams/tool/qa/web/action/QaAuthoringConditionAction.java'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 6d9587c552af599d4fc4e68399d218f5f4ca7cf4 refers to a dead (removed) revision in file `lams_tool_laqa/src/java/org/lamsfoundation/lams/tool/qa/web/action/QaLearningAction.java'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 6d9587c552af599d4fc4e68399d218f5f4ca7cf4 refers to a dead (removed) revision in file `lams_tool_laqa/src/java/org/lamsfoundation/lams/tool/qa/web/action/QaLearningStarterAction.java'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 6d9587c552af599d4fc4e68399d218f5f4ca7cf4 refers to a dead (removed) revision in file `lams_tool_laqa/src/java/org/lamsfoundation/lams/tool/qa/web/action/QaMonitoringAction.java'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 6d9587c552af599d4fc4e68399d218f5f4ca7cf4 refers to a dead (removed) revision in file `lams_tool_laqa/src/java/org/lamsfoundation/lams/tool/qa/web/action/QaMonitoringStarterAction.java'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 6d9587c552af599d4fc4e68399d218f5f4ca7cf4 refers to a dead (removed) revision in file `lams_tool_laqa/src/java/org/lamsfoundation/lams/tool/qa/web/action/QaPedagogicalPlannerAction.java'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 6d9587c552af599d4fc4e68399d218f5f4ca7cf4 refers to a dead (removed) revision in file `lams_tool_laqa/src/java/org/lamsfoundation/lams/tool/qa/web/action/QaStarterAction.java'. Fisheye: No comparison available. Pass `N' to diff? Index: lams_tool_laqa/src/java/org/lamsfoundation/lams/tool/qa/web/controller/ClearSessionController.java =================================================================== diff -u --- lams_tool_laqa/src/java/org/lamsfoundation/lams/tool/qa/web/controller/ClearSessionController.java (revision 0) +++ lams_tool_laqa/src/java/org/lamsfoundation/lams/tool/qa/web/controller/ClearSessionController.java (revision 6d9587c552af599d4fc4e68399d218f5f4ca7cf4) @@ -0,0 +1,67 @@ +/**************************************************************** + * Copyright (C) 2005 LAMS Foundation (http://lamsfoundation.org) + * ============================================================= + * License Information: http://lamsfoundation.org/licensing/lams/2.0/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + * USA + * + * http://www.gnu.org/licenses/gpl.txt + * **************************************************************** + */ + +package org.lamsfoundation.lams.tool.qa.web.controller; + +import java.io.IOException; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; + +import org.lamsfoundation.lams.authoring.web.LamsAuthoringFinishController; +import org.lamsfoundation.lams.tool.ToolAccessMode; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.context.WebApplicationContext; + +/** + * This class give a chance to clear HttpSession when user save/close authoring + * page. + * + * + * + * + * + * @version $Revision$ + */ +@Controller +public class ClearSessionController extends LamsAuthoringFinishController { + + @Autowired + private WebApplicationContext applicationContext; + + @RequestMapping("/clearsession") + public void execute(HttpServletRequest request, HttpServletResponse response) throws IOException { + super.execute(request, response, applicationContext); + } + + @Override + public void clearSession(String customiseSessionID, HttpSession session, ToolAccessMode mode) { + if (mode.isAuthor()) { + session.removeAttribute(customiseSessionID); + } + } + +} \ No newline at end of file Index: lams_tool_laqa/src/java/org/lamsfoundation/lams/tool/qa/web/controller/QaAdminController.java =================================================================== diff -u --- lams_tool_laqa/src/java/org/lamsfoundation/lams/tool/qa/web/controller/QaAdminController.java (revision 0) +++ lams_tool_laqa/src/java/org/lamsfoundation/lams/tool/qa/web/controller/QaAdminController.java (revision 6d9587c552af599d4fc4e68399d218f5f4ca7cf4) @@ -0,0 +1,377 @@ +/**************************************************************** + * Copyright (C) 2008 LAMS Foundation (http://lamsfoundation.org) + * ============================================================= + * License Information: http://lamsfoundation.org/licensing/lams/2.0/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2.0 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 * USA + * + * http://www.gnu.org/licenses/gpl.txt + * **************************************************************** + */ + +package org.lamsfoundation.lams.tool.qa.web.controller; + +import java.io.IOException; +import java.io.OutputStream; +import java.io.StringReader; +import java.util.SortedSet; +import java.util.TreeSet; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; + +import org.apache.log4j.Logger; +import org.apache.struts.action.ActionForm; +import org.apache.struts.action.ActionForward; +import org.apache.struts.action.ActionMapping; +import org.lamsfoundation.lams.learningdesign.service.ExportToolContentException; +import org.lamsfoundation.lams.tool.qa.QaConfigItem; +import org.lamsfoundation.lams.tool.qa.QaWizardCategory; +import org.lamsfoundation.lams.tool.qa.QaWizardCognitiveSkill; +import org.lamsfoundation.lams.tool.qa.QaWizardQuestion; +import org.lamsfoundation.lams.tool.qa.service.IQaService; +import org.lamsfoundation.lams.tool.qa.web.form.QaAdminForm; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.NamedNodeMap; +import org.w3c.dom.NodeList; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; + +import com.thoughtworks.xstream.XStream; +import com.thoughtworks.xstream.converters.reflection.SunUnsafeReflectionProvider; +import com.thoughtworks.xstream.security.AnyTypePermission; + +/** + * Handles the admin page for question and answer which includes the settings + * and items for the q&a question wizard + * + * @author lfoxton + * + * + */ +@Controller +@RequestMapping("/laqa11admin") +public class QaAdminController { + + private static Logger logger = Logger.getLogger(QaAdminController.class.getName()); + + public static final String ATTR_CATEGORIES = "categories"; + public static final String ATTR_CATEGORY = "category"; + public static final String ATTR_QUESTION = "question"; + public static final String ATTR_SKILL = "skill"; + public static final String ATTR_TITLE = "title"; + public static final String ATTR_UID = "uid"; + public static final String NULL = "null"; + public static final String FILE_EXPORT = "qa-wizard.xml"; + + @Autowired + private IQaService qaService; + + /** + * Sets up the admin page + */ + @RequestMapping("/") + public String unspecified(QaAdminForm adminForm, HttpServletRequest request) { + + QaConfigItem enableQaWizard = qaService.getConfigItem(QaConfigItem.KEY_ENABLE_QAWIZARD); + if (enableQaWizard != null) { + adminForm.setQaWizardEnabled(enableQaWizard.getConfigValue()); + } + + request.setAttribute("error", false); + request.setAttribute(ATTR_CATEGORIES, getQaWizardCategories()); + + return "admin/config"; + } + + /** + * Saves admin page, if the wizard is enabled, saves the wizard content + * + * @param mapping + * @param form + * @param request + * @param response + * @return + */ + @RequestMapping("/saveContent") + public String saveContent(QaAdminForm adminForm, HttpServletRequest request) { + + QaConfigItem enableQaWizard = qaService.getConfigItem(QaConfigItem.KEY_ENABLE_QAWIZARD); + + if (adminForm.getQaWizardEnabled() != null && adminForm.getQaWizardEnabled()) { + enableQaWizard.setConfigValue(QaAdminForm.TRUE); + + // get the wizard content and save + if (adminForm.getSerialiseXML() != null && !adminForm.getSerialiseXML().trim().equals("")) { + updateWizardFromXML(adminForm.getSerialiseXML().trim()); + } + + // remove any wizard items that were removed + removeWizardItems(adminForm.getDeleteCategoriesCSV(), adminForm.getDeleteSkillsCSV(), + adminForm.getDeleteQuestionsCSV()); + } else { + enableQaWizard.setConfigValue(QaAdminForm.FALSE); + } + qaService.saveOrUpdateConfigItem(enableQaWizard); + + request.setAttribute(ATTR_CATEGORIES, getQaWizardCategories()); + request.setAttribute("savedSuccess", true); + return "admin/config"; + + } + + /** + * Gets the complete set of wizard categories + * + * @return + */ + public SortedSet getQaWizardCategories() { + return qaService.getWizardCategories(); + } + + /** + * Removes all the removed wizard items from the db using CSV values + * + * @param categoriesCSV + * @param skillsCSV + * @param questionsCSV + */ + public void removeWizardItems(String categoriesCSV, String skillsCSV, String questionsCSV) { + + // remove categories + if (categoriesCSV != null && !categoriesCSV.equals("")) { + String categoryUIDs[] = categoriesCSV.split(","); + for (int i = 0; i < categoryUIDs.length; i++) { + qaService.deleteWizardCategoryByUID(Long.parseLong(categoryUIDs[i])); + } + } + + // remove skills + if (skillsCSV != null && !skillsCSV.equals("")) { + String skillUIDs[] = skillsCSV.split(","); + for (int i = 0; i < skillUIDs.length; i++) { + qaService.deleteWizardSkillByUID(Long.parseLong(skillUIDs[i])); + } + } + + // remove questions + if (questionsCSV != null && !questionsCSV.equals("")) { + String questionUIDs[] = questionsCSV.split(","); + for (int i = 0; i < questionUIDs.length; i++) { + qaService.deleteWizardQuestionByUID(Long.parseLong(questionUIDs[i])); + } + } + } + + /** + * Saves all the wizard items from the xml serialisation sent from the form + * + * @param xmlStr + */ + @SuppressWarnings("unchecked") + public void updateWizardFromXML(String xmlStr) { + //SortedSet currentCategories = getQaWizardCategories(); + SortedSet newCategories = new TreeSet<>(); + try { + DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); + DocumentBuilder db = dbf.newDocumentBuilder(); + Document document = db.parse(new InputSource(new StringReader(xmlStr))); + + // Get a list of category nodes + NodeList categoryNodeList = document.getElementsByTagName(ATTR_CATEGORY); + + for (int i = 0; i < categoryNodeList.getLength(); i++) { + + Element categoryElement = (Element) categoryNodeList.item(i); + + // Get the attributes for this category + NamedNodeMap categoryNamedNode = categoryNodeList.item(i).getAttributes(); + + QaWizardCategory category = new QaWizardCategory(); + category.setTitle(categoryNamedNode.getNamedItem(ATTR_TITLE).getNodeValue()); + category.setCognitiveSkills(new TreeSet()); + + if (categoryNamedNode.getNamedItem(ATTR_UID).getNodeValue() != null + && !categoryNamedNode.getNamedItem(ATTR_UID).getNodeValue().equals(NULL)) { + category.setUid(Long.parseLong(categoryNamedNode.getNamedItem(ATTR_UID).getNodeValue())); + } + + // Get a list of cognitive skill nodes + NodeList skillNodeList = categoryElement.getElementsByTagName(ATTR_SKILL); + for (int j = 0; j < skillNodeList.getLength(); j++) { + Element skillElement = (Element) skillNodeList.item(j); + + // Get the attributes for this skill + NamedNodeMap skillNamedNode = skillNodeList.item(j).getAttributes(); + + // Create the skill and add attributes from the node + QaWizardCognitiveSkill skill = new QaWizardCognitiveSkill(); + skill.setCategory(category); + skill.setTitle(skillNamedNode.getNamedItem(ATTR_TITLE).getNodeValue()); + skill.setQuestions(new TreeSet()); + + if (skillNamedNode.getNamedItem(ATTR_UID).getNodeValue() != null + && !skillNamedNode.getNamedItem(ATTR_UID).getNodeValue().equals(NULL)) { + skill.setUid(Long.parseLong(skillNamedNode.getNamedItem(ATTR_UID).getNodeValue())); + } + + // add the skill to the parent category + category.getCognitiveSkills().add(skill); + + // Get a list of questions for this skill + NodeList questionNodeList = skillElement.getElementsByTagName(ATTR_QUESTION); + for (int k = 0; k < questionNodeList.getLength(); k++) { + // Get the attributes for this question + NamedNodeMap questionNamedNode = questionNodeList.item(k).getAttributes(); + + // Create the question, and add attributes from the node + QaWizardQuestion question = new QaWizardQuestion(); + question.setQuestion(questionNamedNode.getNamedItem(ATTR_QUESTION).getNodeValue()); + + if (questionNamedNode.getNamedItem(ATTR_UID).getNodeValue() != null + && !questionNamedNode.getNamedItem(ATTR_UID).getNodeValue().equals(NULL)) { + question.setUid(Long.parseLong(questionNamedNode.getNamedItem(ATTR_UID).getNodeValue())); + } + + // add the question to the parent cognitive skill + skill.getQuestions().add(question); + } + } + newCategories.add(category); + } + + } catch (ParserConfigurationException e) { + logger.error("Could not parse wizard serialise xml", e); + } catch (SAXException e) { + logger.error("Could not parse wizard serialise xml", e); + } catch (IOException e) { + logger.error("Could not parse wizard serialise xml", e); + } + + qaService.saveOrUpdateQaWizardCategories(newCategories); + } + + /** + * Exports the wizard categories list so it can be imported elsewhere The + * export format is the same xml format used by the export ld servlet + * + * @param mapping + * @param form + * @param request + * @param response + * @return + */ + @RequestMapping("/exportWizard") + public String exportWizard(HttpServletResponse response) throws Exception { + + // now start the export + SortedSet exportCategories = new TreeSet<>(); + for (QaWizardCategory category : getQaWizardCategories()) { + exportCategories.add((QaWizardCategory) category.clone()); + } + + // exporting XML + XStream designXml = new XStream(new SunUnsafeReflectionProvider()); + designXml.addPermission(AnyTypePermission.ANY); + String exportXml = designXml.toXML(exportCategories); + + response.setContentType("application/x-download"); + response.setHeader("Content-Disposition", "attachment;filename=" + FILE_EXPORT); + OutputStream out = null; + try { + out = response.getOutputStream(); + out.write(exportXml.getBytes()); + response.setContentLength(exportXml.getBytes().length); + out.flush(); + } catch (Exception e) { + log.error("Exception occured writing out file:" + e.getMessage()); + throw new ExportToolContentException(e); + } finally { + try { + if (out != null) { + out.close(); + } + } catch (Exception e) { + log.error("Error Closing file. File already written out - no exception being thrown.", e); + } + } + + return null; + } + + /** + * Imports the wizard model from an xml file and replaces the current model + * First, saves the configurations, then performs the import using xstream + * + * @param mapping + * @param form + * @param request + * @param response + * @return + */ + @SuppressWarnings("unchecked") + public ActionForward importWizard(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) { + QaAdminForm adminForm = (QaAdminForm) form; + + // First save the config items + QaConfigItem enableQaWizard = qaService.getConfigItem(QaConfigItem.KEY_ENABLE_QAWIZARD); + + if (adminForm.getQaWizardEnabled() != null && adminForm.getQaWizardEnabled()) { + enableQaWizard.setConfigValue(QaAdminForm.TRUE); + + // get the wizard content and save + if (adminForm.getSerialiseXML() != null && !adminForm.getSerialiseXML().trim().equals("")) { + updateWizardFromXML(adminForm.getSerialiseXML().trim()); + } + + // remove any wizard items that were removed + removeWizardItems(adminForm.getDeleteCategoriesCSV(), adminForm.getDeleteSkillsCSV(), + adminForm.getDeleteQuestionsCSV()); + } else { + enableQaWizard.setConfigValue(QaAdminForm.FALSE); + } + qaService.saveOrUpdateConfigItem(enableQaWizard); + + // Now perform the import + try { + String xml = new String(adminForm.getImportFile().getFileData()); + XStream conversionXml = new XStream(new SunUnsafeReflectionProvider()); + conversionXml.addPermission(AnyTypePermission.ANY); + SortedSet exportCategories = (SortedSet) conversionXml.fromXML(xml); + + qaService.deleteAllWizardCategories(); + qaService.saveOrUpdateQaWizardCategories(exportCategories); + } catch (Exception e) { + logger.error("Failed to import wizard model", e); + request.setAttribute("error", true); + request.setAttribute("errorKey", "wizard.import.error"); + request.setAttribute(ATTR_CATEGORIES, getQaWizardCategories()); + return mapping.findForward("config"); + } + + request.setAttribute(ATTR_CATEGORIES, getQaWizardCategories()); + request.setAttribute("savedSuccess", true); + return mapping.findForward("config"); + + } + +} Index: lams_tool_laqa/src/java/org/lamsfoundation/lams/tool/qa/web/controller/QaAuthoringConditionController.java =================================================================== diff -u --- lams_tool_laqa/src/java/org/lamsfoundation/lams/tool/qa/web/controller/QaAuthoringConditionController.java (revision 0) +++ lams_tool_laqa/src/java/org/lamsfoundation/lams/tool/qa/web/controller/QaAuthoringConditionController.java (revision 6d9587c552af599d4fc4e68399d218f5f4ca7cf4) @@ -0,0 +1,442 @@ +/**************************************************************** + * Copyright (C) 2005 LAMS Foundation (http://lamsfoundation.org) + * ============================================================= + * License Information: http://lamsfoundation.org/licensing/lams/2.0/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2.0 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 * USA + * + * http://www.gnu.org/licenses/gpl.txt + * **************************************************************** + */ + +package org.lamsfoundation.lams.tool.qa.web.controller; + +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.List; +import java.util.SortedSet; +import java.util.TreeSet; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; + +import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang.math.NumberUtils; +import org.apache.struts.action.ActionForm; +import org.apache.struts.util.LabelValueBean; +import org.lamsfoundation.lams.learningdesign.TextSearchConditionComparator; +import org.lamsfoundation.lams.tool.qa.QaAppConstants; +import org.lamsfoundation.lams.tool.qa.QaCondition; +import org.lamsfoundation.lams.tool.qa.dto.QaQuestionDTO; +import org.lamsfoundation.lams.tool.qa.service.IQaService; +import org.lamsfoundation.lams.tool.qa.web.form.QaConditionForm; +import org.lamsfoundation.lams.util.MessageService; +import org.lamsfoundation.lams.util.WebUtil; +import org.lamsfoundation.lams.web.util.SessionMap; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.stereotype.Controller; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; + +/** + * Auxiliary action in author mode. It contains operations with QaCondition. The + * rest of operations are located in QaAction action. + * + * @author Marcin Cieslak + * @see org.lamsfoundation.lams.tool.qa.web.controller.QaAction + */ +@Controller +@RequestMapping("/authoringConditions") +public class QaAuthoringConditionController { + + @Autowired + private IQaService qaService; + + @Autowired + @Qualifier("qaMessageService") + private MessageService messageService; + + /** + * Display empty page for a new condition. + * + * @param QaConditionForm + * @param request + * @return + */ + @RequestMapping("/newConditionInit") + private String newConditionInit(QaConditionForm QaConditionForm, HttpServletRequest request) { + + populateFormWithPossibleItems(QaConditionForm, request); + QaConditionForm.setOrderId(-1); + return "authoring/addCondition"; + } + + /** + * Display edit page for an existing condition. + * + * @param QaConditionForm + * @param request + * @return + */ + @RequestMapping("/editCondition") + private String editCondition(QaConditionForm QaConditionForm, HttpServletRequest request) { + + String sessionMapID = QaConditionForm.getSessionMapID(); + SessionMap sessionMap = (SessionMap) request.getSession().getAttribute(sessionMapID); + + int orderId = NumberUtils.stringToInt(request.getParameter(QaAppConstants.PARAM_ORDER_ID), -1); + QaCondition condition = null; + if (orderId != -1) { + SortedSet conditionSet = getQaConditionSet(sessionMap); + List conditionList = new ArrayList<>(conditionSet); + condition = conditionList.get(orderId); + if (condition != null) { + populateConditionToForm(orderId, condition, QaConditionForm, request); + } + } + + populateFormWithPossibleItems(QaConditionForm, request); + return condition == null ? null : "authoring/addCondition"; + } + + /** + * This method will get necessary information from condition form and save + * or update into HttpSession condition list. Notice, this + * save is not persist them into database, just save + * HttpSession temporarily. Only they will be persist when + * the entire authoring page is being persisted. + * + * @param QaConditionForm + * @param request + * @return + * @throws ServletException + */ + @RequestMapping(value = "/saveOrUpdateCondition", method = RequestMethod.POST) + private String saveOrUpdateCondition(QaConditionForm QaConditionForm, HttpServletRequest request) { + + MultiValueMap errorMap = validateQaCondition(QaConditionForm, request); + + if (!errorMap.isEmpty()) { + populateFormWithPossibleItems(QaConditionForm, request); + request.setAttribute("errorMap", errorMap); + return "authoring/addCondition"; + } + + try { + extractFormToQaCondition(request, QaConditionForm); + } catch (Exception e) { + + errorMap.add("GLOBAL", messageService.getMessage("error.condition", new Object[] { e.getMessage() })); + if (!errorMap.isEmpty()) { + populateFormWithPossibleItems(QaConditionForm, request); + request.setAttribute("errorMap", errorMap); + return "authoring/addCondition"; + } + } + + request.setAttribute(QaAppConstants.ATTR_SESSION_MAP_ID, QaConditionForm.getSessionMapID()); + + return "authoring/conditionList"; + } + + /** + * Remove condition from HttpSession list and update page display. As + * authoring rule, all persist only happen when user submit whole page. So + * this remove is just impact HttpSession values. + * + * @param request + * @return + */ + @RequestMapping("/removeCondition") + private String removeCondition(HttpServletRequest request) { + + // get back sessionMAP + String sessionMapID = WebUtil.readStrParam(request, QaAppConstants.ATTR_SESSION_MAP_ID); + SessionMap sessionMap = (SessionMap) request.getSession().getAttribute(sessionMapID); + + int orderId = NumberUtils.stringToInt(request.getParameter(QaAppConstants.PARAM_ORDER_ID), -1); + if (orderId != -1) { + SortedSet conditionSet = getQaConditionSet(sessionMap); + List conditionList = new ArrayList<>(conditionSet); + QaCondition condition = conditionList.remove(orderId); + for (QaCondition otherCondition : conditionSet) { + if (otherCondition.getOrderId() > orderId) { + otherCondition.setOrderId(otherCondition.getOrderId() - 1); + } + } + conditionSet.clear(); + conditionSet.addAll(conditionList); + // add to delList + List deletedList = getDeletedQaConditionList(sessionMap); + deletedList.add(condition); + } + + request.setAttribute(QaAppConstants.ATTR_SESSION_MAP_ID, sessionMapID); + return "authoring/conditionList"; + } + + /** + * Move up current item. + * + * @param request + * @return + */ + @RequestMapping("/upCondition") + private String upCondition(HttpServletRequest request) { + return switchItem(request, true); + } + + /** + * Move down current item. + * + * @param request + * @return + */ + @RequestMapping("/downCondition") + private String downCondition(HttpServletRequest request) { + return switchItem(request, false); + } + + private String switchItem(HttpServletRequest request, boolean up) { + // get back sessionMAP + String sessionMapID = WebUtil.readStrParam(request, QaAppConstants.ATTR_SESSION_MAP_ID); + SessionMap sessionMap = (SessionMap) request.getSession().getAttribute(sessionMapID); + + int orderId = NumberUtils.stringToInt(request.getParameter(QaAppConstants.PARAM_ORDER_ID), -1); + if (orderId != -1) { + SortedSet conditionSet = getQaConditionSet(sessionMap); + List conditionList = new ArrayList<>(conditionSet); + // get current and the target item, and switch their sequnece + QaCondition condition = conditionList.get(orderId); + QaCondition repCondition; + if (up) { + repCondition = conditionList.get(--orderId); + } else { + repCondition = conditionList.get(++orderId); + } + int upSeqId = repCondition.getOrderId(); + repCondition.setOrderId(condition.getOrderId()); + condition.setOrderId(upSeqId); + + // put back list, it will be sorted again + conditionSet.clear(); + conditionSet.addAll(conditionList); + } + + request.setAttribute(QaAppConstants.ATTR_SESSION_MAP_ID, sessionMapID); + return "authoring/conditionList"; + } + + // ************************************************************************************* + // Private methods for internal needs + // ************************************************************************************* + + /** + * List save current taskList items. + * + * @param request + * @return + */ + private SortedSet getQaConditionSet(SessionMap sessionMap) { + SortedSet list = (SortedSet) sessionMap.get(QaAppConstants.ATTR_CONDITION_SET); + if (list == null) { + list = new TreeSet<>(new TextSearchConditionComparator()); + sessionMap.put(QaAppConstants.ATTR_CONDITION_SET, list); + } + return list; + } + + /** + * List save current taskList items. + * + * @param request + * @return + */ + private List getQuestionList(SessionMap sessionMap) { + List list = (List) sessionMap.get(QaAppConstants.LIST_QUESTION_DTOS); + if (list == null) { + list = new LinkedList<>(); + sessionMap.put(QaAppConstants.LIST_QUESTION_DTOS, list); + } + return list; + } + + /** + * Get the deleted condition list, which could be persisted or non-persisted + * items. + * + * @param request + * @return + */ + private List getDeletedQaConditionList(SessionMap sessionMap) { + return getListFromSession(sessionMap, QaAppConstants.ATTR_DELETED_CONDITION_LIST); + } + + /** + * Get java.util.List from HttpSession by given name. + * + * @param request + * @param name + * @return + */ + private List getListFromSession(SessionMap sessionMap, String name) { + List list = (List) sessionMap.get(name); + if (list == null) { + list = new ArrayList(); + sessionMap.put(name, list); + } + return list; + } + + /** + * This method will populate condition information to its form for edit use. + * + * @param orderId + * @param condition + * @param form + * @param request + */ + private void populateConditionToForm(int orderId, QaCondition condition, QaConditionForm form, + HttpServletRequest request) { + form.populateForm(condition); + if (orderId >= 0) { + form.setOrderId(orderId + 1); + } + } + + /** + * This method will populate questions to choose to the form for edit use. + * + * @param sequenceId + * @param condition + * @param form + * @param request + */ + private void populateFormWithPossibleItems(ActionForm form, HttpServletRequest request) { + QaConditionForm conditionForm = (QaConditionForm) form; + // get back sessionMAP + String sessionMapID = conditionForm.getSessionMapID(); + SessionMap sessionMap = (SessionMap) request.getSession().getAttribute(sessionMapID); + + List questions = getQuestionList(sessionMap); + + // Initialise the LabelValueBeans in the possibleOptions array. + LabelValueBean[] lvBeans = new LabelValueBean[questions.size()]; + + int i = 0; + for (QaQuestionDTO question : questions) { + String nonHTMLQuestion = question.getQuestion(); + if (nonHTMLQuestion != null) { + nonHTMLQuestion = WebUtil.removeHTMLtags(nonHTMLQuestion); + // we don't want to cite the whole question, so we just leave some first characters; it should be enough + // to recognise the question by a teacher + if (nonHTMLQuestion.length() > QaAppConstants.QUESTION_CUTOFF_INDEX) { + nonHTMLQuestion = nonHTMLQuestion.substring(0, QaAppConstants.QUESTION_CUTOFF_INDEX) + "..."; + } + } + lvBeans[i++] = new LabelValueBean(nonHTMLQuestion, new Integer(question.getDisplayOrder()).toString()); + } + conditionForm.setPossibleItems(lvBeans); + } + + /** + * Extract form content to QaCondition. + * + * @param request + * @param form + * @throws QaException + */ + private void extractFormToQaCondition(HttpServletRequest request, QaConditionForm form) throws Exception { + + SessionMap sessionMap = (SessionMap) request.getSession().getAttribute(form.getSessionMapID()); + // check whether it is "edit(old item)" or "add(new item)" + SortedSet conditionSet = getQaConditionSet(sessionMap); + int orderId = form.getOrderId(); + QaCondition condition = null; + + if (orderId == -1) { // add + String properConditionName = qaService.createConditionName(conditionSet); + condition = form.extractCondition(); + condition.setName(properConditionName); + int maxOrderId = 1; + if (conditionSet != null && conditionSet.size() > 0) { + QaCondition last = conditionSet.last(); + maxOrderId = last.getOrderId() + 1; + } + condition.setOrderId(maxOrderId); + conditionSet.add(condition); + } else { // edit + List conditionList = new ArrayList<>(conditionSet); + condition = conditionList.get(orderId - 1); + form.extractCondition(condition); + } + + Integer[] selectedItems = form.getSelectedItems(); + List questions = getQuestionList(sessionMap); + + condition.temporaryQuestionDTOSet.clear(); + for (Integer selectedItem : selectedItems) { + for (QaQuestionDTO question : questions) { + if (selectedItem.equals(new Integer(question.getDisplayOrder()))) { + condition.temporaryQuestionDTOSet.add(question); + } + } + } + + } + + /** + * Validate QaCondition + * + * @param QaConditionForm + * @return + */ + private MultiValueMap validateQaCondition(QaConditionForm QaConditionForm, + HttpServletRequest request) { + MultiValueMap errorMap = new LinkedMultiValueMap<>(); + + String formConditionName = QaConditionForm.getDisplayName(); + if (StringUtils.isBlank(formConditionName)) { + + errorMap.add("GLOBAL", messageService.getMessage("error.condition.name.blank")); + } else { + + Integer formConditionOrderId = QaConditionForm.getOrderId(); + + String sessionMapID = QaConditionForm.getSessionMapID(); + SessionMap sessionMap = (SessionMap) request.getSession().getAttribute(sessionMapID); + SortedSet conditionSet = getQaConditionSet(sessionMap); + for (QaCondition condition : conditionSet) { + if (formConditionName.equals(condition.getDisplayName()) + && !formConditionOrderId.equals(condition.getOrderId())) { + + errorMap.add("GLOBAL", messageService.getMessage("error.condition.duplicated.name")); + break; + } + } + } + + // should be selected at least one question + Integer[] selectedItems = QaConditionForm.getSelectedItems(); + if (selectedItems == null || selectedItems.length == 0) { + errorMap.add("GLOBAL", messageService.getMessage("error.condition.no.questions.selected")); + } + + return errorMap; + } + +} \ No newline at end of file Index: lams_tool_laqa/src/java/org/lamsfoundation/lams/tool/qa/web/controller/QaController.java =================================================================== diff -u --- lams_tool_laqa/src/java/org/lamsfoundation/lams/tool/qa/web/controller/QaController.java (revision 0) +++ lams_tool_laqa/src/java/org/lamsfoundation/lams/tool/qa/web/controller/QaController.java (revision 6d9587c552af599d4fc4e68399d218f5f4ca7cf4) @@ -0,0 +1,975 @@ +/**************************************************************** + * Copyright (C) 2005 LAMS Foundation (http://lamsfoundation.org) + * ============================================================= + * License Information: http://lamsfoundation.org/licensing/lams/2.0/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + * USA + * + * http://www.gnu.org/licenses/gpl.txt + * **************************************************************** + */ + +package org.lamsfoundation.lams.tool.qa.web.controller; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Date; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.Set; +import java.util.SortedSet; +import java.util.TreeSet; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpSession; + +import org.apache.log4j.Logger; +import org.lamsfoundation.lams.authoring.web.AuthoringConstants; +import org.lamsfoundation.lams.learningdesign.TextSearchConditionComparator; +import org.lamsfoundation.lams.rating.model.RatingCriteria; +import org.lamsfoundation.lams.tool.ToolAccessMode; +import org.lamsfoundation.lams.tool.qa.QaAppConstants; +import org.lamsfoundation.lams.tool.qa.QaCondition; +import org.lamsfoundation.lams.tool.qa.QaConfigItem; +import org.lamsfoundation.lams.tool.qa.QaContent; +import org.lamsfoundation.lams.tool.qa.QaQueContent; +import org.lamsfoundation.lams.tool.qa.dto.QaQuestionDTO; +import org.lamsfoundation.lams.tool.qa.service.IQaService; +import org.lamsfoundation.lams.tool.qa.util.AuthoringUtil; +import org.lamsfoundation.lams.tool.qa.util.QaQueContentComparator; +import org.lamsfoundation.lams.tool.qa.util.QaQuestionContentDTOComparator; +import org.lamsfoundation.lams.tool.qa.util.QaUtils; +import org.lamsfoundation.lams.tool.qa.web.form.QaAuthoringForm; +import org.lamsfoundation.lams.usermanagement.dto.UserDTO; +import org.lamsfoundation.lams.util.MessageService; +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.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.stereotype.Controller; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; +import org.springframework.web.bind.annotation.RequestMapping; + +/** + * Q&A Tool's authoring methods. Additionally, there is one more method that initializes authoring and it's located in + * QaStarterAction.java. + * + * @author Ozgur Demirtas + */ +@Controller +@RequestMapping("/authoring") +public class QaController implements QaAppConstants { + private static Logger logger = Logger.getLogger(QaController.class.getName()); + + @Autowired + private IQaService qaService; + + @Autowired + @Qualifier("qaMessageService") + private MessageService messageService; + + @RequestMapping("/") + public String unspecified() { + return "authoring/AuthoringTabsHolder"; + } + + /** + * submits content into the tool database + */ + @RequestMapping("/submitAllContent") + public String submitAllContent(QaAuthoringForm qaAuthoringForm, HttpServletRequest request) + throws IOException, ServletException { + + String httpSessionID = qaAuthoringForm.getHttpSessionID(); + SessionMap sessionMap = (SessionMap) request.getSession() + .getAttribute(httpSessionID); + + String contentFolderID = WebUtil.readStrParam(request, AttributeNames.PARAM_CONTENT_FOLDER_ID); + qaAuthoringForm.setContentFolderID(contentFolderID); + + String strToolContentID = request.getParameter(AttributeNames.PARAM_TOOL_CONTENT_ID); + Long toolContentID = new Long(strToolContentID); + + List questionDTOs = (List) sessionMap.get(QaAppConstants.LIST_QUESTION_DTOS); + + MultiValueMap errorMap = new LinkedMultiValueMap<>(); + if (questionDTOs.size() == 0) { + errorMap.add("GLOBAL", messageService.getMessage("questions.none.submitted")); + } + + String richTextTitle = request.getParameter(QaAppConstants.TITLE); + String richTextInstructions = request.getParameter(QaAppConstants.INSTRUCTIONS); + + qaAuthoringForm.setTitle(richTextTitle); + qaAuthoringForm.setInstructions(richTextInstructions); + + sessionMap.put(QaAppConstants.ACTIVITY_TITLE_KEY, richTextTitle); + sessionMap.put(QaAppConstants.ACTIVITY_INSTRUCTIONS_KEY, richTextInstructions); + + if (!errorMap.isEmpty()) { + request.setAttribute("errorMap", errorMap); + QaController.logger.debug("errors saved: " + errorMap); + } + + QaContent qaContent = qaService.getQaContent(toolContentID); + if (errorMap.isEmpty()) { + ToolAccessMode mode = WebUtil.readToolAccessModeAuthorDefaulted(request); + request.setAttribute(AttributeNames.ATTR_MODE, mode.toString()); + + List deletedQuestionDTOs = (List) sessionMap.get(LIST_DELETED_QUESTION_DTOS); + + // in case request is from monitoring module - recalculate User Answers + if (mode.isTeacher()) { + Set oldQuestions = qaContent.getQaQueContents(); + qaService.removeQuestionsFromCache(qaContent); + qaService.setDefineLater(strToolContentID, false); + + // audit log the teacher has started editing activity in monitor + qaService.auditLogStartEditingActivityInMonitor(toolContentID); + + // recalculate User Answers + qaService.recalculateUserAnswers(qaContent, oldQuestions, questionDTOs, deletedQuestionDTOs); + } + + // remove deleted questions + for (QaQuestionDTO deletedQuestionDTO : deletedQuestionDTOs) { + QaQueContent removeableQuestion = qaService.getQuestionByUid(deletedQuestionDTO.getUid()); + if (removeableQuestion != null) { + qaContent.getQaQueContents().remove(removeableQuestion); + qaService.removeQuestion(removeableQuestion); + } + } + + // store content + SortedSet conditionSet = (SortedSet) sessionMap + .get(QaAppConstants.ATTR_CONDITION_SET); + qaContent = saveOrUpdateQaContent(questionDTOs, request, qaContent, toolContentID, conditionSet); + + //reOrganizeDisplayOrder + List sortedQuestions = qaService.getAllQuestionEntriesSorted(qaContent.getUid().longValue()); + Iterator iter = sortedQuestions.iterator(); + int displayOrder = 1; + while (iter.hasNext()) { + QaQueContent question = iter.next(); + + QaQueContent existingQaQueContent = qaService.getQuestionByUid(question.getUid()); + existingQaQueContent.setDisplayOrder(displayOrder); + qaService.saveOrUpdateQuestion(existingQaQueContent); + displayOrder++; + } + + // ************************* Handle rating criterias ******************* + List oldCriterias = (List) sessionMap + .get(AttributeNames.ATTR_RATING_CRITERIAS); + qaService.saveRatingCriterias(request, oldCriterias, toolContentID); + + QaUtils.setFormProperties(request, qaAuthoringForm, strToolContentID, httpSessionID); + + request.setAttribute(AuthoringConstants.LAMS_AUTHORING_SUCCESS_FLAG, Boolean.TRUE); + + } else { + if (qaContent != null) { + QaUtils.setFormProperties(request, qaAuthoringForm, strToolContentID, httpSessionID); + } + } + + List delConditionList = getDeletedQaConditionList(sessionMap); + Iterator iter = delConditionList.iterator(); + while (iter.hasNext()) { + QaCondition condition = iter.next(); + iter.remove(); + qaService.deleteCondition(condition); + } + + qaAuthoringForm.resetUserAction(); + qaAuthoringForm.setToolContentID(strToolContentID); + qaAuthoringForm.setHttpSessionID(httpSessionID); + qaAuthoringForm.setCurrentTab("1"); + + request.setAttribute(QaAppConstants.LIST_QUESTION_DTOS, questionDTOs); + request.getSession().setAttribute(httpSessionID, sessionMap); + request.setAttribute(QaAppConstants.TOTAL_QUESTION_COUNT, new Integer(questionDTOs.size())); + sessionMap.put(QaAppConstants.LIST_QUESTION_DTOS, questionDTOs); + + return "authoring/AuthoringTabsHolder"; + } + + private QaContent saveOrUpdateQaContent(List questionDTOs, HttpServletRequest request, + QaContent qaContent, Long toolContentId, Set conditions) { + UserDTO toolUser = (UserDTO) SessionManager.getSession().getAttribute(AttributeNames.USER); + + String richTextTitle = request.getParameter(QaAppConstants.TITLE); + String richTextInstructions = request.getParameter(QaAppConstants.INSTRUCTIONS); + String usernameVisible = request.getParameter(QaAppConstants.USERNAME_VISIBLE); + String allowRateQuestions = request.getParameter(QaAppConstants.ALLOW_RATE_ANSWERS); + String notifyTeachersOnResponseSubmit = request.getParameter(QaAppConstants.NOTIFY_TEACHERS_ON_RESPONSE_SUBMIT); + String showOtherAnswers = request.getParameter("showOtherAnswers"); + String questionsSequenced = request.getParameter(QaAppConstants.QUESTIONS_SEQUENCED); + String lockWhenFinished = request.getParameter("lockWhenFinished"); + String noReeditAllowed = request.getParameter("noReeditAllowed"); + String allowRichEditor = request.getParameter("allowRichEditor"); + String useSelectLeaderToolOuput = request.getParameter("useSelectLeaderToolOuput"); + String reflect = request.getParameter(QaAppConstants.REFLECT); + String reflectionSubject = request.getParameter(QaAppConstants.REFLECTION_SUBJECT); + int minimumRates = WebUtil.readIntParam(request, "minimumRates"); + int maximumRates = WebUtil.readIntParam(request, "maximumRates"); + + boolean questionsSequencedBoolean = false; + boolean lockWhenFinishedBoolean = false; + boolean noReeditAllowedBoolean = false; + boolean usernameVisibleBoolean = false; + boolean allowRateQuestionsBoolean = false; + boolean notifyTeachersOnResponseSubmitBoolean = false; + boolean showOtherAnswersBoolean = false; + boolean reflectBoolean = false; + boolean allowRichEditorBoolean = false; + boolean useSelectLeaderToolOuputBoolean = false; + + if (questionsSequenced != null && questionsSequenced.equalsIgnoreCase("1")) { + questionsSequencedBoolean = true; + } + + if (lockWhenFinished != null && lockWhenFinished.equalsIgnoreCase("1")) { + lockWhenFinishedBoolean = true; + } + + if (noReeditAllowed != null && noReeditAllowed.equalsIgnoreCase("1")) { + noReeditAllowedBoolean = true; + lockWhenFinishedBoolean = true; + } + + if (usernameVisible != null && usernameVisible.equalsIgnoreCase("1")) { + usernameVisibleBoolean = true; + } + + if (showOtherAnswers != null && showOtherAnswers.equalsIgnoreCase("1")) { + showOtherAnswersBoolean = true; + } + + if (allowRateQuestions != null && allowRateQuestions.equalsIgnoreCase("1") && showOtherAnswersBoolean) { + allowRateQuestionsBoolean = true; + } + + if (notifyTeachersOnResponseSubmit != null && notifyTeachersOnResponseSubmit.equalsIgnoreCase("1")) { + notifyTeachersOnResponseSubmitBoolean = true; + } + + if (allowRichEditor != null && allowRichEditor.equalsIgnoreCase("1")) { + allowRichEditorBoolean = true; + } + + if (useSelectLeaderToolOuput != null && useSelectLeaderToolOuput.equalsIgnoreCase("1")) { + useSelectLeaderToolOuputBoolean = true; + } + + if (reflect != null && reflect.equalsIgnoreCase("1")) { + reflectBoolean = true; + } + long userId = 0; + if (toolUser != null) { + userId = toolUser.getUserID().longValue(); + } else { + HttpSession ss = SessionManager.getSession(); + UserDTO user = (UserDTO) ss.getAttribute(AttributeNames.USER); + if (user != null) { + userId = user.getUserID().longValue(); + } else { + userId = 0; + } + } + + boolean newContent = false; + if (qaContent == null) { + qaContent = new QaContent(); + newContent = true; + } + + qaContent.setQaContentId(toolContentId); + qaContent.setTitle(richTextTitle); + qaContent.setInstructions(richTextInstructions); + qaContent.setUpdateDate(new Date(System.currentTimeMillis())); + /** keep updating this one */ + qaContent.setCreatedBy(userId); + /** make sure we are setting the userId from the User object above */ + + qaContent.setUsernameVisible(usernameVisibleBoolean); + qaContent.setAllowRateAnswers(allowRateQuestionsBoolean); + qaContent.setNotifyTeachersOnResponseSubmit(notifyTeachersOnResponseSubmitBoolean); + qaContent.setShowOtherAnswers(showOtherAnswersBoolean); + qaContent.setQuestionsSequenced(questionsSequencedBoolean); + qaContent.setLockWhenFinished(lockWhenFinishedBoolean); + qaContent.setNoReeditAllowed(noReeditAllowedBoolean); + qaContent.setReflect(reflectBoolean); + qaContent.setReflectionSubject(reflectionSubject); + qaContent.setAllowRichEditor(allowRichEditorBoolean); + qaContent.setUseSelectLeaderToolOuput(useSelectLeaderToolOuputBoolean); + qaContent.setMinimumRates(minimumRates); + qaContent.setMaximumRates(maximumRates); + + qaContent.setConditions(new TreeSet(new TextSearchConditionComparator())); + if (newContent) { + qaService.createQaContent(qaContent); + } else { + qaService.updateQaContent(qaContent); + } + + qaContent = qaService.getQaContent(toolContentId); + + for (QaCondition condition : conditions) { + condition.setQuestions(new TreeSet<>(new QaQueContentComparator())); + for (QaQuestionDTO dto : condition.temporaryQuestionDTOSet) { + for (QaQueContent queContent : qaContent.getQaQueContents()) { + if (dto.getDisplayOrder().equals(String.valueOf(queContent.getDisplayOrder()))) { + condition.getQuestions().add(queContent); + } + } + } + } + qaContent.setConditions(conditions); + qaService.updateQaContent(qaContent); + + // persist questions + int displayOrder = 0; + for (QaQuestionDTO questionDTO : questionDTOs) { + + String questionText = questionDTO.getQuestion(); + + // skip empty questions + if (questionText.isEmpty()) { + continue; + } + + ++displayOrder; + + QaQueContent question = qaService.getQuestionByUid(questionDTO.getUid()); + + // in case question doesn't exist + if (question == null) { + question = new QaQueContent(questionText, displayOrder, questionDTO.getFeedback(), + questionDTO.isRequired(), questionDTO.getMinWordsLimit(), qaContent); + qaContent.getQaQueContents().add(question); + question.setQaContent(qaContent); + + // in case question exists already + } else { + + question.setQuestion(questionText); + question.setFeedback(questionDTO.getFeedback()); + question.setDisplayOrder(displayOrder); + question.setRequired(questionDTO.isRequired()); + question.setMinWordsLimit(questionDTO.getMinWordsLimit()); + } + + qaService.saveOrUpdateQuestion(question); + } + + return qaContent; + } + + /** + * saveSingleQuestion + */ + @RequestMapping("/saveSingleQuestion") + public String saveSingleQuestion(QaAuthoringForm qaAuthoringForm, HttpServletRequest request) + throws IOException, ServletException { + + String httpSessionID = qaAuthoringForm.getHttpSessionID(); + + SessionMap sessionMap = (SessionMap) request.getSession() + .getAttribute(httpSessionID); + + String contentFolderID = WebUtil.readStrParam(request, AttributeNames.PARAM_CONTENT_FOLDER_ID); + qaAuthoringForm.setContentFolderID(contentFolderID); + + String strToolContentID = request.getParameter(AttributeNames.PARAM_TOOL_CONTENT_ID); + + String editQuestionBoxRequest = request.getParameter("editQuestionBoxRequest"); + + List questionDTOs = (List) sessionMap.get(QaAppConstants.LIST_QUESTION_DTOS); + + String newQuestion = request.getParameter("newQuestion"); + + String feedback = request.getParameter("feedback"); + + String editableQuestionIndex = request.getParameter("editableQuestionIndex"); + + String required = request.getParameter("required"); + boolean requiredBoolean = false; + if (required != null && required.equalsIgnoreCase("1")) { + requiredBoolean = true; + } + int minWordsLimit = WebUtil.readIntParam(request, "minWordsLimit"); + + if (newQuestion != null && newQuestion.length() > 0) { + if (editQuestionBoxRequest != null && editQuestionBoxRequest.equals("false")) { + //request for add and save + boolean duplicates = AuthoringUtil.checkDuplicateQuestions(questionDTOs, newQuestion); + + if (!duplicates) { + QaQuestionDTO qaQuestionDTO = null; + Iterator iter = questionDTOs.iterator(); + while (iter.hasNext()) { + qaQuestionDTO = iter.next(); + + String displayOrder = qaQuestionDTO.getDisplayOrder(); + if (displayOrder != null && !displayOrder.equals("")) { + if (displayOrder.equals(editableQuestionIndex)) { + break; + } + + } + } + + qaQuestionDTO.setQuestion(newQuestion); + qaQuestionDTO.setFeedback(feedback); + qaQuestionDTO.setDisplayOrder(editableQuestionIndex); + qaQuestionDTO.setRequired(requiredBoolean); + qaQuestionDTO.setMinWordsLimit(minWordsLimit); + + questionDTOs = AuthoringUtil.reorderUpdateQuestionDTOs(questionDTOs, qaQuestionDTO, + editableQuestionIndex); + } else { + //duplicate question entry, not adding + } + } else { + //request for edit and save + QaQuestionDTO qaQuestionDTO = null; + Iterator iter = questionDTOs.iterator(); + while (iter.hasNext()) { + qaQuestionDTO = iter.next(); + + String displayOrder = qaQuestionDTO.getDisplayOrder(); + + if (displayOrder != null && !displayOrder.equals("")) { + if (displayOrder.equals(editableQuestionIndex)) { + break; + } + + } + } + + qaQuestionDTO.setQuestion(newQuestion); + qaQuestionDTO.setFeedback(feedback); + qaQuestionDTO.setDisplayOrder(editableQuestionIndex); + qaQuestionDTO.setRequired(requiredBoolean); + qaQuestionDTO.setMinWordsLimit(minWordsLimit); + + questionDTOs = AuthoringUtil.reorderUpdateQuestionDTOs(questionDTOs, qaQuestionDTO, + editableQuestionIndex); + } + } else { + //entry blank, not adding + } + + request.setAttribute(QaAppConstants.LIST_QUESTION_DTOS, questionDTOs); + sessionMap.put(QaAppConstants.LIST_QUESTION_DTOS, questionDTOs); + + String richTextTitle = request.getParameter(QaAppConstants.TITLE); + String richTextInstructions = request.getParameter(QaAppConstants.INSTRUCTIONS); + + qaAuthoringForm.setTitle(richTextTitle); + qaAuthoringForm.setInstructions(richTextInstructions); + + sessionMap.put(QaAppConstants.ACTIVITY_TITLE_KEY, richTextTitle); + sessionMap.put(QaAppConstants.ACTIVITY_INSTRUCTIONS_KEY, richTextInstructions); + + request.getSession().setAttribute(httpSessionID, sessionMap); + + QaUtils.setFormProperties(request, qaAuthoringForm, strToolContentID, httpSessionID); + + qaAuthoringForm.setToolContentID(strToolContentID); + qaAuthoringForm.setHttpSessionID(httpSessionID); + qaAuthoringForm.setCurrentTab("1"); + + request.getSession().setAttribute(httpSessionID, sessionMap); + request.setAttribute(QaAppConstants.TOTAL_QUESTION_COUNT, new Integer(questionDTOs.size())); + return "authoring/AuthoringTabsHolder"; + } + + /** + * addSingleQuestion + */ + @RequestMapping("/addSingleQuestion") + public String addSingleQuestion(QaAuthoringForm qaAuthoringForm, HttpServletRequest request) + throws IOException, ServletException { + + String httpSessionID = qaAuthoringForm.getHttpSessionID(); + + SessionMap sessionMap = (SessionMap) request.getSession() + .getAttribute(httpSessionID); + + String contentFolderID = WebUtil.readStrParam(request, AttributeNames.PARAM_CONTENT_FOLDER_ID); + qaAuthoringForm.setContentFolderID(contentFolderID); + + String strToolContentID = request.getParameter(AttributeNames.PARAM_TOOL_CONTENT_ID); + + List questionDTOs = (List) sessionMap.get(QaAppConstants.LIST_QUESTION_DTOS); + + String newQuestion = request.getParameter("newQuestion"); + String feedback = request.getParameter("feedback"); + String required = request.getParameter("required"); + boolean requiredBoolean = false; + if (required != null && required.equalsIgnoreCase("1")) { + requiredBoolean = true; + } + int minWordsLimit = WebUtil.readIntParam(request, "minWordsLimit"); + + int listSize = questionDTOs.size(); + + if (newQuestion != null && newQuestion.length() > 0) { + boolean duplicates = AuthoringUtil.checkDuplicateQuestions(questionDTOs, newQuestion); + + if (!duplicates) { + QaQuestionDTO qaQuestionDTO = new QaQuestionDTO(newQuestion, new Long(listSize + 1).toString(), + feedback, requiredBoolean, minWordsLimit); + questionDTOs.add(qaQuestionDTO); + } else { + //entry duplicate, not adding + } + } else { + //entry blank, not adding + } + + request.setAttribute(QaAppConstants.LIST_QUESTION_DTOS, questionDTOs); + sessionMap.put(QaAppConstants.LIST_QUESTION_DTOS, questionDTOs); + + String richTextTitle = request.getParameter(QaAppConstants.TITLE); + String richTextInstructions = request.getParameter(QaAppConstants.INSTRUCTIONS); + + qaAuthoringForm.setTitle(richTextTitle); + qaAuthoringForm.setInstructions(richTextInstructions); + + sessionMap.put(QaAppConstants.ACTIVITY_TITLE_KEY, richTextTitle); + sessionMap.put(QaAppConstants.ACTIVITY_INSTRUCTIONS_KEY, richTextInstructions); + + request.getSession().setAttribute(httpSessionID, sessionMap); + + QaUtils.setFormProperties(request, qaAuthoringForm, strToolContentID, httpSessionID); + + qaAuthoringForm.setToolContentID(strToolContentID); + qaAuthoringForm.setHttpSessionID(httpSessionID); + qaAuthoringForm.setCurrentTab("1"); + + request.getSession().setAttribute(httpSessionID, sessionMap); + request.setAttribute(QaAppConstants.TOTAL_QUESTION_COUNT, new Integer(questionDTOs.size())); + return "authoring/AuthoringTabsHolder"; + } + + /** + * opens up an new screen within the current page for adding a new question + */ + @RequestMapping("/newQuestionBox") + public String newQuestionBox(QaAuthoringForm qaAuthoringForm, HttpServletRequest request) + throws IOException, ServletException { + + String httpSessionID = qaAuthoringForm.getHttpSessionID(); + + SessionMap sessionMap = (SessionMap) request.getSession() + .getAttribute(httpSessionID); + + String contentFolderID = WebUtil.readStrParam(request, AttributeNames.PARAM_CONTENT_FOLDER_ID); + + qaAuthoringForm.setContentFolderID(contentFolderID); + + String strToolContentID = request.getParameter(AttributeNames.PARAM_TOOL_CONTENT_ID); + + String richTextTitle = request.getParameter(QaAppConstants.TITLE); + + String richTextInstructions = request.getParameter(QaAppConstants.INSTRUCTIONS); + + qaAuthoringForm.setTitle(richTextTitle); + qaAuthoringForm.setInstructions(richTextInstructions); + + QaUtils.setFormProperties(request, qaAuthoringForm, strToolContentID, httpSessionID); + + Collection questionDTOs = (Collection) sessionMap + .get(QaAppConstants.LIST_QUESTION_DTOS); + + request.setAttribute(QaAppConstants.TOTAL_QUESTION_COUNT, new Integer(questionDTOs.size())); + + // Adding in the qa wizard data if it is turned on + if (qaService.getConfigItem(QaConfigItem.KEY_ENABLE_QAWIZARD) != null + && qaService.getConfigItem(QaConfigItem.KEY_ENABLE_QAWIZARD).getConfigValue().equals("true")) { + request.setAttribute(QaAppConstants.ATTR_WIZARD_ENABLED, true); + request.setAttribute(QaAppConstants.ATTR_WIZARD_CATEGORIES, qaService.getWizardCategories()); + } + + return "authoring/newQuestionBox"; + } + + /** + * opens up an new screen within the current page for editing a question + */ + @RequestMapping("/newEditableQuestionBox") + public String newEditableQuestionBox(QaAuthoringForm qaAuthoringForm, HttpServletRequest request) + throws IOException, ServletException { + + String httpSessionID = qaAuthoringForm.getHttpSessionID(); + + SessionMap sessionMap = (SessionMap) request.getSession() + .getAttribute(httpSessionID); + + String questionIndex = request.getParameter("questionIndex"); + + qaAuthoringForm.setEditableQuestionIndex(questionIndex); + + List questionDTOs = (List) sessionMap.get(QaAppConstants.LIST_QUESTION_DTOS); + + String editableQuestion = ""; + String editableFeedback = ""; + boolean requiredBoolean = false; + int minWordsLimit = 0; + Iterator iter = questionDTOs.iterator(); + while (iter.hasNext()) { + QaQuestionDTO qaQuestionDTO = iter.next(); + String displayOrder = qaQuestionDTO.getDisplayOrder(); + + if (displayOrder != null && !displayOrder.equals("")) { + if (displayOrder.equals(questionIndex)) { + editableFeedback = qaQuestionDTO.getFeedback(); + editableQuestion = qaQuestionDTO.getQuestion(); + requiredBoolean = qaQuestionDTO.isRequired(); + minWordsLimit = qaQuestionDTO.getMinWordsLimit(); + break; + } + + } + } + + String contentFolderID = WebUtil.readStrParam(request, AttributeNames.PARAM_CONTENT_FOLDER_ID); + qaAuthoringForm.setContentFolderID(contentFolderID); + + String strToolContentID = request.getParameter(AttributeNames.PARAM_TOOL_CONTENT_ID); + + String richTextTitle = request.getParameter(QaAppConstants.TITLE); + String richTextInstructions = request.getParameter(QaAppConstants.INSTRUCTIONS); + + qaAuthoringForm.setTitle(richTextTitle); + qaAuthoringForm.setInstructions(richTextInstructions); + + QaUtils.setFormProperties(request, qaAuthoringForm, strToolContentID, httpSessionID); + + qaAuthoringForm.setRequired(requiredBoolean); + qaAuthoringForm.setMinWordsLimit(minWordsLimit); + qaAuthoringForm.setEditableQuestionText(editableQuestion); + qaAuthoringForm.setFeedback(editableFeedback); + + request.setAttribute(QaAppConstants.TOTAL_QUESTION_COUNT, new Integer(questionDTOs.size())); + + return "authoring/newQuestionBox"; + } + + /** + * removes a question from the questions map + */ + @RequestMapping("/removeQuestion") + public String removeQuestion(QaAuthoringForm qaAuthoringForm, HttpServletRequest request) + throws IOException, ServletException { + + String httpSessionID = qaAuthoringForm.getHttpSessionID(); + SessionMap sessionMap = (SessionMap) request.getSession() + .getAttribute(httpSessionID); + + String questionIndexToDelete = request.getParameter("questionIndex"); + QaQuestionDTO questionToDelete = null; + List questionDTOs = (List) sessionMap.get(QaAppConstants.LIST_QUESTION_DTOS); + + List listFinalQuestionDTO = new LinkedList<>(); + int queIndex = 0; + for (QaQuestionDTO questionDTO : questionDTOs) { + + String questionText = questionDTO.getQuestion(); + String displayOrder = questionDTO.getDisplayOrder(); + + if (questionText != null && !questionText.equals("") && (!displayOrder.equals(questionIndexToDelete))) { + + ++queIndex; + questionDTO.setDisplayOrder(new Integer(queIndex).toString()); + listFinalQuestionDTO.add(questionDTO); + } + if ((questionText != null) && (!questionText.isEmpty()) && displayOrder.equals(questionIndexToDelete)) { + List deletedQuestionDTOs = (List) sessionMap + .get(LIST_DELETED_QUESTION_DTOS); + ; + deletedQuestionDTOs.add(questionDTO); + sessionMap.put(LIST_DELETED_QUESTION_DTOS, deletedQuestionDTOs); + questionToDelete = questionDTO; + } + } + request.setAttribute(QaAppConstants.LIST_QUESTION_DTOS, listFinalQuestionDTO); + sessionMap.put(QaAppConstants.LIST_QUESTION_DTOS, listFinalQuestionDTO); + request.setAttribute(QaAppConstants.TOTAL_QUESTION_COUNT, new Integer(listFinalQuestionDTO.size())); + + SortedSet conditions = (SortedSet) sessionMap.get(QaAppConstants.ATTR_CONDITION_SET); + Iterator conditionIter = conditions.iterator(); + while (conditionIter.hasNext()) { + QaCondition condition = conditionIter.next(); + Iterator dtoIter = condition.temporaryQuestionDTOSet.iterator(); + while (dtoIter.hasNext()) { + if (dtoIter.next() == questionToDelete) { + dtoIter.remove(); + } + } + if (condition.temporaryQuestionDTOSet.isEmpty()) { + conditionIter.remove(); + } + } + + String contentFolderID = WebUtil.readStrParam(request, AttributeNames.PARAM_CONTENT_FOLDER_ID); + qaAuthoringForm.setContentFolderID(contentFolderID); + String richTextTitle = request.getParameter(QaAppConstants.TITLE); + String richTextInstructions = request.getParameter(QaAppConstants.INSTRUCTIONS); + sessionMap.put(QaAppConstants.ACTIVITY_TITLE_KEY, richTextTitle); + sessionMap.put(QaAppConstants.ACTIVITY_INSTRUCTIONS_KEY, richTextInstructions); + String strToolContentID = request.getParameter(AttributeNames.PARAM_TOOL_CONTENT_ID); + qaAuthoringForm.setTitle(richTextTitle); + qaAuthoringForm.setInstructions(richTextInstructions); + request.getSession().setAttribute(httpSessionID, sessionMap); + QaUtils.setFormProperties(request, qaAuthoringForm, strToolContentID, httpSessionID); + qaAuthoringForm.setToolContentID(strToolContentID); + qaAuthoringForm.setHttpSessionID(httpSessionID); + qaAuthoringForm.setCurrentTab("1"); + + return "authoring/AuthoringTabsHolder"; + } + + /** + * moves a question down in the list + */ + @RequestMapping("/moveQuestionDown") + public String moveQuestionDown(QaAuthoringForm qaAuthoringForm, HttpServletRequest request) + throws IOException, ServletException { + + String httpSessionID = qaAuthoringForm.getHttpSessionID(); + SessionMap sessionMap = (SessionMap) request.getSession() + .getAttribute(httpSessionID); + + String questionIndex = request.getParameter("questionIndex"); + + List questionDTOs = (List) sessionMap.get(QaAppConstants.LIST_QUESTION_DTOS); + + SortedSet conditionSet = (SortedSet) sessionMap + .get(QaAppConstants.ATTR_CONDITION_SET); + + questionDTOs = QaController.swapQuestions(questionDTOs, questionIndex, "down", conditionSet); + + questionDTOs = QaController.reorderQuestionDTOs(questionDTOs); + + sessionMap.put(QaAppConstants.LIST_QUESTION_DTOS, questionDTOs); + + String contentFolderID = WebUtil.readStrParam(request, AttributeNames.PARAM_CONTENT_FOLDER_ID); + qaAuthoringForm.setContentFolderID(contentFolderID); + + String richTextTitle = request.getParameter(QaAppConstants.TITLE); + + String richTextInstructions = request.getParameter(QaAppConstants.INSTRUCTIONS); + + sessionMap.put(QaAppConstants.ACTIVITY_TITLE_KEY, richTextTitle); + sessionMap.put(QaAppConstants.ACTIVITY_INSTRUCTIONS_KEY, richTextInstructions); + + String strToolContentID = request.getParameter(AttributeNames.PARAM_TOOL_CONTENT_ID); + + qaAuthoringForm.setTitle(richTextTitle); + qaAuthoringForm.setInstructions(richTextInstructions); + request.getSession().setAttribute(httpSessionID, sessionMap); + + QaUtils.setFormProperties(request, qaAuthoringForm, strToolContentID, httpSessionID); + + qaAuthoringForm.setToolContentID(strToolContentID); + qaAuthoringForm.setHttpSessionID(httpSessionID); + qaAuthoringForm.setCurrentTab("1"); + + request.setAttribute(QaAppConstants.LIST_QUESTION_DTOS, questionDTOs); + + request.setAttribute(QaAppConstants.TOTAL_QUESTION_COUNT, new Integer(questionDTOs.size())); + return "authoring/AuthoringTabsHolder"; + } + + /** + * moves a question up in the list + */ + @RequestMapping("/moveQuestionUp") + public String moveQuestionUp(QaAuthoringForm qaAuthoringForm, HttpServletRequest request) + throws IOException, ServletException { + + String httpSessionID = qaAuthoringForm.getHttpSessionID(); + + SessionMap sessionMap = (SessionMap) request.getSession() + .getAttribute(httpSessionID); + + String questionIndex = request.getParameter("questionIndex"); + + List questionDTOs = (List) sessionMap.get(QaAppConstants.LIST_QUESTION_DTOS); + + SortedSet conditionSet = (SortedSet) sessionMap + .get(QaAppConstants.ATTR_CONDITION_SET); + questionDTOs = QaController.swapQuestions(questionDTOs, questionIndex, "up", conditionSet); + + questionDTOs = QaController.reorderQuestionDTOs(questionDTOs); + + sessionMap.put(QaAppConstants.LIST_QUESTION_DTOS, questionDTOs); + + String contentFolderID = WebUtil.readStrParam(request, AttributeNames.PARAM_CONTENT_FOLDER_ID); + + qaAuthoringForm.setContentFolderID(contentFolderID); + + String richTextTitle = request.getParameter(QaAppConstants.TITLE); + + String richTextInstructions = request.getParameter(QaAppConstants.INSTRUCTIONS); + + sessionMap.put(QaAppConstants.ACTIVITY_TITLE_KEY, richTextTitle); + sessionMap.put(QaAppConstants.ACTIVITY_INSTRUCTIONS_KEY, richTextInstructions); + + String strToolContentID = request.getParameter(AttributeNames.PARAM_TOOL_CONTENT_ID); + + qaAuthoringForm.setTitle(richTextTitle); + qaAuthoringForm.setInstructions(richTextInstructions); + + request.getSession().setAttribute(httpSessionID, sessionMap); + + QaUtils.setFormProperties(request, qaAuthoringForm, strToolContentID, httpSessionID); + + qaAuthoringForm.setToolContentID(strToolContentID); + qaAuthoringForm.setHttpSessionID(httpSessionID); + qaAuthoringForm.setCurrentTab("1"); + + request.setAttribute(QaAppConstants.LIST_QUESTION_DTOS, questionDTOs); + + request.setAttribute(QaAppConstants.TOTAL_QUESTION_COUNT, new Integer(questionDTOs.size())); + return "authoring/AuthoringTabsHolder"; + } + + private static List swapQuestions(List questionDTOs, String questionIndex, + String direction, Set conditions) { + + int intQuestionIndex = new Integer(questionIndex).intValue(); + int intOriginalQuestionIndex = intQuestionIndex; + + int replacedQuestionIndex = 0; + if (direction.equals("down")) { + // direction down + replacedQuestionIndex = ++intQuestionIndex; + } else { + // direction up + replacedQuestionIndex = --intQuestionIndex; + } + + QaQuestionDTO mainQuestion = QaController.getQuestionAtDisplayOrder(questionDTOs, intOriginalQuestionIndex); + + QaQuestionDTO replacedQuestion = QaController.getQuestionAtDisplayOrder(questionDTOs, replacedQuestionIndex); + + List newQuestionDtos = new LinkedList<>(); + + Iterator iter = questionDTOs.iterator(); + while (iter.hasNext()) { + QaQuestionDTO questionDTO = iter.next(); + QaQuestionDTO tempQuestion = null; + + if (!questionDTO.getDisplayOrder().equals(new Integer(intOriginalQuestionIndex).toString()) + && !questionDTO.getDisplayOrder().equals(new Integer(replacedQuestionIndex).toString())) { + // normal copy + tempQuestion = questionDTO; + + } else if (questionDTO.getDisplayOrder().equals(new Integer(intOriginalQuestionIndex).toString())) { + // move type 1 + tempQuestion = replacedQuestion; + + } else if (questionDTO.getDisplayOrder().equals(new Integer(replacedQuestionIndex).toString())) { + // move type 1 + tempQuestion = mainQuestion; + } + + newQuestionDtos.add(tempQuestion); + } + + // references in conditions also need to be changed + if (conditions != null) { + for (QaCondition condition : conditions) { + SortedSet newQuestionDTOSet = new TreeSet<>(new QaQuestionContentDTOComparator()); + for (QaQuestionDTO dto : newQuestionDtos) { + if (condition.temporaryQuestionDTOSet.contains(dto)) { + newQuestionDTOSet.add(dto); + } + } + condition.temporaryQuestionDTOSet = newQuestionDTOSet; + } + } + + return newQuestionDtos; + } + + private static QaQuestionDTO getQuestionAtDisplayOrder(List questionDTOs, + int intOriginalQuestionIndex) { + + Iterator iter = questionDTOs.iterator(); + while (iter.hasNext()) { + QaQuestionDTO qaQuestionDTO = iter.next(); + if (new Integer(intOriginalQuestionIndex).toString().equals(qaQuestionDTO.getDisplayOrder())) { + return qaQuestionDTO; + } + } + return null; + } + + private static List reorderQuestionDTOs(List questionDTOs) { + List listFinalQuestionDTO = new LinkedList<>(); + + int queIndex = 0; + Iterator iter = questionDTOs.iterator(); + while (iter.hasNext()) { + QaQuestionDTO qaQuestionDTO = iter.next(); + + String question = qaQuestionDTO.getQuestion(); + String feedback = qaQuestionDTO.getFeedback(); + boolean required = qaQuestionDTO.isRequired(); + int minWordsLimit = qaQuestionDTO.getMinWordsLimit(); + + if (question != null && !question.equals("")) { + ++queIndex; + + qaQuestionDTO.setQuestion(question); + qaQuestionDTO.setDisplayOrder(new Integer(queIndex).toString()); + qaQuestionDTO.setFeedback(feedback); + qaQuestionDTO.setRequired(required); + qaQuestionDTO.setMinWordsLimit(minWordsLimit); + + listFinalQuestionDTO.add(qaQuestionDTO); + } + } + return listFinalQuestionDTO; + } + + /** + * Get the deleted condition list, which could be persisted or non-persisted + * items. + * + * @param request + * @return + */ + private List getDeletedQaConditionList(SessionMap sessionMap) { + List list = (List) sessionMap.get(QaAppConstants.ATTR_DELETED_CONDITION_LIST); + if (list == null) { + list = new ArrayList<>(); + sessionMap.put(QaAppConstants.ATTR_DELETED_CONDITION_LIST, list); + } + return list; + } +} Index: lams_tool_laqa/src/java/org/lamsfoundation/lams/tool/qa/web/controller/QaLearningController.java =================================================================== diff -u --- lams_tool_laqa/src/java/org/lamsfoundation/lams/tool/qa/web/controller/QaLearningController.java (revision 0) +++ lams_tool_laqa/src/java/org/lamsfoundation/lams/tool/qa/web/controller/QaLearningController.java (revision 6d9587c552af599d4fc4e68399d218f5f4ca7cf4) @@ -0,0 +1,1149 @@ +/*************************************************************************** +Copyright (C) 2005 LAMS Foundation (http://lamsfoundation.org) +License Information: http://lamsfoundation.org/licensing/lams/2.0/ + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License version 2 as +published by the Free Software Foundation. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 +USA + +http://www.gnu.org/licenses/gpl.txt + * ***********************************************************************/ + +package org.lamsfoundation.lams.tool.qa.web.controller; + +import java.io.IOException; +import java.util.Date; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.TimeZone; +import java.util.TreeMap; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; + +import org.apache.commons.lang.StringEscapeUtils; +import org.apache.commons.lang.StringUtils; +import org.apache.log4j.Logger; +import org.apache.struts.Globals; +import org.apache.struts.action.ActionForm; +import org.lamsfoundation.lams.notebook.model.NotebookEntry; +import org.lamsfoundation.lams.notebook.service.CoreNotebookConstants; +import org.lamsfoundation.lams.rating.dto.ItemRatingCriteriaDTO; +import org.lamsfoundation.lams.rating.dto.ItemRatingDTO; +import org.lamsfoundation.lams.rating.dto.RatingCommentDTO; +import org.lamsfoundation.lams.rating.model.LearnerItemRatingCriteria; +import org.lamsfoundation.lams.tool.exception.ToolException; +import org.lamsfoundation.lams.tool.qa.QaAppConstants; +import org.lamsfoundation.lams.tool.qa.QaContent; +import org.lamsfoundation.lams.tool.qa.QaQueContent; +import org.lamsfoundation.lams.tool.qa.QaQueUsr; +import org.lamsfoundation.lams.tool.qa.QaSession; +import org.lamsfoundation.lams.tool.qa.QaUsrResp; +import org.lamsfoundation.lams.tool.qa.dto.GeneralLearnerFlowDTO; +import org.lamsfoundation.lams.tool.qa.dto.QaQuestionDTO; +import org.lamsfoundation.lams.tool.qa.service.IQaService; +import org.lamsfoundation.lams.tool.qa.util.LearningUtil; +import org.lamsfoundation.lams.tool.qa.util.QaComparator; +import org.lamsfoundation.lams.tool.qa.util.QaStringComparator; +import org.lamsfoundation.lams.tool.qa.web.form.QaLearningForm; +import org.lamsfoundation.lams.usermanagement.dto.UserDTO; +import org.lamsfoundation.lams.util.DateUtil; +import org.lamsfoundation.lams.util.MessageService; +import org.lamsfoundation.lams.util.ValidationUtil; +import org.lamsfoundation.lams.util.WebUtil; +import org.lamsfoundation.lams.web.session.SessionManager; +import org.lamsfoundation.lams.web.util.AttributeNames; +import org.lamsfoundation.lams.web.util.SessionMap; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.stereotype.Controller; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; +import org.springframework.web.bind.annotation.RequestMapping; + +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.JsonNodeFactory; +import com.fasterxml.jackson.databind.node.ObjectNode; + +/** + * @author Ozgur Demirtas + */ +@Controller +@RequestMapping("/learning") +public class QaLearningController implements QaAppConstants { + private static Logger logger = Logger.getLogger(QaLearningController.class.getName()); + + @Autowired + private IQaService qaService; + + @Autowired + @Qualifier("qaMessageService") + private MessageService messageService; + + @RequestMapping("/") + public String unspecified() throws IOException, ServletException, ToolException { + QaLearningController.logger.warn("dispatching unspecified..."); + return null; + } + + /** + * submits users responses + * + * @param mapping + * @param form + * @param request + * @param response + * @return + * @throws IOException + * @throws ServletException + */ + @RequestMapping("/submitAnswersContent") + public String submitAnswersContent(QaLearningForm qaLearningForm, HttpServletRequest request) + throws IOException, ServletException { + + LearningUtil.saveFormRequestData(request, qaLearningForm); + String toolSessionID = request.getParameter(AttributeNames.PARAM_TOOL_SESSION_ID); + + QaSession qaSession = qaService.getSessionById(new Long(toolSessionID).longValue()); + QaContent qaContent = qaSession.getQaContent(); + + QaQueUsr qaQueUsr = getCurrentUser(toolSessionID); + //prohibit users from submitting answers after response is finalized but Resubmit button is not pressed (e.g. using 2 browsers) + if (qaQueUsr.isResponseFinalized()) { + String redirectURL = "redirect:/learning/learningStarter.do"; + redirectURL = WebUtil.appendParameterToURL(redirectURL, AttributeNames.PARAM_TOOL_SESSION_ID, + toolSessionID.toString()); + redirectURL = WebUtil.appendParameterToURL(redirectURL, QaAppConstants.MODE, "learner"); + return redirectURL; + } + + GeneralLearnerFlowDTO generalLearnerFlowDTO = LearningUtil.buildGeneralLearnerFlowDTO(qaService, qaContent); + + String totalQuestionCount = generalLearnerFlowDTO.getTotalQuestionCount().toString(); + int intTotalQuestionCount = new Integer(totalQuestionCount).intValue(); + + String questionListingMode = generalLearnerFlowDTO.getQuestionListingMode(); + + Map mapAnswers = new TreeMap(new QaComparator()); + Map mapAnswersPresentable = new TreeMap(new QaComparator()); + + String forwardName = QaAppConstants.INDIVIDUAL_LEARNER_RESULTS; + + String httpSessionID = qaLearningForm.getHttpSessionID(); + SessionMap sessionMap = (SessionMap) request.getSession() + .getAttribute(httpSessionID); + + MultiValueMap errorMap = new LinkedMultiValueMap<>(); + /* if the listing mode is QUESTION_LISTING_MODE_COMBINED populate the answers here */ + if (questionListingMode.equalsIgnoreCase(QaAppConstants.QUESTION_LISTING_MODE_COMBINED)) { + + for (int questionIndex = QaAppConstants.INITIAL_QUESTION_COUNT + .intValue(); questionIndex <= intTotalQuestionCount; questionIndex++) { + // TestHarness can not send "answerX" fields, so stick to the original, unfiltered field + boolean isTestHarness = Boolean.valueOf(request.getParameter("testHarness")); + String answerParamName = "answer" + questionIndex + (isTestHarness ? "__textarea" : ""); + String answer = request.getParameter(answerParamName); + + Integer questionIndexInteger = new Integer(questionIndex); + mapAnswers.put(questionIndexInteger.toString(), answer); + mapAnswersPresentable.put(questionIndexInteger.toString(), answer); + + //validate + errorMap = validateQuestionAnswer(answer, questionIndexInteger, generalLearnerFlowDTO); + + // store + if (errorMap.isEmpty()) { + qaService.updateResponseWithNewAnswer(answer, toolSessionID, new Long(questionIndex), false); + } + } + + } else { + Object[] results = storeSequentialAnswer(qaLearningForm, request, generalLearnerFlowDTO, true); + mapAnswers = (Map) results[0]; + errorMap = (MultiValueMap) results[1]; + + mapAnswersPresentable = (Map) sessionMap.get(QaAppConstants.MAP_ALL_RESULTS_KEY); + mapAnswersPresentable = QaLearningController.removeNewLinesMap(mapAnswersPresentable); + } + + //finalize response so user won't need to edit his answers again, if coming back to the activity after leaving activity at this point + if (errorMap.isEmpty()) { + qaQueUsr.setResponseFinalized(true); + qaService.updateUser(qaQueUsr); + + //in case of errors - prompt learner to enter answers again + } else { + request.setAttribute("errorMap", errorMap); + forwardName = QaAppConstants.LOAD_LEARNER; + } + + generalLearnerFlowDTO.setMapAnswers(mapAnswers); + generalLearnerFlowDTO.setMapAnswersPresentable(mapAnswersPresentable); + + /* mapAnswers will be used in the viewAllAnswers screen */ + if (sessionMap == null) { + sessionMap = new SessionMap<>(); + } + + sessionMap.put(QaAppConstants.MAP_ALL_RESULTS_KEY, mapAnswers); + request.getSession().setAttribute(sessionMap.getSessionID(), sessionMap); + qaLearningForm.setHttpSessionID(sessionMap.getSessionID()); + qaLearningForm.resetAll(); + generalLearnerFlowDTO.setHttpSessionID(sessionMap.getSessionID()); + + boolean lockWhenFinished = qaContent.isLockWhenFinished(); + generalLearnerFlowDTO.setLockWhenFinished(new Boolean(lockWhenFinished).toString()); + generalLearnerFlowDTO.setNoReeditAllowed(qaContent.isNoReeditAllowed()); + generalLearnerFlowDTO.setReflection(new Boolean(qaContent.isReflect()).toString()); + + request.setAttribute(QaAppConstants.GENERAL_LEARNER_FLOW_DTO, generalLearnerFlowDTO); + + // notify teachers on response submit + if (errorMap.isEmpty() && qaContent.isNotifyTeachersOnResponseSubmit()) { + qaService.notifyTeachersOnResponseSubmit(new Long(toolSessionID)); + } + + return "learning/AnswersContent"; + } + + @RequestMapping("/checkLeaderProgress") + public String checkLeaderProgress(HttpServletRequest request, HttpServletResponse response) throws IOException { + + Long toolSessionId = WebUtil.readLongParam(request, AttributeNames.PARAM_TOOL_SESSION_ID); + + QaSession session = qaService.getSessionById(toolSessionId); + QaQueUsr leader = session.getGroupLeader(); + + boolean isLeaderResponseFinalized = leader.isResponseFinalized(); + + ObjectNode ObjectNode = JsonNodeFactory.instance.objectNode(); + ObjectNode.put("isLeaderResponseFinalized", isLeaderResponseFinalized); + response.setContentType("application/x-json;charset=utf-8"); + response.getWriter().print(ObjectNode); + return null; + } + + /** + * auto saves responses + * + * @param mapping + * @param form + * @param request + * @param response + * @return + * @throws IOException + * @throws ServletException + */ + @RequestMapping("/autoSaveAnswers") + public String autoSaveAnswers(QaLearningForm qaLearningForm, HttpServletRequest request) + throws IOException, ServletException { + String toolSessionID = request.getParameter(AttributeNames.PARAM_TOOL_SESSION_ID); + + QaQueUsr qaQueUsr = getCurrentUser(toolSessionID); + //prohibit users from autosaving answers after response is finalized but Resubmit button is not pressed (e.g. using 2 browsers) + if (qaQueUsr.isResponseFinalized()) { + return null; + } + + LearningUtil.saveFormRequestData(request, qaLearningForm); + QaSession qaSession = qaService.getSessionById(new Long(toolSessionID).longValue()); + QaContent qaContent = qaSession.getQaContent(); + int intTotalQuestionCount = qaContent.getQaQueContents().size(); + + if (!qaContent.isQuestionsSequenced()) { + + for (int questionIndex = QaAppConstants.INITIAL_QUESTION_COUNT + .intValue(); questionIndex <= intTotalQuestionCount; questionIndex++) { + String newAnswer = request.getParameter("answer" + questionIndex); + qaService.updateResponseWithNewAnswer(newAnswer, toolSessionID, new Long(questionIndex), true); + } + + } else { + String currentQuestionIndex = qaLearningForm.getCurrentQuestionIndex(); + String newAnswer = qaLearningForm.getAnswer(); + QaQueContent currentQuestion = qaService.getQuestionByContentAndDisplayOrder(new Long(currentQuestionIndex), + qaContent.getUid()); + + boolean isRequiredQuestionMissed = currentQuestion.isRequired() && isEmpty(newAnswer); + if (!isRequiredQuestionMissed) { + qaService.updateResponseWithNewAnswer(newAnswer, toolSessionID, new Long(currentQuestionIndex), true); + } + } + return null; + } + + /** + * enables retaking the activity + * + * @param mapping + * @param form + * @param request + * @param response + * @return + * @throws IOException + * @throws ServletException + */ + @RequestMapping("/redoQuestions") + public String redoQuestions(QaLearningForm qaLearningForm, HttpServletRequest request) + throws IOException, ServletException { + + LearningUtil.saveFormRequestData(request, qaLearningForm); + + String toolSessionID = request.getParameter(AttributeNames.PARAM_TOOL_SESSION_ID); + QaSession qaSession = qaService.getSessionById(new Long(toolSessionID).longValue()); + QaContent qaContent = qaSession.getQaContent(); + + GeneralLearnerFlowDTO generalLearnerFlowDTO = LearningUtil.buildGeneralLearnerFlowDTO(qaService, qaContent); + + qaLearningForm.setCurrentQuestionIndex(new Integer(1).toString()); + + String httpSessionID = qaLearningForm.getHttpSessionID(); + + SessionMap sessionMap = (SessionMap) request.getSession() + .getAttribute(httpSessionID); + request.getSession().setAttribute(sessionMap.getSessionID(), sessionMap); + qaLearningForm.setHttpSessionID(sessionMap.getSessionID()); + generalLearnerFlowDTO.setHttpSessionID(sessionMap.getSessionID()); + generalLearnerFlowDTO.setToolContentID(qaContent.getQaContentId().toString()); + + // create mapQuestions + Map mapQuestions = generalLearnerFlowDTO.getMapQuestionContentLearner(); + generalLearnerFlowDTO.setMapQuestions(mapQuestions); + generalLearnerFlowDTO.setTotalQuestionCount(new Integer(mapQuestions.size())); + generalLearnerFlowDTO.setRemainingQuestionCount(new Integer(mapQuestions.size()).toString()); + qaLearningForm.setTotalQuestionCount(new Integer(mapQuestions.size()).toString()); + + //in order to track whether redo button is pressed store this info + QaQueUsr qaQueUsr = getCurrentUser(toolSessionID); + qaQueUsr.setResponseFinalized(false); + qaService.updateUser(qaQueUsr); + + // populate answers + LearningUtil.populateAnswers(sessionMap, qaContent, qaQueUsr, mapQuestions, generalLearnerFlowDTO, qaService); + + request.setAttribute(QaAppConstants.GENERAL_LEARNER_FLOW_DTO, generalLearnerFlowDTO); + qaLearningForm.resetAll(); + return "learning/AnswersContent"; + } + + /** + * Stores all results and moves onto the next step. If view other users answers = true, then goes to the view all + * answers screen, otherwise goes straight to the reflection screen (if any). + * + * @return Learner Report for a session + * @throws IOException + * @throws ServletException + */ + @RequestMapping("/storeAllResults") + public String storeAllResults(QaLearningForm qaLearningForm, HttpServletRequest request, + HttpServletResponse response) throws IOException, ServletException { + + LearningUtil.saveFormRequestData(request, qaLearningForm); + + String toolSessionID = request.getParameter(AttributeNames.PARAM_TOOL_SESSION_ID); + String userID = request.getParameter("userID"); + QaQueUsr user = qaService.getUserByIdAndSession(new Long(userID), new Long(toolSessionID)); + QaSession qaSession = qaService.getSessionById(new Long(toolSessionID).longValue()); + QaContent qaContent = qaSession.getQaContent(); + + // LearningUtil.storeResponses(mapAnswers, qaService, toolContentID, new Long(toolSessionID)); + + qaLearningForm.resetUserActions(); + qaLearningForm.setSubmitAnswersContent(null); + + if (qaContent.isShowOtherAnswers()) { + GeneralLearnerFlowDTO generalLearnerFlowDTO = LearningUtil.buildGeneralLearnerFlowDTO(qaService, qaContent); + String httpSessionID = qaLearningForm.getHttpSessionID(); + generalLearnerFlowDTO.setHttpSessionID(httpSessionID); + + /** Set up the data for the view all answers screen */ + QaLearningController.refreshSummaryData(request, qaContent, qaSession, qaService, httpSessionID, user, + generalLearnerFlowDTO); + + generalLearnerFlowDTO.setRequestLearningReport(new Boolean(true).toString()); + generalLearnerFlowDTO.setRequestLearningReportProgress(new Boolean(false).toString()); + + generalLearnerFlowDTO.setReflection(new Boolean(qaContent.isReflect()).toString()); + + qaLearningForm.resetAll(); + + boolean lockWhenFinished = qaContent.isLockWhenFinished(); + generalLearnerFlowDTO.setLockWhenFinished(new Boolean(lockWhenFinished).toString()); + generalLearnerFlowDTO.setNoReeditAllowed(qaContent.isNoReeditAllowed()); + + boolean useSelectLeaderToolOuput = qaContent.isUseSelectLeaderToolOuput(); + generalLearnerFlowDTO.setUseSelectLeaderToolOuput(new Boolean(useSelectLeaderToolOuput).toString()); + + boolean allowRichEditor = qaContent.isAllowRichEditor(); + generalLearnerFlowDTO.setAllowRichEditor(new Boolean(allowRichEditor).toString()); + generalLearnerFlowDTO.setUserUid(user.getQueUsrId().toString()); + + boolean usernameVisible = qaContent.isUsernameVisible(); + generalLearnerFlowDTO.setUserNameVisible(new Boolean(usernameVisible).toString()); + + NotebookEntry notebookEntry = qaService.getEntry(new Long(toolSessionID), + CoreNotebookConstants.NOTEBOOK_TOOL, QaAppConstants.MY_SIGNATURE, new Integer(userID)); + + if (notebookEntry != null) { + // String notebookEntryPresentable=QaUtils.replaceNewLines(notebookEntry.getEntry()); + String notebookEntryPresentable = notebookEntry.getEntry(); + qaLearningForm.setEntryText(notebookEntryPresentable); + } + + request.setAttribute(QaAppConstants.GENERAL_LEARNER_FLOW_DTO, generalLearnerFlowDTO); + return "learning/LearnerRep"; + + } else if (qaContent.isReflect()) { + return forwardtoReflection(request, qaContent, toolSessionID, userID, qaLearningForm); + + } else { + return endLearning(qaLearningForm, request, response); + } + } + + /** + * @param qaLearningForm + * @param request + * @return + * @throws IOException + * @throws ServletException + */ + @RequestMapping("/refreshAllResults") + public String refreshAllResults(QaLearningForm qaLearningForm, HttpServletRequest request) + throws IOException, ServletException { + + LearningUtil.saveFormRequestData(request, qaLearningForm); + + String toolSessionID = request.getParameter(AttributeNames.PARAM_TOOL_SESSION_ID); + qaLearningForm.setToolSessionID(toolSessionID); + + String userID = request.getParameter("userID"); + QaQueUsr user = qaService.getUserByIdAndSession(new Long(userID), new Long(toolSessionID)); + + QaSession qaSession = qaService.getSessionById(new Long(toolSessionID).longValue()); + + QaContent qaContent = qaSession.getQaContent(); + + GeneralLearnerFlowDTO generalLearnerFlowDTO = LearningUtil.buildGeneralLearnerFlowDTO(qaService, qaContent); + + String httpSessionID = qaLearningForm.getHttpSessionID(); + qaLearningForm.setHttpSessionID(httpSessionID); + generalLearnerFlowDTO.setHttpSessionID(httpSessionID); + SessionMap sessionMap = (SessionMap) request.getSession() + .getAttribute(httpSessionID); + + /* recreate the users and responses */ + qaLearningForm.resetUserActions(); + qaLearningForm.setSubmitAnswersContent(null); + + QaLearningController.refreshSummaryData(request, qaContent, qaSession, qaService, httpSessionID, user, + generalLearnerFlowDTO); + + generalLearnerFlowDTO.setRequestLearningReport(new Boolean(true).toString()); + generalLearnerFlowDTO.setRequestLearningReportProgress(new Boolean(false).toString()); + + generalLearnerFlowDTO.setReflection(new Boolean(qaContent.isReflect()).toString()); + // generalLearnerFlowDTO.setNotebookEntriesVisible(new Boolean(false).toString()); + + qaLearningForm.resetAll(); + + boolean lockWhenFinished; + boolean noReeditAllowed; + if (sessionMap.get("noRefresh") != null && (boolean) sessionMap.get("noRefresh")) { + lockWhenFinished = true; + noReeditAllowed = true; + } else { + lockWhenFinished = qaContent.isLockWhenFinished(); + noReeditAllowed = qaContent.isNoReeditAllowed(); + } + generalLearnerFlowDTO.setLockWhenFinished(new Boolean(lockWhenFinished).toString()); + generalLearnerFlowDTO.setNoReeditAllowed(noReeditAllowed); + + boolean allowRichEditor = qaContent.isAllowRichEditor(); + generalLearnerFlowDTO.setAllowRichEditor(new Boolean(allowRichEditor).toString()); + + boolean useSelectLeaderToolOuput = qaContent.isUseSelectLeaderToolOuput(); + generalLearnerFlowDTO.setUseSelectLeaderToolOuput(new Boolean(useSelectLeaderToolOuput).toString()); + + QaQueUsr qaQueUsr = getCurrentUser(toolSessionID); + generalLearnerFlowDTO.setUserUid(qaQueUsr.getQueUsrId().toString()); + + boolean usernameVisible = qaContent.isUsernameVisible(); + generalLearnerFlowDTO.setUserNameVisible(new Boolean(usernameVisible).toString()); + + request.setAttribute(QaAppConstants.GENERAL_LEARNER_FLOW_DTO, generalLearnerFlowDTO); + + return "learning/LearnerRep"; + } + + /** + * moves to the next question and modifies the map ActionForward + * + * @param qaLearningForm + * @param request + * @return + * @throws IOException + * @throws ServletException + * @throws ToolException + */ + @RequestMapping("/getNextQuestion") + public String getNextQuestion(QaLearningForm qaLearningForm, HttpServletRequest request) + throws IOException, ServletException, ToolException { + + LearningUtil.saveFormRequestData(request, qaLearningForm); + + String toolSessionID = request.getParameter(AttributeNames.PARAM_TOOL_SESSION_ID); + qaLearningForm.setToolSessionID(toolSessionID); + String httpSessionID = qaLearningForm.getHttpSessionID(); + qaLearningForm.setHttpSessionID(httpSessionID); + + QaSession qaSession = qaService.getSessionById(new Long(toolSessionID).longValue()); + QaContent qaContent = qaSession.getQaContent(); + + QaQueUsr qaQueUsr = getCurrentUser(toolSessionID); + //prohibit users from submitting answers after response is finalized but Resubmit button is not pressed (e.g. using 2 browsers) + if (qaQueUsr.isResponseFinalized()) { + String redirectURL = "redirect:learning/learningIndex.jsp"; + redirectURL = WebUtil.appendParameterToURL(redirectURL, AttributeNames.PARAM_TOOL_SESSION_ID, + toolSessionID.toString()); + redirectURL = WebUtil.appendParameterToURL(redirectURL, QaAppConstants.MODE, "learner"); + return redirectURL; + } + + GeneralLearnerFlowDTO generalLearnerFlowDTO = LearningUtil.buildGeneralLearnerFlowDTO(qaService, qaContent); + + storeSequentialAnswer(qaLearningForm, request, generalLearnerFlowDTO, true); + + qaLearningForm.resetAll(); + return "learning/AnswersContent"; + } + + /** + * Get the answer from the form and copy into DTO. Set up the next question. If the current question is required and + * the answer is blank, then just persist the error and don't change questions. + * + * @param form + * @param request + * @param generalLearnerFlowDTO + * @param getNextQuestion + * @return + */ + private Object[] storeSequentialAnswer(ActionForm form, HttpServletRequest request, + GeneralLearnerFlowDTO generalLearnerFlowDTO, boolean getNextQuestion) { + QaLearningForm qaLearningForm = (QaLearningForm) form; + String httpSessionID = qaLearningForm.getHttpSessionID(); + SessionMap sessionMap = (SessionMap) request.getSession() + .getAttribute(httpSessionID); + + String currentQuestionIndex = qaLearningForm.getCurrentQuestionIndex(); + + Map mapAnswers = (Map) sessionMap.get(QaAppConstants.MAP_ALL_RESULTS_KEY); + if (mapAnswers == null) { + mapAnswers = new TreeMap(new QaComparator()); + } + + String newAnswer = qaLearningForm.getAnswer(); + Map mapSequentialAnswers = (Map) sessionMap + .get(QaAppConstants.MAP_SEQUENTIAL_ANSWERS_KEY); + if (mapSequentialAnswers.size() >= new Integer(currentQuestionIndex).intValue()) { + mapSequentialAnswers.remove(new Long(currentQuestionIndex).toString()); + } + mapSequentialAnswers.put(new Long(currentQuestionIndex).toString(), newAnswer); + mapAnswers.put(currentQuestionIndex, newAnswer); + + int nextQuestionOffset = getNextQuestion ? 1 : -1; + + // validation only if trying to go to the next question + MultiValueMap errorMap = new LinkedMultiValueMap<>(); + if (getNextQuestion) { + errorMap = validateQuestionAnswer(newAnswer, new Integer(currentQuestionIndex), generalLearnerFlowDTO); + } + + // store + if (errorMap.isEmpty()) { + qaService.updateResponseWithNewAnswer(newAnswer, qaLearningForm.getToolSessionID(), + new Long(currentQuestionIndex), false); + } else { + request.setAttribute("errorMap", errorMap); + nextQuestionOffset = 0; + } + + int intCurrentQuestionIndex = new Integer(currentQuestionIndex).intValue() + nextQuestionOffset; + String currentAnswer = ""; + if (mapAnswers.size() >= intCurrentQuestionIndex) { + currentAnswer = mapAnswers.get(new Long(intCurrentQuestionIndex).toString()); + } + generalLearnerFlowDTO.setCurrentAnswer(currentAnswer); + + // currentQuestionIndex will be: + generalLearnerFlowDTO.setCurrentQuestionIndex(new Integer(intCurrentQuestionIndex)); + + String totalQuestionCount = qaLearningForm.getTotalQuestionCount(); + + int remainingQuestionCount = new Long(totalQuestionCount).intValue() + - new Integer(currentQuestionIndex).intValue() + 1; + String userFeedback = ""; + if (remainingQuestionCount != 0) { + userFeedback = "Remaining question count: " + remainingQuestionCount; + } else { + userFeedback = "End of the questions."; + } + generalLearnerFlowDTO.setUserFeedback(userFeedback); + generalLearnerFlowDTO.setRemainingQuestionCount("" + remainingQuestionCount); + + qaLearningForm.resetUserActions(); /* resets all except submitAnswersContent */ + + sessionMap.put(QaAppConstants.MAP_ALL_RESULTS_KEY, mapAnswers); + sessionMap.put(QaAppConstants.MAP_SEQUENTIAL_ANSWERS_KEY, mapSequentialAnswers); + request.getSession().setAttribute(sessionMap.getSessionID(), sessionMap); + qaLearningForm.setHttpSessionID(sessionMap.getSessionID()); + generalLearnerFlowDTO.setHttpSessionID(sessionMap.getSessionID()); + + request.setAttribute(QaAppConstants.GENERAL_LEARNER_FLOW_DTO, generalLearnerFlowDTO); + + return new Object[] { mapSequentialAnswers, errorMap }; + } + + private MultiValueMap validateQuestionAnswer(String newAnswer, Integer questionIndex, + GeneralLearnerFlowDTO generalLearnerFlowDTO) { + MultiValueMap errorMap = new LinkedMultiValueMap<>(); + + Map questionMap = generalLearnerFlowDTO.getMapQuestionContentLearner(); + QaQuestionDTO dto = questionMap.get(questionIndex); + + // if so, check if the answer is blank and generate an error if it is blank. + boolean isRequiredQuestionMissed = dto.isRequired() && isEmpty(newAnswer); + if (isRequiredQuestionMissed) { + errorMap.add(Globals.ERROR_KEY, + messageService.getMessage("error.required", new Object[] { questionIndex })); + } + + boolean isMinWordsLimitReached = ValidationUtil.isMinWordsLimitReached(newAnswer, dto.getMinWordsLimit(), + Boolean.parseBoolean(generalLearnerFlowDTO.getAllowRichEditor())); + if (!isMinWordsLimitReached) { + errorMap.add(Globals.ERROR_KEY, messageService.getMessage("label.minimum.number.words", + ": " + new Object[] { dto.getMinWordsLimit() })); + } + + return errorMap; + } + + /** + * Is this string empty? Need to strip out all HTML tags first otherwise an empty DIV might look like a valid answer + * Smileys and math functions only put in an img tag so explicitly look for that. + */ + private boolean isEmpty(String answer) { + if ((answer != null) && ((answer.indexOf(" -1) || (answer.indexOf(" -1))) { + return false; + } else { + return StringUtils.isBlank(WebUtil.removeHTMLtags(answer)); + } + } + + /** + * moves to the previous question and modifies the map ActionForward + * + * @param qaLearningForm + * @param request + * @return + * @throws IOException + * @throws ServletException + * @throws ToolException + */ + @RequestMapping("/getPreviousQuestion") + public String getPreviousQuestion(QaLearningForm qaLearningForm, HttpServletRequest request) + throws IOException, ServletException, ToolException { + + LearningUtil.saveFormRequestData(request, qaLearningForm); + + String httpSessionID = qaLearningForm.getHttpSessionID(); + qaLearningForm.setHttpSessionID(httpSessionID); + String toolSessionID = request.getParameter(AttributeNames.PARAM_TOOL_SESSION_ID); + qaLearningForm.setToolSessionID(toolSessionID); + QaSession qaSession = qaService.getSessionById(new Long(toolSessionID).longValue()); + QaContent qaContent = qaSession.getQaContent(); + + QaQueUsr qaQueUsr = getCurrentUser(toolSessionID); + //prohibit users from submitting answers after response is finalized but Resubmit button is not pressed (e.g. using 2 browsers) + if (qaQueUsr.isResponseFinalized()) { + String redirectURL = "redirect:learning/learningIndex.jsp"; + redirectURL = WebUtil.appendParameterToURL(redirectURL, AttributeNames.PARAM_TOOL_SESSION_ID, + toolSessionID.toString()); + redirectURL = WebUtil.appendParameterToURL(redirectURL, QaAppConstants.MODE, "learner"); + return redirectURL; + } + + GeneralLearnerFlowDTO generalLearnerFlowDTO = LearningUtil.buildGeneralLearnerFlowDTO(qaService, qaContent); + + storeSequentialAnswer(qaLearningForm, request, generalLearnerFlowDTO, false); + + qaLearningForm.resetAll(); + return "learning/AnswersContent"; + } + + /** + * finishes the user's tool activity + * + * @param request + * @param qaService + * @param response + * @throws IOException + * @throws ToolException + */ + @RequestMapping("/endLearning") + public String endLearning(QaLearningForm qaLearningForm, HttpServletRequest request, HttpServletResponse response) + throws IOException, ServletException, ToolException { + + LearningUtil.saveFormRequestData(request, qaLearningForm); + + String toolSessionID = request.getParameter(AttributeNames.PARAM_TOOL_SESSION_ID); + qaLearningForm.setToolSessionID(toolSessionID); + + String userID = request.getParameter("userID"); + qaLearningForm.setUserID(userID); + + QaSession qaSession = qaService.getSessionById(new Long(toolSessionID).longValue()); + + QaQueUsr qaQueUsr = qaService.getUserByIdAndSession(new Long(userID), qaSession.getQaSessionId()); + qaQueUsr.setLearnerFinished(true); + qaService.updateUser(qaQueUsr); + + /* + * The learner is done with the tool session. The tool needs to clean-up. + */ + HttpSession ss = SessionManager.getSession(); + /* get back login user DTO */ + UserDTO user = (UserDTO) ss.getAttribute(AttributeNames.USER); + + qaSession.setSession_end_date(new Date(System.currentTimeMillis())); + qaSession.setSession_status(QaAppConstants.COMPLETED); + qaService.updateSession(qaSession); + + String httpSessionID = qaLearningForm.getHttpSessionID(); + // request.getSession().removeAttribute(httpSessionID); + qaLearningForm.setHttpSessionID(httpSessionID); + + qaLearningForm.resetAll(); + + String nextActivityUrl = qaService.leaveToolSession(new Long(toolSessionID), + new Long(user.getUserID().longValue())); + response.sendRedirect(nextActivityUrl); + + return null; + } + + /** + * + * @param qaLearningForm + * @param request + * @param response + * @return + * @throws IOException + * @throws ServletException + * @throws ToolException + */ + @RequestMapping("/submitReflection") + public String submitReflection(QaLearningForm qaLearningForm, HttpServletRequest request, + HttpServletResponse response) throws IOException, ServletException, ToolException { + + LearningUtil.saveFormRequestData(request, qaLearningForm); + + String httpSessionID = qaLearningForm.getHttpSessionID(); + + qaLearningForm.setHttpSessionID(httpSessionID); + + String toolSessionIDString = request.getParameter(AttributeNames.PARAM_TOOL_SESSION_ID); + qaLearningForm.setToolSessionID(toolSessionIDString); + Long toolSessionID = new Long(toolSessionIDString); + + String userIDString = request.getParameter("userID"); + qaLearningForm.setUserID(userIDString); + Integer userID = new Integer(userIDString); + + String reflectionEntry = request.getParameter(QaAppConstants.ENTRY_TEXT); + + // check for existing notebook entry + NotebookEntry entry = qaService.getEntry(toolSessionID, CoreNotebookConstants.NOTEBOOK_TOOL, MY_SIGNATURE, + userID); + + if (entry == null) { + // create new entry + qaService.createNotebookEntry(toolSessionID, CoreNotebookConstants.NOTEBOOK_TOOL, + QaAppConstants.MY_SIGNATURE, userID, reflectionEntry); + + } else { + // update existing entry + entry.setEntry(reflectionEntry); + entry.setLastModified(new Date()); + qaService.updateEntry(entry); + } + + qaLearningForm.resetUserActions(); /* resets all except submitAnswersContent */ + return endLearning(qaLearningForm, request, response); + } + + /** + * + * @param qaLearningForm + * @param request + * @return + * @throws IOException + * @throws ServletException + * @throws ToolException + */ + @RequestMapping("/forwardtoReflection") + public String forwardtoReflection(QaLearningForm qaLearningForm, HttpServletRequest request) + throws IOException, ServletException, ToolException { + + String httpSessionID = qaLearningForm.getHttpSessionID(); + + qaLearningForm.setHttpSessionID(httpSessionID); + + String toolSessionID = request.getParameter(AttributeNames.PARAM_TOOL_SESSION_ID); + + QaSession qaSession = qaService.getSessionById(new Long(toolSessionID).longValue()); + + QaContent qaContent = qaSession.getQaContent(); + + String userID = request.getParameter("userID"); + qaLearningForm.setUserID(userID); + + return forwardtoReflection(request, qaContent, toolSessionID, userID, qaLearningForm); + } + + @RequestMapping("/forwardtoReflection") + private String forwardtoReflection(HttpServletRequest request, QaContent qaContent, String toolSessionID, + String userID, QaLearningForm qaLearningForm) { + + GeneralLearnerFlowDTO generalLearnerFlowDTO = new GeneralLearnerFlowDTO(); + generalLearnerFlowDTO.setActivityTitle(qaContent.getTitle()); + String reflectionSubject = qaContent.getReflectionSubject(); + // reflectionSubject = QaUtils.replaceNewLines(reflectionSubject); + generalLearnerFlowDTO.setReflectionSubject(reflectionSubject); + + // attempt getting notebookEntry + NotebookEntry notebookEntry = qaService.getEntry(new Long(toolSessionID), CoreNotebookConstants.NOTEBOOK_TOOL, + QaAppConstants.MY_SIGNATURE, new Integer(userID)); + + if (notebookEntry != null) { + // String notebookEntryPresentable=QaUtils.replaceNewLines(notebookEntry.getEntry()); + String notebookEntryPresentable = notebookEntry.getEntry(); + generalLearnerFlowDTO.setNotebookEntry(notebookEntryPresentable); + qaLearningForm.setEntryText(notebookEntryPresentable); + } + + request.setAttribute(QaAppConstants.GENERAL_LEARNER_FLOW_DTO, generalLearnerFlowDTO); + qaLearningForm.resetUserActions(); /* resets all except submitAnswersContent */ + + qaLearningForm.resetAll(); + return "learning/Notebook"; + } + + /** + * populates data for summary screen, view all results screen. + * + * User id is needed if isUserNamesVisible is false && learnerRequest is true, as it is required to work out if the + * data being analysed is the current user. + */ + public static void refreshSummaryData(HttpServletRequest request, QaContent qaContent, QaSession qaSession, + IQaService qaService, String httpSessionID, QaQueUsr user, GeneralLearnerFlowDTO generalLearnerFlowDTO) { + + SessionMap sessionMap = (SessionMap) request.getSession() + .getAttribute(httpSessionID); + Long userId = user.getQueUsrId(); + Set questions = qaContent.getQaQueContents(); + generalLearnerFlowDTO.setQuestions(questions); + generalLearnerFlowDTO.setUserNameVisible(new Boolean(qaContent.isUsernameVisible()).toString()); + + // potentially empty list if the user starts the lesson after the time restriction has expired. + List userResponses = qaService.getResponsesByUserUid(user.getUid()); + + //handle rating criterias + int commentsMinWordsLimit = 0; + boolean isCommentsEnabled = false; + int countRatedQuestions = 0; + if (qaContent.isAllowRateAnswers()) { + + if (userResponses.isEmpty()) { + Set criterias = qaContent.getRatingCriterias(); + for (LearnerItemRatingCriteria criteria : criterias) { + if (criteria.isCommentRating()) { + isCommentsEnabled = true; + break; + } + } + + } else { + // create itemIds list + List itemIds = new LinkedList<>(); + for (QaUsrResp responseIter : userResponses) { + itemIds.add(responseIter.getResponseId()); + } + + List itemRatingDtos = qaService.getRatingCriteriaDtos(qaContent.getQaContentId(), + qaSession.getQaSessionId(), itemIds, true, userId); + sessionMap.put(AttributeNames.ATTR_ITEM_RATING_DTOS, itemRatingDtos); + + if (itemRatingDtos.size() > 0) { + commentsMinWordsLimit = itemRatingDtos.get(0).getCommentsMinWordsLimit(); + isCommentsEnabled = itemRatingDtos.get(0).isCommentsEnabled(); + } + + //map itemRatingDto to corresponding response + for (QaUsrResp response : userResponses) { + + //find corresponding itemRatingDto + ItemRatingDTO itemRatingDto = null; + for (ItemRatingDTO itemRatingDtoIter : itemRatingDtos) { + if (itemRatingDtoIter.getItemId().equals(response.getResponseId())) { + itemRatingDto = itemRatingDtoIter; + break; + } + } + + response.setItemRatingDto(itemRatingDto); + } + + // store how many items are rated + countRatedQuestions = qaService.getCountItemsRatedByUser(qaContent.getQaContentId(), userId.intValue()); + } + } + + request.setAttribute(TOOL_SESSION_ID, qaSession.getQaSessionId()); + + sessionMap.put("commentsMinWordsLimit", commentsMinWordsLimit); + sessionMap.put("isCommentsEnabled", isCommentsEnabled); + sessionMap.put(AttributeNames.ATTR_COUNT_RATED_ITEMS, countRatedQuestions); + + generalLearnerFlowDTO.setUserResponses(userResponses); + generalLearnerFlowDTO.setRequestLearningReportProgress(new Boolean(true).toString()); + } + + /** + * Refreshes user list. + */ + @RequestMapping("/getResponses") + public String getResponses(HttpServletRequest request, HttpServletResponse res) + throws IOException, ServletException { + + // teacher timezone + HttpSession ss = SessionManager.getSession(); + UserDTO userDto = (UserDTO) ss.getAttribute(AttributeNames.USER); + TimeZone userTimeZone = userDto.getTimeZone(); + + boolean isAllowRateAnswers = WebUtil.readBooleanParam(request, "isAllowRateAnswers"); + boolean isAllowRichEditor = WebUtil.readBooleanParam(request, "isAllowRichEditor"); + boolean isOnlyLeadersIncluded = WebUtil.readBooleanParam(request, "isOnlyLeadersIncluded", false); + Long qaContentId = WebUtil.readLongParam(request, "qaContentId"); + + Long questionUid = WebUtil.readLongParam(request, "questionUid"); + Long qaSessionId = WebUtil.readLongParam(request, "qaSessionId"); + + //in case of monitoring we show all results. in case of learning - don't show results from the current user + boolean isMonitoring = WebUtil.readBooleanParam(request, "isMonitoring", false); + Long userId = isMonitoring ? -1 : WebUtil.readLongParam(request, "userId"); + + //paging parameters of tablesorter + int size = WebUtil.readIntParam(request, "size"); + int page = WebUtil.readIntParam(request, "page"); + Integer sortByCol1 = WebUtil.readIntParam(request, "column[0]", true); + Integer sortByCol2 = WebUtil.readIntParam(request, "column[1]", true); + String searchString = request.getParameter("fcol[0]"); + + int sorting = QaAppConstants.SORT_BY_NO; + if (sortByCol1 != null) { + if (isMonitoring) { + sorting = sortByCol1.equals(0) ? QaAppConstants.SORT_BY_USERNAME_ASC + : QaAppConstants.SORT_BY_USERNAME_DESC; + } else { + sorting = sortByCol1.equals(0) ? QaAppConstants.SORT_BY_ANSWER_ASC : QaAppConstants.SORT_BY_ANSWER_DESC; + } + + } else if (sortByCol2 != null) { + sorting = sortByCol2.equals(0) ? QaAppConstants.SORT_BY_RATING_ASC : QaAppConstants.SORT_BY_RATING_DESC; + + } else if (!isMonitoring) { + // Is it learner and comment only? If so sort by number of comments. + QaSession qaSession = qaService.getSessionById(qaSessionId); + Set criterias = qaSession.getQaContent().getRatingCriterias(); + boolean hasComment = false; + boolean hasRating = false; + for (LearnerItemRatingCriteria criteria : criterias) { + if (criteria.isCommentRating()) { + hasComment = true; + } else { + hasRating = true; + } + } + if (hasComment && !hasRating) { + sorting = QaAppConstants.SORT_BY_COMMENT_COUNT; + } + } + + List responses = qaService.getResponsesForTablesorter(qaContentId, qaSessionId, questionUid, userId, + isOnlyLeadersIncluded, page, size, sorting, searchString); + + ObjectNode responcedata = JsonNodeFactory.instance.objectNode(); + ArrayNode rows = JsonNodeFactory.instance.arrayNode(); + + responcedata.put("total_rows", qaService.getCountResponsesBySessionAndQuestion(qaSessionId, questionUid, userId, + isOnlyLeadersIncluded, searchString)); + + // handle rating criterias - even though we may have searched on ratings earlier we can't use the average ratings + // calculated as they may have been averages over more than one criteria. + List itemRatingDtos = null; + if (isAllowRateAnswers && !responses.isEmpty()) { + //create itemIds list + List itemIds = new LinkedList<>(); + for (QaUsrResp response : responses) { + itemIds.add(response.getResponseId()); + } + + //all comments required only for monitoring + boolean isCommentsByOtherUsersRequired = isMonitoring; + itemRatingDtos = qaService.getRatingCriteriaDtos(qaContentId, qaSessionId, itemIds, + isCommentsByOtherUsersRequired, userId); + + // store how many items are rated + int countRatedQuestions = qaService.getCountItemsRatedByUser(qaContentId, userId.intValue()); + responcedata.put(AttributeNames.ATTR_COUNT_RATED_ITEMS, countRatedQuestions); + } + + for (QaUsrResp response : responses) { + QaQueUsr user = response.getQaQueUser(); + + /* + * LDEV-3891: This code has been commented out, as the escapeCsv puts double quotes in the string, which + * goes through to the + * client and wrecks img src entries. It appears the browser cannot process the string with all the double + * quotes. + * This is the second time it is being fixed - the escapeCsv was removed in LDEV-3448 and then added back in + * when Peer Review was added (LDEV-3480). If escapeCsv needs to be added in again, make sure it does not + * break + * learner added images being seen in monitoring. + * //remove leading and trailing quotes + * String answer = StringEscapeUtils.escapeCsv(response.getAnswer()); + * if (isAllowRichEditor && answer.startsWith("\"") && answer.length() >= 3) { + * answer = answer.substring(1, answer.length() - 1); + * } + */ + + ObjectNode responseRow = JsonNodeFactory.instance.objectNode(); + responseRow.put("responseUid", response.getResponseId().toString()); + responseRow.put("answer", response.getAnswer()); + responseRow.put("userName", StringEscapeUtils.escapeCsv(user.getFullname())); + responseRow.put("visible", new Boolean(response.isVisible()).toString()); + responseRow.put("userID", user.getQueUsrId()); + responseRow.put("portraitId", response.getPortraitId()); + + // format attemptTime - got straight from server time to other timezones in formatter + // as trying to convert dates runs into tz issues - any Date object created is still + // in the server time zone. + Date attemptTime = response.getAttemptTime(); + responseRow.put("attemptTime", DateUtil.convertToStringForJSON(attemptTime, request.getLocale())); + responseRow.put("timeAgo", DateUtil.convertToStringForTimeagoJSON(attemptTime)); + + if (isAllowRateAnswers) { + + //find corresponding itemRatingDto + ItemRatingDTO itemRatingDto = null; + for (ItemRatingDTO itemRatingDtoIter : itemRatingDtos) { + if (response.getResponseId().equals(itemRatingDtoIter.getItemId())) { + itemRatingDto = itemRatingDtoIter; + break; + } + } + + boolean isItemAuthoredByUser = response.getQaQueUser().getQueUsrId().equals(userId); + responseRow.put("isItemAuthoredByUser", isItemAuthoredByUser); + + ArrayNode criteriasRows = JsonNodeFactory.instance.arrayNode(); + for (ItemRatingCriteriaDTO criteriaDto : itemRatingDto.getCriteriaDtos()) { + ObjectNode criteriasRow = JsonNodeFactory.instance.objectNode(); + criteriasRow.put("ratingCriteriaId", criteriaDto.getRatingCriteria().getRatingCriteriaId()); + criteriasRow.put("title", criteriaDto.getRatingCriteria().getTitle()); + criteriasRow.put("averageRating", criteriaDto.getAverageRating()); + criteriasRow.put("numberOfVotes", criteriaDto.getNumberOfVotes()); + criteriasRow.put("userRating", criteriaDto.getUserRating()); + + criteriasRows.add(criteriasRow); + } + responseRow.set("criteriaDtos", criteriasRows); + + //handle comments + responseRow.put("commentsCriteriaId", itemRatingDto.getCommentsCriteriaId()); + String commentPostedByUser = itemRatingDto.getCommentPostedByUser() == null ? "" + : itemRatingDto.getCommentPostedByUser().getComment(); + responseRow.put("commentPostedByUser", commentPostedByUser); + if (itemRatingDto.getCommentDtos() != null) { + + ArrayNode comments = JsonNodeFactory.instance.arrayNode(); + for (RatingCommentDTO commentDto : itemRatingDto.getCommentDtos()) { + ObjectNode comment = JsonNodeFactory.instance.objectNode(); + comment.put("comment", StringEscapeUtils.escapeCsv(commentDto.getComment())); + + if (isMonitoring) { + // format attemptTime + Date postedDate = commentDto.getPostedDate(); + postedDate = DateUtil.convertToTimeZoneFromDefault(userTimeZone, postedDate); + comment.put("postedDate", DateUtil.convertToStringForJSON(postedDate, request.getLocale())); + + comment.put("userFullName", StringEscapeUtils.escapeCsv(commentDto.getUserFullName())); + } + + comments.add(comment); + } + responseRow.set("comments", comments); + } + } + + rows.add(responseRow); + } + responcedata.set("rows", rows); + + res.setContentType("application/json;charset=utf-8"); + res.getWriter().print(new String(responcedata.toString())); + return null; + } + + private static Map removeNewLinesMap(Map map) { + Map newMap = new TreeMap(new QaStringComparator()); + + Iterator itMap = map.entrySet().iterator(); + while (itMap.hasNext()) { + Map.Entry pairs = (Map.Entry) itMap.next(); + String newText = ""; + if (pairs.getValue().toString() != null) { + newText = pairs.getValue().toString().replaceAll("\n", "
"); + } + newMap.put(pairs.getKey(), newText); + } + return newMap; + } + + private QaQueUsr getCurrentUser(String toolSessionID) { + + // get back login user DTO + HttpSession ss = SessionManager.getSession(); + UserDTO toolUser = (UserDTO) ss.getAttribute(AttributeNames.USER); + Long userId = new Long(toolUser.getUserID().longValue()); + + return qaService.getUserByIdAndSession(userId, new Long(toolSessionID)); + } + +} Index: lams_tool_laqa/src/java/org/lamsfoundation/lams/tool/qa/web/controller/QaLearningStarterController.java =================================================================== diff -u --- lams_tool_laqa/src/java/org/lamsfoundation/lams/tool/qa/web/controller/QaLearningStarterController.java (revision 0) +++ lams_tool_laqa/src/java/org/lamsfoundation/lams/tool/qa/web/controller/QaLearningStarterController.java (revision 6d9587c552af599d4fc4e68399d218f5f4ca7cf4) @@ -0,0 +1,457 @@ +/**************************************************************** + * Copyright (C) 2005 LAMS Foundation (http://lamsfoundation.org) + * ============================================================= + * License Information: http://lamsfoundation.org/licensing/lams/2.0/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + * USA + * + * http://www.gnu.org/licenses/gpl.txt + * **************************************************************** + */ + + +package org.lamsfoundation.lams.tool.qa.web.controller; + +import java.io.IOException; +import java.util.Date; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.TimeZone; +import java.util.TreeMap; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; + +import org.apache.log4j.Logger; +import org.apache.struts.Globals; +import org.apache.struts.action.Action; +import org.apache.struts.action.ActionForm; +import org.apache.struts.action.ActionForward; +import org.apache.struts.action.ActionMapping; +import org.apache.struts.action.ActionMessage; +import org.apache.struts.action.ActionMessages; +import org.lamsfoundation.lams.learning.web.bean.ActivityPositionDTO; +import org.lamsfoundation.lams.learning.web.util.LearningWebUtil; +import org.lamsfoundation.lams.notebook.model.NotebookEntry; +import org.lamsfoundation.lams.notebook.service.CoreNotebookConstants; +import org.lamsfoundation.lams.tool.ToolAccessMode; +import org.lamsfoundation.lams.tool.qa.QaAppConstants; +import org.lamsfoundation.lams.tool.qa.QaContent; +import org.lamsfoundation.lams.tool.qa.QaQueContent; +import org.lamsfoundation.lams.tool.qa.QaQueUsr; +import org.lamsfoundation.lams.tool.qa.QaSession; +import org.lamsfoundation.lams.tool.qa.dto.GeneralLearnerFlowDTO; +import org.lamsfoundation.lams.tool.qa.dto.QaQuestionDTO; +import org.lamsfoundation.lams.tool.qa.service.IQaService; +import org.lamsfoundation.lams.tool.qa.service.QaServiceProxy; +import org.lamsfoundation.lams.tool.qa.util.LearningUtil; +import org.lamsfoundation.lams.tool.qa.util.QaApplicationException; +import org.lamsfoundation.lams.tool.qa.util.QaComparator; +import org.lamsfoundation.lams.tool.qa.util.QaUtils; +import org.lamsfoundation.lams.tool.qa.web.form.QaLearningForm; +import org.lamsfoundation.lams.usermanagement.dto.UserDTO; +import org.lamsfoundation.lams.util.DateUtil; +import org.lamsfoundation.lams.util.MessageService; +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.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; + +/** + * This class is used to load the default content and initialize the presentation Map for Learner mode. + * It is important that ALL the session attributes created in this action gets removed by: + * QaUtils.cleanupSession(request) + * + * @author Ozgur Demirtas + * + */ +@Controller +@RequestMapping("/learningStarter") +public class QaLearningStarterController implements QaAppConstants { + private static Logger logger = Logger.getLogger(QaLearningStarterController.class.getName()); + + @Autowired + private IQaService qaService; + + @Autowired + @Qualifier("qaMessageService") + private MessageService messageService; + + @Override + public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) throws IOException, ServletException, QaApplicationException { + + QaUtils.cleanUpSessionAbsolute(request); + if (qaService == null) { + qaService = QaServiceProxy.getQaService(getServlet().getServletContext()); + } + + QaLearningForm qaLearningForm = (QaLearningForm) form; + /* validate learning mode parameters */ + validateParameters(request, mapping, qaLearningForm); + String mode = qaLearningForm.getMode(); + String toolSessionID = qaLearningForm.getToolSessionID(); + + /* + * By now, the passed tool session id MUST exist in the db by calling: + * public void createToolSession(Long toolSessionId, Long toolContentId) by the core. + * + * make sure this session exists in tool's session table by now. + */ + QaSession qaSession = qaService.getSessionById(new Long(toolSessionID).longValue()); + if (qaSession == null) { + QaUtils.cleanUpSessionAbsolute(request); + throw new ServletException("No session found"); + } + + QaContent qaContent = qaSession.getQaContent(); + if (qaContent == null) { + QaUtils.cleanUpSessionAbsolute(request); + throw new ServletException("No QA content found"); + } + + QaQueUsr user = null; + if ((mode != null) && mode.equals(ToolAccessMode.TEACHER.toString())) { + // monitoring mode - user is specified in URL + // assessmentUser may be null if the user was force completed. + user = getSpecifiedUser(toolSessionID, WebUtil.readIntParam(request, AttributeNames.PARAM_USER_ID, false)); + } else { + user = getCurrentUser(toolSessionID); + } + Long userId = user.getQueUsrId(); + qaLearningForm.setUserID(user.getQueUsrId().toString()); + + QaQueUsr groupLeader = null; + if (qaContent.isUseSelectLeaderToolOuput()) { + groupLeader = qaService.checkLeaderSelectToolForSessionLeader(user, new Long(toolSessionID).longValue()); + + // forwards to the leaderSelection page + if (groupLeader == null && !mode.equals(ToolAccessMode.TEACHER.toString())) { + + List groupUsers = qaService.getUsersBySessionId(new Long(toolSessionID).longValue()); + request.setAttribute(ATTR_GROUP_USERS, groupUsers); + request.setAttribute(TOOL_SESSION_ID, toolSessionID); + request.setAttribute(ATTR_CONTENT, qaContent); + + return mapping.findForward(WAIT_FOR_LEADER); + } + + // check if leader has submitted all answers + if (groupLeader.isResponseFinalized() && !mode.equals(ToolAccessMode.TEACHER.toString())) { + + // in case user joins the lesson after leader has answers some answers already - we need to make sure + // he has the same scratches as leader + qaService.copyAnswersFromLeader(user, groupLeader); + + user.setResponseFinalized(true); + qaService.updateUser(user); + } + } + + /* holds the question contents for a given tool session and relevant content */ + Map mapQuestionStrings = new TreeMap(new QaComparator()); + Map mapQuestions = new TreeMap(); + + String httpSessionID = qaLearningForm.getHttpSessionID(); + SessionMap sessionMap = httpSessionID == null ? null + : (SessionMap) request.getSession().getAttribute(httpSessionID); + if (sessionMap == null) { + sessionMap = new SessionMap(); + Map mapSequentialAnswers = new HashMap(); + sessionMap.put(MAP_SEQUENTIAL_ANSWERS_KEY, mapSequentialAnswers); + request.getSession().setAttribute(sessionMap.getSessionID(), sessionMap); + qaLearningForm.setHttpSessionID(sessionMap.getSessionID()); + + sessionMap.put(AttributeNames.ATTR_LEARNER_CONTENT_FOLDER, + qaService.getLearnerContentFolder(new Long(toolSessionID), user.getQueUsrId())); + } + String sessionMapId = sessionMap.getSessionID(); + sessionMap.put(IS_DISABLED, qaContent.isLockWhenFinished() && user.isLearnerFinished() + || (mode != null) && mode.equals(ToolAccessMode.TEACHER.toString())); + + sessionMap.put(ATTR_GROUP_LEADER, groupLeader); + boolean isUserLeader = qaService.isUserGroupLeader(user, new Long(toolSessionID)); + boolean lockWhenFinished = qaContent.isLockWhenFinished(); + sessionMap.put(ATTR_IS_USER_LEADER, isUserLeader); + sessionMap.put(AttributeNames.ATTR_MODE, mode); + sessionMap.put(ATTR_CONTENT, qaContent); + sessionMap.put(AttributeNames.USER, user); + + GeneralLearnerFlowDTO generalLearnerFlowDTO = LearningUtil.buildGeneralLearnerFlowDTO(qaService, qaContent); + generalLearnerFlowDTO.setUserUid(user.getQueUsrId().toString()); + generalLearnerFlowDTO.setHttpSessionID(sessionMapId); + generalLearnerFlowDTO.setToolSessionID(toolSessionID); + generalLearnerFlowDTO.setToolContentID(qaContent.getQaContentId().toString()); + generalLearnerFlowDTO.setReportTitleLearner(qaContent.getReportTitle()); + + generalLearnerFlowDTO.setLockWhenFinished(new Boolean(lockWhenFinished).toString()); + generalLearnerFlowDTO.setNoReeditAllowed(qaContent.isNoReeditAllowed()); + generalLearnerFlowDTO.setReflection(new Boolean(qaContent.isReflect()).toString()); + generalLearnerFlowDTO.setReflectionSubject(qaContent.getReflectionSubject()); + + NotebookEntry notebookEntry = qaService.getEntry(new Long(toolSessionID), CoreNotebookConstants.NOTEBOOK_TOOL, + MY_SIGNATURE, userId.intValue()); + if (notebookEntry != null) { + //String notebookEntryPresentable = QaUtils.replaceNewLines(notebookEntry.getEntry()); + qaLearningForm.setEntryText(notebookEntry.getEntry()); + generalLearnerFlowDTO.setNotebookEntry(notebookEntry.getEntry()); + } + + /* + * Is the tool activity been checked as Define Later in the property inspector? + */ + if (qaContent.isDefineLater()) { + QaUtils.cleanUpSessionAbsolute(request); + return (mapping.findForward(DEFINE_LATER)); + } + + ActivityPositionDTO activityPosition = LearningWebUtil.putActivityPositionInRequestByToolSessionId( + new Long(toolSessionID), request, getServlet().getServletContext()); + sessionMap.put(AttributeNames.ATTR_ACTIVITY_POSITION, activityPosition); + + /* + * fetch question content from content + */ + Iterator contentIterator = qaContent.getQaQueContents().iterator(); + while (contentIterator.hasNext()) { + QaQueContent qaQuestion = (QaQueContent) contentIterator.next(); + if (qaQuestion != null) { + int displayOrder = qaQuestion.getDisplayOrder(); + + if (displayOrder != 0) { + /* + * add the question to the questions Map in the displayOrder + */ + QaQuestionDTO questionDTO = new QaQuestionDTO(qaQuestion); + mapQuestions.put(displayOrder, questionDTO); + + mapQuestionStrings.put(new Integer(displayOrder).toString(), qaQuestion.getQuestion()); + + } + } + } + generalLearnerFlowDTO.setMapQuestions(mapQuestionStrings); + generalLearnerFlowDTO.setMapQuestionContentLearner(mapQuestions); + generalLearnerFlowDTO.setTotalQuestionCount(new Integer(mapQuestions.size())); + qaLearningForm.setTotalQuestionCount(new Integer(mapQuestions.size()).toString()); + + String feedBackType = ""; + if (qaContent.isQuestionsSequenced()) { + feedBackType = FEEDBACK_TYPE_SEQUENTIAL; + } else { + feedBackType = FEEDBACK_TYPE_COMBINED; + } + String userFeedback = feedBackType + generalLearnerFlowDTO.getTotalQuestionCount() + QUESTIONS; + generalLearnerFlowDTO.setUserFeedback(userFeedback); + + generalLearnerFlowDTO.setRemainingQuestionCount(generalLearnerFlowDTO.getTotalQuestionCount().toString()); + generalLearnerFlowDTO.setInitialScreen(new Boolean(true).toString()); + + request.setAttribute(GENERAL_LEARNER_FLOW_DTO, generalLearnerFlowDTO); + + /* + * by now, we know that the mode is either teacher or learner + * check if the mode is teacher and request is for Learner Progress + */ + if (mode.equals("teacher")) { + //start generating learner progress report for toolSessionID + + /* + * the report should have the all entries for the users in this tool session, + * and display under the "my answers" section the answers for the user id in the url + */ +// Long learnerProgressUserId = WebUtil.readLongParam(request, AttributeNames.PARAM_USER_ID, false); + generalLearnerFlowDTO.setRequestLearningReport(new Boolean(true).toString()); + generalLearnerFlowDTO.setRequestLearningReportProgress(new Boolean(true).toString()); + generalLearnerFlowDTO.setTeacherViewOnly(new Boolean(true).toString()); + + QaLearningAction.refreshSummaryData(request, qaContent, qaSession, qaService, sessionMapId, user, + generalLearnerFlowDTO); + request.setAttribute(QaAppConstants.GENERAL_LEARNER_FLOW_DTO, generalLearnerFlowDTO); + + return (mapping.findForward(LEARNER_REP)); + } + + //check if there is submission deadline + Date submissionDeadline = qaContent.getSubmissionDeadline(); + if (submissionDeadline != null) { + // store submission deadline to sessionMap + sessionMap.put(QaAppConstants.ATTR_SUBMISSION_DEADLINE, submissionDeadline); + + HttpSession ss = SessionManager.getSession(); + UserDTO learnerDto = (UserDTO) ss.getAttribute(AttributeNames.USER); + TimeZone learnerTimeZone = learnerDto.getTimeZone(); + Date tzSubmissionDeadline = DateUtil.convertToTimeZoneFromDefault(learnerTimeZone, submissionDeadline); + Date currentLearnerDate = DateUtil.convertToTimeZoneFromDefault(learnerTimeZone, new Date()); + + // calculate whether submission deadline has passed, and if so forward to "submissionDeadline" + if (currentLearnerDate.after(tzSubmissionDeadline)) { + + //if ShowOtherAnswersAfterDeadline is enabled - show others answers + if (qaContent.isShowOtherAnswersAfterDeadline()) { + generalLearnerFlowDTO.setLockWhenFinished(Boolean.TRUE.toString()); + generalLearnerFlowDTO.setNoReeditAllowed(true); + //only for ActionForward refreshAllResults(..) method + sessionMap.put("noRefresh", true); + /* + * the report should have all the users' entries OR the report should have only the current + * session's entries + */ + generalLearnerFlowDTO.setRequestLearningReport(new Boolean(true).toString()); + + QaLearningAction.refreshSummaryData(request, qaContent, qaSession, qaService, sessionMapId, user, + generalLearnerFlowDTO); + + if (user.isLearnerFinished()) { + generalLearnerFlowDTO.setRequestLearningReportViewOnly(new Boolean(true).toString()); + return (mapping.findForward(REVISITED_LEARNER_REP)); + } else { + generalLearnerFlowDTO.setRequestLearningReportViewOnly(new Boolean(false).toString()); + return (mapping.findForward(LEARNER_REP)); + } + + // show submissionDeadline page otherwise + } else { + return mapping.findForward("submissionDeadline"); + } + } + } + + /* + * Verify that userId does not already exist in the db. + * If it does exist and the passed tool session id exists in the db, that means the user already responded to + * the content and + * his answers must be displayed read-only + * + * if the user's tool session id AND user id exists in the tool tables go to learner's report. + */ + /* + * if the 'All Responses' has been clicked no more user entry is accepted, and isResponseFinalized() returns + * true + */ + Long currentToolSessionID = new Long(qaLearningForm.getToolSessionID()); + + //if Response is Finalized + if (user.isResponseFinalized()) { + QaSession checkSession = user.getQaSession(); + + if (checkSession != null) { + Long checkQaSessionId = checkSession.getQaSessionId(); + + if (checkQaSessionId.toString().equals(currentToolSessionID.toString())) { + + // the learner is in the same session and has already responsed to this content + + generalLearnerFlowDTO.setLockWhenFinished(new Boolean(qaContent.isLockWhenFinished()).toString()); + generalLearnerFlowDTO.setNoReeditAllowed(qaContent.isNoReeditAllowed()); + /* + * the report should have all the users' entries OR the report should have only the current + * session's entries + */ + generalLearnerFlowDTO.setRequestLearningReport(new Boolean(true).toString()); + + QaLearningAction.refreshSummaryData(request, qaContent, qaSession, qaService, sessionMapId, user, + generalLearnerFlowDTO); + + if (user.isLearnerFinished()) { + generalLearnerFlowDTO.setRequestLearningReportViewOnly(new Boolean(true).toString()); + return (mapping.findForward(REVISITED_LEARNER_REP)); + } else { + generalLearnerFlowDTO.setRequestLearningReportViewOnly(new Boolean(false).toString()); + return (mapping.findForward(LEARNER_REP)); + } + } + } + } + + //**---- showing AnswersContent.jsp ----** + LearningUtil.populateAnswers(sessionMap, qaContent, user, mapQuestions, generalLearnerFlowDTO, qaService); + + return (mapping.findForward(LOAD_LEARNER)); + } + + /** + * validates the learning mode parameters + * + * @param request + * @param mapping + * @return ActionForward + */ + protected void validateParameters(HttpServletRequest request, ActionMapping mapping, + QaLearningForm qaLearningForm) { + /* + * process incoming tool session id and later derive toolContentId from it. + */ + String strToolSessionId = request.getParameter(AttributeNames.PARAM_TOOL_SESSION_ID); + long toolSessionId = 0; + if ((strToolSessionId == null) || (strToolSessionId.length() == 0)) { + ActionMessages errors = new ActionMessages(); + errors.add(Globals.ERROR_KEY, new ActionMessage("error.toolSessionId.required")); + logger.error("error.toolSessionId.required"); + saveErrors(request, errors); + return; + } else { + try { + toolSessionId = new Long(strToolSessionId).longValue(); + qaLearningForm.setToolSessionID(new Long(toolSessionId).toString()); + } catch (NumberFormatException e) { + logger.error("add error.sessionId.numberFormatException to ActionMessages."); + return; + } + } + + /* mode can be learner, teacher or author */ + String mode = request.getParameter(MODE); + if ((mode == null) || (mode.length() == 0)) { + logger.error("Mode is empty"); + return; + } + if ((!mode.equals("learner")) && (!mode.equals("teacher")) && (!mode.equals("author"))) { + logger.error("Wrong mode"); + return; + } + qaLearningForm.setMode(mode); + } + + private QaQueUsr getCurrentUser(String toolSessionId) { + // get back login user DTO + HttpSession ss = SessionManager.getSession(); + UserDTO toolUser = (UserDTO) ss.getAttribute(AttributeNames.USER); + Integer userId = toolUser.getUserID(); + + QaQueUsr qaUser = qaService.getUserByIdAndSession(userId.longValue(), new Long(toolSessionId)); + if (qaUser == null) { + qaUser = qaService.createUser(new Long(toolSessionId), userId); + } + + return qaUser; + } + + private QaQueUsr getSpecifiedUser(String toolSessionId, Integer userId) { + QaQueUsr qaUser = qaService.getUserByIdAndSession(userId.longValue(), new Long(toolSessionId)); + if (qaUser == null) { + qaUser = qaService.createUser(new Long(toolSessionId), userId); + } + return qaUser; + } +} \ No newline at end of file Index: lams_tool_laqa/src/java/org/lamsfoundation/lams/tool/qa/web/controller/QaMonitoringController.java =================================================================== diff -u --- lams_tool_laqa/src/java/org/lamsfoundation/lams/tool/qa/web/controller/QaMonitoringController.java (revision 0) +++ lams_tool_laqa/src/java/org/lamsfoundation/lams/tool/qa/web/controller/QaMonitoringController.java (revision 6d9587c552af599d4fc4e68399d218f5f4ca7cf4) @@ -0,0 +1,314 @@ +/*************************************************************************** +Copyright (C) 2005 LAMS Foundation (http://lamsfoundation.org) +License Information: http://lamsfoundation.org/licensing/lams/2.0/ + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License version 2 as +published by the Free Software Foundation. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 +USA + +http://www.gnu.org/licenses/gpl.txt + * ***********************************************************************/ + +package org.lamsfoundation.lams.tool.qa.web.controller; + +import java.io.IOException; +import java.util.Collection; +import java.util.Date; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.TimeZone; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; + +import org.apache.struts.action.ActionForm; +import org.apache.struts.action.ActionMapping; +import org.lamsfoundation.lams.rating.dto.ItemRatingDTO; +import org.lamsfoundation.lams.rating.dto.RatingCommentDTO; +import org.lamsfoundation.lams.rating.model.LearnerItemRatingCriteria; +import org.lamsfoundation.lams.tool.exception.ToolException; +import org.lamsfoundation.lams.tool.qa.QaAppConstants; +import org.lamsfoundation.lams.tool.qa.QaContent; +import org.lamsfoundation.lams.tool.qa.QaQueContent; +import org.lamsfoundation.lams.tool.qa.QaSession; +import org.lamsfoundation.lams.tool.qa.QaUsrResp; +import org.lamsfoundation.lams.tool.qa.dto.QaQuestionDTO; +import org.lamsfoundation.lams.tool.qa.service.IQaService; +import org.lamsfoundation.lams.tool.qa.service.QaServiceProxy; +import org.lamsfoundation.lams.usermanagement.dto.UserDTO; +import org.lamsfoundation.lams.util.DateUtil; +import org.lamsfoundation.lams.util.WebUtil; +import org.lamsfoundation.lams.web.session.SessionManager; +import org.lamsfoundation.lams.web.util.AttributeNames; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.MediaType; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.context.WebApplicationContext; +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; + +/** + * @author Ozgur Demirtas + */ +@Controller +@RequestMapping("/monitoring") +public class QaMonitoringController implements QaAppConstants { + + @Autowired + private IQaService qaService; + + @Autowired + private WebApplicationContext applicationContext; + + @RequestMapping("/") + public String unspecified() throws IOException, ServletException, ToolException { + return null; + } + + @RequestMapping("/updateResponse") + public String updateResponse(HttpServletRequest request) throws IOException, ServletException { + + Long responseUid = WebUtil.readLongParam(request, QaAppConstants.RESPONSE_UID); + String updatedResponse = request.getParameter("updatedResponse"); + QaUsrResp qaUsrResp = qaService.getResponseById(responseUid); + + /* + * write out the audit log entry. If you move this after the update of the response, then make sure you update + * the audit call to use a copy of the original answer + */ + Long toolContentId = null; + if (qaUsrResp.getQaQuestion() != null && qaUsrResp.getQaQuestion().getQaContent() != null) { + toolContentId = qaUsrResp.getQaQuestion().getQaContent().getQaContentId(); + } + qaService.getLogEventService().logChangeLearnerContent(qaUsrResp.getQaQueUser().getQueUsrId(), + qaUsrResp.getQaQueUser().getUsername(), toolContentId, qaUsrResp.getAnswer(), updatedResponse); + + qaUsrResp.setAnswer(updatedResponse); + qaService.updateUserResponse(qaUsrResp); + + return null; + } + + @RequestMapping("/updateResponseVisibility") + public String updateResponseVisibility(HttpServletRequest request) + throws IOException, ServletException, ToolException { + + Long responseUid = WebUtil.readLongParam(request, QaAppConstants.RESPONSE_UID); + boolean isHideItem = WebUtil.readBooleanParam(request, QaAppConstants.IS_HIDE_ITEM); + qaService.updateResponseVisibility(responseUid, isHideItem); + + return null; + } + + /** + * Set Submission Deadline + * + * @param mapping + * @param form + * @param request + * @param response + * @return + * @throws IOException + */ + @RequestMapping("/setSubmissionDeadline") + public String setSubmissionDeadline(HttpServletRequest request, HttpServletResponse response) throws IOException { + + Long contentID = WebUtil.readLongParam(request, AttributeNames.PARAM_TOOL_CONTENT_ID); + QaContent content = qaService.getQaContent(contentID); + + Long dateParameter = WebUtil.readLongParam(request, QaAppConstants.ATTR_SUBMISSION_DEADLINE, true); + Date tzSubmissionDeadline = null; + String formattedDate = ""; + if (dateParameter != null) { + Date submissionDeadline = new Date(dateParameter); + HttpSession ss = SessionManager.getSession(); + UserDTO teacher = (UserDTO) ss.getAttribute(AttributeNames.USER); + TimeZone teacherTimeZone = teacher.getTimeZone(); + tzSubmissionDeadline = DateUtil.convertFromTimeZoneToDefault(teacherTimeZone, submissionDeadline); + formattedDate = DateUtil.convertToStringForJSON(tzSubmissionDeadline, request.getLocale()); + } else { + //set showOtherAnswersAfterDeadline to false + content.setShowOtherAnswersAfterDeadline(false); + } + content.setSubmissionDeadline(tzSubmissionDeadline); + qaService.saveOrUpdateQaContent(content); + + response.setContentType("text/plain;charset=utf-8"); + response.getWriter().print(formattedDate); + return null; + } + + /** + * Set Submission Deadline + * + * @param mapping + * @param form + * @param request + * @param response + * @return + */ + @RequestMapping("/setShowOtherAnswersAfterDeadline") + public String setShowOtherAnswersAfterDeadline(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) { + + Long contentID = WebUtil.readLongParam(request, AttributeNames.PARAM_TOOL_CONTENT_ID); + QaContent content = qaService.getQaContent(contentID); + + boolean showOtherAnswersAfterDeadline = WebUtil.readBooleanParam(request, + QaAppConstants.PARAM_SHOW_OTHER_ANSWERS_AFTER_DEADLINE); + content.setShowOtherAnswersAfterDeadline(showOtherAnswersAfterDeadline); + qaService.saveOrUpdateQaContent(content); + + return null; + } + + private IQaService getQAService() { + return QaServiceProxy.getQaService(applicationContext.getServletContext()); + } + + /** + * Get Paged Reflections + * + * @param request + * @return + */ + @RequestMapping(path = "/getReflectionsJSON", produces = MediaType.APPLICATION_JSON_UTF8_VALUE) + @ResponseBody + public String getReflectionsJSON(HttpServletRequest request) throws IOException, ServletException, ToolException { + + Long toolSessionId = WebUtil.readLongParam(request, QaAppConstants.TOOL_SESSION_ID); + + // paging parameters of tablesorter + int size = WebUtil.readIntParam(request, "size"); + int page = WebUtil.readIntParam(request, "page"); + Integer sortByName = WebUtil.readIntParam(request, "column[0]", true); + String searchString = request.getParameter("fcol[0]"); + + int sorting = QaAppConstants.SORT_BY_NO; + if (sortByName != null) { + sorting = sortByName.equals(0) ? QaAppConstants.SORT_BY_USERNAME_ASC : QaAppConstants.SORT_BY_USERNAME_DESC; + } + + //return user list according to the given sessionID + IQaService qaService = getQAService(); + List users = qaService.getUserReflectionsForTablesorter(toolSessionId, page, size, sorting, + searchString); + + ArrayNode rows = JsonNodeFactory.instance.arrayNode(); + ObjectNode responsedata = JsonNodeFactory.instance.objectNode(); + responsedata.put("total_rows", qaService.getCountUsersBySessionWithSearch(toolSessionId, searchString)); + + for (Object[] userAndReflection : users) { + ObjectNode responseRow = JsonNodeFactory.instance.objectNode(); + responseRow.put("username", HtmlUtils.htmlEscape((String) userAndReflection[1])); + if (userAndReflection.length > 2 && userAndReflection[2] != null) { + String reflection = HtmlUtils.htmlEscape((String) userAndReflection[2]); + responseRow.put(QaAppConstants.NOTEBOOK, reflection.replaceAll("\n", "
")); + } + rows.add(responseRow); + } + responsedata.set("rows", rows); + return responsedata.toString(); + } + + /** + * Start to download the page that has an HTML version of the answers. Calls answersDownload + * which forwards to the jsp to download the file. + * + * @throws ServletException + */ + @RequestMapping("/getPrintAnswers") + public String getPrintAnswers(HttpServletRequest request) throws ServletException { + + Long allUserIdValue = -1L; + + Long toolSessionID = WebUtil.readLongParam(request, AttributeNames.PARAM_TOOL_SESSION_ID); + QaSession qaSession = qaService.getSessionById(toolSessionID); + QaContent qaContent = qaSession.getQaContent(); + + Long questionUid = WebUtil.readLongParam(request, "questionUid"); + QaQueContent question = null; + for (QaQueContent check : qaContent.getQaQueContents()) { + if (check.getUid().equals(questionUid)) { + question = check; + break; + } + } + + if (question == null) { + log.error("Cannot display printable answers as we cannot find question details for toolSessionId " + + toolSessionID + " questionUid " + questionUid); + throw new ServletException("Question details missing."); + } + + QaQuestionDTO questionDTO = new QaQuestionDTO(question); + request.setAttribute(QaAppConstants.QUESTION_DTO, questionDTO); + + List responses = qaService.getResponsesForTablesorter(qaContent.getQaContentId(), toolSessionID, + questionUid, allUserIdValue, qaContent.isUseSelectLeaderToolOuput(), 1, 0, + QaAppConstants.SORT_BY_USERNAME_ASC, null); + request.setAttribute(QaAppConstants.RESPONSES, responses); + request.setAttribute(QaAppConstants.ATTR_CONTENT, qaContent); + + boolean isAllowRateAnswers = qaContent.isAllowRateAnswers(); + boolean isCommentsEnabled = false; + if (isAllowRateAnswers) { + Set criterias = qaContent.getRatingCriterias(); + for (LearnerItemRatingCriteria criteria : criterias) { + if (criteria.isCommentRating()) { + isCommentsEnabled = true; + break; + } + } + } + request.setAttribute("isCommentsEnabled", isCommentsEnabled); + + // handle rating criterias - even though we may have searched on ratings earlier we can't use the average ratings + // calculated as they may have been averages over more than one criteria. + Map criteriaMap = null; + Map> commentMap = null; + if (isAllowRateAnswers && !responses.isEmpty()) { + //create itemIds list + List itemIds = new LinkedList<>(); + for (QaUsrResp usrResponse : responses) { + itemIds.add(usrResponse.getResponseId()); + } + List itemRatingDtos = qaService.getRatingCriteriaDtos(qaContent.getQaContentId(), + toolSessionID, itemIds, true, allUserIdValue); + if (itemRatingDtos.size() > 0) { + criteriaMap = new HashMap<>(); + commentMap = new HashMap<>(); + for (ItemRatingDTO itemRatingDto : itemRatingDtos) { + criteriaMap.put(itemRatingDto.getItemId(), itemRatingDto.getCriteriaDtos()); + commentMap.put(itemRatingDto.getItemId(), itemRatingDto.getCommentDtos()); + } + } + } + request.setAttribute("criteriaMap", criteriaMap); + request.setAttribute("commentMap", commentMap); + request.setAttribute(QaAppConstants.ATTR_CONTENT, qaContent); + + return "monitoring/PrintAnswers"; + } + +} \ No newline at end of file Index: lams_tool_laqa/src/java/org/lamsfoundation/lams/tool/qa/web/controller/QaMonitoringStarterController.java =================================================================== diff -u --- lams_tool_laqa/src/java/org/lamsfoundation/lams/tool/qa/web/controller/QaMonitoringStarterController.java (revision 0) +++ lams_tool_laqa/src/java/org/lamsfoundation/lams/tool/qa/web/controller/QaMonitoringStarterController.java (revision 6d9587c552af599d4fc4e68399d218f5f4ca7cf4) @@ -0,0 +1,224 @@ +/**************************************************************** + * Copyright (C) 2005 LAMS Foundation (http://lamsfoundation.org) + * ============================================================= + * License Information: http://lamsfoundation.org/licensing/lams/2.0/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + * USA + * + * http://www.gnu.org/licenses/gpl.txt + * **************************************************************** + */ + + +package org.lamsfoundation.lams.tool.qa.web.controller; + +import java.io.IOException; +import java.util.Date; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.Set; +import java.util.TimeZone; +import java.util.TreeSet; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; + +import org.apache.log4j.Logger; +import org.apache.struts.action.Action; +import org.apache.struts.action.ActionForm; +import org.apache.struts.action.ActionForward; +import org.apache.struts.action.ActionMapping; +import org.lamsfoundation.lams.tool.qa.QaAppConstants; +import org.lamsfoundation.lams.tool.qa.QaContent; +import org.lamsfoundation.lams.tool.qa.QaQueContent; +import org.lamsfoundation.lams.tool.qa.QaQueUsr; +import org.lamsfoundation.lams.tool.qa.QaSession; +import org.lamsfoundation.lams.tool.qa.dto.GroupDTO; +import org.lamsfoundation.lams.tool.qa.dto.QaQuestionDTO; +import org.lamsfoundation.lams.tool.qa.dto.QaStatsDTO; +import org.lamsfoundation.lams.tool.qa.service.IQaService; +import org.lamsfoundation.lams.tool.qa.service.QaServiceProxy; +import org.lamsfoundation.lams.tool.qa.util.QaApplicationException; +import org.lamsfoundation.lams.tool.qa.util.QaSessionComparator; +import org.lamsfoundation.lams.tool.qa.util.QaUtils; +import org.lamsfoundation.lams.tool.qa.web.form.QaMonitoringForm; +import org.lamsfoundation.lams.usermanagement.dto.UserDTO; +import org.lamsfoundation.lams.util.DateUtil; +import org.lamsfoundation.lams.util.WebUtil; +import org.lamsfoundation.lams.web.session.SessionManager; +import org.lamsfoundation.lams.web.util.AttributeNames; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; + +/** + * Starts up the monitoring module + * + * @author Ozgur Demirtas + */ +@Controller +@RequestMapping("/monitoringStarter") +public class QaMonitoringStarterController implements QaAppConstants { + private static Logger logger = Logger.getLogger(QaMonitoringStarterController.class.getName()); + + @Override + public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) throws IOException, ServletException, QaApplicationException { + QaUtils.cleanUpSessionAbsolute(request); + + QaMonitoringForm qaMonitoringForm = (QaMonitoringForm) form; + + IQaService qaService = QaServiceProxy.getQaService(getServlet().getServletContext()); + + String contentFolderID = WebUtil.readStrParam(request, AttributeNames.PARAM_CONTENT_FOLDER_ID); + qaMonitoringForm.setContentFolderID(contentFolderID); + + ActionForward validateParameters = validateParameters(request, mapping, qaMonitoringForm); + if (validateParameters != null) { + return validateParameters; + } + + String toolContentID = qaMonitoringForm.getToolContentID(); + QaContent qaContent = qaService.getQaContent(new Long(toolContentID).longValue()); + if (qaContent == null) { + QaUtils.cleanUpSessionAbsolute(request); + throw new ServletException("Data not initialised in Monitoring"); + } + + qaMonitoringForm.setCurrentTab("1"); + + String strToolContentID = request.getParameter(AttributeNames.PARAM_TOOL_CONTENT_ID); + qaMonitoringForm.setToolContentID(strToolContentID); + + /* this section is related to summary tab. Starts here. */ +// SessionMap sessionMap = new SessionMap(); +// sessionMap.put(ACTIVITY_TITLE_KEY, qaContent.getTitle()); +// sessionMap.put(ACTIVITY_INSTRUCTIONS_KEY, qaContent.getInstructions()); +// +// qaMonitoringForm.setHttpSessionID(sessionMap.getSessionID()); +// request.getSession().setAttribute(sessionMap.getSessionID(), sessionMap); + + List questionDTOs = new LinkedList(); + for (QaQueContent question : qaContent.getQaQueContents()) { + QaQuestionDTO questionDTO = new QaQuestionDTO(question); + questionDTOs.add(questionDTO); + } + request.setAttribute(LIST_QUESTION_DTOS, questionDTOs); +// sessionMap.put(LIST_QUESTION_DTOS, questionDTOs); +// request.setAttribute(TOTAL_QUESTION_COUNT, new Integer(questionDTOs.size())); + + //session dto list + List groupDTOs = new LinkedList(); + Set sessions = new TreeSet(new QaSessionComparator()); + sessions.addAll(qaContent.getQaSessions()); + for (QaSession session : sessions) { + String sessionId = session.getQaSessionId().toString(); + String sessionName = session.getSession_name(); + + GroupDTO groupDTO = new GroupDTO(); + groupDTO.setSessionName(sessionName); + groupDTO.setSessionId(sessionId); + groupDTOs.add(groupDTO); + } + request.setAttribute(LIST_ALL_GROUPS_DTO, groupDTOs); + + // setting up the advanced summary for LDEV-1662 + request.setAttribute(QaAppConstants.ATTR_CONTENT, qaContent); + + boolean isGroupedActivity = qaService.isGroupedActivity(qaContent.getQaContentId()); + request.setAttribute("isGroupedActivity", isGroupedActivity); + + //ratings stuff + boolean isRatingsEnabled = qaService.isRatingsEnabled(qaContent); + request.setAttribute("isRatingsEnabled", isRatingsEnabled); + + //comments stuff + boolean isCommentsEnabled = qaService.isCommentsEnabled(qaContent.getQaContentId()); + request.setAttribute("isCommentsEnabled", isCommentsEnabled); + + //buildQaStatsDTO + QaStatsDTO qaStatsDTO = new QaStatsDTO(); + int countSessionComplete = 0; + int countAllUsers = 0; + Iterator iteratorSession = qaContent.getQaSessions().iterator(); + while (iteratorSession.hasNext()) { + QaSession qaSession = (QaSession) iteratorSession.next(); + + if (qaSession != null) { + + if (qaSession.getSession_status().equals(COMPLETED)) { + ++countSessionComplete; + } + + Iterator iteratorUser = qaSession.getQaQueUsers().iterator(); + while (iteratorUser.hasNext()) { + QaQueUsr qaQueUsr = (QaQueUsr) iteratorUser.next(); + + if (qaQueUsr != null) { + ++countAllUsers; + } + } + } + } + qaStatsDTO.setCountAllUsers(new Integer(countAllUsers).toString()); + qaStatsDTO.setCountSessionComplete(new Integer(countSessionComplete).toString()); + request.setAttribute(QA_STATS_DTO, qaStatsDTO); + + // set SubmissionDeadline, if any + if (qaContent.getSubmissionDeadline() != null) { + Date submissionDeadline = qaContent.getSubmissionDeadline(); + HttpSession ss = SessionManager.getSession(); + UserDTO teacher = (UserDTO) ss.getAttribute(AttributeNames.USER); + TimeZone teacherTimeZone = teacher.getTimeZone(); + Date tzSubmissionDeadline = DateUtil.convertToTimeZoneFromDefault(teacherTimeZone, submissionDeadline); + request.setAttribute(QaAppConstants.ATTR_SUBMISSION_DEADLINE, tzSubmissionDeadline.getTime()); + // use the unconverted time, as convertToStringForJSON() does the timezone conversion if needed + request.setAttribute(QaAppConstants.ATTR_SUBMISSION_DEADLINE_DATESTRING, DateUtil.convertToStringForJSON(submissionDeadline, request.getLocale())); + } + + return (mapping.findForward(LOAD_MONITORING)); + } + + /** + * validates request paramaters based on tool contract + * + * @param request + * @param mapping + * @return ActionForward + * @throws ServletException + */ + protected ActionForward validateParameters(HttpServletRequest request, ActionMapping mapping, + QaMonitoringForm qaMonitoringForm) throws ServletException { + + String strToolContentId = request.getParameter(AttributeNames.PARAM_TOOL_CONTENT_ID); + + if ((strToolContentId == null) || (strToolContentId.length() == 0)) { + QaUtils.cleanUpSessionAbsolute(request); + throw new ServletException("No Tool Content ID found"); + } else { + try { + long toolContentId = new Long(strToolContentId).longValue(); + + qaMonitoringForm.setToolContentID(new Long(toolContentId).toString()); + } catch (NumberFormatException e) { + QaUtils.cleanUpSessionAbsolute(request); + throw e; + } + } + return null; + } +} Index: lams_tool_laqa/src/java/org/lamsfoundation/lams/tool/qa/web/controller/QaPedagogicalPlannerController.java =================================================================== diff -u --- lams_tool_laqa/src/java/org/lamsfoundation/lams/tool/qa/web/controller/QaPedagogicalPlannerController.java (revision 0) +++ lams_tool_laqa/src/java/org/lamsfoundation/lams/tool/qa/web/controller/QaPedagogicalPlannerController.java (revision 6d9587c552af599d4fc4e68399d218f5f4ca7cf4) @@ -0,0 +1,123 @@ +/**************************************************************** + * Copyright (C) 2005 LAMS Foundation (http://lamsfoundation.org) + * ============================================================= + * License Information: http://lamsfoundation.org/licensing/lams/2.0/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + * USA + * + * http://www.gnu.org/licenses/gpl.txt + * **************************************************************** + */ + +package org.lamsfoundation.lams.tool.qa.web.controller; + +import java.io.IOException; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.lang.StringUtils; +import org.lamsfoundation.lams.tool.qa.QaContent; +import org.lamsfoundation.lams.tool.qa.QaQueContent; +import org.lamsfoundation.lams.tool.qa.service.IQaService; +import org.lamsfoundation.lams.tool.qa.web.form.QaPedagogicalPlannerForm; +import org.lamsfoundation.lams.util.WebUtil; +import org.lamsfoundation.lams.web.util.AttributeNames; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.util.MultiValueMap; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; + +@Controller +@RequestMapping("/pedagogicalPlanner") +public class QaPedagogicalPlannerController { + + @Autowired + private IQaService qaService; + + @RequestMapping("/") + protected String unspecified(QaPedagogicalPlannerForm pedagogicalPlannerForm, HttpServletRequest request, + HttpServletResponse response) { + return initPedagogicalPlannerForm(pedagogicalPlannerForm, request); + } + + @RequestMapping("/initPedagogicalPlannerForm") + public String initPedagogicalPlannerForm(QaPedagogicalPlannerForm pedagogicalPlannerForm, + HttpServletRequest request) { + Long toolContentID = WebUtil.readLongParam(request, AttributeNames.PARAM_TOOL_CONTENT_ID); + QaContent qaContent = qaService.getQaContent(toolContentID); + pedagogicalPlannerForm.fillForm(qaContent); + String contentFolderId = WebUtil.readStrParam(request, AttributeNames.PARAM_CONTENT_FOLDER_ID); + pedagogicalPlannerForm.setContentFolderID(contentFolderId); + return "authoring/pedagogicalPlannerForm"; + } + + @RequestMapping(value = "/saveOrUpdatePedagogicalPlannerForm", method = RequestMethod.POST) + public String saveOrUpdatePedagogicalPlannerForm(QaPedagogicalPlannerForm pedagogicalPlannerForm, + HttpServletRequest request) throws IOException { + + MultiValueMap errorMap = pedagogicalPlannerForm.validate(); + if (errorMap.isEmpty()) { + + QaContent qaContent = qaService.getQaContent(pedagogicalPlannerForm.getToolContentID()); + + int questionIndex = 0; + String question = null; + + do { + question = pedagogicalPlannerForm.getQuestion(questionIndex); + if (StringUtils.isEmpty(question)) { + pedagogicalPlannerForm.removeQuestion(questionIndex); + } else { + if (questionIndex < qaContent.getQaQueContents().size()) { + QaQueContent qaQuestion = qaService + .getQuestionByContentAndDisplayOrder((long) questionIndex + 1, qaContent.getUid()); + qaQuestion.setQuestion(question); + qaService.saveOrUpdateQuestion(qaQuestion); + + } else { + QaQueContent qaQuestion = new QaQueContent(); + qaQuestion.setDisplayOrder(questionIndex + 1); + qaQuestion.setRequired(false); + qaQuestion.setQaContent(qaContent); + qaQuestion.setQuestion(question); + qaService.saveOrUpdateQuestion(qaQuestion); + } + questionIndex++; + } + } while (question != null); + if (questionIndex < qaContent.getQaQueContents().size()) { + qaService.removeQuestionsFromCache(qaContent); + qaService.removeQaContentFromCache(qaContent); + for (; questionIndex < qaContent.getQaQueContents().size(); questionIndex++) { + QaQueContent qaQuestion = qaService.getQuestionByContentAndDisplayOrder((long) questionIndex + 1, + qaContent.getUid()); + qaService.removeQuestion(qaQuestion); + } + } + } else { + request.setAttribute("errorMap", errorMap); + } + return "authoring/pedagogicalPlannerForm"; + } + + @RequestMapping("/createPedagogicalPlannerQuestion") + public String createPedagogicalPlannerQuestion(QaPedagogicalPlannerForm pedagogicalPlannerForm) { + pedagogicalPlannerForm.setQuestion(pedagogicalPlannerForm.getQuestionCount().intValue(), ""); + return "authoring/pedagogicalPlannerForm"; + } + +} \ No newline at end of file Index: lams_tool_laqa/src/java/org/lamsfoundation/lams/tool/qa/web/controller/QaStarterController.java =================================================================== diff -u --- lams_tool_laqa/src/java/org/lamsfoundation/lams/tool/qa/web/controller/QaStarterController.java (revision 0) +++ lams_tool_laqa/src/java/org/lamsfoundation/lams/tool/qa/web/controller/QaStarterController.java (revision 6d9587c552af599d4fc4e68399d218f5f4ca7cf4) @@ -0,0 +1,285 @@ +/**************************************************************** + * Copyright (C) 2005 LAMS Foundation (http://lamsfoundation.org) + * ============================================================= + * License Information: http://lamsfoundation.org/licensing/lams/2.0/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + * USA + * + * http://www.gnu.org/licenses/gpl.txt + * **************************************************************** + */ + +package org.lamsfoundation.lams.tool.qa.web.controller; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.SortedSet; +import java.util.TreeSet; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.log4j.Logger; +import org.apache.struts.Globals; +import org.apache.struts.action.ActionForm; +import org.apache.struts.action.ActionForward; +import org.apache.struts.action.ActionMapping; +import org.apache.struts.action.ActionMessage; +import org.apache.struts.action.ActionMessages; +import org.lamsfoundation.lams.learningdesign.TextSearchConditionComparator; +import org.lamsfoundation.lams.rating.model.RatingCriteria; +import org.lamsfoundation.lams.tool.ToolAccessMode; +import org.lamsfoundation.lams.tool.qa.QaAppConstants; +import org.lamsfoundation.lams.tool.qa.QaCondition; +import org.lamsfoundation.lams.tool.qa.QaContent; +import org.lamsfoundation.lams.tool.qa.QaQueContent; +import org.lamsfoundation.lams.tool.qa.dto.QaQuestionDTO; +import org.lamsfoundation.lams.tool.qa.service.IQaService; +import org.lamsfoundation.lams.tool.qa.service.QaServiceProxy; +import org.lamsfoundation.lams.tool.qa.util.QaApplicationException; +import org.lamsfoundation.lams.tool.qa.util.QaUtils; +import org.lamsfoundation.lams.tool.qa.web.form.QaAuthoringForm; +import org.lamsfoundation.lams.util.WebUtil; +import org.lamsfoundation.lams.web.util.AttributeNames; +import org.lamsfoundation.lams.web.util.SessionMap; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; + +/** + * Initializes the tool's authoring mode + * + * @author Ozgur Demirtas + */ +@Controller +@RequestMapping("/authoringStarter") +public class QaStarterController implements QaAppConstants { + private static Logger logger = Logger.getLogger(QaStarterController.class.getName()); + + @Override + public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) throws IOException, ServletException, QaApplicationException { + + QaUtils.cleanUpSessionAbsolute(request); + QaAuthoringForm qaAuthoringForm = (QaAuthoringForm) form; + + String contentFolderID = WebUtil.readStrParam(request, AttributeNames.PARAM_CONTENT_FOLDER_ID); + qaAuthoringForm.setContentFolderID(contentFolderID); + + qaAuthoringForm.resetRadioBoxes(); + + IQaService qaService = null; + if (getServlet() == null || getServlet().getServletContext() == null) { + qaService = qaAuthoringForm.getQaService(); + } else { + qaService = QaServiceProxy.getQaService(getServlet().getServletContext()); + } + + validateDefaultContent(request, mapping, qaService, qaAuthoringForm); + + //no problems getting the default content, will render authoring screen + String strToolContentID = ""; + /* the authoring url must be passed a tool content id */ + strToolContentID = request.getParameter(AttributeNames.PARAM_TOOL_CONTENT_ID); + qaAuthoringForm.setToolContentID(strToolContentID); + + SessionMap sessionMap = new SessionMap<>(); + sessionMap.put(QaAppConstants.ACTIVITY_TITLE_KEY, ""); + sessionMap.put(QaAppConstants.ACTIVITY_INSTRUCTIONS_KEY, ""); + sessionMap.put(AttributeNames.PARAM_CONTENT_FOLDER_ID, contentFolderID); + qaAuthoringForm.setHttpSessionID(sessionMap.getSessionID()); + + if (strToolContentID == null || strToolContentID.equals("")) { + QaUtils.cleanUpSessionAbsolute(request); + throw new ServletException("No Tool Content ID found"); + } + + QaContent qaContent = qaService.getQaContent(new Long(strToolContentID).longValue()); + if (qaContent == null) { + /* fetch default content */ + long defaultContentID = qaService.getToolDefaultContentIdBySignature(QaAppConstants.MY_SIGNATURE); + qaContent = qaService.getQaContent(defaultContentID); + qaContent = QaContent.newInstance(qaContent, new Long(strToolContentID)); + } + + prepareDTOandForm(request, qaAuthoringForm, qaContent, qaService, sessionMap); + + ToolAccessMode mode = WebUtil.readToolAccessModeAuthorDefaulted(request); + // request is from monitoring module + if (mode.isTeacher()) { + qaService.setDefineLater(strToolContentID, true); + } + request.setAttribute(AttributeNames.ATTR_MODE, mode.toString()); + + SortedSet conditionList = getQaConditionList(sessionMap); + conditionList.clear(); + conditionList.addAll(qaContent.getConditions()); + + qaAuthoringForm.setAllowRichEditor(qaContent.isAllowRichEditor()); + qaAuthoringForm.setUseSelectLeaderToolOuput(qaContent.isUseSelectLeaderToolOuput()); + + sessionMap.put(QaAppConstants.ATTR_QA_AUTHORING_FORM, qaAuthoringForm); + request.getSession().setAttribute(sessionMap.getSessionID(), sessionMap); + + // get rating criterias from DB + List ratingCriterias = qaService.getRatingCriterias(qaContent.getQaContentId()); + sessionMap.put(AttributeNames.ATTR_RATING_CRITERIAS, ratingCriterias); + + return mapping.findForward(LOAD_QUESTIONS); + } + + /** + * retrives the existing content information from the db and prepares the data for presentation purposes. + * + * @param request + * @param mapping + * @param qaAuthoringForm + * @param mapQuestionContent + * @param toolContentID + * @return ActionForward + */ + protected QaContent prepareDTOandForm(HttpServletRequest request, QaAuthoringForm qaAuthoringForm, + QaContent qaContent, IQaService qaService, SessionMap sessionMap) { + + qaAuthoringForm.setUsernameVisible(qaContent.isUsernameVisible() ? "1" : "0"); + qaAuthoringForm.setAllowRateAnswers(qaContent.isAllowRateAnswers() ? "1" : "0"); + qaAuthoringForm.setNotifyTeachersOnResponseSubmit(qaContent.isNotifyTeachersOnResponseSubmit() ? "1" : "0"); + qaAuthoringForm.setShowOtherAnswers(qaContent.isShowOtherAnswers() ? "1" : "0"); + qaAuthoringForm.setQuestionsSequenced(qaContent.isQuestionsSequenced() ? "1" : "0"); + qaAuthoringForm.setLockWhenFinished(qaContent.isLockWhenFinished() ? "1" : "0"); + qaAuthoringForm.setNoReeditAllowed(qaContent.isNoReeditAllowed() ? "1" : "0"); + qaAuthoringForm.setMaximumRates(qaContent.getMaximumRates()); + qaAuthoringForm.setMinimumRates(qaContent.getMinimumRates()); + qaAuthoringForm.setReflect(qaContent.isReflect() ? "1" : "0"); + qaAuthoringForm.setReflectionSubject(qaContent.getReflectionSubject()); + qaAuthoringForm.setTitle(qaContent.getTitle()); + qaAuthoringForm.setInstructions(qaContent.getInstructions()); + sessionMap.put(QaAppConstants.ACTIVITY_TITLE_KEY, qaContent.getTitle()); + sessionMap.put(QaAppConstants.ACTIVITY_INSTRUCTIONS_KEY, qaContent.getInstructions()); + + List questionDTOs = new LinkedList(); + + /* + * get the existing question content + */ + Iterator queIterator = qaContent.getQaQueContents().iterator(); + while (queIterator.hasNext()) { + + QaQueContent qaQuestion = (QaQueContent) queIterator.next(); + if (qaQuestion != null) { + QaQuestionDTO qaQuestionDTO = new QaQuestionDTO(qaQuestion); + questionDTOs.add(qaQuestionDTO); + } + } + + request.setAttribute(QaAppConstants.TOTAL_QUESTION_COUNT, new Integer(questionDTOs.size())); + request.setAttribute(QaAppConstants.LIST_QUESTION_DTOS, questionDTOs); + sessionMap.put(QaAppConstants.LIST_QUESTION_DTOS, questionDTOs); + + SortedSet conditionSet = new TreeSet<>(new TextSearchConditionComparator()); + for (QaCondition condition : qaContent.getConditions()) { + conditionSet.add(condition); + for (QaQuestionDTO dto : questionDTOs) { + for (QaQueContent question : condition.getQuestions()) { + if (dto.getDisplayOrder().equals(String.valueOf(question.getDisplayOrder()))) { + condition.temporaryQuestionDTOSet.add(dto); + } + } + } + } + sessionMap.put(QaAppConstants.ATTR_CONDITION_SET, conditionSet); + + List listDeletedQuestionDTOs = new ArrayList<>(); + sessionMap.put(QaAppConstants.LIST_DELETED_QUESTION_DTOS, listDeletedQuestionDTOs); + + qaAuthoringForm.resetUserAction(); + + return qaContent; + } + + /** + * each tool has a signature. QA tool's signature is stored in MY_SIGNATURE. + * The default tool content id and other depending content ids are obtained + * in this method. if all the default content has been setup properly the + * method persists DEFAULT_CONTENT_ID in the session. + * + * @param request + * @param mapping + * @return ActionForward + */ + public boolean validateDefaultContent(HttpServletRequest request, ActionMapping mapping, IQaService qaService, + QaAuthoringForm qaAuthoringForm) { + + /* + * retrieve the default content id based on tool signature + */ + long defaultContentID = 0; + try { + defaultContentID = qaService.getToolDefaultContentIdBySignature(QaAppConstants.MY_SIGNATURE); + if (defaultContentID == 0) { + QaStarterController.logger.debug("default content id has not been setup"); + return false; + } + } catch (Exception e) { + QaStarterController.logger.error("error getting the default content id: " + e.getMessage()); + persistError(request, "error.defaultContent.notSetup"); + return false; + } + + /* + * retrieve uid of the content based on default content id determined above + */ + try { + //retrieve uid of the content based on default content id determined above + QaContent qaContent = qaService.getQaContent(defaultContentID); + if (qaContent == null) { + QaStarterController.logger.error("Exception occured: No default content"); + persistError(request, "error.defaultContent.notSetup"); + return false; + } + + } catch (Exception e) { + QaStarterController.logger.error("Exception occured: No default question content"); + persistError(request, "error.defaultContent.notSetup"); + return false; + } + + return true; + } + + /** + * persists error messages to request scope + * + * @param request + * @param message + */ + public void persistError(HttpServletRequest request, String message) { + ActionMessages errors = new ActionMessages(); + errors.add(Globals.ERROR_KEY, new ActionMessage(message)); + saveErrors(request, errors); + } + + private SortedSet getQaConditionList(SessionMap sessionMap) { + SortedSet list = (SortedSet) sessionMap.get(QaAppConstants.ATTR_CONDITION_SET); + if (list == null) { + list = new TreeSet<>(new TextSearchConditionComparator()); + sessionMap.put(QaAppConstants.ATTR_CONDITION_SET, list); + } + return list; + } +} Index: lams_tool_laqa/src/java/org/lamsfoundation/lams/tool/qa/web/form/QaAdminForm.java =================================================================== diff -u -r2f725f8ef2aa09a2663b2335bf67213074426d11 -r6d9587c552af599d4fc4e68399d218f5f4ca7cf4 --- lams_tool_laqa/src/java/org/lamsfoundation/lams/tool/qa/web/form/QaAdminForm.java (.../QaAdminForm.java) (revision 2f725f8ef2aa09a2663b2335bf67213074426d11) +++ lams_tool_laqa/src/java/org/lamsfoundation/lams/tool/qa/web/form/QaAdminForm.java (.../QaAdminForm.java) (revision 6d9587c552af599d4fc4e68399d218f5f4ca7cf4) @@ -20,13 +20,11 @@ * **************************************************************** */ - package org.lamsfoundation.lams.tool.qa.web.form; -import org.apache.struts.action.ActionForm; import org.apache.struts.upload.FormFile; -public class QaAdminForm extends ActionForm { +public class QaAdminForm { public static final long serialVersionUID = 978235712395273523L; Index: lams_tool_laqa/src/java/org/lamsfoundation/lams/tool/qa/web/form/QaConditionForm.java =================================================================== diff -u -r2f725f8ef2aa09a2663b2335bf67213074426d11 -r6d9587c552af599d4fc4e68399d218f5f4ca7cf4 --- lams_tool_laqa/src/java/org/lamsfoundation/lams/tool/qa/web/form/QaConditionForm.java (.../QaConditionForm.java) (revision 2f725f8ef2aa09a2663b2335bf67213074426d11) +++ lams_tool_laqa/src/java/org/lamsfoundation/lams/tool/qa/web/form/QaConditionForm.java (.../QaConditionForm.java) (revision 6d9587c552af599d4fc4e68399d218f5f4ca7cf4) @@ -20,21 +20,20 @@ * **************************************************************** */ - package org.lamsfoundation.lams.tool.qa.web.form; import org.apache.struts.util.LabelValueBean; import org.lamsfoundation.lams.tool.qa.QaCondition; import org.lamsfoundation.lams.tool.qa.dto.QaQuestionDTO; -import org.lamsfoundation.lams.web.TextSearchActionForm; +import org.lamsfoundation.lams.web.TextSearchForm; /** * A text search form with additional parameters for Q&A needs. * * @author Marcin Cieslak * */ -public class QaConditionForm extends TextSearchActionForm { +public class QaConditionForm extends TextSearchForm { /** * Names of the questions that could be selected by a user. */ Index: lams_tool_laqa/src/java/org/lamsfoundation/lams/tool/qa/web/form/QaEmptyForm.java =================================================================== diff -u -r2f725f8ef2aa09a2663b2335bf67213074426d11 -r6d9587c552af599d4fc4e68399d218f5f4ca7cf4 --- lams_tool_laqa/src/java/org/lamsfoundation/lams/tool/qa/web/form/QaEmptyForm.java (.../QaEmptyForm.java) (revision 2f725f8ef2aa09a2663b2335bf67213074426d11) +++ lams_tool_laqa/src/java/org/lamsfoundation/lams/tool/qa/web/form/QaEmptyForm.java (.../QaEmptyForm.java) (revision 6d9587c552af599d4fc4e68399d218f5f4ca7cf4) @@ -21,16 +21,13 @@ * **************************************************************** */ - package org.lamsfoundation.lams.tool.qa.web.form; -import org.apache.struts.action.ActionForm; - /** * @author Ozgur Demirtas * * TODO To change the template for this generated type comment go to Window - * Preferences - Java - Code Style - Code Templates */ -public class QaEmptyForm extends ActionForm { +public class QaEmptyForm { } Index: lams_tool_laqa/src/java/org/lamsfoundation/lams/tool/qa/web/form/QaLearningForm.java =================================================================== diff -u -r2f725f8ef2aa09a2663b2335bf67213074426d11 -r6d9587c552af599d4fc4e68399d218f5f4ca7cf4 --- lams_tool_laqa/src/java/org/lamsfoundation/lams/tool/qa/web/form/QaLearningForm.java (.../QaLearningForm.java) (revision 2f725f8ef2aa09a2663b2335bf67213074426d11) +++ lams_tool_laqa/src/java/org/lamsfoundation/lams/tool/qa/web/form/QaLearningForm.java (.../QaLearningForm.java) (revision 6d9587c552af599d4fc4e68399d218f5f4ca7cf4) @@ -21,17 +21,14 @@ * **************************************************************** */ - package org.lamsfoundation.lams.tool.qa.web.form; -/** ActionForm for the Learning environment */ -import org.apache.struts.action.ActionForm; import org.lamsfoundation.lams.tool.qa.QaAppConstants; /** * @author Ozgur Demirtas */ -public class QaLearningForm extends ActionForm implements QaAppConstants { +public class QaLearningForm implements QaAppConstants { //controls which method is called by the Lookup map */ protected String method; Index: lams_tool_laqa/src/java/org/lamsfoundation/lams/tool/qa/web/form/QaMonitoringForm.java =================================================================== diff -u -r2f725f8ef2aa09a2663b2335bf67213074426d11 -r6d9587c552af599d4fc4e68399d218f5f4ca7cf4 --- lams_tool_laqa/src/java/org/lamsfoundation/lams/tool/qa/web/form/QaMonitoringForm.java (.../QaMonitoringForm.java) (revision 2f725f8ef2aa09a2663b2335bf67213074426d11) +++ lams_tool_laqa/src/java/org/lamsfoundation/lams/tool/qa/web/form/QaMonitoringForm.java (.../QaMonitoringForm.java) (revision 6d9587c552af599d4fc4e68399d218f5f4ca7cf4) @@ -21,7 +21,6 @@ * **************************************************************** */ - package org.lamsfoundation.lams.tool.qa.web.form; /* ActionForm for the Monitoring environment */ Index: lams_tool_laqa/src/java/org/lamsfoundation/lams/tool/qa/web/form/QaPedagogicalPlannerForm.java =================================================================== diff -u -r2f725f8ef2aa09a2663b2335bf67213074426d11 -r6d9587c552af599d4fc4e68399d218f5f4ca7cf4 --- lams_tool_laqa/src/java/org/lamsfoundation/lams/tool/qa/web/form/QaPedagogicalPlannerForm.java (.../QaPedagogicalPlannerForm.java) (revision 2f725f8ef2aa09a2663b2335bf67213074426d11) +++ lams_tool_laqa/src/java/org/lamsfoundation/lams/tool/qa/web/form/QaPedagogicalPlannerForm.java (.../QaPedagogicalPlannerForm.java) (revision 6d9587c552af599d4fc4e68399d218f5f4ca7cf4) @@ -20,21 +20,28 @@ * **************************************************************** */ - package org.lamsfoundation.lams.tool.qa.web.form; import java.util.ArrayList; import java.util.List; import java.util.Set; import org.apache.commons.lang.StringUtils; -import org.apache.struts.action.ActionMessage; -import org.apache.struts.action.ActionMessages; import org.lamsfoundation.lams.tool.qa.QaContent; import org.lamsfoundation.lams.tool.qa.QaQueContent; -import org.lamsfoundation.lams.web.planner.PedagogicalPlannerActivityForm; +import org.lamsfoundation.lams.util.MessageService; +import org.lamsfoundation.lams.web.planner.PedagogicalPlannerActivitySpringForm; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; -public class QaPedagogicalPlannerForm extends PedagogicalPlannerActivityForm { +public class QaPedagogicalPlannerForm extends PedagogicalPlannerActivitySpringForm { + + @Autowired + @Qualifier("qaMessageService") + private MessageService messageService; + private List question; private String contentFolderID; @@ -46,9 +53,8 @@ this.contentFolderID = contentFolderID; } - @Override - public ActionMessages validate() { - ActionMessages errors = new ActionMessages(); + public MultiValueMap validate() { + MultiValueMap errorMap = new LinkedMultiValueMap<>(); boolean valid = true; boolean allEmpty = true; if (question != null && !question.isEmpty()) { @@ -60,21 +66,20 @@ } } if (allEmpty) { - ActionMessage error = new ActionMessage("questions.none.submitted"); - errors.add(ActionMessages.GLOBAL_MESSAGE, error); + errorMap.add("GLOBAL", messageService.getMessage("questions.none.submitted")); valid = false; question = null; } setValid(valid); - return errors; + return errorMap; } public void fillForm(QaContent qaContent) { if (qaContent != null) { setToolContentID(qaContent.getQaContentId()); - question = new ArrayList(); + question = new ArrayList<>(); Set questions = qaContent.getQaQueContents(); if (questions != null) { int topicIndex = 0; @@ -87,7 +92,7 @@ public void setQuestion(int number, String Questions) { if (question == null) { - question = new ArrayList(); + question = new ArrayList<>(); } while (number >= question.size()) { question.add(null); Index: lams_tool_laqa/web/WEB-INF/spring-servlet.xml =================================================================== diff -u --- lams_tool_laqa/web/WEB-INF/spring-servlet.xml (revision 0) +++ lams_tool_laqa/web/WEB-INF/spring-servlet.xml (revision 6d9587c552af599d4fc4e68399d218f5f4ca7cf4) @@ -0,0 +1,17 @@ + + + + + + + + + + + \ No newline at end of file Index: lams_tool_laqa/web/WEB-INF/web.xml =================================================================== diff -u -r26513e4a3a00a82cf700663c7cfe79d39c47732a -r6d9587c552af599d4fc4e68399d218f5f4ca7cf4 --- lams_tool_laqa/web/WEB-INF/web.xml (.../web.xml) (revision 26513e4a3a00a82cf700663c7cfe79d39c47732a) +++ lams_tool_laqa/web/WEB-INF/web.xml (.../web.xml) (revision 6d9587c552af599d4fc4e68399d218f5f4ca7cf4) @@ -69,24 +69,10 @@ - action - org.apache.struts.action.ActionServlet - - config - /WEB-INF/struts-config.xml - - - debug - 999 - - - detail - 2 - - - validate - true - + spring + + org.springframework.web.servlet.DispatcherServlet + 1 @@ -117,7 +103,7 @@ - action + spring *.do Index: lams_tool_larsrc/.externalToolBuilders/SASS_lams_tool_larsrc.launch =================================================================== diff -u -r6f2ada697a81118661a72a78b711e86542ed3dad -r6d9587c552af599d4fc4e68399d218f5f4ca7cf4 --- lams_tool_larsrc/.externalToolBuilders/SASS_lams_tool_larsrc.launch (.../SASS_lams_tool_larsrc.launch) (revision 6f2ada697a81118661a72a78b711e86542ed3dad) +++ lams_tool_larsrc/.externalToolBuilders/SASS_lams_tool_larsrc.launch (.../SASS_lams_tool_larsrc.launch) (revision 6d9587c552af599d4fc4e68399d218f5f4ca7cf4) @@ -5,6 +5,12 @@ + + + + + + Index: lams_tool_larsrc/src/java/org/lamsfoundation/lams/tool/rsrc/service/IResourceService.java =================================================================== diff -u -r6f2ada697a81118661a72a78b711e86542ed3dad -r6d9587c552af599d4fc4e68399d218f5f4ca7cf4 --- lams_tool_larsrc/src/java/org/lamsfoundation/lams/tool/rsrc/service/IResourceService.java (.../IResourceService.java) (revision 6f2ada697a81118661a72a78b711e86542ed3dad) +++ lams_tool_larsrc/src/java/org/lamsfoundation/lams/tool/rsrc/service/IResourceService.java (.../IResourceService.java) (revision 6d9587c552af599d4fc4e68399d218f5f4ca7cf4) @@ -27,7 +27,6 @@ import java.util.List; import java.util.SortedSet; -import org.apache.struts.upload.FormFile; import org.lamsfoundation.lams.contentrepository.IVersionedNode; import org.lamsfoundation.lams.notebook.model.NotebookEntry; import org.lamsfoundation.lams.rating.RatingException; @@ -40,6 +39,7 @@ import org.lamsfoundation.lams.tool.rsrc.model.ResourceItem; import org.lamsfoundation.lams.tool.rsrc.model.ResourceSession; import org.lamsfoundation.lams.tool.rsrc.model.ResourceUser; +import org.springframework.web.multipart.MultipartFile; /** * @author Dapeng.Ni @@ -91,7 +91,7 @@ * @param file * @throws UploadResourceFileException */ - void uploadResourceItemFile(ResourceItem item, FormFile file) throws UploadResourceFileException; + void uploadResourceItemFile(ResourceItem item, MultipartFile file) throws UploadResourceFileException; // ********** for user methods ************* /** @@ -272,20 +272,23 @@ * @return */ boolean isGroupedActivity(long toolContentID); - + /** * Audit log the teacher has started editing activity in monitor. - * + * * @param toolContentID */ void auditLogStartEditingActivityInMonitor(long toolContentID); - + void evict(Object object); /** Create an anonymous star rating criteria */ LearnerItemRatingCriteria createRatingCriteria(Long toolContentId) throws RatingException; + /** Delete an anonymous star rating criteria */ int deleteRatingCriteria(Long toolContentId); + /** Get the actual ratings and the criteria for display */ - List getRatingCriteriaDtos(Long toolContentId, Long toolSessionId, Collection itemIds, Long userId); + List getRatingCriteriaDtos(Long toolContentId, Long toolSessionId, Collection itemIds, + Long userId); } Index: lams_tool_larsrc/src/java/org/lamsfoundation/lams/tool/rsrc/service/ResourceServiceImpl.java =================================================================== diff -u -rf2c0865cbb95219b30d59d6152b20dff389dc7b0 -r6d9587c552af599d4fc4e68399d218f5f4ca7cf4 --- lams_tool_larsrc/src/java/org/lamsfoundation/lams/tool/rsrc/service/ResourceServiceImpl.java (.../ResourceServiceImpl.java) (revision f2c0865cbb95219b30d59d6152b20dff389dc7b0) +++ lams_tool_larsrc/src/java/org/lamsfoundation/lams/tool/rsrc/service/ResourceServiceImpl.java (.../ResourceServiceImpl.java) (revision 6d9587c552af599d4fc4e68399d218f5f4ca7cf4) @@ -44,7 +44,6 @@ import org.apache.commons.lang.StringUtils; import org.apache.log4j.Logger; -import org.apache.struts.upload.FormFile; import org.lamsfoundation.lams.confidencelevel.ConfidenceLevelDTO; import org.lamsfoundation.lams.contentrepository.ICredentials; import org.lamsfoundation.lams.contentrepository.ITicket; @@ -112,6 +111,7 @@ import org.lamsfoundation.lams.util.zipfile.ZipFileUtil; import org.lamsfoundation.lams.util.zipfile.ZipFileUtilException; import org.lamsfoundation.lams.web.util.AttributeNames; +import org.springframework.web.multipart.MultipartFile; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.node.ArrayNode; @@ -488,13 +488,13 @@ } } } - + group.setAllowComments(allowComments); groupList.add(group); } - if ( groupList.size() == 0) { + if (groupList.size() == 0) { // no sessions but we still need to be able to view the resources in monitoring groupList.add(createAuthoredItemsGroupList(contentId, resource)); } @@ -506,18 +506,18 @@ group.setSessionId(0L); group.setSessionName(""); - Set items = new TreeSet(new ResourceItemComparator()); + Set items = new TreeSet<>(new ResourceItemComparator()); // get the authored items items.addAll(resource.getResourceItems()); // get all item which is accessed by users in this session for (ResourceItem item : items) { ResourceItemDTO resourceItemDTO = new ResourceItemDTO(item); group.getItems().add(resourceItemDTO); - if ( item.isAllowRating() ) { + if (item.isAllowRating()) { group.setAllowRating(true); } - if ( item.isAllowComments() ) { + if (item.isAllowComments()) { group.setAllowComments(true); } } @@ -700,10 +700,10 @@ * @throws RepositoryCheckedException * @throws InvalidParameterException */ - private NodeKey processFile(FormFile file) throws UploadResourceFileException { + private NodeKey processFile(MultipartFile file) throws UploadResourceFileException { NodeKey node = null; - if ((file != null) && !StringUtils.isEmpty(file.getFileName())) { - String fileName = file.getFileName(); + if ((file != null) && !StringUtils.isEmpty(file.getOriginalFilename())) { + String fileName = file.getOriginalFilename(); try { node = resourceToolContentHandler.uploadFile(file.getInputStream(), fileName, file.getContentType()); } catch (InvalidParameterException e) { @@ -732,10 +732,10 @@ } @Override - public void uploadResourceItemFile(ResourceItem item, FormFile file) throws UploadResourceFileException { + public void uploadResourceItemFile(ResourceItem item, MultipartFile file) throws UploadResourceFileException { try { InputStream is = file.getInputStream(); - String fileName = file.getFileName(); + String fileName = file.getOriginalFilename(); String fileType = file.getContentType(); // For file only upload one sigle file if (item.getType() == ResourceConstants.RESOURCE_TYPE_FILE) { Fisheye: Tag 6d9587c552af599d4fc4e68399d218f5f4ca7cf4 refers to a dead (removed) revision in file `lams_tool_larsrc/src/java/org/lamsfoundation/lams/tool/rsrc/web/action/AuthoringAction.java'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 6d9587c552af599d4fc4e68399d218f5f4ca7cf4 refers to a dead (removed) revision in file `lams_tool_larsrc/src/java/org/lamsfoundation/lams/tool/rsrc/web/action/ClearSessionAction.java'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 6d9587c552af599d4fc4e68399d218f5f4ca7cf4 refers to a dead (removed) revision in file `lams_tool_larsrc/src/java/org/lamsfoundation/lams/tool/rsrc/web/action/LearningAction.java'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 6d9587c552af599d4fc4e68399d218f5f4ca7cf4 refers to a dead (removed) revision in file `lams_tool_larsrc/src/java/org/lamsfoundation/lams/tool/rsrc/web/action/MonitoringAction.java'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 6d9587c552af599d4fc4e68399d218f5f4ca7cf4 refers to a dead (removed) revision in file `lams_tool_larsrc/src/java/org/lamsfoundation/lams/tool/rsrc/web/action/ViewItemAction.java'. Fisheye: No comparison available. Pass `N' to diff? Index: lams_tool_larsrc/src/java/org/lamsfoundation/lams/tool/rsrc/web/controller/AuthoringController.java =================================================================== diff -u -r3b02999189bd74f83f390d8c340d34188923cde7 -r6d9587c552af599d4fc4e68399d218f5f4ca7cf4 --- lams_tool_larsrc/src/java/org/lamsfoundation/lams/tool/rsrc/web/controller/AuthoringController.java (.../AuthoringController.java) (revision 3b02999189bd74f83f390d8c340d34188923cde7) +++ lams_tool_larsrc/src/java/org/lamsfoundation/lams/tool/rsrc/web/controller/AuthoringController.java (.../AuthoringController.java) (revision 6d9587c552af599d4fc4e68399d218f5f4ca7cf4) @@ -49,8 +49,6 @@ import org.apache.commons.lang.math.NumberUtils; import org.apache.log4j.Logger; import org.apache.struts.action.ActionMessage; -import org.apache.struts.action.ActionMessages; -import org.apache.struts.upload.FormFile; import org.lamsfoundation.lams.authoring.web.AuthoringConstants; import org.lamsfoundation.lams.rating.model.LearnerItemRatingCriteria; import org.lamsfoundation.lams.tool.ToolAccessMode; @@ -68,7 +66,6 @@ import org.lamsfoundation.lams.tool.rsrc.web.form.ResourcePedagogicalPlannerForm; import org.lamsfoundation.lams.usermanagement.dto.UserDTO; import org.lamsfoundation.lams.util.FileValidatorSpringUtil; -import org.lamsfoundation.lams.util.FileValidatorUtil; import org.lamsfoundation.lams.util.MessageService; import org.lamsfoundation.lams.util.WebUtil; import org.lamsfoundation.lams.web.session.SessionManager; @@ -82,6 +79,7 @@ import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.multipart.MultipartFile; /** * @author Steve.Ni @@ -356,8 +354,8 @@ * @throws ServletException * */ - @RequestMapping("/start") - private String start(ResourceForm authoringForm, HttpServletRequest request) throws ServletException { + @RequestMapping(value="/start") + private String start(@ModelAttribute ResourceForm startForm, HttpServletRequest request) throws ServletException { ToolAccessMode mode = WebUtil.readToolAccessModeAuthorDefaulted(request); request.setAttribute(AttributeNames.ATTR_MODE, mode.toString()); @@ -372,12 +370,12 @@ // Get contentFolderID and save to form. String contentFolderID = WebUtil.readStrParam(request, AttributeNames.PARAM_CONTENT_FOLDER_ID); - authoringForm.setContentFolderID(contentFolderID); + startForm.setContentFolderID(contentFolderID); // initial Session Map SessionMap sessionMap = new SessionMap<>(); request.getSession().setAttribute(sessionMap.getSessionID(), sessionMap); - authoringForm.setSessionMapID(sessionMap.getSessionID()); + startForm.setSessionMapID(sessionMap.getSessionID()); try { resource = resourceService.getResourceByContentId(contentId); @@ -393,7 +391,7 @@ items = resourceService.getAuthoredItems(resource.getUid()); } - authoringForm.setResource(resource); + startForm.setResource(resource); } catch (Exception e) { AuthoringController.log.error(e); throw new ServletException(e); @@ -432,9 +430,10 @@ i++; } - sessionMap.put(ResourceConstants.ATTR_RESOURCE_FORM, authoringForm); + sessionMap.put(ResourceConstants.ATTR_RESOURCE_FORM, startForm); request.getSession().setAttribute(AttributeNames.PARAM_NOTIFY_CLOSE_URL, request.getParameter(AttributeNames.PARAM_NOTIFY_CLOSE_URL)); + request.setAttribute("startForm", startForm); return "pages/authoring/start"; } @@ -538,20 +537,21 @@ */ @RequestMapping("/init") - private String initPage(ResourceForm AuthoringForm, HttpServletRequest request) throws ServletException { + private String initPage(@ModelAttribute ResourceForm startForm, HttpServletRequest request) throws ServletException { String sessionMapID = WebUtil.readStrParam(request, ResourceConstants.ATTR_SESSION_MAP_ID); SessionMap sessionMap = (SessionMap) request.getSession() .getAttribute(sessionMapID); ResourceForm existForm = (ResourceForm) sessionMap.get(ResourceConstants.ATTR_RESOURCE_FORM); try { - PropertyUtils.copyProperties(AuthoringForm, existForm); + PropertyUtils.copyProperties(startForm, existForm); } catch (Exception e) { throw new ServletException(e); } ToolAccessMode mode = WebUtil.readToolAccessModeAuthorDefaulted(request); request.setAttribute(AttributeNames.ATTR_MODE, mode.toString()); + request.setAttribute("authoringForm", startForm); return "pages/authoring/authoring"; } @@ -568,7 +568,7 @@ * @throws ServletException */ @RequestMapping(value = "/update", method = RequestMethod.POST) - private String updateContent(ResourceForm authoringForm, HttpServletRequest request) throws Exception { + private String updateContent(@ModelAttribute ResourceForm authoringForm, HttpServletRequest request) throws Exception { // get back sessionMAP SessionMap sessionMap = (SessionMap) request.getSession() @@ -680,6 +680,7 @@ authoringForm.setResource(resourcePO); request.setAttribute(AuthoringConstants.LAMS_AUTHORING_SUCCESS_FLAG, Boolean.TRUE); + request.setAttribute("authoringForm", authoringForm); return "pages/authoring/authoring"; } @@ -939,7 +940,7 @@ * @param resourceItemForm * @return */ - private void validateResourceItem(ResourceItemForm resourceItemForm, MultiValueMap errorMap) { + private void validateResourceItem(ResourceItemForm resourceItemForm, MultiValueMap errorMap) { if (StringUtils.isBlank(resourceItemForm.getTitle())) { errorMap.add("GLOBAL", messageService.getMessage(ResourceConstants.ERROR_MSG_TITLE_BLANK)); } @@ -967,10 +968,11 @@ || resourceItemForm.getItemType() == ResourceConstants.RESOURCE_TYPE_LEARNING_OBJECT || resourceItemForm.getItemType() == ResourceConstants.RESOURCE_TYPE_FILE) { // validate item size - boolean fileSizeValid = FileValidatorSpringUtil.validateFileSize(resourceItemForm.getFile().getSize(), false); + boolean fileSizeValid = FileValidatorSpringUtil.validateFileSize(resourceItemForm.getFile().getSize(), + false); // for edit validate: file already exist if (!resourceItemForm.isHasFile() && (resourceItemForm.getFile() == null - || StringUtils.isEmpty(resourceItemForm.getFile().getFileName()))) { + || StringUtils.isEmpty(resourceItemForm.getFile().getOriginalFilename()))) { errorMap.add("GLOBAL", messageService.getMessage(ResourceConstants.ERROR_MSG_FILE_BLANK)); } } @@ -990,8 +992,10 @@ @RequestMapping(value = "/saveOrUpdatePedagogicalPlannerForm", method = RequestMethod.POST) public String saveOrUpdatePedagogicalPlannerForm(ResourcePedagogicalPlannerForm pedagogicalPlannerForm, HttpServletRequest request) throws IOException { - pedagogicalPlannerForm.validate(); - if (errors.isEmpty()) { + + MultiValueMap errorMap = new LinkedMultiValueMap<>(); + pedagogicalPlannerForm.validate(messageService); + if (errorMap.isEmpty()) { Resource taskList = resourceService.getResourceByContentId(pedagogicalPlannerForm.getToolContentID()); taskList.setInstructions(pedagogicalPlannerForm.getInstructions()); @@ -1045,9 +1049,9 @@ resourceItem.setFileType(null); } } else if (type.equals(ResourceConstants.RESOURCE_TYPE_FILE)) { - FormFile file = pedagogicalPlannerForm.getFile(itemIndex); + MultipartFile file = pedagogicalPlannerForm.getFile(itemIndex); resourceItem.setUrl(null); - if (file != null && !StringUtils.isEmpty(file.getFileName())) { + if (file != null && !StringUtils.isEmpty(file.getOriginalFilename())) { try { if (hasFile) { // delete the old file @@ -1058,8 +1062,8 @@ } catch (Exception e) { AuthoringController.log.error(e); ActionMessage error = new ActionMessage("error.msg.io.exception"); - errors.add(ActionMessages.GLOBAL_MESSAGE, error); - saveErrors(request, errors); + errorMap.add("GLOBAL", messageService.getMessage("error.msg.io.exception")); + request.setAttribute("errorMap", errorMap); pedagogicalPlannerForm.setValid(false); return "pages/authoring/pedagogicalPlannerForm"; } @@ -1086,7 +1090,7 @@ taskList.getResourceItems().addAll(resourceItems); resourceService.saveOrUpdateResource(taskList); } else { - saveErrors(request, errors); + request.setAttribute("errorMap", errorMap); } return "pages/authoring/pedagogicalPlannerForm"; } Index: lams_tool_larsrc/src/java/org/lamsfoundation/lams/tool/rsrc/web/controller/ClearSessionController.java =================================================================== diff -u --- lams_tool_larsrc/src/java/org/lamsfoundation/lams/tool/rsrc/web/controller/ClearSessionController.java (revision 0) +++ lams_tool_larsrc/src/java/org/lamsfoundation/lams/tool/rsrc/web/controller/ClearSessionController.java (revision 6d9587c552af599d4fc4e68399d218f5f4ca7cf4) @@ -0,0 +1,64 @@ +/**************************************************************** + * 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.rsrc.web.controller; + +import java.io.IOException; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; + +import org.lamsfoundation.lams.authoring.web.LamsAuthoringFinishController; +import org.lamsfoundation.lams.tool.ToolAccessMode; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.context.WebApplicationContext; + +/** + * This class give a chance to clear HttpSession when user save/close authoring page. + * + * @author Steve.Ni + * + * @version $Revision$ + */ +@Controller +public class ClearSessionController extends LamsAuthoringFinishController { + + @Autowired + private WebApplicationContext applicationContext; + + @RequestMapping("/clearsession") + public void execute(HttpServletRequest request, HttpServletResponse response) throws IOException { + super.execute(request, response, applicationContext); + } + + @Override + public void clearSession(String customiseSessionID, HttpSession session, ToolAccessMode mode) { + if (mode.isAuthor()) { + session.removeAttribute(customiseSessionID); + } + } + +} \ No newline at end of file Index: lams_tool_larsrc/src/java/org/lamsfoundation/lams/tool/rsrc/web/controller/LearningController.java =================================================================== diff -u --- lams_tool_larsrc/src/java/org/lamsfoundation/lams/tool/rsrc/web/controller/LearningController.java (revision 0) +++ lams_tool_larsrc/src/java/org/lamsfoundation/lams/tool/rsrc/web/controller/LearningController.java (revision 6d9587c552af599d4fc4e68399d218f5f4ca7cf4) @@ -0,0 +1,704 @@ +/**************************************************************** + * 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.rsrc.web.controller; + +import java.io.IOException; +import java.sql.Timestamp; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Date; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.SortedSet; +import java.util.TreeSet; + +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.ActionErrors; +import org.apache.struts.action.ActionForward; +import org.apache.struts.action.ActionMapping; +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.rating.dto.ItemRatingDTO; +import org.lamsfoundation.lams.tool.ToolAccessMode; +import org.lamsfoundation.lams.tool.rsrc.ResourceConstants; +import org.lamsfoundation.lams.tool.rsrc.model.Resource; +import org.lamsfoundation.lams.tool.rsrc.model.ResourceItem; +import org.lamsfoundation.lams.tool.rsrc.model.ResourceSession; +import org.lamsfoundation.lams.tool.rsrc.model.ResourceUser; +import org.lamsfoundation.lams.tool.rsrc.service.IResourceService; +import org.lamsfoundation.lams.tool.rsrc.service.ResourceApplicationException; +import org.lamsfoundation.lams.tool.rsrc.service.UploadResourceFileException; +import org.lamsfoundation.lams.tool.rsrc.util.ResourceItemComparator; +import org.lamsfoundation.lams.tool.rsrc.web.form.ReflectionForm; +import org.lamsfoundation.lams.tool.rsrc.web.form.ResourceItemForm; +import org.lamsfoundation.lams.usermanagement.dto.UserDTO; +import org.lamsfoundation.lams.util.FileUtil; +import org.lamsfoundation.lams.util.FileValidatorSpringUtil; +import org.lamsfoundation.lams.util.MessageService; +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.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.stereotype.Controller; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.context.WebApplicationContext; + +/** + * @author Steve.Ni + */ +@Controller +@RequestMapping("/learning") +public class LearningController { + + private static Logger log = Logger.getLogger(LearningController.class); + + @Autowired + @Qualifier("resourceService") + private IResourceService resourceService; + + @Autowired + private WebApplicationContext applicationContext; + + @Autowired + @Qualifier("resourceMessageService") + private MessageService messageService; + + /** + * Initial page for add resource item (single file or URL). + * + * @param mapping + * @param form + * @param request + * @param response + * @return + */ + @RequestMapping("/addfile") + private String addfile(ResourceItemForm resourceItemForm, HttpServletRequest request) { + resourceItemForm.setMode(WebUtil.readStrParam(request, AttributeNames.ATTR_MODE)); + resourceItemForm.setSessionMapID(WebUtil.readStrParam(request, ResourceConstants.ATTR_SESSION_MAP_ID)); + return "pages/learning/addfile"; + } + + @RequestMapping("/addurl") + private String addurl(ResourceItemForm resourceItemForm, HttpServletRequest request) { + resourceItemForm.setMode(WebUtil.readStrParam(request, AttributeNames.ATTR_MODE)); + resourceItemForm.setSessionMapID(WebUtil.readStrParam(request, ResourceConstants.ATTR_SESSION_MAP_ID)); + return "pages/learning/addurl"; + } + + /** + * + */ + @RequestMapping("/start") + private String start(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(ResourceConstants.PARAM_TOOL_SESSION_ID)); + + request.setAttribute(ResourceConstants.ATTR_SESSION_MAP_ID, sessionMap.getSessionID()); + request.setAttribute(AttributeNames.ATTR_MODE, mode); + request.setAttribute(AttributeNames.PARAM_TOOL_SESSION_ID, sessionId); + + // get back the resource and item list and display them on page + ResourceUser resourceUser = null; + if ((mode != null) && mode.isTeacher()) { + // monitoring mode - user is specified in URL + // resourceUser may be null if the user was force completed. + resourceUser = getSpecifiedUser(resourceService, sessionId, + WebUtil.readIntParam(request, AttributeNames.PARAM_USER_ID, false)); + } else { + resourceUser = getCurrentUser(resourceService, sessionId); + } + + List items = null; + Resource resource; + items = resourceService.getResourceItemsBySessionId(sessionId); + resource = resourceService.getResourceBySessionId(sessionId); + + // check whether finish lock is on/off + boolean lock = resource.getLockWhenFinished() && (resourceUser != null) && resourceUser.isSessionFinished(); + + // check whether there is only one resource item and run auto flag is true or not. + boolean runAuto = false; + Long runAutoItemUid = null; + int itemsNumber = 0; + if (resource.getResourceItems() != null) { + itemsNumber = resource.getResourceItems().size(); + if (resource.isRunAuto() && (itemsNumber == 1)) { + ResourceItem item = (ResourceItem) resource.getResourceItems().iterator().next(); + // only visible item can be run auto. + if (!item.isHide()) { + runAuto = true; + runAutoItemUid = item.getUid(); + } + } + } + + // get notebook entry + String entryText = new String(); + if (resourceUser != null) { + NotebookEntry notebookEntry = resourceService.getEntry(sessionId, CoreNotebookConstants.NOTEBOOK_TOOL, + ResourceConstants.TOOL_SIGNATURE, resourceUser.getUserId().intValue()); + if (notebookEntry != null) { + entryText = notebookEntry.getEntry(); + } + } + + // basic information + sessionMap.put(ResourceConstants.ATTR_TITLE, resource.getTitle()); + sessionMap.put(ResourceConstants.ATTR_RESOURCE_INSTRUCTION, resource.getInstructions()); + sessionMap.put(ResourceConstants.ATTR_FINISH_LOCK, lock); + sessionMap.put(ResourceConstants.ATTR_LOCK_ON_FINISH, resource.getLockWhenFinished()); + sessionMap.put(ResourceConstants.ATTR_USER_FINISHED, + (resourceUser != null) && resourceUser.isSessionFinished()); + + sessionMap.put(AttributeNames.PARAM_TOOL_SESSION_ID, sessionId); + sessionMap.put(AttributeNames.ATTR_MODE, mode); + // reflection information + sessionMap.put(ResourceConstants.ATTR_REFLECTION_ON, resource.isReflectOnActivity()); + sessionMap.put(ResourceConstants.ATTR_REFLECTION_INSTRUCTION, resource.getReflectInstructions()); + sessionMap.put(ResourceConstants.ATTR_REFLECTION_ENTRY, entryText); + sessionMap.put(ResourceConstants.ATTR_RUN_AUTO, new Boolean(runAuto)); + + // add define later support + if (resource.isDefineLater()) { + return "pages/learning/definelater"; + } + + // set contentInUse flag to true! + resource.setContentInUse(true); + resource.setDefineLater(false); + resourceService.saveOrUpdateResource(resource); + + ActivityPositionDTO activityPosition = LearningWebUtil.putActivityPositionInRequestByToolSessionId(sessionId, + request, applicationContext.getServletContext()); + sessionMap.put(AttributeNames.ATTR_ACTIVITY_POSITION, activityPosition); + + // init resource item list + SortedSet resourceItemList = getResourceItemList(sessionMap); + resourceItemList.clear(); + Collection itemsToBeRated = new ArrayList<>(); + if (items != null) { + // remove hidden items. + for (ResourceItem item : items) { + // because in webpage will use this login name. Here is just + // initial it to avoid session close error in proxy object. + if (item.getCreateBy() != null) { + item.getCreateBy().getLoginName(); + } + if (!item.isHide()) { + resourceItemList.add(item); + } + if (item.isAllowRating()) { + itemsToBeRated.add(item.getUid()); + } + } + } + + List ratingDTOs = resourceService.getRatingCriteriaDtos(resource.getContentId(), sessionId, + itemsToBeRated, resourceUser.getUserId()); + for (ItemRatingDTO ratingDTO : ratingDTOs) { + for (ResourceItem item : resourceItemList) { + if (item.getUid().equals(ratingDTO.getItemId())) { + item.setRatingDTO(ratingDTO); + } + } + } + sessionMap.put(ResourceConstants.ATTR_RATE_ITEMS, itemsToBeRated.size() > 0); + + // set complete flag for display purpose + if (resourceUser != null) { + resourceService.retrieveComplete(resourceItemList, resourceUser); + } + sessionMap.put(ResourceConstants.ATTR_RESOURCE, resource); + + if (runAuto) { + String redirectURL = "redirect:/learning/reviewItem.do"; + redirectURL = WebUtil.appendParameterToURL(redirectURL, ResourceConstants.ATTR_SESSION_MAP_ID, + sessionMap.getSessionID()); + redirectURL = WebUtil.appendParameterToURL(redirectURL, ResourceConstants.ATTR_TOOL_SESSION_ID, + sessionId.toString()); + redirectURL = WebUtil.appendParameterToURL(redirectURL, ResourceConstants.ATTR_RESOURCE_ITEM_UID, + runAutoItemUid.toString()); + redirectURL = WebUtil.appendParameterToURL(redirectURL, AttributeNames.ATTR_MODE, mode.toString()); + return redirectURL; + + } else { + return "pages/learning/learning"; + } + + } + + /** + * Finish learning session. + * + * @param mapping + * @param form + * @param request + * @param response + * @return + */ + @RequestMapping("/finish") + private String finish(HttpServletRequest request) { + + // get back SessionMap + String sessionMapID = request.getParameter(ResourceConstants.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); + + // auto run mode, when use finish the only one resource item, mark it as complete then finish this activity as + // well. + String resourceItemUid = request.getParameter(ResourceConstants.PARAM_RESOURCE_ITEM_UID); + if (resourceItemUid != null) { + doComplete(request); + // NOTE:So far this flag is useless(31/08/2006). + // set flag, then finish page can know redir target is parent(AUTO_RUN) or self(normal) + request.setAttribute(ResourceConstants.ATTR_RUN_AUTO, true); + } else { + request.setAttribute(ResourceConstants.ATTR_RUN_AUTO, false); + } + + if (!validateBeforeFinish(request, sessionMapID)) { + return "pages/learning/learning"; + } + + // get sessionId from HttpServletRequest + String nextActivityUrl = null; + try { + HttpSession ss = SessionManager.getSession(); + UserDTO user = (UserDTO) ss.getAttribute(AttributeNames.USER); + Long userID = new Long(user.getUserID().longValue()); + + nextActivityUrl = resourceService.finishToolSession(sessionId, userID); + request.setAttribute(ResourceConstants.ATTR_NEXT_ACTIVITY_URL, nextActivityUrl); + } catch (ResourceApplicationException e) { + LearningController.log.error("Failed get next activity url:" + e.getMessage()); + } + + return "pages/learning/finish"; + } + + /** + * Save file or url resource item into database. + * + * @param mapping + * @param form + * @param request + * @param response + * @return + */ + @RequestMapping(value = "/saveOrUpdateItem", method = RequestMethod.POST) + private String saveOrUpdateItem(ResourceItemForm resourceItemForm, HttpServletRequest request) { + // get back SessionMap + String sessionMapID = request.getParameter(ResourceConstants.ATTR_SESSION_MAP_ID); + SessionMap sessionMap = (SessionMap) request.getSession() + .getAttribute(sessionMapID); + request.setAttribute(ResourceConstants.ATTR_SESSION_MAP_ID, sessionMapID); + + Long sessionId = (Long) sessionMap.get(ResourceConstants.ATTR_TOOL_SESSION_ID); + + String mode = request.getParameter(AttributeNames.ATTR_MODE); + MultiValueMap errorMap = new LinkedMultiValueMap<>(); + validateResourceItem(resourceItemForm, errorMap); + + if (!errorMap.isEmpty()) { + request.setAttribute("errorMap", errorMap); + switch (resourceItemForm.getItemType()) { + case 1: + return "pages/authoring/parts/addurl"; + case 2: + return "pages/authoring/parts/addfile"; + default: + throw new IllegalArgumentException("Unknown item type" + resourceItemForm.getItemType()); + } + } + short type = resourceItemForm.getItemType(); + + // create a new ResourceItem + ResourceItem item = new ResourceItem(); + ResourceUser resourceUser = getCurrentUser(resourceService, sessionId); + item.setType(type); + item.setTitle(resourceItemForm.getTitle()); + item.setDescription(resourceItemForm.getDescription()); + item.setCreateDate(new Timestamp(new Date().getTime())); + item.setCreateByAuthor(false); + item.setCreateBy(resourceUser); + + // special attribute for URL or FILE + if (type == ResourceConstants.RESOURCE_TYPE_FILE) { + try { + resourceService.uploadResourceItemFile(item, resourceItemForm.getFile()); + } catch (UploadResourceFileException e) { + LearningController.log.error("Failed upload Resource File " + e.toString()); + return "error"; + } + item.setOpenUrlNewWindow(resourceItemForm.isOpenUrlNewWindow()); + + } else if (type == ResourceConstants.RESOURCE_TYPE_URL) { + item.setUrl(resourceItemForm.getUrl()); + item.setOpenUrlNewWindow(resourceItemForm.isOpenUrlNewWindow()); + } + // save and update session + + ResourceSession resSession = resourceService.getResourceSessionBySessionId(sessionId); + if (resSession == null) { + LearningController.log.error("Failed update ResourceSession by ID[" + sessionId + "]"); + return "error"; + } + Set items = resSession.getResourceItems(); + if (items == null) { + items = new HashSet<>(); + resSession.setResourceItems(items); + } + items.add(item); + resourceService.saveOrUpdateResourceSession(resSession); + + // update session value + SortedSet resourceItemList = getResourceItemList(sessionMap); + resourceItemList.add(item); + + // URL or file upload + request.setAttribute(ResourceConstants.ATTR_ADD_RESOURCE_TYPE, new Short(type)); + request.setAttribute(AttributeNames.ATTR_MODE, mode); + + Resource resource = resSession.getResource(); + if (resource.isNotifyTeachersOnAssigmentSumbit()) { + resourceService.notifyTeachersOnAssigmentSumbit(sessionId, resourceUser); + } + + if (resource.isNotifyTeachersOnFileUpload() && (type == ResourceConstants.RESOURCE_TYPE_FILE)) { + resourceService.notifyTeachersOnFileUpload(resource.getContentId(), sessionId, sessionMapID, + resourceUser.getFirstName() + " " + resourceUser.getLastName(), item.getUid(), + resourceItemForm.getFile().getOriginalFilename()); + } + + return "pages/learning/success"; + } + + /** + * Display empty reflection form. + * + * @param mapping + * @param form + * @param request + * @param response + * @return + */ + + @RequestMapping("/newReflection") + private String newReflection(ReflectionForm reflectionForm, HttpServletRequest request) { + + // get session value + String sessionMapID = WebUtil.readStrParam(request, ResourceConstants.ATTR_SESSION_MAP_ID); + if (!validateBeforeFinish(request, sessionMapID)) { + return "pages/learning/notebook"; + } + + HttpSession ss = SessionManager.getSession(); + UserDTO user = (UserDTO) ss.getAttribute(AttributeNames.USER); + + reflectionForm.setUserID(user.getUserID()); + reflectionForm.setSessionMapID(sessionMapID); + + // get the existing reflection entry + + SessionMap map = (SessionMap) request.getSession().getAttribute(sessionMapID); + Long toolSessionID = (Long) map.get(AttributeNames.PARAM_TOOL_SESSION_ID); + NotebookEntry entry = resourceService.getEntry(toolSessionID, CoreNotebookConstants.NOTEBOOK_TOOL, + ResourceConstants.TOOL_SIGNATURE, user.getUserID()); + + if (entry != null) { + reflectionForm.setEntryText(entry.getEntry()); + } + + return "pages/learning/finish"; + } + + /** + * Submit reflection form input database. + * + * @param mapping + * @param form + * @param request + * @param response + * @return + */ + @RequestMapping("/submitReflection") + private String submitReflection(ReflectionForm reflectionForm, HttpServletRequest request) { + Integer userId = reflectionForm.getUserID(); + + String sessionMapID = WebUtil.readStrParam(request, ResourceConstants.ATTR_SESSION_MAP_ID); + SessionMap sessionMap = (SessionMap) request.getSession() + .getAttribute(sessionMapID); + Long sessionId = (Long) sessionMap.get(AttributeNames.PARAM_TOOL_SESSION_ID); + + // check for existing notebook entry + NotebookEntry entry = resourceService.getEntry(sessionId, CoreNotebookConstants.NOTEBOOK_TOOL, + ResourceConstants.TOOL_SIGNATURE, userId); + + if (entry == null) { + // create new entry + resourceService.createNotebookEntry(sessionId, CoreNotebookConstants.NOTEBOOK_TOOL, + ResourceConstants.TOOL_SIGNATURE, userId, reflectionForm.getEntryText()); + } else { + // update existing entry + entry.setEntry(reflectionForm.getEntryText()); + entry.setLastModified(new Date()); + resourceService.updateEntry(entry); + } + + return finish(request); + } + + // ************************************************************************************* + // Private method + // ************************************************************************************* + private boolean validateBeforeFinish(HttpServletRequest request, String sessionMapID) { + SessionMap sessionMap = (SessionMap) request.getSession() + .getAttribute(sessionMapID); + Long sessionId = (Long) sessionMap.get(AttributeNames.PARAM_TOOL_SESSION_ID); + + HttpSession ss = SessionManager.getSession(); + UserDTO user = (UserDTO) ss.getAttribute(AttributeNames.USER); + Long userID = new Long(user.getUserID().longValue()); + + int miniViewFlag = resourceService.checkMiniView(sessionId, userID); + // if current user view less than reqired view count number, then just return error message. + if (miniViewFlag > 0) { + MultiValueMap errorMap = new LinkedMultiValueMap<>(); + errorMap.add("GLOBAL", messageService.getMessage("lable.learning.minimum.view.number.less" + miniViewFlag)); + request.setAttribute("errorMap", errorMap); + return false; + } + + return true; + } + + /** + * List save current resource items. + * + * @param request + * @return + */ + private SortedSet getResourceItemList(SessionMap sessionMap) { + SortedSet list = (SortedSet) sessionMap + .get(ResourceConstants.ATTR_RESOURCE_ITEM_LIST); + if (list == null) { + list = new TreeSet<>(new ResourceItemComparator()); + sessionMap.put(ResourceConstants.ATTR_RESOURCE_ITEM_LIST, list); + } + return list; + } + + /** + * Get java.util.List from HttpSession by given name. + * + * @param request + * @param name + * @return + */ + private List getListFromSession(SessionMap sessionMap, String name) { + List list = (List) sessionMap.get(name); + if (list == null) { + list = new ArrayList(); + sessionMap.put(name, list); + } + return list; + } + + /** + * Return ActionForward according to resource item type. + * + * @param type + * @param mapping + * @return + */ + private ActionForward findForward(short type, ActionMapping mapping) { + ActionForward forward; + switch (type) { + case ResourceConstants.RESOURCE_TYPE_URL: + forward = mapping.findForward("url"); + break; + case ResourceConstants.RESOURCE_TYPE_FILE: + forward = mapping.findForward("file"); + break; + case ResourceConstants.RESOURCE_TYPE_WEBSITE: + forward = mapping.findForward("website"); + break; + case ResourceConstants.RESOURCE_TYPE_LEARNING_OBJECT: + forward = mapping.findForward("learningobject"); + break; + default: + forward = null; + break; + } + return forward; + } + + private ResourceUser getCurrentUser(IResourceService service, Long sessionId) { + // try to get form system session + HttpSession ss = SessionManager.getSession(); + // get back login user DTO + UserDTO user = (UserDTO) ss.getAttribute(AttributeNames.USER); + ResourceUser resourceUser = service.getUserByIDAndSession(new Long(user.getUserID().intValue()), sessionId); + + if (resourceUser == null) { + ResourceSession session = service.getResourceSessionBySessionId(sessionId); + resourceUser = new ResourceUser(user, session); + service.createUser(resourceUser); + } + return resourceUser; + } + + private ResourceUser getSpecifiedUser(IResourceService service, Long sessionId, Integer userId) { + ResourceUser resourceUser = service.getUserByIDAndSession(new Long(userId.intValue()), sessionId); + if (resourceUser == null) { + LearningController.log.error( + "Unable to find specified user for share resources activity. Screens are likely to fail. SessionId=" + + sessionId + " UserId=" + userId); + } + return resourceUser; + } + + /** + * @param resourceItemForm + * @return + */ + private void validateResourceItem(ResourceItemForm resourceItemForm, MultiValueMap errorMap) { + ActionErrors errors = new ActionErrors(); + if (StringUtils.isBlank(resourceItemForm.getTitle())) { + errorMap.add("GLOBAL", messageService.getMessage(ResourceConstants.ERROR_MSG_TITLE_BLANK)); + } + + if (resourceItemForm.getItemType() == ResourceConstants.RESOURCE_TYPE_URL) { + if (StringUtils.isBlank(resourceItemForm.getUrl())) { + errorMap.add("GLOBAL", messageService.getMessage(ResourceConstants.ERROR_MSG_URL_BLANK)); + // URL validation: Commom URL validate(1.3.0) work not very well: it can not support http://address:port + // format!!! + // UrlValidator validator = new UrlValidator(); + // if(!validator.isValid(itemForm.getUrl())) + // errors.add(ActionMessages.GLOBAL_MESSAGE,new ActionMessage(ResourceConstants.ERROR_MSG_INVALID_URL)); + } + } + // if(itemForm.getItemType() == ResourceConstants.RESOURCE_TYPE_WEBSITE + // ||itemForm.getItemType() == ResourceConstants.RESOURCE_TYPE_LEARNING_OBJECT){ + // if(StringUtils.isBlank(itemForm.getDescription())) + // errors.add(ActionMessages.GLOBAL_MESSAGE,new ActionMessage(ResourceConstants.ERROR_MSG_DESC_BLANK)); + // } + if ((resourceItemForm.getItemType() == ResourceConstants.RESOURCE_TYPE_WEBSITE) + || (resourceItemForm.getItemType() == ResourceConstants.RESOURCE_TYPE_LEARNING_OBJECT) + || (resourceItemForm.getItemType() == ResourceConstants.RESOURCE_TYPE_FILE)) { + + if ((resourceItemForm.getFile() != null) + && FileUtil.isExecutableFile(resourceItemForm.getFile().getOriginalFilename())) { + errorMap.add("Global", messageService.getMessage("error.attachment.executable")); + } + + // validate item size + FileValidatorSpringUtil.validateFileSize(resourceItemForm.getFile(), false); + + // for edit validate: file already exist + if (!resourceItemForm.isHasFile() && ((resourceItemForm.getFile() == null) + || StringUtils.isEmpty(resourceItemForm.getFile().getOriginalFilename()))) { + errorMap.add("GLOBAL", messageService.getMessage(ResourceConstants.ERROR_MSG_FILE_BLANK)); + } + } + } + + /** + * Set complete flag for given resource item. + * + * @param request + * @param sessionId + */ + private void doComplete(HttpServletRequest request) { + // get back sessionMap + String sessionMapID = request.getParameter(ResourceConstants.ATTR_SESSION_MAP_ID); + SessionMap sessionMap = (SessionMap) request.getSession() + .getAttribute(sessionMapID); + + Long resourceItemUid = new Long(request.getParameter(ResourceConstants.PARAM_RESOURCE_ITEM_UID)); + HttpSession ss = SessionManager.getSession(); + // get back login user DTO + UserDTO user = (UserDTO) ss.getAttribute(AttributeNames.USER); + + Long sessionId = (Long) sessionMap.get(ResourceConstants.ATTR_TOOL_SESSION_ID); + resourceService.setItemComplete(resourceItemUid, new Long(user.getUserID().intValue()), sessionId); + + // set resource item complete tag + SortedSet resourceItemList = getResourceItemList(sessionMap); + for (ResourceItem item : resourceItemList) { + if (item.getUid().equals(resourceItemUid)) { + item.setComplete(true); + break; + } + } + } + + @RequestMapping("/hideItem") + private ActionForward hideItem(HttpServletRequest request, HttpServletResponse response) throws IOException { + HttpSession ss = SessionManager.getSession(); + UserDTO user = (UserDTO) ss.getAttribute(AttributeNames.USER); + Long itemUid = WebUtil.readLongParam(request, ResourceConstants.PARAM_RESOURCE_ITEM_UID); + + // get back sessionMap + String sessionMapID = request.getParameter(ResourceConstants.ATTR_SESSION_MAP_ID); + SessionMap sessionMap = (SessionMap) request.getSession() + .getAttribute(sessionMapID); + Long sessionId = (Long) sessionMap.get(ResourceConstants.ATTR_TOOL_SESSION_ID); + Long contentId = (Long) sessionMap.get(ResourceConstants.ATTR_TOOL_CONTENT_ID); + ResourceItem resourceItem = resourceService.getResourceItemByUid(itemUid); + if (!resourceItem.isCreateByAuthor() + && user.getUserID().longValue() == resourceItem.getCreateBy().getUserId()) { + resourceService.setItemVisible(itemUid, sessionId, contentId, false); + //open session Map + } else { + response.sendError(HttpServletResponse.SC_FORBIDDEN, "You are not allowed to hide this item"); + } + return null; + } +} \ No newline at end of file Index: lams_tool_larsrc/src/java/org/lamsfoundation/lams/tool/rsrc/web/controller/MonitoringController.java =================================================================== diff -u --- lams_tool_larsrc/src/java/org/lamsfoundation/lams/tool/rsrc/web/controller/MonitoringController.java (revision 0) +++ lams_tool_larsrc/src/java/org/lamsfoundation/lams/tool/rsrc/web/controller/MonitoringController.java (revision 6d9587c552af599d4fc4e68399d218f5f4ca7cf4) @@ -0,0 +1,249 @@ +/**************************************************************** + * 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.rsrc.web.controller; + +import java.io.IOException; +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.List; +import java.util.TimeZone; + +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.lamsfoundation.lams.notebook.model.NotebookEntry; +import org.lamsfoundation.lams.notebook.service.CoreNotebookConstants; +import org.lamsfoundation.lams.tool.rsrc.ResourceConstants; +import org.lamsfoundation.lams.tool.rsrc.dto.ReflectDTO; +import org.lamsfoundation.lams.tool.rsrc.dto.ResourceItemDTO; +import org.lamsfoundation.lams.tool.rsrc.dto.SessionDTO; +import org.lamsfoundation.lams.tool.rsrc.dto.VisitLogDTO; +import org.lamsfoundation.lams.tool.rsrc.model.Resource; +import org.lamsfoundation.lams.tool.rsrc.model.ResourceSession; +import org.lamsfoundation.lams.tool.rsrc.model.ResourceUser; +import org.lamsfoundation.lams.tool.rsrc.service.IResourceService; +import org.lamsfoundation.lams.usermanagement.dto.UserDTO; +import org.lamsfoundation.lams.util.DateUtil; +import org.lamsfoundation.lams.util.WebUtil; +import org.lamsfoundation.lams.web.session.SessionManager; +import org.lamsfoundation.lams.web.util.AttributeNames; +import org.lamsfoundation.lams.web.util.SessionMap; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; +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; + +@Controller +@RequestMapping("/monitoring") +public class MonitoringController { + public static Logger log = Logger.getLogger(MonitoringController.class); + + @Autowired + @Qualifier("resourceService") + private IResourceService resourceService; + + @RequestMapping("/summary") + private String summary(HttpServletRequest request) { + // initial Session Map + SessionMap sessionMap = new SessionMap(); + request.getSession().setAttribute(sessionMap.getSessionID(), sessionMap); + request.setAttribute(ResourceConstants.ATTR_SESSION_MAP_ID, sessionMap.getSessionID()); + // save contentFolderID into session + sessionMap.put(AttributeNames.PARAM_CONTENT_FOLDER_ID, + WebUtil.readStrParam(request, AttributeNames.PARAM_CONTENT_FOLDER_ID)); + + Long contentId = WebUtil.readLongParam(request, AttributeNames.PARAM_TOOL_CONTENT_ID); + List groupList = resourceService.getSummary(contentId); + + Resource resource = resourceService.getResourceByContentId(contentId); + + // Create reflectList if reflection is enabled. + if (resource.isReflectOnActivity()) { + List relectList = resourceService.getReflectList(contentId); + sessionMap.put(ResourceConstants.ATTR_REFLECT_LIST, relectList); + } + + // cache into sessionMap + sessionMap.put(ResourceConstants.ATTR_SUMMARY_LIST, groupList); + sessionMap.put(ResourceConstants.PAGE_EDITABLE, resource.isContentInUse()); + sessionMap.put(ResourceConstants.ATTR_RESOURCE, resource); + sessionMap.put(ResourceConstants.ATTR_TOOL_CONTENT_ID, contentId); + sessionMap.put(ResourceConstants.ATTR_IS_GROUPED_ACTIVITY, resourceService.isGroupedActivity(contentId)); + return "pages/monitoring/monitoring"; + } + + @RequestMapping("/listuser") + private String listuser(HttpServletRequest request) { + Long sessionId = WebUtil.readLongParam(request, AttributeNames.PARAM_TOOL_SESSION_ID); + Long itemUid = WebUtil.readLongParam(request, ResourceConstants.PARAM_RESOURCE_ITEM_UID); + + // get user list by given item uid + List list = resourceService.getUserListBySessionItem(sessionId, itemUid); + + // set to request + request.setAttribute(ResourceConstants.ATTR_USER_LIST, list); + return "pages/monitoring/userlist"; + } + + @RequestMapping("/getSubgridData") + private String getSubgridData(HttpServletRequest request, HttpServletResponse response) throws IOException { + + Long itemUid = WebUtil.readLongParam(request, ResourceConstants.ATTR_RESOURCE_ITEM_UID); + Long sessionId = WebUtil.readLongParam(request, AttributeNames.PARAM_TOOL_SESSION_ID); + + // Getting the params passed in from the jqGrid + int page = WebUtil.readIntParam(request, AttributeNames.PARAM_PAGE); + int rowLimit = WebUtil.readIntParam(request, AttributeNames.PARAM_ROWS); + String sortOrder = WebUtil.readStrParam(request, AttributeNames.PARAM_SORD); + String sortBy = WebUtil.readStrParam(request, AttributeNames.PARAM_SIDX, true); + if (StringUtils.isEmpty(sortBy)) { + sortBy = "userName"; + } + String searchString = WebUtil.readStrParam(request, "userName", true); + + List visitLogDtos = resourceService.getPagedVisitLogsBySessionAndItem(sessionId, itemUid, page - 1, + rowLimit, sortBy, sortOrder, searchString); + int countVisitLogs = resourceService.getCountVisitLogsBySessionAndItem(sessionId, itemUid, searchString); + + int totalPages = new Double( + Math.ceil(new Integer(countVisitLogs).doubleValue() / new Integer(rowLimit).doubleValue())).intValue(); + + ArrayNode rows = JsonNodeFactory.instance.arrayNode(); + DateFormat timeTakenFormatter = new SimpleDateFormat("H:mm:ss"); + DateFormat dateFormatter = new SimpleDateFormat("d-MMM-yyyy h:mm a"); + HttpSession ss = SessionManager.getSession(); + UserDTO learnerDto = (UserDTO) ss.getAttribute(AttributeNames.USER); + TimeZone monitorTimeZone = learnerDto.getTimeZone(); + int i = 1; + for (VisitLogDTO visitLogDto : visitLogDtos) { + + ArrayNode visitLogData = JsonNodeFactory.instance.arrayNode(); + visitLogData.add(visitLogDto.getUserId()); + String fullName = HtmlUtils.htmlEscape(visitLogDto.getUserFullName()); + visitLogData.add(fullName); + String accessDate = (visitLogDto.getAccessDate() == null) ? "" + : dateFormatter.format( + DateUtil.convertToTimeZoneFromDefault(monitorTimeZone, visitLogDto.getAccessDate())); + visitLogData.add(accessDate); + String completeDate = (visitLogDto.getCompleteDate() == null) ? "" + : dateFormatter.format( + DateUtil.convertToTimeZoneFromDefault(monitorTimeZone, visitLogDto.getCompleteDate())); + visitLogData.add(completeDate); + String timeTaken = (visitLogDto.getTimeTaken() == null) ? "" + : timeTakenFormatter.format(visitLogDto.getTimeTaken()); + visitLogData.add(timeTaken); + visitLogData.add(visitLogDto.getPortraitId()); + + ObjectNode userRow = JsonNodeFactory.instance.objectNode(); + userRow.put("id", i++); + userRow.set("cell", visitLogData); + + rows.add(userRow); + } + + ObjectNode responseJSON = JsonNodeFactory.instance.objectNode(); + responseJSON.put("total", totalPages); + responseJSON.put("page", page); + responseJSON.put("records", countVisitLogs); + responseJSON.set("rows", rows); + + response.setContentType("application/json;charset=utf-8"); + response.getWriter().write(responseJSON.toString()); + return null; + } + + @RequestMapping("/changeItemVisibility") + private String changeItemVisibility(HttpServletRequest request) { + Long itemUid = WebUtil.readLongParam(request, ResourceConstants.PARAM_RESOURCE_ITEM_UID); + boolean isHideItem = WebUtil.readBooleanParam(request, ResourceConstants.PARAM_IS_HIDE_ITEM); + Long sessionId = WebUtil.readLongParam(request, AttributeNames.PARAM_TOOL_SESSION_ID); + Long contentId = WebUtil.readLongParam(request, AttributeNames.PARAM_TOOL_CONTENT_ID); + resourceService.setItemVisible(itemUid, sessionId, contentId, !isHideItem); + + return null; + } + + @RequestMapping("/viewReflection") + private String viewReflection(HttpServletRequest request) { + + Long uid = WebUtil.readLongParam(request, ResourceConstants.ATTR_USER_UID); + Long sessionID = WebUtil.readLongParam(request, AttributeNames.PARAM_TOOL_SESSION_ID); + + ResourceUser user = resourceService.getUser(uid); + NotebookEntry notebookEntry = resourceService.getEntry(sessionID, CoreNotebookConstants.NOTEBOOK_TOOL, + ResourceConstants.TOOL_SIGNATURE, user.getUserId().intValue()); + + ResourceSession session = resourceService.getResourceSessionBySessionId(sessionID); + + ReflectDTO refDTO = new ReflectDTO(user); + if (notebookEntry == null) { + refDTO.setFinishReflection(false); + refDTO.setReflect(null); + } else { + refDTO.setFinishReflection(true); + refDTO.setReflect(notebookEntry.getEntry()); + } + refDTO.setReflectInstrctions(session.getResource().getReflectInstructions()); + + request.setAttribute("userDTO", refDTO); + return "pages/monitoring/reflections"; + } + + @RequestMapping("/viewComments") + private String viewComments(HttpServletRequest request) { + + Long itemUid = WebUtil.readLongParam(request, ResourceConstants.ATTR_RESOURCE_ITEM_UID); + Long sessionId = WebUtil.readLongParam(request, AttributeNames.PARAM_TOOL_SESSION_ID); + + String sessionMapID = WebUtil.readStrParam(request, ResourceConstants.ATTR_SESSION_MAP_ID); + SessionMap sessionMap = (SessionMap) request.getSession() + .getAttribute(sessionMapID); + List sessionList = (List) sessionMap.get(ResourceConstants.ATTR_SUMMARY_LIST); + for (SessionDTO session : sessionList) { + if (session.getSessionId().equals(sessionId)) { + for (ResourceItemDTO item : session.getItems()) { + if (item.getItemUid().equals(itemUid)) { + request.setAttribute("itemTitle", item.getItemTitle()); + break; + } + } + break; + } + } + + request.setAttribute(ResourceConstants.ATTR_RESOURCE_ITEM_UID, itemUid); + request.setAttribute(ResourceConstants.ATTR_TOOL_SESSION_ID, sessionId); + request.setAttribute("mode", "teacher"); + return "pages/monitoring/comments"; + } + +} Index: lams_tool_larsrc/src/java/org/lamsfoundation/lams/tool/rsrc/web/controller/ViewItemController.java =================================================================== diff -u --- lams_tool_larsrc/src/java/org/lamsfoundation/lams/tool/rsrc/web/controller/ViewItemController.java (revision 0) +++ lams_tool_larsrc/src/java/org/lamsfoundation/lams/tool/rsrc/web/controller/ViewItemController.java (revision 6d9587c552af599d4fc4e68399d218f5f4ca7cf4) @@ -0,0 +1,330 @@ +/**************************************************************** + * 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.rsrc.web.controller; + +import java.util.ArrayList; +import java.util.List; +import java.util.Set; +import java.util.SortedSet; +import java.util.TreeSet; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpSession; + +import org.apache.commons.lang.math.NumberUtils; +import org.apache.log4j.Logger; +import org.lamsfoundation.lams.tool.ToolAccessMode; +import org.lamsfoundation.lams.tool.rsrc.ResourceConstants; +import org.lamsfoundation.lams.tool.rsrc.dto.InstructionNavDTO; +import org.lamsfoundation.lams.tool.rsrc.model.ResourceItem; +import org.lamsfoundation.lams.tool.rsrc.model.ResourceItemInstruction; +import org.lamsfoundation.lams.tool.rsrc.service.IResourceService; +import org.lamsfoundation.lams.tool.rsrc.util.ResourceItemComparator; +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.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; + +@Controller +public class ViewItemController { + + private static final Logger log = Logger.getLogger(ViewItemController.class); + + @Autowired + @Qualifier("resourceService") + private IResourceService resourceService; + + /** + * Display main frame to display instrcution and item content. + * + * @param mapping + * @param form + * @param request + * @param response + * @return + */ + + @RequestMapping("/reviewItem") + private String reviewItem(HttpServletRequest request) { + String mode = request.getParameter(AttributeNames.ATTR_MODE); + + String sessionMapID = WebUtil.readStrParam(request, ResourceConstants.ATTR_SESSION_MAP_ID); + SessionMap sessionMap = (SessionMap) request.getSession() + .getAttribute(sessionMapID); + + ResourceItem item = getResourceItem(request, sessionMap, mode); + + String idStr = request.getParameter(ResourceConstants.ATTR_TOOL_SESSION_ID); + Long sessionId = NumberUtils.createLong(idStr); + // mark this item access flag if it is learner + if (ToolAccessMode.LEARNER.toString().equals(mode)) { + HttpSession ss = SessionManager.getSession(); + // get back login user DTO + UserDTO user = (UserDTO) ss.getAttribute(AttributeNames.USER); + resourceService.setItemAccess(item.getUid(), new Long(user.getUserID().intValue()), sessionId); + } + + if (item == null) { + return "error"; + } + if (item.getType() == ResourceConstants.RESOURCE_TYPE_LEARNING_OBJECT) { + sessionMap.put(ResourceConstants.ATT_LEARNING_OBJECT, item); + } + // set url to content frame + + int itemIdx = NumberUtils.stringToInt(request.getParameter(ResourceConstants.PARAM_ITEM_INDEX)); + request.setAttribute(ResourceConstants.ATTR_RESOURCE_REVIEW_URL, + getReviewUrl(request, item, sessionMapID, mode, itemIdx)); + + request.setAttribute(ResourceConstants.ATTR_ALLOW_COMMENTS, item.isAllowComments()); + + // these attribute will be use to instruction navigator page + request.setAttribute(AttributeNames.ATTR_MODE, mode); + request.setAttribute(ResourceConstants.PARAM_ITEM_INDEX, itemIdx); + Long itemUid = NumberUtils.createLong(request.getParameter(ResourceConstants.PARAM_RESOURCE_ITEM_UID)); + request.setAttribute(ResourceConstants.PARAM_RESOURCE_ITEM_UID, itemUid); + request.setAttribute(ResourceConstants.ATTR_TOOL_SESSION_ID, sessionId); + request.setAttribute(ResourceConstants.ATTR_SESSION_MAP_ID, sessionMapID); + + return "pages/itemreview/mainframe"; + + } + + /** + * Return next instrucion to page. It need four input parameters, mode, itemIndex or itemUid, and insIdx. + * + * @param mapping + * @param form + * @param request + * @param response + * @return + */ + + @RequestMapping("/nextInstruction") + private String nextInstruction(HttpServletRequest request) { + String mode = request.getParameter(AttributeNames.ATTR_MODE); + + String sessionMapID = WebUtil.readStrParam(request, ResourceConstants.ATTR_SESSION_MAP_ID); + SessionMap sesionMap = (SessionMap) request.getSession() + .getAttribute(sessionMapID); + + ResourceItem item = getResourceItem(request, sesionMap, mode); + if (item == null) { + return "error"; + } + + int currIns = NumberUtils.stringToInt(request.getParameter(ResourceConstants.PARAM_CURRENT_INSTRUCTION_INDEX), + 0); + + Set instructions = item.getItemInstructions(); + InstructionNavDTO navDto = new InstructionNavDTO(); + // For Learner upload item, its instruction will display description/comment fields in ReosourceItem. + if (!item.isCreateByAuthor()) { + List navItems = new ArrayList<>(1); + // create a new instruction and put ResourceItem description into it: just for display use. + ResourceItemInstruction ins = new ResourceItemInstruction(); + ins.setSequenceId(1); + ins.setDescription(item.getDescription()); + navItems.add(ins); + navDto.setAllInstructions(navItems); + instructions.add(ins); + } else { + navDto.setAllInstructions(new ArrayList(instructions)); + } + navDto.setTitle(item.getTitle()); + navDto.setType(item.getType()); + navDto.setTotal(instructions.size()); + if (instructions.size() > 0) { + navDto.setInstruction((ResourceItemInstruction) new ArrayList(instructions).get(currIns)); + navDto.setCurrent(currIns + 1); + } else { + navDto.setCurrent(0); + navDto.setInstruction(null); + } + + request.setAttribute(ResourceConstants.ATTR_SESSION_MAP_ID, sessionMapID); + request.setAttribute(ResourceConstants.ATTR_RESOURCE_INSTRUCTION, navDto); + return "pages/itemreview/instructionsnav"; + } + + /** + * Open url or file in a popup window page. + * + * @param mapping + * @param form + * @param request + * @param response + * @return + */ + + @RequestMapping("/openUrlPopup") + private String openUrlPopup(HttpServletRequest request) { + String mode = request.getParameter(AttributeNames.ATTR_MODE); + + String sessionMapID = WebUtil.readStrParam(request, ResourceConstants.ATTR_SESSION_MAP_ID); + SessionMap sessionMap = (SessionMap) request.getSession() + .getAttribute(sessionMapID); + + ResourceItem item = getResourceItem(request, sessionMap, mode); + + boolean isUrlItemType = item.getType() == ResourceConstants.RESOURCE_TYPE_URL; + request.setAttribute(ResourceConstants.ATTR_IS_URL_ITEM_TYPE, isUrlItemType); + + String popupUrl = (isUrlItemType) ? item.getUrl() + : "/download/?uuid=" + item.getFileUuid() + "&preferDownload=false"; + request.setAttribute(ResourceConstants.PARAM_OPEN_URL_POPUP, popupUrl); + + request.setAttribute(ResourceConstants.PARAM_TITLE, item.getTitle()); + return "pages/itemreview/openurl"; + } + + // ************************************************************************************* + // Private method + // ************************************************************************************* + /** + * Return resource item according to ToolAccessMode. + * + * @param request + * @param sessionMap + * @param mode + * @return + */ + private ResourceItem getResourceItem(HttpServletRequest request, SessionMap sessionMap, + String mode) { + ResourceItem item = null; + if (ResourceConstants.MODE_AUTHOR_SESSION.equals(mode)) { + int itemIdx = NumberUtils.stringToInt(request.getParameter(ResourceConstants.PARAM_ITEM_INDEX), 0); + // authoring: does not save item yet, so only has ItemList from session and identity by Index + List resourceList = new ArrayList<>(getResourceItemList(sessionMap)); + item = resourceList.get(itemIdx); + } else { + Long itemUid = NumberUtils.createLong(request.getParameter(ResourceConstants.PARAM_RESOURCE_ITEM_UID)); + // get back the resource and item list and display them on page + item = resourceService.getResourceItemByUid(itemUid); + } + return item; + } + + private static Pattern usePopupButtonForURL = Pattern.compile("wikipedia|google", + Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE); + private static Pattern protocolExists = Pattern.compile("http://|https://|ftp://|nntp://", + Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE); + private static Pattern httpPattern = Pattern.compile("http://", Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE); + public static final String DEFAULT_PROTOCOL = "http://"; + public static final String HTTPS_SCHEME = "https"; + + private Object getReviewUrl(HttpServletRequest request, ResourceItem item, String sessionMapID, String mode, + int itemIdx) { + short type = item.getType(); + String url = null; + switch (type) { + case ResourceConstants.RESOURCE_TYPE_URL: + // protocol missing? Assume http. Must do before the popup checks otherwise LDEV-4503 case may be missed. + url = item.getUrl(); + if (!protocolExists.matcher(url).find()) { + url = DEFAULT_PROTOCOL + url; + } + + // check all three cases that trigger popup - first is set in authoring + boolean usePopup = item.isOpenUrlNewWindow(); + // See LDEV-4503 regarding https/http issues + if (!usePopup) { + String serverScheme = request.getScheme(); + usePopup = HTTPS_SCHEME.equalsIgnoreCase(serverScheme) && httpPattern.matcher(url).find(); + } + // See LDEV-1736 regarding wikipedia regex + if (!usePopup) { + Matcher matcher = usePopupButtonForURL.matcher(url); + usePopup = matcher.find(); + } + + if (usePopup) { + url = constructUrlOpenInNewWindow(item, sessionMapID, mode, itemIdx); + } + break; + + case ResourceConstants.RESOURCE_TYPE_FILE: + if (item.isOpenUrlNewWindow()) { + url = constructUrlOpenInNewWindow(item, sessionMapID, mode, itemIdx); + } else { + url = "/download/?uuid=" + item.getFileUuid() + "&preferDownload=false"; + } + break; + + case ResourceConstants.RESOURCE_TYPE_WEBSITE: + url = "/download/?uuid=" + item.getFileUuid() + "&preferDownload=false"; + break; + + case ResourceConstants.RESOURCE_TYPE_LEARNING_OBJECT: + url = "/pages/learningobj/mainframe.jsp?sessionMapID=" + sessionMapID; + break; + } + return url; + } + + /** + * Creates url for opening in a new window depending whether it's authoring environment or not. + * + * @param item + * @param sessionMapID + * @param mode + * @param itemIdx + * @return + */ + private String constructUrlOpenInNewWindow(ResourceItem item, String sessionMapID, String mode, int itemIdx) { + String url; + if (ResourceConstants.MODE_AUTHOR_SESSION.equals(mode)) { + url = "/openUrlPopup.do?" + AttributeNames.ATTR_MODE + "=" + mode + "&" + ResourceConstants.PARAM_ITEM_INDEX + + "=" + itemIdx + "&" + ResourceConstants.ATTR_SESSION_MAP_ID + "=" + sessionMapID; + } else { + url = "/openUrlPopup.do?" + ResourceConstants.PARAM_RESOURCE_ITEM_UID + "=" + item.getUid() + "&" + + ResourceConstants.ATTR_SESSION_MAP_ID + "=" + sessionMapID; + } + + return url; + } + + /** + * List save current resource items. + * + * @param request + * @return + */ + private SortedSet getResourceItemList(SessionMap sessionMap) { + SortedSet list = (SortedSet) sessionMap.get(ResourceConstants.ATTR_RESOURCE_ITEM_LIST); + if (list == null) { + list = new TreeSet<>(new ResourceItemComparator()); + sessionMap.put(ResourceConstants.ATTR_RESOURCE_ITEM_LIST, list); + } + return list; + } + +} Index: lams_tool_larsrc/src/java/org/lamsfoundation/lams/tool/rsrc/web/form/ReflectionForm.java =================================================================== diff -u -r2f725f8ef2aa09a2663b2335bf67213074426d11 -r6d9587c552af599d4fc4e68399d218f5f4ca7cf4 --- lams_tool_larsrc/src/java/org/lamsfoundation/lams/tool/rsrc/web/form/ReflectionForm.java (.../ReflectionForm.java) (revision 2f725f8ef2aa09a2663b2335bf67213074426d11) +++ lams_tool_larsrc/src/java/org/lamsfoundation/lams/tool/rsrc/web/form/ReflectionForm.java (.../ReflectionForm.java) (revision 6d9587c552af599d4fc4e68399d218f5f4ca7cf4) @@ -21,7 +21,6 @@ * **************************************************************** */ - package org.lamsfoundation.lams.tool.rsrc.web.form; import org.apache.log4j.Logger; Index: lams_tool_larsrc/src/java/org/lamsfoundation/lams/tool/rsrc/web/form/ResourceForm.java =================================================================== diff -u -r2f725f8ef2aa09a2663b2335bf67213074426d11 -r6d9587c552af599d4fc4e68399d218f5f4ca7cf4 --- lams_tool_larsrc/src/java/org/lamsfoundation/lams/tool/rsrc/web/form/ResourceForm.java (.../ResourceForm.java) (revision 2f725f8ef2aa09a2663b2335bf67213074426d11) +++ lams_tool_larsrc/src/java/org/lamsfoundation/lams/tool/rsrc/web/form/ResourceForm.java (.../ResourceForm.java) (revision 6d9587c552af599d4fc4e68399d218f5f4ca7cf4) @@ -23,12 +23,7 @@ package org.lamsfoundation.lams.tool.rsrc.web.form; -import javax.servlet.http.HttpServletRequest; - -import org.apache.commons.lang.StringUtils; import org.apache.log4j.Logger; -import org.apache.struts.action.ActionForm; -import org.apache.struts.action.ActionMapping; import org.apache.struts.upload.FormFile; import org.lamsfoundation.lams.tool.rsrc.model.Resource; @@ -40,7 +35,7 @@ * * User: Dapeng.Ni */ -public class ResourceForm extends ActionForm { +public class ResourceForm { private static final long serialVersionUID = 3599879328307492312L; private static Logger logger = Logger.getLogger(ResourceForm.class.getName()); @@ -51,6 +46,7 @@ private int currentTab; private FormFile offlineFile; private FormFile onlineFile; + private Resource resource; @@ -68,21 +64,6 @@ } } - @Override - public void reset(ActionMapping mapping, HttpServletRequest request) { - String param = mapping.getParameter(); - // if it is start page, all data read out from database or current session - // so need not reset checkbox to refresh value! - if (!StringUtils.equals(param, "start") && !StringUtils.equals(param, "initPage")) { - resource.setAllowAddFiles(false); - resource.setAllowAddUrls(false); - resource.setLockWhenFinished(false); - resource.setDefineLater(false); - resource.setRunAuto(false); - resource.setReflectOnActivity(false); - } - } - public int getCurrentTab() { return currentTab; } Index: lams_tool_larsrc/src/java/org/lamsfoundation/lams/tool/rsrc/web/form/ResourceItemForm.java =================================================================== diff -u -r1bf70a335f5b30a1907ccae506908b05374c6c8c -r6d9587c552af599d4fc4e68399d218f5f4ca7cf4 --- lams_tool_larsrc/src/java/org/lamsfoundation/lams/tool/rsrc/web/form/ResourceItemForm.java (.../ResourceItemForm.java) (revision 1bf70a335f5b30a1907ccae506908b05374c6c8c) +++ lams_tool_larsrc/src/java/org/lamsfoundation/lams/tool/rsrc/web/form/ResourceItemForm.java (.../ResourceItemForm.java) (revision 6d9587c552af599d4fc4e68399d218f5f4ca7cf4) @@ -23,8 +23,7 @@ package org.lamsfoundation.lams.tool.rsrc.web.form; -import org.apache.struts.action.ActionForm; -import org.apache.struts.upload.FormFile; +import org.springframework.web.multipart.MultipartFile; /** * Resource Item Form. @@ -33,7 +32,7 @@ * * @version $Revision$ */ -public class ResourceItemForm extends ActionForm { +public class ResourceItemForm { private String itemIndex; private String sessionMapID; @@ -50,10 +49,9 @@ private Long fileUuid; private Long fileVersionId; private String fileName; - private FormFile file; + private MultipartFile file; private boolean allowRating; private boolean allowComments; - public String getDescription() { return description; @@ -63,11 +61,11 @@ this.description = description; } - public FormFile getFile() { + public MultipartFile getFile() { return file; } - public void setFile(FormFile file) { + public void setFile(MultipartFile file) { this.file = file; } @@ -168,10 +166,10 @@ } public boolean isAllowComments() { - return allowComments; + return allowComments; } public void setAllowComments(boolean allowComments) { - this.allowComments = allowComments; + this.allowComments = allowComments; } } Index: lams_tool_larsrc/src/java/org/lamsfoundation/lams/tool/rsrc/web/form/ResourcePedagogicalPlannerForm.java =================================================================== diff -u -r3b02999189bd74f83f390d8c340d34188923cde7 -r6d9587c552af599d4fc4e68399d218f5f4ca7cf4 --- lams_tool_larsrc/src/java/org/lamsfoundation/lams/tool/rsrc/web/form/ResourcePedagogicalPlannerForm.java (.../ResourcePedagogicalPlannerForm.java) (revision 3b02999189bd74f83f390d8c340d34188923cde7) +++ lams_tool_larsrc/src/java/org/lamsfoundation/lams/tool/rsrc/web/form/ResourcePedagogicalPlannerForm.java (.../ResourcePedagogicalPlannerForm.java) (revision 6d9587c552af599d4fc4e68399d218f5f4ca7cf4) @@ -20,7 +20,6 @@ * **************************************************************** */ - package org.lamsfoundation.lams.tool.rsrc.web.form; import java.util.ArrayList; @@ -29,25 +28,23 @@ import org.apache.commons.lang.StringUtils; import org.apache.struts.action.ActionMessage; -import org.apache.struts.action.ActionMessages; -import org.apache.struts.upload.FormFile; import org.lamsfoundation.lams.tool.rsrc.ResourceConstants; import org.lamsfoundation.lams.tool.rsrc.model.Resource; import org.lamsfoundation.lams.tool.rsrc.model.ResourceItem; -import org.lamsfoundation.lams.util.FileValidatorUtil; +import org.lamsfoundation.lams.util.FileValidatorSpringUtil; import org.lamsfoundation.lams.util.MessageService; -import org.lamsfoundation.lams.web.planner.PedagogicalPlannerActivityForm; import org.lamsfoundation.lams.web.planner.PedagogicalPlannerActivitySpringForm; import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; +import org.springframework.web.multipart.MultipartFile; /** * */ public class ResourcePedagogicalPlannerForm extends PedagogicalPlannerActivitySpringForm { private List title; private List url; - private List file; + private List file; private List fileName; private List fileUuid; private List fileVersion; @@ -67,22 +64,26 @@ allEmpty = false; Short itemType = type.get(index); // URL should not be blank - + if (itemType.equals(ResourceConstants.RESOURCE_TYPE_URL) && StringUtils.isEmpty(url.get(index))) { - errorMap.add("GLOBAL", messageService.getMessage("error.planner.url.blank", new Object[] {index + 1})); + errorMap.add("GLOBAL", + messageService.getMessage("error.planner.url.blank", new Object[] { index + 1 })); } else if (itemType.equals(ResourceConstants.RESOURCE_TYPE_FILE)) { /* * File should be saved already or it should be provided. This functionality required some * changes in pedagogicalPlanner.js in lams_central (see prepareFormData() there) */ - FileValidatorUtil.validateFileSize(file.get(index), true, errors); - if (fileUuid.get(index) == null && file.get(index) == null) { - ActionMessage error = new ActionMessage("error.planner.file.blank",(Object) (index + 1)); - errorMap.add("GLOBAL",messageService.getMessage("error.planner.file.blank", new Object[] {index + 1})); + boolean fileSizeValid = FileValidatorSpringUtil.validateFileSize(file.get(index), true); + if (!fileSizeValid) { + if (fileUuid.get(index) == null && file.get(index) == null) { + ActionMessage error = new ActionMessage("error.planner.file.blank", index + 1); + errorMap.add("GLOBAL", messageService.getMessage("error.planner.file.blank", + new Object[] { index + 1 })); + } } } - } + } } } if (allEmpty) { @@ -97,18 +98,19 @@ setValid(valid); return errorMap; + } public void fillForm(Resource resource) { if (resource != null) { setToolContentID(resource.getContentId()); setInstructions(resource.getInstructions()); - title = new ArrayList(); - url = new ArrayList(); - fileName = new ArrayList(); - file = new ArrayList(); - type = new ArrayList(); + title = new ArrayList<>(); + url = new ArrayList<>(); + fileName = new ArrayList<>(); + file = new ArrayList<>(); + type = new ArrayList<>(); Set items = resource.getResourceItems(); if (items != null) { int topicIndex = 0; @@ -131,7 +133,7 @@ public void setTitle(int number, String formTitle) { if (title == null) { - title = new ArrayList(); + title = new ArrayList<>(); } while (number >= title.size()) { title.add(null); @@ -152,7 +154,7 @@ public void setUrl(int number, String formUrl) { if (url == null) { - url = new ArrayList(); + url = new ArrayList<>(); } while (number >= url.size()) { url.add(null); @@ -169,7 +171,7 @@ public void setType(int number, Short formType) { if (type == null) { - type = new ArrayList(); + type = new ArrayList<>(); } while (number >= type.size()) { type.add(null); @@ -184,31 +186,31 @@ return type.get(number); } - public void setFile(int number, FormFile formFile) { + public void setFile(int number, MultipartFile MultipartFile) { if (file == null) { - file = new ArrayList(); + file = new ArrayList<>(); } while (number >= file.size()) { file.add(null); } - file.set(number, formFile); + file.set(number, MultipartFile); } - public FormFile getFile(int number) { + public MultipartFile getFile(int number) { if (file == null || number >= file.size()) { return null; } return file.get(number); } - public void setFileName(int number, String formFileName) { + public void setFileName(int number, String multipartFileName) { if (fileName == null) { - fileName = new ArrayList(); + fileName = new ArrayList<>(); } while (number >= fileName.size()) { fileName.add(null); } - fileName.set(number, formFileName); + fileName.set(number, multipartFileName); } public String getFileName(int number) { @@ -218,14 +220,14 @@ return fileName.get(number); } - public void setFileVersion(int number, Long formFileVersion) { + public void setFileVersion(int number, Long multipartFileVersion) { if (fileVersion == null) { - fileVersion = new ArrayList(); + fileVersion = new ArrayList<>(); } while (number >= fileVersion.size()) { fileVersion.add(null); } - fileVersion.set(number, formFileVersion); + fileVersion.set(number, multipartFileVersion); } public Long getFileVersion(int number) { @@ -235,17 +237,17 @@ return fileVersion.get(number); } - public void setFileUuid(int number, Long formFileUuid) { + public void setFileUuid(int number, Long multipartFileUuid) { if (fileUuid == null) { - fileUuid = new ArrayList(); + fileUuid = new ArrayList<>(); } while (number >= fileUuid.size()) { fileUuid.add(null); } - if (new Long(0).equals(formFileUuid)) { + if (new Long(0).equals(multipartFileUuid)) { fileUuid.set(number, null); } else { - fileUuid.set(number, formFileUuid); + fileUuid.set(number, multipartFileUuid); } } Index: lams_tool_larsrc/web/WEB-INF/spring-servlet.xml =================================================================== diff -u --- lams_tool_larsrc/web/WEB-INF/spring-servlet.xml (revision 0) +++ lams_tool_larsrc/web/WEB-INF/spring-servlet.xml (revision 6d9587c552af599d4fc4e68399d218f5f4ca7cf4) @@ -0,0 +1,17 @@ + + + + + + + + + + + \ No newline at end of file Index: lams_tool_larsrc/web/WEB-INF/tags/Page.tag =================================================================== diff -u -rb32cbfc76a3cd150823b3696160d5fd4fa6cde84 -r6d9587c552af599d4fc4e68399d218f5f4ca7cf4 --- lams_tool_larsrc/web/WEB-INF/tags/Page.tag (.../Page.tag) (revision b32cbfc76a3cd150823b3696160d5fd4fa6cde84) +++ lams_tool_larsrc/web/WEB-INF/tags/Page.tag (.../Page.tag) (revision 6d9587c552af599d4fc4e68399d218f5f4ca7cf4) @@ -4,6 +4,7 @@ <%@ taglib uri="tags-lams" prefix="lams"%> <%@ attribute name="type" required="true" rtexprvalue="true"%> +<%@ attribute name="formID" required="false" rtexprvalue="true"%> <%@ attribute name="style" required="false" rtexprvalue="true"%> <%@ attribute name="title" required="false" rtexprvalue="true"%> <%@ attribute name="titleHelpURL" required="false" rtexprvalue="true"%> @@ -88,8 +89,8 @@ - - + + ${toolForm.toolSessionID} @@ -434,4 +435,4 @@ - + \ No newline at end of file Index: lams_tool_larsrc/web/WEB-INF/tags/TextSearch.tag =================================================================== diff -u -r08a45e4407f4200f34653a91d402ac4ad2f43f50 -r6d9587c552af599d4fc4e68399d218f5f4ca7cf4 --- lams_tool_larsrc/web/WEB-INF/tags/TextSearch.tag (.../TextSearch.tag) (revision 08a45e4407f4200f34653a91d402ac4ad2f43f50) +++ lams_tool_larsrc/web/WEB-INF/tags/TextSearch.tag (.../TextSearch.tag) (revision 6d9587c552af599d4fc4e68399d218f5f4ca7cf4) @@ -32,12 +32,11 @@ <%@ tag body-content="scriptless" %> <%@ taglib uri="tags-core" prefix="c" %> <%@ taglib uri="tags-fmt" prefix="fmt" %> -<%@ taglib uri="tags-html" prefix="html" %> +<%@ taglib uri="http://www.springframework.org/tags/form" prefix="form" %> <%@ taglib uri="tags-lams" prefix="lams" %> <%-- Required attributes --%> <%@ attribute name="sessionMapID" required="true" rtexprvalue="true" %> -<%@ attribute name="wrapInFormTag" required="true" rtexprvalue="true" %> <%-- Optional attributes --%> <%@ attribute name="action" required="false" rtexprvalue="true" %> @@ -53,10 +52,10 @@ <%-- Default value for message key --%> - + - + @@ -85,52 +84,40 @@ - -
- - -

- - - - - - - - - - - - - - - - - -
- - - -
- - - -
- - - -
- - - -
- - - - - - - - - + +

+ + + + + + + + + + + + + + + + + +
+ + + +
+ + + +
+ + + +
+ + + +
\ No newline at end of file Index: lams_tool_larsrc/web/WEB-INF/tlds/lams/lams.tld =================================================================== diff -u -r60d9a173d5590295376322fc3e857ae2dca37717 -r6d9587c552af599d4fc4e68399d218f5f4ca7cf4 --- lams_tool_larsrc/web/WEB-INF/tlds/lams/lams.tld (.../lams.tld) (revision 60d9a173d5590295376322fc3e857ae2dca37717) +++ lams_tool_larsrc/web/WEB-INF/tlds/lams/lams.tld (.../lams.tld) (revision 6d9587c552af599d4fc4e68399d218f5f4ca7cf4) @@ -212,192 +212,6 @@ - - STRUTS-textarea - org.lamsfoundation.lams.web.tag.MultiLinesTextareaTag - empty - - accesskey - false - true - - - alt - false - true - - - altKey - false - true - - - bundle - false - true - - - cols - false - true - - - disabled - false - true - - - errorKey - false - true - - - errorStyle - false - true - - - errorStyleClass - false - true - - - errorStyleId - false - true - - - index - false - true - - - indexed - false - true - - - name - false - true - - - onblur - false - true - - - onchange - false - true - - - onclick - false - true - - - ondblclick - false - true - - - onfocus - false - true - - - onkeydown - false - true - - - onkeypress - false - true - - - onkeyup - false - true - - - onmousedown - false - true - - - onmousemove - false - true - - - onmouseout - false - true - - - onmouseover - false - true - - - onmouseup - false - true - - - property - true - true - - - readonly - false - true - - - rows - false - true - - - style - false - true - - - styleClass - false - true - - - styleId - false - true - - - tabindex - false - true - - - title - false - true - - - titleKey - false - true - - - value - false - true - - - Small portrait of a user User Portrait Index: lams_tool_larsrc/web/WEB-INF/web.xml =================================================================== diff -u -rac280c8fb2043ec90a0b7756ede0c7ab64c089d8 -r6d9587c552af599d4fc4e68399d218f5f4ca7cf4 --- lams_tool_larsrc/web/WEB-INF/web.xml (.../web.xml) (revision ac280c8fb2043ec90a0b7756ede0c7ab64c089d8) +++ lams_tool_larsrc/web/WEB-INF/web.xml (.../web.xml) (revision 6d9587c552af599d4fc4e68399d218f5f4ca7cf4) @@ -79,25 +79,11 @@ - 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 @@ -128,7 +114,7 @@ - action + spring *.do Index: lams_tool_larsrc/web/common/messages.jsp =================================================================== diff -u -r48be6456edafa05b5486a6b3fc37f33d926d3c58 -r6d9587c552af599d4fc4e68399d218f5f4ca7cf4 --- lams_tool_larsrc/web/common/messages.jsp (.../messages.jsp) (revision 48be6456edafa05b5486a6b3fc37f33d926d3c58) +++ lams_tool_larsrc/web/common/messages.jsp (.../messages.jsp) (revision 6d9587c552af599d4fc4e68399d218f5f4ca7cf4) @@ -1,8 +1,10 @@ <%-- Error Messages --%> - - - -
-
-
-
\ No newline at end of file +<%-- Error Messages --%> + + + + + + + + \ No newline at end of file Index: lams_tool_larsrc/web/common/taglibs.jsp =================================================================== diff -u -r9d26aaf34391eb58df037978365deda31de85c1b -r6d9587c552af599d4fc4e68399d218f5f4ca7cf4 --- lams_tool_larsrc/web/common/taglibs.jsp (.../taglibs.jsp) (revision 9d26aaf34391eb58df037978365deda31de85c1b) +++ lams_tool_larsrc/web/common/taglibs.jsp (.../taglibs.jsp) (revision 6d9587c552af599d4fc4e68399d218f5f4ca7cf4) @@ -1,11 +1,7 @@ <%@ page language="java" errorPage="/error.jsp" pageEncoding="UTF-8" contentType="text/html;charset=utf-8" %> -<%@ taglib uri="tags-bean" prefix="bean" %> -<%@ taglib uri="tags-html" prefix="html" %> -<%@ taglib uri="tags-logic" prefix="logic" %> <%@ taglib uri="tags-function" prefix="fn" %> <%@ taglib uri="tags-core" prefix="c" %> <%@ taglib uri="tags-fmt" prefix="fmt" %> <%@ taglib uri="tags-xml" prefix="x" %> <%@ taglib uri="tags-lams" prefix="lams" %> - - +<%@ taglib uri="http://www.springframework.org/tags/form" prefix="form" %> \ No newline at end of file Index: lams_tool_larsrc/web/pages/authoring/advance.jsp =================================================================== diff -u -r17b8d4d2fa5dffd734e4a62d06cb92dfdc6ca9bf -r6d9587c552af599d4fc4e68399d218f5f4ca7cf4 --- lams_tool_larsrc/web/pages/authoring/advance.jsp (.../advance.jsp) (revision 17b8d4d2fa5dffd734e4a62d06cb92dfdc6ca9bf) +++ lams_tool_larsrc/web/pages/authoring/advance.jsp (.../advance.jsp) (revision 6d9587c552af599d4fc4e68399d218f5f4ca7cf4) @@ -1,23 +1,22 @@ <%@ include file="/common/taglibs.jsp"%> -
-
- + + test="${authoringForm.resource.miniViewResourceNumber == status.index}"> @@ -29,18 +28,18 @@ - +
-
-
@@ -51,14 +50,14 @@
@@ -68,18 +67,18 @@
-
-
- +
Index: lams_tool_larsrc/web/pages/authoring/authoring.jsp =================================================================== diff -u -r16ce604dcc21fbcf8b462fe28d660723ff7c925a -r6d9587c552af599d4fc4e68399d218f5f4ca7cf4 --- lams_tool_larsrc/web/pages/authoring/authoring.jsp (.../authoring.jsp) (revision 16ce604dcc21fbcf8b462fe28d660723ff7c925a) +++ lams_tool_larsrc/web/pages/authoring/authoring.jsp (.../authoring.jsp) (revision 6d9587c552af599d4fc4e68399d218f5f4ca7cf4) @@ -66,13 +66,12 @@ - - - - - - - + + + + + + @@ -104,19 +103,19 @@ accessMode="author" --%> + toolSignature="<%=ResourceConstants.TOOL_SIGNATURE%>" toolContentID="${authoringForm.resource.contentId}" + customiseSessionID="${authoringForm.sessionMapID}" accessMode="${mode}" defineLater="${mode=='teacher'}" + contentFolderID="${authoringForm.contentFolderID}" /> - + Index: lams_tool_larsrc/web/pages/authoring/basic.jsp =================================================================== diff -u -rafefa4ff09424c4462d405b7b8a6f75c8461e0c0 -r6d9587c552af599d4fc4e68399d218f5f4ca7cf4 --- lams_tool_larsrc/web/pages/authoring/basic.jsp (.../basic.jsp) (revision afefa4ff09424c4462d405b7b8a6f75c8461e0c0) +++ lams_tool_larsrc/web/pages/authoring/basic.jsp (.../basic.jsp) (revision 6d9587c552af599d4fc4e68399d218f5f4ca7cf4) @@ -2,7 +2,6 @@ <%-- If you change this file, remember to update the copy made for CNG-36 --%> - - + @@ -71,20 +71,19 @@ <%@ include file="/common/messages.jsp"%> - + - + - +
: - +
- <%@ include file="/pages/authoring/parts/itemattachment.jsp"%> @@ -94,7 +93,7 @@
<%@ include file="ratings.jsp"%>
- + <%@ include file="instructions.jsp"%> Index: lams_tool_larsrc/web/pages/authoring/parts/addheader.jsp =================================================================== diff -u -ra4bc09633e07b301174911591702607f522c7037 -r6d9587c552af599d4fc4e68399d218f5f4ca7cf4 --- lams_tool_larsrc/web/pages/authoring/parts/addheader.jsp (.../addheader.jsp) (revision a4bc09633e07b301174911591702607f522c7037) +++ lams_tool_larsrc/web/pages/authoring/parts/addheader.jsp (.../addheader.jsp) (revision 6d9587c552af599d4fc4e68399d218f5f4ca7cf4) @@ -13,7 +13,7 @@ - + - + @@ -71,21 +71,20 @@ <%@ include file="/common/messages.jsp"%> - + - + - +
: - +
- <%@ include file="/pages/authoring/parts/itemattachment.jsp"%> @@ -96,7 +95,7 @@
<%@ include file="ratings.jsp"%>
- + <%@ include file="instructions.jsp"%> Index: lams_tool_larsrc/web/pages/authoring/parts/addurl.jsp =================================================================== diff -u -r1bf70a335f5b30a1907ccae506908b05374c6c8c -r6d9587c552af599d4fc4e68399d218f5f4ca7cf4 --- lams_tool_larsrc/web/pages/authoring/parts/addurl.jsp (.../addurl.jsp) (revision 1bf70a335f5b30a1907ccae506908b05374c6c8c) +++ lams_tool_larsrc/web/pages/authoring/parts/addurl.jsp (.../addurl.jsp) (revision 6d9587c552af599d4fc4e68399d218f5f4ca7cf4) @@ -32,7 +32,7 @@ }); - + @@ -45,30 +45,30 @@ <%@ include file="/common/messages.jsp"%> - - + + - +
: - +
: - +
- +  
<%@ include file="ratings.jsp"%>
-
+ <%@ include file="instructions.jsp"%> Index: lams_tool_larsrc/web/pages/authoring/parts/addwebsite.jsp =================================================================== diff -u -r15ec99e33ef653781c53cd13a773d4d7d1927e3f -r6d9587c552af599d4fc4e68399d218f5f4ca7cf4 --- lams_tool_larsrc/web/pages/authoring/parts/addwebsite.jsp (.../addwebsite.jsp) (revision 15ec99e33ef653781c53cd13a773d4d7d1927e3f) +++ lams_tool_larsrc/web/pages/authoring/parts/addwebsite.jsp (.../addwebsite.jsp) (revision 6d9587c552af599d4fc4e68399d218f5f4ca7cf4) @@ -57,7 +57,7 @@ } }); - + @@ -71,22 +71,20 @@ <%@ include file="/common/messages.jsp"%> - - + + - +
: - +
- <%@ include file="/pages/authoring/parts/itemattachment.jsp"%> @@ -98,7 +96,7 @@ <%@ include file="ratings.jsp"%>
-
+ <%@ include file="instructions.jsp"%> Index: lams_tool_larsrc/web/pages/authoring/parts/ratings.jsp =================================================================== diff -u -r82bf89723d09c2fce9fdb8ddb6e70db837123f6d -r6d9587c552af599d4fc4e68399d218f5f4ca7cf4 --- lams_tool_larsrc/web/pages/authoring/parts/ratings.jsp (.../ratings.jsp) (revision 82bf89723d09c2fce9fdb8ddb6e70db837123f6d) +++ lams_tool_larsrc/web/pages/authoring/parts/ratings.jsp (.../ratings.jsp) (revision 6d9587c552af599d4fc4e68399d218f5f4ca7cf4) @@ -1,7 +1,7 @@ <%@ include file="/common/taglibs.jsp"%> - +   - +   \ No newline at end of file Index: lams_tool_larsrc/web/pages/authoring/pedagogicalPlannerForm.jsp =================================================================== diff -u -r2fab2e212d7c46f61829635d0834821eb5484837 -r6d9587c552af599d4fc4e68399d218f5f4ca7cf4 --- lams_tool_larsrc/web/pages/authoring/pedagogicalPlannerForm.jsp (.../pedagogicalPlannerForm.jsp) (revision 2fab2e212d7c46f61829635d0834821eb5484837) +++ lams_tool_larsrc/web/pages/authoring/pedagogicalPlannerForm.jsp (.../pedagogicalPlannerForm.jsp) (revision 6d9587c552af599d4fc4e68399d218f5f4ca7cf4) @@ -73,46 +73,45 @@ <%@ include file="/common/messages.jsp"%> - - - - - + + + + + -

- +

- + @@ -125,7 +124,7 @@
- - - - - - + + + + + +

- +

- +
- +

: ${itemFileName}

- +
-
+ Index: lams_tool_larsrc/web/pages/authoring/start.jsp =================================================================== diff -u -r16ce604dcc21fbcf8b462fe28d660723ff7c925a -r6d9587c552af599d4fc4e68399d218f5f4ca7cf4 --- lams_tool_larsrc/web/pages/authoring/start.jsp (.../start.jsp) (revision 16ce604dcc21fbcf8b462fe28d660723ff7c925a) +++ lams_tool_larsrc/web/pages/authoring/start.jsp (.../start.jsp) (revision 6d9587c552af599d4fc4e68399d218f5f4ca7cf4) @@ -3,10 +3,10 @@ <%@ include file="/common/taglibs.jsp" %> - - - - + + + + - + Index: lams_tool_survey/src/java/org/lamsfoundation/lams/tool/survey/web/controller/AuthoringController.java =================================================================== diff -u -r51891afa31c2dcc90ef04fe7976d3fd1fea509f8 -r6d9587c552af599d4fc4e68399d218f5f4ca7cf4 --- lams_tool_survey/src/java/org/lamsfoundation/lams/tool/survey/web/controller/AuthoringController.java (.../AuthoringController.java) (revision 51891afa31c2dcc90ef04fe7976d3fd1fea509f8) +++ lams_tool_survey/src/java/org/lamsfoundation/lams/tool/survey/web/controller/AuthoringController.java (.../AuthoringController.java) (revision 6d9587c552af599d4fc4e68399d218f5f4ca7cf4) @@ -346,7 +346,7 @@ * */ @RequestMapping(value = "/start") - public String start(SurveyForm startForm, HttpServletRequest request) throws Exception { + private String start(SurveyForm startForm, HttpServletRequest request) throws Exception { ToolAccessMode mode = WebUtil.readToolAccessModeAuthorDefaulted(request); request.setAttribute(AttributeNames.ATTR_MODE, mode.toString());