Index: lams_learning/src/java/org/lamsfoundation/lams/learning/learningApplicationContext.xml
===================================================================
diff -u -rffe8c4f79b7746db65aa6707f15ef1e001b90d71 -r8033905f61b3c293f92b5c9c468dd22606ab9a42
--- lams_learning/src/java/org/lamsfoundation/lams/learning/learningApplicationContext.xml (.../learningApplicationContext.xml) (revision ffe8c4f79b7746db65aa6707f15ef1e001b90d71)
+++ lams_learning/src/java/org/lamsfoundation/lams/learning/learningApplicationContext.xml (.../learningApplicationContext.xml) (revision 8033905f61b3c293f92b5c9c468dd22606ab9a42)
@@ -73,6 +73,7 @@
PROPAGATION_REQUIRED
PROPAGATION_REQUIRED
PROPAGATION_REQUIRED,readOnly
+ PROPAGATION_REQUIRES_NEW
Index: lams_learning/src/java/org/lamsfoundation/lams/learning/service/ICoreLearnerService.java
===================================================================
diff -u -r81bec2c4c018269cb6a8d65212aae7e37b406fb3 -r8033905f61b3c293f92b5c9c468dd22606ab9a42
--- lams_learning/src/java/org/lamsfoundation/lams/learning/service/ICoreLearnerService.java (.../ICoreLearnerService.java) (revision 81bec2c4c018269cb6a8d65212aae7e37b406fb3)
+++ lams_learning/src/java/org/lamsfoundation/lams/learning/service/ICoreLearnerService.java (.../ICoreLearnerService.java) (revision 8033905f61b3c293f92b5c9c468dd22606ab9a42)
@@ -23,6 +23,7 @@
package org.lamsfoundation.lams.learning.service;
+import java.util.ArrayList;
import java.util.List;
import java.util.Set;
@@ -34,6 +35,7 @@
import org.lamsfoundation.lams.learningdesign.Group;
import org.lamsfoundation.lams.learningdesign.Grouping;
import org.lamsfoundation.lams.learningdesign.SequenceActivity;
+import org.lamsfoundation.lams.learningdesign.dao.IActivityDAO;
import org.lamsfoundation.lams.lesson.LearnerProgress;
import org.lamsfoundation.lams.lesson.Lesson;
import org.lamsfoundation.lams.lesson.dto.LessonDTO;
@@ -335,4 +337,9 @@
*/
SequenceActivity selectBranch(Lesson lesson, BranchingActivity branchingActivity, Integer learnerId, Long branchId)
throws LearnerServiceException;
+
+ /* Added for RepopulateProgressMarksServlet - can be removed later */
+ String[] recalcProgressForLearner(Lesson lesson, ArrayList activityList, LearnerProgress learnerProgress, boolean updateGradebookForAll);
+ IActivityDAO getActivityDAO();
+
}
Index: lams_learning/src/java/org/lamsfoundation/lams/learning/service/LearnerService.java
===================================================================
diff -u -rbdf9ae9c42902b4b2a275fdc787e1814368c8fb2 -r8033905f61b3c293f92b5c9c468dd22606ab9a42
--- lams_learning/src/java/org/lamsfoundation/lams/learning/service/LearnerService.java (.../LearnerService.java) (revision bdf9ae9c42902b4b2a275fdc787e1814368c8fb2)
+++ lams_learning/src/java/org/lamsfoundation/lams/learning/service/LearnerService.java (.../LearnerService.java) (revision 8033905f61b3c293f92b5c9c468dd22606ab9a42)
@@ -51,6 +51,7 @@
import org.lamsfoundation.lams.learningdesign.BranchActivityEntry;
import org.lamsfoundation.lams.learningdesign.BranchCondition;
import org.lamsfoundation.lams.learningdesign.BranchingActivity;
+import org.lamsfoundation.lams.learningdesign.ComplexActivity;
import org.lamsfoundation.lams.learningdesign.ConditionGateActivity;
import org.lamsfoundation.lams.learningdesign.DataFlowObject;
import org.lamsfoundation.lams.learningdesign.GateActivity;
@@ -69,6 +70,7 @@
import org.lamsfoundation.lams.learningdesign.dao.IDataFlowDAO;
import org.lamsfoundation.lams.learningdesign.dao.IGroupUserDAO;
import org.lamsfoundation.lams.learningdesign.dao.IGroupingDAO;
+import org.lamsfoundation.lams.lesson.CompletedActivityProgress;
import org.lamsfoundation.lams.lesson.LearnerProgress;
import org.lamsfoundation.lams.lesson.Lesson;
import org.lamsfoundation.lams.lesson.dao.ILearnerProgressDAO;
@@ -78,6 +80,8 @@
import org.lamsfoundation.lams.lesson.service.LessonServiceException;
import org.lamsfoundation.lams.logevent.LogEvent;
import org.lamsfoundation.lams.logevent.service.ILogEventService;
+import org.lamsfoundation.lams.tool.Tool;
+import org.lamsfoundation.lams.tool.ToolCompletionStatus;
import org.lamsfoundation.lams.tool.ToolOutput;
import org.lamsfoundation.lams.tool.ToolSession;
import org.lamsfoundation.lams.tool.exception.LamsToolServiceException;
@@ -1415,4 +1419,184 @@
}
return true;
}
+
+ /* Added for RepopulateProgressMarksServlet - can be removed later */
+ private static final String TOOL_SIGNATURE_ASSESSMENT = "laasse10";
+ private static final String TOOL_SIGNATURE_SCRATCHIE = "lascrt11";
+ private static final String TOOL_SIGNATURE_MCQ = "lamc11";
+
+ public String[] recalcProgressForLearner(Lesson lesson, ArrayList activityList, LearnerProgress learnerProgress, boolean updateGradebookForAll) {
+
+ StringBuilder auditLogBuilder = new StringBuilder("");
+ StringBuilder errorBuilder = new StringBuilder("");
+
+ User learner = learnerProgress.getUser();
+ Date lessonStartDate = learnerProgress.getStartDate();
+ auditLogBuilder.append("\n\nUpdating ").append(learner.getLogin()).append(" ")
+ .append(learner.getFullName()).append("\n");
+
+ boolean updated = false;
+ for (Activity activity : activityList) {
+
+ CompletedActivityProgress completedProgress = learnerProgress.getCompletedActivities().get(activity);
+ if (completedProgress == null || completedProgress.getStartDate() == null || completedProgress.getFinishDate() == null) {
+ updated = updateProgress(lesson.getLessonId(), auditLogBuilder, errorBuilder, learnerProgress,
+ learner, lessonStartDate, activity) || updated;
+ }
+
+ // is completed (previously or just now?), in which case update gradebook.
+ if (activity.isToolActivity()) {
+ CompletedActivityProgress updatedCompletedProgress = learnerProgress.getCompletedActivities().get(
+ activity);
+ if (updatedCompletedProgress != null) {
+ ToolActivity toolActivity = (ToolActivity) activity;
+ Tool tool = toolActivity.getTool();
+ if (updateGradebookForAll || TOOL_SIGNATURE_ASSESSMENT.equals(tool.getToolSignature())
+ || TOOL_SIGNATURE_SCRATCHIE.equals(tool.getToolSignature())
+ || TOOL_SIGNATURE_MCQ.equals(tool.getToolSignature())) {
+ auditLogBuilder.append("Pushing mark to Gradebook for activity ")
+ .append(activity.getActivityId()).append(" ").append(activity.getTitle()).append("\n");
+ gradebookService.updateUserActivityGradebookMark(lesson, activity, learner);
+ }
+ }
+ }
+
+ }
+
+ if ( updated )
+ learnerProgressDAO.updateLearnerProgress(learnerProgress);
+
+ return new String[] { auditLogBuilder.toString(), errorBuilder.toString() };
+ }
+
+ private boolean updateProgress(Long lessonId, StringBuilder auditLogBuilder, StringBuilder errorBuilder,
+ LearnerProgress learnerProgress, User learner, Date lessonStartDate, Activity activity) {
+
+ boolean updated = false;
+ ToolCompletionStatus results = recalcActivityProgress(activity, learner, lessonId, learnerProgress, auditLogBuilder, errorBuilder);
+
+ // results == null ignore - won't harm anything if it is in attempted and nothing in the tool and
+ // do not remove from completed in case it was force completed, or the tool doesn't support this
+
+ if (results != null) {
+
+ if (results.getStatus() == ToolCompletionStatus.ACTIVITY_COMPLETED) {
+ // completed
+ Date startedDateFromAttempted = learnerProgress.getAttemptedActivities().get(activity);
+ CompletedActivityProgress cap = learnerProgress.getCompletedActivities().get(activity);
+ if (cap != null) {
+ if (cap.getStartDate() == null) {
+ if (startedDateFromAttempted != null)
+ cap.setStartDate(startedDateFromAttempted);
+ else if (results.getStartDate() != null)
+ cap.setStartDate(results.getStartDate());
+ }
+ if (cap.getFinishDate() == null && results.getFinishDate() != null) {
+ cap.setFinishDate(results.getFinishDate());
+ }
+ } else {
+ cap = new CompletedActivityProgress(learnerProgress, activity,
+ startedDateFromAttempted != null ? startedDateFromAttempted : results.getStartDate(),
+ results.getFinishDate());
+ }
+ if ( cap.getStartDate() == null ) {
+ // must have something or it is not seen as completed
+ cap.setStartDate(lessonStartDate);
+ }
+ learnerProgress.getCompletedActivities().put(activity, cap);
+ learnerProgress.getAttemptedActivities().remove(activity);
+
+ auditLogBuilder.append("Progress updated for completed activity ").append(activity.getActivityId())
+ .append(" ").append(activity.getTitle()).append("\n");
+ updated = true;
+
+ } else if (results.getStatus() == ToolCompletionStatus.ACTIVITY_ATTEMPTED) {
+ // Attempted - if not already there add with tool's start date, or failing that the tool's value for
+ // session start date, or the core's value for session start date, or the lesson start date.
+ // Must have a date or it can't be saved.
+ if (results.getStartDate() != null)
+ learnerProgress.getAttemptedActivities().putIfAbsent(activity, results.getStartDate());
+ else {
+ learnerProgress.getAttemptedActivities().putIfAbsent(activity, lessonStartDate);
+ }
+ auditLogBuilder.append("Progress updated for attempted activity ").append(activity.getActivityId())
+ .append(" ").append(activity.getTitle()).append("\n");
+ updated = true;
+ }
+
+ }
+
+ return updated;
+ }
+
+ private ToolCompletionStatus recalcActivityProgress(Activity activity, User learner, Long lessonId, LearnerProgress learnerProgress, StringBuilder auditLogEntry, StringBuilder errorBuilder) {
+
+ ToolCompletionStatus status = null;
+
+ if (activity.isToolActivity()) {
+ ToolSession toolSession = lamsCoreToolService.getToolSessionByLearner(learner, activity);
+ if (toolSession != null) {
+ status = lamsCoreToolService.getCompletionStatusFromTool(learner, activity);
+ if ( status.getStartDate() == null )
+ status.setStartDate(toolSession.getCreateDateTime());
+ }
+
+ } else if ( activity.isComplexActivity() ) {
+ ComplexActivity complexActivity = (ComplexActivity) activity;
+ boolean attempted = false;
+ boolean allComplete = true;
+ Date caStartDate = null;
+ Date caEndDate = null;
+ for (Iterator i = complexActivity.getActivities().iterator(); i.hasNext();) {
+ Activity childActivity = (Activity) i.next();
+ Date childStartDate = learnerProgress.getAttemptedActivities().get(childActivity);
+ Date childEndDate = null;
+ if ( childStartDate != null ) {
+ attempted = true;
+ }
+ CompletedActivityProgress childCap = learnerProgress.getCompletedActivities().get(childActivity);
+ if ( childCap == null ) {
+ allComplete = false;
+ } else {
+ attempted = true;
+ if ( childStartDate == null )
+ childStartDate = childCap.getStartDate();
+ childEndDate = childCap.getFinishDate();
+ }
+ if ( caStartDate == null || (childStartDate != null && childStartDate.before(caStartDate)) )
+ caStartDate = childStartDate;
+ if ( caEndDate == null || (childEndDate != null && childEndDate.after(caStartDate)) )
+ caEndDate = childEndDate;
+ }
+
+ if ( attempted ) {
+ if ( allComplete )
+ status = new ToolCompletionStatus(ToolCompletionStatus.ACTIVITY_COMPLETED, caStartDate, caEndDate);
+ else
+ status = new ToolCompletionStatus(ToolCompletionStatus.ACTIVITY_ATTEMPTED, caStartDate, null);
+ }
+
+ } else if ( activity.isGateActivity() ){
+ // do nothing
+ ;
+ } else if ( activity.isGroupingActivity() ) {
+ GroupingActivity groupingActivity = (GroupingActivity) activity;
+ Grouping grouping = groupingActivity.getCreateGrouping();
+ if ( grouping.doesLearnerExist(learner) ) {
+ status = new ToolCompletionStatus(ToolCompletionStatus.ACTIVITY_COMPLETED, null, null);
+ }
+ } else {
+ errorBuilder.append("Unable to update status for unexpected activity ").append(activity.getActivityId())
+ .append(" ").append(activity.getTitle());
+ }
+ return status;
+
+ }
+
+ @Override
+ public IActivityDAO getActivityDAO() {
+ return activityDAO;
+ }
+
+
}
\ No newline at end of file
Index: lams_learning/src/java/org/lamsfoundation/lams/learning/web/RepopulateProgressMarksServlet.java
===================================================================
diff -u
--- lams_learning/src/java/org/lamsfoundation/lams/learning/web/RepopulateProgressMarksServlet.java (revision 0)
+++ lams_learning/src/java/org/lamsfoundation/lams/learning/web/RepopulateProgressMarksServlet.java (revision 8033905f61b3c293f92b5c9c468dd22606ab9a42)
@@ -0,0 +1,218 @@
+/****************************************************************
+ * Copyright (C) 2005 LAMS Foundation (http://lamsfoundation.org)
+ * =============================================================
+ * License Information: http://lamsfoundation.org/licensing/lams/2.0/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2.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.learning.web;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.Map;
+import java.util.Set;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+
+import org.apache.log4j.Logger;
+import org.hibernate.SessionFactory;
+import org.lamsfoundation.lams.gradebook.service.IGradebookService;
+import org.lamsfoundation.lams.learning.service.ICoreLearnerService;
+import org.lamsfoundation.lams.learningdesign.Activity;
+import org.lamsfoundation.lams.learningdesign.ComplexActivity;
+import org.lamsfoundation.lams.learningdesign.LearningDesign;
+import org.lamsfoundation.lams.learningdesign.LearningDesignProcessor;
+import org.lamsfoundation.lams.learningdesign.SimpleActivity;
+import org.lamsfoundation.lams.learningdesign.ToolActivity;
+import org.lamsfoundation.lams.learningdesign.dao.IActivityDAO;
+import org.lamsfoundation.lams.learningdesign.exception.LearningDesignProcessorException;
+import org.lamsfoundation.lams.lesson.CompletedActivityProgress;
+import org.lamsfoundation.lams.lesson.LearnerProgress;
+import org.lamsfoundation.lams.lesson.Lesson;
+import org.lamsfoundation.lams.lesson.dao.ILearnerProgressDAO;
+import org.lamsfoundation.lams.lesson.service.ILessonService;
+import org.lamsfoundation.lams.tool.Tool;
+import org.lamsfoundation.lams.tool.ToolCompletionStatus;
+import org.lamsfoundation.lams.tool.ToolSession;
+import org.lamsfoundation.lams.tool.service.ILamsCoreToolService;
+import org.lamsfoundation.lams.usermanagement.User;
+import org.lamsfoundation.lams.usermanagement.dto.UserDTO;
+import org.lamsfoundation.lams.util.WebUtil;
+import org.lamsfoundation.lams.util.audit.IAuditService;
+import org.lamsfoundation.lams.web.session.SessionManager;
+import org.lamsfoundation.lams.web.util.AttributeNames;
+import org.springframework.orm.hibernate4.SessionHolder;
+import org.springframework.transaction.support.TransactionSynchronizationManager;
+import org.springframework.web.context.WebApplicationContext;
+import org.springframework.web.context.support.WebApplicationContextUtils;
+
+@SuppressWarnings("serial")
+public class RepopulateProgressMarksServlet extends HttpServlet {
+
+ private static Logger log = Logger.getLogger(RepopulateProgressMarksServlet.class);
+
+ private static IAuditService auditService;
+ private static ILessonService lessonService;
+ private static ICoreLearnerService learnerService;
+
+ @Override
+ public void init() throws ServletException {
+ WebApplicationContext ctx = WebApplicationContextUtils.getRequiredWebApplicationContext(getServletContext());
+ RepopulateProgressMarksServlet.auditService = (IAuditService) ctx.getBean("auditService");
+ RepopulateProgressMarksServlet.lessonService = (ILessonService) ctx.getBean("lessonService");
+ RepopulateProgressMarksServlet.learnerService = (ICoreLearnerService) ctx.getBean("learnerService");
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
+
+ String header="";
+ StringBuilder errorBuilder = new StringBuilder("");
+ StringBuilder auditLogBuilder = new StringBuilder("");
+ UserDTO userDTO = null;
+
+ PrintWriter out = response.getWriter();
+ try {
+
+ Long lessonId = WebUtil.readLongParam(request, AttributeNames.PARAM_LESSON_ID);
+ Integer restrictToLearnerId = WebUtil.readIntParam(request, AttributeNames.PARAM_USER_ID, true);
+ Boolean gradebookAll = WebUtil.readBooleanParam(request, "gradebookAll", false);
+ HttpSession ss = SessionManager.getSession();
+ userDTO = (UserDTO) ss.getAttribute(AttributeNames.USER);
+
+ Lesson lesson = lessonService.getLesson(lessonId);
+ if (lesson == null) {
+ log.error("RepopulateProgressMarksServlet: lesson not found " + lessonId);
+ out.println("ERROR: lesson not found " + lessonId);
+ return;
+ }
+
+ header = new StringBuilder(
+ "Learner progress and gradebook marks to be repopulated for lesson ").append(lessonId).append(" ")
+ .append(lesson.getLessonName())
+ .append(".\n----------------------------------------------------------------------------------\n\n").toString();
+
+ ActivitiesToCheckProcessor processor = new ActivitiesToCheckProcessor(lesson.getLearningDesign(),
+ learnerService.getActivityDAO());
+ processor.parseLearningDesign();
+ ArrayList activityList = processor.getActivityList();
+
+ auditLogBuilder.append("Full log:\n\nUpdating progress for the following activities: ");
+ for (Activity activity : activityList) {
+ auditLogBuilder.append(activity.getActivityId()).append(" ").append(activity.getTitle()).append("; ");
+ }
+ auditLogBuilder.append("\n\n");
+
+ if (restrictToLearnerId == null) {
+ Set progresses = (Set) lesson.getLearnerProgresses();
+ for (LearnerProgress learnerProgress : progresses) {
+ processLearner(errorBuilder, auditLogBuilder, lesson, activityList, learnerProgress, gradebookAll);
+ }
+ } else {
+ LearnerProgress learnerProgress = learnerService.getProgress(restrictToLearnerId, lessonId);
+ if (learnerProgress != null) {
+ processLearner(errorBuilder, auditLogBuilder, lesson, activityList, learnerProgress, gradebookAll);
+ } else {
+ log.error("RepopulateProgressMarksServlet: learner's progress not found " + restrictToLearnerId);
+ out.println("ERROR: progress for learner " + restrictToLearnerId + " not found");
+ return;
+ }
+ }
+
+ } catch (Throwable e) {
+
+ log.error("Error: " + e.getMessage() + e.getCause(), e);
+ errorBuilder.append("Error occured ").append(e.getMessage());
+ }
+
+ String errors = errorBuilder.append("\n").toString();
+ String msg;
+ if (errors.length() > 1) {
+ msg = new StringBuilder(header).append("Errors occured. Some data may be been updated.\n").append(errors).append(auditLogBuilder.toString()).toString();
+ } else {
+ msg = new StringBuilder(header).append("Successful run, no errors\n").append(auditLogBuilder.toString()).toString();
+ }
+ auditService.log(userDTO, "RepopulateProgressMarksServlet",msg);
+ out.println(msg);
+ return;
+ }
+
+ private void processLearner(StringBuilder errorBuilder, StringBuilder auditLogBuilder, Lesson lesson,
+ ArrayList activityList, LearnerProgress learnerProgress, boolean updateGradebookForAll) {
+ try {
+ String messages[] = learnerService.recalcProgressForLearner(lesson, activityList, learnerProgress, updateGradebookForAll);
+ auditLogBuilder.append(messages[0]);
+ errorBuilder.append(messages[1]);
+ } catch ( Throwable e ) {
+ log.error("Error thrown while processing "+learnerProgress.getUser().getLogin(), e);
+ String msg = new StringBuilder("Error occured while processing user ")
+ .append(learnerProgress.getUser().getLogin()).append(" ").append(learnerProgress.getUser().getFullName()).append(". Proceeding entries in log for this user may or may not have worked. Error was ")
+ .append(e.getMessage()).append("\n")
+ .toString();
+ auditLogBuilder.append(msg);
+ errorBuilder.append(msg);
+ }
+ }
+
+ @Override
+ protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException,
+ IOException {
+ doGet(request, response);
+ }
+
+ class ActivitiesToCheckProcessor extends LearningDesignProcessor {
+
+ ArrayList activityList;
+
+ public ActivitiesToCheckProcessor(LearningDesign design, IActivityDAO activityDAO) {
+ super(design, activityDAO);
+ activityList = new ArrayList();
+ }
+
+ @Override
+ public boolean startComplexActivity(ComplexActivity activity) throws LearningDesignProcessorException {
+ return true;
+ }
+
+ @Override
+ public void endComplexActivity(ComplexActivity activity) throws LearningDesignProcessorException {
+ activityList.add(activity);
+ }
+
+ @Override
+ public void startSimpleActivity(SimpleActivity activity) throws LearningDesignProcessorException {
+ }
+
+ @Override
+ public void endSimpleActivity(SimpleActivity activity) throws LearningDesignProcessorException {
+ activityList.add(activity);
+ }
+
+ public ArrayList getActivityList() {
+ return activityList;
+ }
+ }
+}
\ No newline at end of file
Index: lams_learning/web/WEB-INF/web.xml
===================================================================
diff -u -r0ddeb3a1dcf29cbbba6ed0fccbd139f9c31c347f -r8033905f61b3c293f92b5c9c468dd22606ab9a42
--- lams_learning/web/WEB-INF/web.xml (.../web.xml) (revision 0ddeb3a1dcf29cbbba6ed0fccbd139f9c31c347f)
+++ lams_learning/web/WEB-INF/web.xml (.../web.xml) (revision 8033905f61b3c293f92b5c9c468dd22606ab9a42)
@@ -96,6 +96,18 @@
1
+
+
+ RepopulateProgressMarksServlet
+
+ org.lamsfoundation.lams.learning.web.RepopulateProgressMarksServlet
+
+
+
+ RepopulateProgressMarksServlet
+ /repopulateProgress
+
+