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