Index: lams_build/lib/lams/lams.jar =================================================================== diff -u -r1c1c6b24a18fffc7a7b2bccdee8fedb110d1669e -r1af4378c901cea902392d4ef17f9d990f25e16f3 Binary files differ Fisheye: Tag 1af4378c901cea902392d4ef17f9d990f25e16f3 refers to a dead (removed) revision in file `lams_monitoring/src/java/org/lamsfoundation/lams/monitoring/BranchDTO.java'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 1af4378c901cea902392d4ef17f9d990f25e16f3 refers to a dead (removed) revision in file `lams_monitoring/src/java/org/lamsfoundation/lams/monitoring/BranchingDTO.java'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 1af4378c901cea902392d4ef17f9d990f25e16f3 refers to a dead (removed) revision in file `lams_monitoring/src/java/org/lamsfoundation/lams/monitoring/ContributeActivityDTO.java'. Fisheye: No comparison available. Pass `N' to diff? Index: lams_monitoring/src/java/org/lamsfoundation/lams/monitoring/ContributeDTOFactory.java =================================================================== diff -u -r7651b7a24448e75a74e89ed815d8f9f1d7328636 -r1af4378c901cea902392d4ef17f9d990f25e16f3 --- lams_monitoring/src/java/org/lamsfoundation/lams/monitoring/ContributeDTOFactory.java (.../ContributeDTOFactory.java) (revision 7651b7a24448e75a74e89ed815d8f9f1d7328636) +++ lams_monitoring/src/java/org/lamsfoundation/lams/monitoring/ContributeDTOFactory.java (.../ContributeDTOFactory.java) (revision 1af4378c901cea902392d4ef17f9d990f25e16f3) @@ -34,6 +34,7 @@ import org.lamsfoundation.lams.learningdesign.strategy.ComplexActivityStrategy; import org.lamsfoundation.lams.learningdesign.strategy.IContributionTypeStrategy; import org.lamsfoundation.lams.learningdesign.strategy.SimpleActivityStrategy; +import org.lamsfoundation.lams.monitoring.dto.ContributeActivityDTO; import org.lamsfoundation.lams.tool.exception.LamsToolServiceException; import org.lamsfoundation.lams.tool.service.ILamsCoreToolService; import org.lamsfoundation.lams.util.WebUtil; Fisheye: Tag 1af4378c901cea902392d4ef17f9d990f25e16f3 refers to a dead (removed) revision in file `lams_monitoring/src/java/org/lamsfoundation/lams/monitoring/LearnerProgressBatchDTO.java'. Fisheye: No comparison available. Pass `N' to diff? Index: lams_monitoring/src/java/org/lamsfoundation/lams/monitoring/MonitoringConstants.java =================================================================== diff -u -r1c1c6b24a18fffc7a7b2bccdee8fedb110d1669e -r1af4378c901cea902392d4ef17f9d990f25e16f3 --- lams_monitoring/src/java/org/lamsfoundation/lams/monitoring/MonitoringConstants.java (.../MonitoringConstants.java) (revision 1c1c6b24a18fffc7a7b2bccdee8fedb110d1669e) +++ lams_monitoring/src/java/org/lamsfoundation/lams/monitoring/MonitoringConstants.java (.../MonitoringConstants.java) (revision 1af4378c901cea902392d4ef17f9d990f25e16f3) @@ -24,29 +24,43 @@ /* $$Id$$ */ package org.lamsfoundation.lams.monitoring; - - public class MonitoringConstants { - public static final String MONITORING_SERVICE_BEAN_NAME = "monitoringService"; - public static final String CREATE_LESSON_MESSAGE_KEY = "createLessonClass"; - public static final String INIT_LESSON_MESSAGE_KEY = "initializeLesson"; - public static final String PERFORM_CHOSEN_GROUPING_KEY = "performChosenGrouping"; - public static final String KEY_ORGANISATION_ID = "organisationID"; - public static final String KEY_LESSON_ID = "lessonID"; - public static final String KEY_USER_ID = "userID"; - public static final String KEY_STAFF = "staff"; - public static final String KEY_LEARNER = "learners"; - public static final String JOB_START_LESSON = "startScheduleLessonJob"; - public static final String JOB_FINISH_LESSON = "finishScheduleLessonJob"; - public static final String PARAM_LESSON_START_DATE = "lessonStartDate"; - public static final String PARAM_SCHEDULED_NUMBER_DAYS_TO_LESSON_FINISH = "scheduledNumberDaysToLessonFinish"; - public static final String PARAM_LEARNER_ID = "learnerID"; - public static final String KEY_GROUPING_ACTIVITY = "groupingActivityID"; - public static final String KEY_GROUPS = "groups"; - public static final String KEY_GROUP_NAME = "groupName"; - public static final String KEY_GROUP_ORDER_ID = "orderID"; - public static final String KEY_GROUP_LEARNERS = "learners"; - public static final Object KEY_USERS = "users"; - public static final String PARAM_SCHEDULE_TIME_ZONE_IDX = "scheduleTimeZoneIdx"; -} + public static final String MONITORING_SERVICE_BEAN_NAME = "monitoringService"; + public static final String CREATE_LESSON_MESSAGE_KEY = "createLessonClass"; + public static final String INIT_LESSON_MESSAGE_KEY = "initializeLesson"; + public static final String PERFORM_CHOSEN_GROUPING_KEY = "performChosenGrouping"; + public static final String KEY_ORGANISATION_ID = "organisationID"; + public static final String KEY_LESSON_ID = "lessonID"; + public static final String KEY_USER_ID = "userID"; + public static final String KEY_STAFF = "staff"; + public static final String KEY_LEARNER = "learners"; + public static final String JOB_START_LESSON = "startScheduleLessonJob"; + public static final String JOB_FINISH_LESSON = "finishScheduleLessonJob"; + public static final String JOB_EMAIL_MESSAGE = "emailScheduleMessageJob"; + public static final String PARAM_LESSON_START_DATE = "lessonStartDate"; + public static final String PARAM_SCHEDULED_NUMBER_DAYS_TO_LESSON_FINISH = "scheduledNumberDaysToLessonFinish"; + public static final String PARAM_LEARNER_ID = "learnerID"; + public static final String KEY_GROUPING_ACTIVITY = "groupingActivityID"; + public static final String KEY_GROUPS = "groups"; + public static final String KEY_GROUP_NAME = "groupName"; + public static final String KEY_GROUP_ORDER_ID = "orderID"; + public static final String KEY_GROUP_LEARNERS = "learners"; + public static final Object KEY_USERS = "users"; + public static final String PARAM_SCHEDULE_TIME_ZONE_IDX = "scheduleTimeZoneIdx"; + + // --------------------------------------------------------------------- + // Search type constants used in EmailNotificationsAction + // --------------------------------------------------------------------- + public static final int LESSON_TYPE_ASSIGNED_TO_LESSON = 0; + public static final int LESSON_TYPE_HAVENT_FINISHED_LESSON = 1; + public static final int LESSON_TYPE_HAVE_FINISHED_LESSON = 2; + public static final int LESSON_TYPE_HAVENT_STARTED_LESSON = 3; + public static final int LESSON_TYPE_HAVE_STARTED_LESSON = 4; + public static final int LESSON_TYPE_HAVENT_REACHED_PARTICULAR_ACTIVITY = 5; + public static final int LESSON_TYPE_LESS_THAN_X_DAYS_TO_DEADLINE = 6; + public static final int COURSE_TYPE_HAVE_FINISHED_PARTICULAR_LESSON = 7; + public static final int COURSE_TYPE_HAVENT_STARTED_PARTICULAR_LESSON = 8; + public static final int COURSE_TYPE_HAVENT_STARTED_ANY_LESSONS = 9; + public static final int COURSE_TYPE_HAVE_FINISHED_THESE_LESSONS = 10; +} \ No newline at end of file Fisheye: Tag 1af4378c901cea902392d4ef17f9d990f25e16f3 refers to a dead (removed) revision in file `lams_monitoring/src/java/org/lamsfoundation/lams/monitoring/URLFactory.java'. Fisheye: No comparison available. Pass `N' to diff? Index: lams_monitoring/src/java/org/lamsfoundation/lams/monitoring/dto/BranchDTO.java =================================================================== diff -u --- lams_monitoring/src/java/org/lamsfoundation/lams/monitoring/dto/BranchDTO.java (revision 0) +++ lams_monitoring/src/java/org/lamsfoundation/lams/monitoring/dto/BranchDTO.java (revision 1af4378c901cea902392d4ef17f9d990f25e16f3) @@ -0,0 +1,72 @@ +package org.lamsfoundation.lams.monitoring.dto; + +import java.io.Serializable; +import java.util.SortedSet; + +import org.apache.commons.lang.builder.CompareToBuilder; +import org.apache.commons.lang.builder.ToStringBuilder; +import org.lamsfoundation.lams.learningdesign.Group; +import org.lamsfoundation.lams.learningdesign.SequenceActivity; + +/** + * Represents a single branch within a branching activity. Used by the Teacher Chosen Grouping screen for allocating + * learners to branches, and on the other branching screens to view the current branch -> group mappings + *

+ * A branch is equivalent to a SequenceActivity within a BranchingActivity + */ +public class BranchDTO implements Serializable, Comparable { + + private Long branchId; + private String branchName; + private SortedSet groups; + + public BranchDTO(SequenceActivity activity, SortedSet groups) { + this.branchId = activity.getActivityId(); + this.branchName = activity.getTitle(); + this.groups = groups; + } + + /** Get the activity id for the sequence activity that is equivalent to this branch */ + public Long getBranchId() { + return branchId; + } + + public void setBranchId(Long branchId) { + this.branchId = branchId; + } + + /** The branch name is the title of the sequence activity that is equivalent to this branch */ + public String getBranchName() { + return branchName; + } + + public void setBranchName(String branchName) { + this.branchName = branchName; + } + + /** + * Get the groups currently assigned to this branch. For a teacher chosen branching activity, there will be one + * group per branch. + * + * @return + */ + public SortedSet getGroups() { + return groups; + } + + public void setGroups(SortedSet groups) { + this.groups = groups; + } + + public String toString() { + return new ToStringBuilder(this).append("branchName", branchName).append("branchId", branchId) + .append("groups", groups).toString(); + } + + public int compareTo(Object other) { + BranchDTO otherBranch = (BranchDTO) other; + return new CompareToBuilder().append(branchName, otherBranch.branchName).append(branchId, otherBranch.branchId) + .toComparison(); + } + +} Index: lams_monitoring/src/java/org/lamsfoundation/lams/monitoring/dto/BranchingDTO.java =================================================================== diff -u --- lams_monitoring/src/java/org/lamsfoundation/lams/monitoring/dto/BranchingDTO.java (revision 0) +++ lams_monitoring/src/java/org/lamsfoundation/lams/monitoring/dto/BranchingDTO.java (revision 1af4378c901cea902392d4ef17f9d990f25e16f3) @@ -0,0 +1,61 @@ +package org.lamsfoundation.lams.monitoring.dto; + +import java.io.Serializable; +import java.util.Iterator; +import java.util.Set; +import java.util.SortedSet; +import java.util.TreeSet; + +import org.apache.commons.lang.builder.CompareToBuilder; +import org.apache.commons.lang.builder.ToStringBuilder; +import org.lamsfoundation.lams.learningdesign.BranchingActivity; +import org.lamsfoundation.lams.learningdesign.Group; +import org.lamsfoundation.lams.learningdesign.BranchActivityEntry; +import org.lamsfoundation.lams.learningdesign.SequenceActivity; + +/** + * Represents an overall branching activity. Used by the Teacher Chosen Grouping screen for allocating learners to + * branches, and on the other branching screens to view the current branch -> group mappings + */ +public class BranchingDTO implements Serializable, Comparable { + + private Long branchActivityId; + private String branchActivityName; + private SortedSet branches; + + public String toString() { + return new ToStringBuilder(this).append("branchActivityId", branchActivityId) + .append("branchActivityName", branchActivityName).append("branches", branches).toString(); + } + + public int compareTo(Object other) { + BranchingDTO otherBranch = (BranchingDTO) other; + return new CompareToBuilder().append(branchActivityId, otherBranch.branchActivityId) + .append(branchActivityName, otherBranch.branchActivityName).toComparison(); + } + + public Long getBranchActivityId() { + return branchActivityId; + } + + public void setBranchActivityId(Long branchActivityId) { + this.branchActivityId = branchActivityId; + } + + public String getBranchActivityName() { + return branchActivityName; + } + + public void setBranchActivityName(String branchActivityName) { + this.branchActivityName = branchActivityName; + } + + public SortedSet getBranches() { + return branches; + } + + public void setBranches(SortedSet branches) { + this.branches = branches; + } + +} Index: lams_monitoring/src/java/org/lamsfoundation/lams/monitoring/dto/ContributeActivityDTO.java =================================================================== diff -u --- lams_monitoring/src/java/org/lamsfoundation/lams/monitoring/dto/ContributeActivityDTO.java (revision 0) +++ lams_monitoring/src/java/org/lamsfoundation/lams/monitoring/dto/ContributeActivityDTO.java (revision 1af4378c901cea902392d4ef17f9d990f25e16f3) @@ -0,0 +1,158 @@ +/**************************************************************** + * 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 + * **************************************************************** + */ +/* $Id$ */ +package org.lamsfoundation.lams.monitoring.dto; + +import java.util.Vector; + +import org.lamsfoundation.lams.learningdesign.Activity; +import org.lamsfoundation.lams.learningdesign.ContributionTypes; + +/** + * DTO used to return the activity details needed for the contribute activities list + * + * @author Fiona Malikoff + */ +public class ContributeActivityDTO { + + private String title; + private String description; + private Long activityID; + private Integer activityTypeID; + private Integer orderID; + private Long parentActivityID; + private Vector childActivities; + private Vector contributeEntries; + + /** Warning: This does not set childActivities or contribution details !!!!!! */ + public ContributeActivityDTO(Activity activity) { + this.title = activity.getTitle(); + this.description = activity.getDescription(); + this.activityID = activity.getActivityId(); + this.activityTypeID = activity.getActivityTypeId(); + this.orderID = activity.getOrderId(); + if (activity.getParentActivity() != null) { + this.parentActivityID = activity.getParentActivity().getActivityId(); + } + this.contributeEntries = new Vector(); + } + + /** + * @return Returns the activityID. + */ + public Long getActivityID() { + return activityID; + } + + /** + * @return Returns the activityTypeID. + */ + public Integer getActivityTypeID() { + return activityTypeID; + } + + /** + * @return Returns the description. + */ + public String getDescription() { + return description; + } + + /** + * @return Returns the orderID. + */ + public Integer getOrderID() { + return orderID; + } + + /** + * @return Returns the title. + */ + public String getTitle() { + return title; + + } + + public Vector getContributeEntries() { + return contributeEntries; + } + + public void setChildActivities(Vector childActivities) { + this.childActivities = childActivities; + } + + public Vector getChildActivities() { + return childActivities; + } + + public Long getParentActivityID() { + return parentActivityID; + } + + public void addContribution(Integer contributionType, String url) { + ContributeEntry entry = new ContributeEntry(); + entry.setContributionType(contributionType); + entry.setURL(url); + contributeEntries.add(entry); + } + + class ContributeEntry { + private Boolean isRequired; + private Integer contributionType; + private String url; + + /** + * @return Returns the contributionType. + */ + public Integer getContributionType() { + return contributionType; + } + + public void setContributionType(Integer contributionType) { + this.contributionType = contributionType; + boolean isReq = contributionType != null + && (contributionType.equals(ContributionTypes.DEFINE_LATER) + || contributionType.equals(ContributionTypes.PERMISSION_GATE) + || contributionType.equals(ContributionTypes.CHOSEN_GROUPING) || contributionType + .equals(ContributionTypes.CHOSEN_BRANCHING)); + + this.isRequired = new Boolean(isReq); + } + + /** + * @return Returns the isRequired. + */ + public Boolean getIsRequired() { + return isRequired; + } + + public String getURL() { + return url; + } + + public void setURL(String url) { + this.url = url; + } + } + +} Index: lams_monitoring/src/java/org/lamsfoundation/lams/monitoring/dto/EmailScheduleMessageJobDTO.java =================================================================== diff -u --- lams_monitoring/src/java/org/lamsfoundation/lams/monitoring/dto/EmailScheduleMessageJobDTO.java (revision 0) +++ lams_monitoring/src/java/org/lamsfoundation/lams/monitoring/dto/EmailScheduleMessageJobDTO.java (revision 1af4378c901cea902392d4ef17f9d990f25e16f3) @@ -0,0 +1,70 @@ +/**************************************************************** + * 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 + * **************************************************************** + */ + +/* $Id$ */ +package org.lamsfoundation.lams.monitoring.dto; + +import java.io.Serializable; +import java.util.Date; + +import org.apache.commons.lang.builder.CompareToBuilder; +import org.apache.commons.lang.builder.ToStringBuilder; + +public class EmailScheduleMessageJobDTO implements Serializable, Comparable { + + private Date triggerDate; + private String emailBody; + private int searchType; + + public Date getTriggerDate() { + return triggerDate; + } + public void setTriggerDate(Date triggerDate) { + this.triggerDate = triggerDate; + } + + public String getEmailBody() { + return emailBody; + } + public void setEmailBody(String emailBody) { + this.emailBody = emailBody; + } + + public int getSearchType() { + return searchType; + } + public void setSearchType(int searchType) { + this.searchType = searchType; + } + + public String toString() { + return new ToStringBuilder(this).append("emailBody", emailBody).append("triggerDate", triggerDate) + .append("searchType", searchType).toString(); + } + + public int compareTo(Object other) { + EmailScheduleMessageJobDTO otherDto = (EmailScheduleMessageJobDTO) other; + return new CompareToBuilder().append(triggerDate, otherDto.triggerDate).append(emailBody, otherDto.emailBody) + .append(searchType, otherDto.searchType).toComparison(); + } + +} Index: lams_monitoring/src/java/org/lamsfoundation/lams/monitoring/dto/LearnerProgressBatchDTO.java =================================================================== diff -u --- lams_monitoring/src/java/org/lamsfoundation/lams/monitoring/dto/LearnerProgressBatchDTO.java (revision 0) +++ lams_monitoring/src/java/org/lamsfoundation/lams/monitoring/dto/LearnerProgressBatchDTO.java (revision 1af4378c901cea902392d4ef17f9d990f25e16f3) @@ -0,0 +1,73 @@ +/**************************************************************** + * 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 + * **************************************************************** + */ + +/* $Id$ */ +package org.lamsfoundation.lams.monitoring.dto; + +import java.util.Vector; + +import org.lamsfoundation.lams.lesson.LearnerProgress; + +/** + * Return the details of the Learner Progress batching - how many learner progress entries exist for this lesson, how + * many in a batch, how many batches available and the first batch of users. + */ +public class LearnerProgressBatchDTO { + + private Vector learnerProgressList; + private Integer batchSize; + private Integer numBatches; + private Integer numAllLearnerProgress; + + public LearnerProgressBatchDTO(Vector progress, int batchSize, int numAllLearnerProgress) { + this.learnerProgressList = progress; + this.batchSize = batchSize; + this.numAllLearnerProgress = numAllLearnerProgress; + + // integer division truncates, so convert to floating point first. + double batchSizeAsDouble = (double) batchSize; + double numAllLearnerProgressAsDouble = (double) numAllLearnerProgress; + double numBatchesDouble = numAllLearnerProgressAsDouble / batchSizeAsDouble; + numBatchesDouble = Math.ceil(numBatchesDouble); + + numBatches = (int) numBatchesDouble; + if (numBatches < 1) { + numBatches = 1; + } + } + + public Vector getLearnerProgressList() { + return learnerProgressList; + } + + public Integer getBatchSize() { + return batchSize; + } + + public Integer getNumBatches() { + return numBatches; + } + + public Integer getNumAllLearnerProgress() { + return numAllLearnerProgress; + } +} Index: lams_monitoring/src/java/org/lamsfoundation/lams/monitoring/monitoringApplicationContext.xml =================================================================== diff -u -r8cbd631849cddfbfc7fb887e8a847894e5baaefa -r1af4378c901cea902392d4ef17f9d990f25e16f3 --- lams_monitoring/src/java/org/lamsfoundation/lams/monitoring/monitoringApplicationContext.xml (.../monitoringApplicationContext.xml) (revision 8cbd631849cddfbfc7fb887e8a847894e5baaefa) +++ lams_monitoring/src/java/org/lamsfoundation/lams/monitoring/monitoringApplicationContext.xml (.../monitoringApplicationContext.xml) (revision 1af4378c901cea902392d4ef17f9d990f25e16f3) @@ -32,6 +32,7 @@ + @@ -93,5 +94,10 @@ org.lamsfoundation.lams.monitoring.quartz.job.FinishScheduleLessonJob + + + org.lamsfoundation.lams.monitoring.quartz.job.EmailScheduleMessageJob + + \ No newline at end of file Index: lams_monitoring/src/java/org/lamsfoundation/lams/monitoring/quartz/job/EmailScheduleMessageJob.java =================================================================== diff -u --- lams_monitoring/src/java/org/lamsfoundation/lams/monitoring/quartz/job/EmailScheduleMessageJob.java (revision 0) +++ lams_monitoring/src/java/org/lamsfoundation/lams/monitoring/quartz/job/EmailScheduleMessageJob.java (revision 1af4378c901cea902392d4ef17f9d990f25e16f3) @@ -0,0 +1,91 @@ +/**************************************************************** + * 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 + * **************************************************************** + */ + +/* $Id$ */ +package org.lamsfoundation.lams.monitoring.quartz.job; + +import java.util.Collection; +import java.util.Map; + +import org.apache.log4j.Logger; +import org.lamsfoundation.lams.events.DeliveryMethodMail; +import org.lamsfoundation.lams.events.IEventNotificationService; +import org.lamsfoundation.lams.monitoring.service.IMonitoringService; +import org.lamsfoundation.lams.usermanagement.User; +import org.lamsfoundation.lams.web.util.AttributeNames; +import org.quartz.JobExecutionContext; +import org.quartz.JobExecutionException; +import org.quartz.SchedulerContext; +import org.quartz.SchedulerException; +import org.springframework.context.ApplicationContext; + +/** + * Email messages at the specified date. List of recipients is being constructed real time based on specified search + * criterias. + * + * @author Andey Balan + */ +public class EmailScheduleMessageJob extends MonitoringJob { + // --------------------------------------------------------------------- + // Instance variables + // --------------------------------------------------------------------- + private static Logger log = Logger.getLogger(EmailScheduleMessageJob.class); + + protected void executeInternal(JobExecutionContext context) throws JobExecutionException { + IMonitoringService monitoringService = getMonitoringService(context); + IEventNotificationService eventNotificationService = getEventNotificationService(context); + + Map properties = context.getJobDetail().getJobDataMap(); + String emailBody = (String) properties.get("emailBody"); + + //get users to whom send emails + int searchType = (Integer) properties.get("searchType"); + Long lessonId = (Long) properties.get(AttributeNames.PARAM_LESSON_ID); + Integer orgId = (Integer) properties.get(AttributeNames.PARAM_ORGANISATION_ID); + Long activityId = (Long) properties.get(AttributeNames.PARAM_ACTIVITY_ID); + Integer xDaystoFinish = (Integer) properties.get("daysToDeadline"); + String[] lessonIds = (String[]) properties.get("lessonIDs"); + Collection users = getMonitoringService(context).getUsersByEmailNotificationSearchType(searchType, + lessonId, lessonIds, activityId, xDaystoFinish, orgId); + + for (User user : users) { + long userId = user.getUserId(); + log.debug("Sending scheduled email to user [" + userId + "]."); + eventNotificationService.sendMessage(userId, DeliveryMethodMail.getInstance(), monitoringService + .getMessageService().getMessage("event.emailnotifications.email.subject", new Object[] {}), + emailBody); + } + } + + private IEventNotificationService getEventNotificationService(JobExecutionContext context) + throws JobExecutionException { + try { + final String CONTEXT_NAME = "context.central"; + + SchedulerContext sc = context.getScheduler().getContext(); + ApplicationContext cxt = (ApplicationContext) sc.get(CONTEXT_NAME); + return (IEventNotificationService) cxt.getBean("eventNotificationService"); + } catch (SchedulerException e) { + throw new JobExecutionException("Failed look up the Scheduler" + e.toString()); + } + } +} \ No newline at end of file Index: lams_monitoring/src/java/org/lamsfoundation/lams/monitoring/service/ContributeActivitiesProcessor.java =================================================================== diff -u -r4f68a533e24967e0185132c5e361a8a054f43941 -r1af4378c901cea902392d4ef17f9d990f25e16f3 --- lams_monitoring/src/java/org/lamsfoundation/lams/monitoring/service/ContributeActivitiesProcessor.java (.../ContributeActivitiesProcessor.java) (revision 4f68a533e24967e0185132c5e361a8a054f43941) +++ lams_monitoring/src/java/org/lamsfoundation/lams/monitoring/service/ContributeActivitiesProcessor.java (.../ContributeActivitiesProcessor.java) (revision 1af4378c901cea902392d4ef17f9d990f25e16f3) @@ -33,8 +33,8 @@ import org.lamsfoundation.lams.learningdesign.SimpleActivity; import org.lamsfoundation.lams.learningdesign.dao.IActivityDAO; import org.lamsfoundation.lams.learningdesign.exception.LearningDesignProcessorException; -import org.lamsfoundation.lams.monitoring.ContributeActivityDTO; import org.lamsfoundation.lams.monitoring.ContributeDTOFactory; +import org.lamsfoundation.lams.monitoring.dto.ContributeActivityDTO; import org.lamsfoundation.lams.tool.exception.LamsToolServiceException; import org.lamsfoundation.lams.tool.service.ILamsCoreToolService; Index: lams_monitoring/src/java/org/lamsfoundation/lams/monitoring/service/IMonitoringService.java =================================================================== diff -u -rcb6d628cd53fe3d51e4f67cbaff7390651a048da -r1af4378c901cea902392d4ef17f9d990f25e16f3 --- lams_monitoring/src/java/org/lamsfoundation/lams/monitoring/service/IMonitoringService.java (.../IMonitoringService.java) (revision cb6d628cd53fe3d51e4f67cbaff7390651a048da) +++ lams_monitoring/src/java/org/lamsfoundation/lams/monitoring/service/IMonitoringService.java (.../IMonitoringService.java) (revision 1af4378c901cea902392d4ef17f9d990f25e16f3) @@ -25,6 +25,7 @@ package org.lamsfoundation.lams.monitoring.service; import java.io.IOException; +import java.util.Collection; import java.util.Date; import java.util.List; import java.util.SortedSet; @@ -443,6 +444,19 @@ * @throws IOException */ public String getLessonStaff(Long lessonID, Integer userID) throws IOException; + + /** + * Returns users by search type criteria. It's sorted by first and last user names. + * + * @param searchType one of 11 constants from MonitoringConstants defining search type + * @param lessonId + * @param lessonIds + * @param activityId + * @param xDaystoFinish + * @param orgId + * @return + */ + Collection getUsersByEmailNotificationSearchType(int searchType, Long lessonId, String[] lessonIds, Long activityId, Integer xDaystoFinish, Integer orgId); /** * This method returns the LearningDesign details for a given Lesson Index: lams_monitoring/src/java/org/lamsfoundation/lams/monitoring/service/MonitoringService.java =================================================================== diff -u -rcb6d628cd53fe3d51e4f67cbaff7390651a048da -r1af4378c901cea902392d4ef17f9d990f25e16f3 --- lams_monitoring/src/java/org/lamsfoundation/lams/monitoring/service/MonitoringService.java (.../MonitoringService.java) (revision cb6d628cd53fe3d51e4f67cbaff7390651a048da) +++ lams_monitoring/src/java/org/lamsfoundation/lams/monitoring/service/MonitoringService.java (.../MonitoringService.java) (revision 1af4378c901cea902392d4ef17f9d990f25e16f3) @@ -84,8 +84,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.monitoring.LearnerProgressBatchDTO; import org.lamsfoundation.lams.monitoring.MonitoringConstants; +import org.lamsfoundation.lams.monitoring.dto.LearnerProgressBatchDTO; import org.lamsfoundation.lams.tool.ToolSession; import org.lamsfoundation.lams.tool.exception.LamsToolServiceException; import org.lamsfoundation.lams.tool.exception.ToolException; @@ -1587,9 +1587,124 @@ } return flashMessage.serializeMessage(); } + + public Collection getUsersByEmailNotificationSearchType(int searchType, Long lessonId, String[] lessonIds, Long activityId, Integer xDaystoFinish, Integer orgId) { + + Lesson lesson = null; + if (lessonId != null) { + lesson = learnerService.getLesson(lessonId); + } + + Collection users = new LinkedList(); + switch (searchType) { + case MonitoringConstants.LESSON_TYPE_ASSIGNED_TO_LESSON: + users = lesson.getAllLearners(); + break; + + case MonitoringConstants.LESSON_TYPE_HAVENT_FINISHED_LESSON: + Set allUsers = lesson.getAllLearners(); + List usersCompletedLesson = getUsersCompletedLesson(lessonId); + users = CollectionUtils.subtract(allUsers, usersCompletedLesson); + break; + + case MonitoringConstants.LESSON_TYPE_HAVE_FINISHED_LESSON: + case MonitoringConstants.COURSE_TYPE_HAVE_FINISHED_PARTICULAR_LESSON: + users = getUsersCompletedLesson(lessonId); + break; + + case MonitoringConstants.LESSON_TYPE_HAVENT_STARTED_LESSON: + case MonitoringConstants.COURSE_TYPE_HAVENT_STARTED_PARTICULAR_LESSON: + allUsers = lesson.getAllLearners(); + List usersStartedLesson = lessonService.getActiveLessonLearners(lessonId); + users = CollectionUtils.subtract(allUsers, usersStartedLesson); + break; + + case MonitoringConstants.LESSON_TYPE_HAVE_STARTED_LESSON: + users = lessonService.getActiveLessonLearners(lessonId); + break; + case MonitoringConstants.LESSON_TYPE_HAVENT_REACHED_PARTICULAR_ACTIVITY: + Activity activity = learnerService.getActivity(activityId); + allUsers = lesson.getAllLearners(); + List usersAttemptedActivity = lessonService.getLearnersHaveAttemptedActivity(activity); + users = CollectionUtils.subtract(allUsers, usersAttemptedActivity); + break; + + case MonitoringConstants.LESSON_TYPE_LESS_THAN_X_DAYS_TO_DEADLINE: + Date now = new Date(); + Calendar currentTimePlusXDays = Calendar.getInstance(); + currentTimePlusXDays.setTime(now); + currentTimePlusXDays.add(Calendar.DATE, xDaystoFinish); + Date scheduleEndDate = lesson.getScheduleEndDate(); + if (scheduleEndDate != null) { + if (now.before(scheduleEndDate) && currentTimePlusXDays.getTime().after(scheduleEndDate)) { + users = lesson.getAllLearners(); + } + + } else if (lesson.isScheduledToCloseForIndividuals()) { + users = groupUserDAO.getUsersWithLessonEndingSoonerThan(lesson, currentTimePlusXDays.getTime()); + } + break; + + case MonitoringConstants.COURSE_TYPE_HAVENT_STARTED_ANY_LESSONS: + List allUSers = learnerService.getUserManagementService().getUsersFromOrganisation(orgId); + Set usersStartedAtLest1Lesson = new TreeSet(); + + Organisation org = (Organisation) learnerService.getUserManagementService().findById(Organisation.class, orgId); + Set lessons = org.getLessons(); + for (Lesson les : lessons) { + Activity firstActivity = les.getLearningDesign().getFirstActivity(); + List usersStartedFirstActivity = learnerProgressDAO.getLearnersHaveAttemptedActivity(firstActivity); + usersStartedAtLest1Lesson.addAll(usersStartedFirstActivity); + } + + users = CollectionUtils.subtract(allUSers, usersStartedAtLest1Lesson); + + break; + + case MonitoringConstants.COURSE_TYPE_HAVE_FINISHED_THESE_LESSONS: + int i = 0; + for (String lessonIdStr : lessonIds) { + lessonId = Long.parseLong(lessonIdStr); + List completedLesson = getUsersCompletedLesson(lessonId); + if (i++ == 0) { + users = completedLesson; + } else { + users = CollectionUtils.intersection(users, completedLesson); + } + } + break; + } + + Set sortedUsers = new TreeSet(new Comparator() { + public int compare(User usr0, User usr1) { + return ((usr0.getFirstName() + usr0.getLastName() + usr0.getLogin()).compareTo(usr1.getFirstName() + usr1.getLastName() + usr1.getLogin())); + } + }); + sortedUsers.addAll(users); + + return sortedUsers; + } + + /** + * Returns list of users who has already finished specified lesson. + * + * @param lessonId specified lesson + * @return + */ + private List getUsersCompletedLesson(Long lessonId) { + List usersCompletedLesson = new LinkedList(); + + List completedLearnerProgresses = learnerProgressDAO.getCompletedLearnerProgressForLesson(lessonId); + for (LearnerProgress learnerProgress : completedLearnerProgresses) { + usersCompletedLesson.add(learnerProgress.getUser()); + } + return usersCompletedLesson; + } + + /** * (non-Javadoc) * * @see org.lamsfoundation.lams.monitoring.service.IMonitoringService#getLearningDesignDetails(java.lang.Long) Index: lams_monitoring/src/java/org/lamsfoundation/lams/monitoring/web/BranchingAction.java =================================================================== diff -u -r12ff0e150f8506d554c1405e0c4d14abda72ca4c -r1af4378c901cea902392d4ef17f9d990f25e16f3 --- lams_monitoring/src/java/org/lamsfoundation/lams/monitoring/web/BranchingAction.java (.../BranchingAction.java) (revision 12ff0e150f8506d554c1405e0c4d14abda72ca4c) +++ lams_monitoring/src/java/org/lamsfoundation/lams/monitoring/web/BranchingAction.java (.../BranchingAction.java) (revision 1af4378c901cea902392d4ef17f9d990f25e16f3) @@ -45,8 +45,8 @@ import org.lamsfoundation.lams.learningdesign.Group; import org.lamsfoundation.lams.learningdesign.BranchActivityEntry; import org.lamsfoundation.lams.learningdesign.SequenceActivity; -import org.lamsfoundation.lams.monitoring.BranchDTO; -import org.lamsfoundation.lams.monitoring.BranchingDTO; +import org.lamsfoundation.lams.monitoring.dto.BranchDTO; +import org.lamsfoundation.lams.monitoring.dto.BranchingDTO; import org.lamsfoundation.lams.monitoring.service.IMonitoringService; import org.lamsfoundation.lams.monitoring.service.MonitoringServiceProxy; import org.lamsfoundation.lams.usermanagement.User; Index: lams_monitoring/src/java/org/lamsfoundation/lams/monitoring/web/ComplexLearnerProgressAction.java =================================================================== diff -u -rf4e88d008fdc553b7e329a8d2d43544fca0a2768 -r1af4378c901cea902392d4ef17f9d990f25e16f3 --- lams_monitoring/src/java/org/lamsfoundation/lams/monitoring/web/ComplexLearnerProgressAction.java (.../ComplexLearnerProgressAction.java) (revision f4e88d008fdc553b7e329a8d2d43544fca0a2768) +++ lams_monitoring/src/java/org/lamsfoundation/lams/monitoring/web/ComplexLearnerProgressAction.java (.../ComplexLearnerProgressAction.java) (revision 1af4378c901cea902392d4ef17f9d990f25e16f3) @@ -50,7 +50,7 @@ import org.lamsfoundation.lams.learningdesign.ParallelActivity; import org.lamsfoundation.lams.learningdesign.SequenceActivity; import org.lamsfoundation.lams.lesson.LearnerProgress; -import org.lamsfoundation.lams.monitoring.ContributeActivityDTO; +import org.lamsfoundation.lams.monitoring.dto.ContributeActivityDTO; import org.lamsfoundation.lams.monitoring.service.IMonitoringService; import org.lamsfoundation.lams.monitoring.service.MonitoringServiceProxy; import org.lamsfoundation.lams.usermanagement.User; Index: lams_monitoring/src/java/org/lamsfoundation/lams/monitoring/web/EmailNotificationsAction.java =================================================================== diff -u -rcb6d628cd53fe3d51e4f67cbaff7390651a048da -r1af4378c901cea902392d4ef17f9d990f25e16f3 --- lams_monitoring/src/java/org/lamsfoundation/lams/monitoring/web/EmailNotificationsAction.java (.../EmailNotificationsAction.java) (revision cb6d628cd53fe3d51e4f67cbaff7390651a048da) +++ lams_monitoring/src/java/org/lamsfoundation/lams/monitoring/web/EmailNotificationsAction.java (.../EmailNotificationsAction.java) (revision 1af4378c901cea902392d4ef17f9d990f25e16f3) @@ -27,123 +27,110 @@ import java.util.Calendar; import java.util.Collection; import java.util.Date; -import java.util.LinkedList; -import java.util.List; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; import java.util.Set; +import java.util.TimeZone; +import java.util.TreeSet; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; -import org.apache.commons.collections.CollectionUtils; import org.apache.struts.action.ActionForm; import org.apache.struts.action.ActionForward; import org.apache.struts.action.ActionMapping; +import org.apache.tomcat.util.json.JSONArray; +import org.apache.tomcat.util.json.JSONException; +import org.apache.tomcat.util.json.JSONObject; +import org.lamsfoundation.lams.events.DeliveryMethodMail; +import org.lamsfoundation.lams.events.IEventNotificationService; import org.lamsfoundation.lams.learning.service.ICoreLearnerService; -import org.lamsfoundation.lams.learningdesign.Activity; import org.lamsfoundation.lams.learningdesign.dao.IGroupUserDAO; -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.monitoring.MonitoringConstants; +import org.lamsfoundation.lams.monitoring.dto.EmailScheduleMessageJobDTO; import org.lamsfoundation.lams.monitoring.service.IMonitoringService; import org.lamsfoundation.lams.monitoring.service.MonitoringServiceProxy; import org.lamsfoundation.lams.usermanagement.Organisation; import org.lamsfoundation.lams.usermanagement.User; import org.lamsfoundation.lams.usermanagement.dto.UserDTO; +import org.lamsfoundation.lams.usermanagement.service.IUserManagementService; +import org.lamsfoundation.lams.util.DateUtil; import org.lamsfoundation.lams.util.WebUtil; import org.lamsfoundation.lams.web.action.LamsDispatchAction; import org.lamsfoundation.lams.web.session.SessionManager; import org.lamsfoundation.lams.web.util.AttributeNames; +import org.quartz.JobDataMap; +import org.quartz.JobDetail; +import org.quartz.Scheduler; +import org.quartz.SchedulerException; +import org.quartz.SimpleTrigger; +import org.quartz.Trigger; +import org.springframework.util.Assert; import org.springframework.web.context.WebApplicationContext; import org.springframework.web.context.support.WebApplicationContextUtils; /** *

- * The action servlet that provide all the monitoring functionalities. It interact with the teacher via flash and JSP - * monitoring interface. + * Responsible for "Email notification" functionality. *

* * @author Andrey Balan * - * ----------------XDoclet Tags-------------------- + * ----------------XDoclet Tags-------------------- * * @struts:action path="/emailNotifications" parameter="method" validate="false" * @struts.action-forward name = "lessonView" path = "/emailnotifications/lessonNotifications.jsp" * @struts.action-forward name = "courseView" path = "/emailnotifications/courseNotifications.jsp" * @struts.action-forward name = "userList" path = "/emailnotifications/userList.jsp" + * @struts.action-forward name = "scheduledEmailList" path = "/emailnotifications/scheduledEmailList.jsp" * - * ----------------XDoclet Tags-------------------- + * ----------------XDoclet Tags-------------------- */ public class EmailNotificationsAction extends LamsDispatchAction { - + // --------------------------------------------------------------------- // Class level constants // --------------------------------------------------------------------- - private static final int LESSON_TYPE_ASSIGNED_TO_LESSON = 0; - private static final int LESSON_TYPE_HAVENT_FINISHED_LESSON = 1; - private static final int LESSON_TYPE_HAVE_FINISHED_LESSON = 2; - private static final int LESSON_TYPE_HAVENT_STARTED_LESSON = 3; - private static final int LESSON_TYPE_HAVE_STARTED_LESSON = 4; - private static final int LESSON_TYPE_HAVENT_REACHED_PARTICULAR_ACTIVITY = 5; - private static final int LESSON_TYPE_LESS_THAN_X_DAYS_TO_DEADLINE = 6; - private static final int COURSE_TYPE_HAVE_STARTED_X_LESSONS = 7; - private static final int COURSE_TYPE_HAVE_FINISHED_X_LESSONS = 8; - private static final int COURSE_TYPE_HAVE_FINISHED_PARTICULAR_LESSON = 9; - private static final int COURSE_TYPE_HAVE_FINISHED_THESE_LESSONS = 10; - - private static ILessonService lessonService; - private static IGroupUserDAO groupUserDAO; - private static ILearnerProgressDAO learnerProgressDAO; + private static final String TRIGGER_PREFIX_NAME = "emailMessageOnScheduleTrigger:"; + private static IEventNotificationService eventNotificationService; + private static IUserManagementService userManagementService; // --------------------------------------------------------------------- // Struts Dispatch Method // --------------------------------------------------------------------- + /** - * This STRUTS action method will initialize a lesson for specific learning design with the given lesson title and - * lesson description. - *

- * If initialization is successed, this method will return a WDDX message which includes the ID of new lesson. - * - * @param mapping - * An ActionMapping class that will be used by the Action class to tell the ActionServlet where to send - * the end-user. - * - * @param form - * The ActionForm class that will contain any data submitted by the end-user via a form. - * @param request - * A standard Servlet HttpServletRequest class. - * @param response - * A standard Servlet HttpServletResponse class. - * @return An ActionForward class that will be returned to the ActionServlet indicating where the user is to go - * next. - * @throws IOException - * @throws ServletException + * Shows "Email notification" page for particular lesson. */ public ActionForward getLessonView(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { - + ICoreLearnerService learnerService = MonitoringServiceProxy.getLearnerService(getServlet() .getServletContext()); long lessonId = WebUtil.readLongParam(request, AttributeNames.PARAM_LESSON_ID); Lesson lesson = learnerService.getLesson(lessonId); Set activities = lesson.getLearningDesign().getActivities(); - Set users = lesson.getAllLearners(); - // activityDAO getActivitiesByLearningDesignId(Long learningDesignId); request.setAttribute("lesson", lesson); request.setAttribute("activities", activities); - request.setAttribute("users", users); return mapping.findForward("lessonView"); } + /** + * Shows "Email notification" page for particular course. + */ public ActionForward getCourseView(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { - + ICoreLearnerService learnerService = MonitoringServiceProxy.getLearnerService(getServlet() .getServletContext()); @@ -152,229 +139,276 @@ // getting the organisation Organisation org = (Organisation) learnerService.getUserManagementService().findById(Organisation.class, orgId); Set lessons = org.getLessons(); -// Set users = lesson.getAllLearners(); - // activityDAO getActivitiesByLearningDesignId(Long learningDesignId); + Lesson firstLesson = null; + Iterator lessonIter = lessons.iterator(); + if (lessonIter.hasNext()) { + firstLesson = lessonIter.next(); + } + request.setAttribute("org", org); request.setAttribute("lessons", lessons); -// request.setAttribute("users", users); + request.setAttribute("firstLesson", firstLesson); return mapping.findForward("courseView"); } + + /** + * Renders a page listing all scheduled emails. + */ + public ActionForward showScheduledEmails(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) throws IOException, ServletException, SchedulerException { + getUserManagementService(); + Scheduler scheduler = getScheduler(); + TreeSet scheduleList = new TreeSet(); + Long lessonId = WebUtil.readLongParam(request, AttributeNames.PARAM_LESSON_ID, true); + boolean isLessonNotifications = (lessonId != null); + Integer organisationId = WebUtil.readIntParam(request, AttributeNames.PARAM_ORGANISATION_ID, true); + + String[] triggerNames = scheduler.getTriggerNames(Scheduler.DEFAULT_GROUP); + for (String triggerName : triggerNames) { + if (triggerName.startsWith(TRIGGER_PREFIX_NAME)) { + Trigger trigger = scheduler.getTrigger(triggerName, Scheduler.DEFAULT_GROUP); + JobDetail jobDetail = scheduler.getJobDetail(trigger.getJobName(), Scheduler.DEFAULT_GROUP); + JobDataMap jobDataMap = jobDetail.getJobDataMap(); + + //filter triggers + if (isLessonNotifications) { + Object jobLessonId = jobDataMap.get(AttributeNames.PARAM_LESSON_ID); + if ((jobLessonId == null) || (! lessonId.equals(jobLessonId))) { + continue; + } + } else { + Object jobOrganisationId = jobDataMap.get(AttributeNames.PARAM_ORGANISATION_ID); + if ((jobOrganisationId == null) || (! organisationId.equals(jobOrganisationId))) { + continue; + } + } + + Date triggerDate = trigger.getNextFireTime(); + String emailBody = WebUtil.convertNewlines((String) jobDataMap.get("emailBody")); + int searchType = (Integer) jobDataMap.get("searchType"); + EmailScheduleMessageJobDTO emailScheduleJobDTO = new EmailScheduleMessageJobDTO(); + emailScheduleJobDTO.setTriggerDate(triggerDate); + emailScheduleJobDTO.setEmailBody(emailBody); + emailScheduleJobDTO.setSearchType(searchType); + scheduleList.add(emailScheduleJobDTO); + } + } + + request.setAttribute("scheduleList", scheduleList); + request.setAttribute(AttributeNames.PARAM_LESSON_ID, lessonId); + request.setAttribute(AttributeNames.PARAM_ORGANISATION_ID, organisationId); + return mapping.findForward("scheduledEmailList"); + } + /** - * The Struts dispatch method that starts a lesson that has been created beforehand. Most likely, the request to - * start lesson should be triggered by the flash component. This method will delegate to the Spring service bean to - * complete all the steps for starting a lesson. Finally, a wddx acknowledgement message will be serialized and sent - * back to the flash component. - * - * @param mapping - * An ActionMapping class that will be used by the Action class to tell the ActionServlet where to send - * the end-user. - * - * @param form - * The ActionForm class that will contain any data submitted by the end-user via a form. - * @param request - * A standard Servlet HttpServletRequest class. - * @param response - * A standard Servlet HttpServletResponse class. - * @return An ActionForward class that will be returned to the ActionServlet indicating where the user is to go - * next. - * @throws IOException - * @throws ServletException + * Method called via Ajax. It either emails selected users or schedules these emails to be sent on specified date. */ public ActionForward emailUsers(ActionMapping mapping, ActionForm form, HttpServletRequest request, - HttpServletResponse response) throws IOException, ServletException { + HttpServletResponse response) throws IOException, ServletException, JSONException { + + JSONObject JSONObject = new JSONObject(); + IMonitoringService monitoringService = MonitoringServiceProxy.getMonitoringService(getServlet() + .getServletContext()); + getEventNotificationService(); - long lessonId = WebUtil.readLongParam(request, AttributeNames.PARAM_LESSON_ID); - String[] userIds = request.getParameterValues("userId"); - + String emailBody = WebUtil.readStrParam(request, "emailBody"); + Long scheduleDateParameter = WebUtil.readLongParam(request, "scheduleDate", true); + + //check if we send email instantly + if (scheduleDateParameter == null) { + boolean isSuccessfullySent = true; + String[] userIdStrs = request.getParameterValues("userId"); + for (String userIdStr : userIdStrs) { + long userId = Long.parseLong(userIdStr); + isSuccessfullySent &= eventNotificationService.sendMessage( + userId, + DeliveryMethodMail.getInstance(), + monitoringService.getMessageService().getMessage("event.emailnotifications.email.subject", + new Object[] {}), emailBody); + } + + JSONObject.put("isSuccessfullySent", isSuccessfullySent); + } else { + try { + Calendar now = Calendar.getInstance(); + + // calculate scheduleDate + Date scheduleDateTeacherTimezone = new Date(scheduleDateParameter); + HttpSession ss = SessionManager.getSession(); + UserDTO teacher = (UserDTO) ss.getAttribute(AttributeNames.USER); + TimeZone teacherTimeZone = teacher.getTimeZone(); + Date scheduleDate = DateUtil.convertFromTimeZoneToDefault(teacherTimeZone, scheduleDateTeacherTimezone); + + JobDetail emailScheduleMessageJob = getEmailScheduleMessageJob(); + emailScheduleMessageJob.setName("emailScheduleMessageJob:" + now.getTimeInMillis()); + emailScheduleMessageJob.setDescription("schedule email message to user(s)"); + emailScheduleMessageJob.getJobDataMap().put("emailBody", emailBody); + + copySearchParametersFromRequestToMap(request, emailScheduleMessageJob.getJobDataMap()); + + // create customized triggers + Trigger startLessonTrigger = new SimpleTrigger(TRIGGER_PREFIX_NAME + now.getTimeInMillis(), + Scheduler.DEFAULT_GROUP, scheduleDate); + // start the scheduling job + Scheduler scheduler = getScheduler(); + scheduler.scheduleJob(emailScheduleMessageJob, startLessonTrigger); + JSONObject.put("isSuccessfullyScheduled", true); + log.debug("Emails have been successfully scheduled to be sent on " + scheduleDate + " [search type is " + request.getParameter("searchType") + "]"); + } catch (SchedulerException e) { + log.error("Error occurred at " + "[emailScheduleMessage]- fail to email scheduling", e); + } + } + + response.setContentType("application/x-json"); + response.getWriter().print(JSONObject); return null; } + /** + * Refreshes user list. + */ public ActionForward getUsers(ActionMapping mapping, ActionForm form, HttpServletRequest request, - HttpServletResponse response) throws IOException, ServletException { + HttpServletResponse response) throws IOException, ServletException, JSONException { + IMonitoringService monitoringService = MonitoringServiceProxy.getMonitoringService(getServlet() + .getServletContext()); ICoreLearnerService learnerService = MonitoringServiceProxy.getLearnerService(getServlet() .getServletContext()); - int searchType = WebUtil.readIntParam(request, "searchType"); - Lesson lesson = null; - Long orgId; - Long activityId = null; - int xDaystoFinish = 0; - int numberLessons = 0; - String[] lessonIds = null; - //TODO check checkOwnerOrStaffMember - //validate request - switch (searchType) { - case LESSON_TYPE_ASSIGNED_TO_LESSON: - case LESSON_TYPE_HAVENT_FINISHED_LESSON: - case LESSON_TYPE_HAVE_FINISHED_LESSON: - case LESSON_TYPE_HAVENT_STARTED_LESSON: - case LESSON_TYPE_HAVE_STARTED_LESSON: - case LESSON_TYPE_HAVENT_REACHED_PARTICULAR_ACTIVITY: - case LESSON_TYPE_LESS_THAN_X_DAYS_TO_DEADLINE: - Long lessonId = WebUtil.readLongParam(request, "lessonId"); - lesson = learnerService.getLesson(lessonId); - break; + Map map = new HashMap(); + copySearchParametersFromRequestToMap(request, map); + + int searchType = (Integer) map.get("searchType"); + Long lessonId = (Long) map.get(AttributeNames.PARAM_LESSON_ID); + Integer orgId = (Integer) map.get(AttributeNames.PARAM_ORGANISATION_ID); + Long activityId = (Long) map.get(AttributeNames.PARAM_ACTIVITY_ID); + Integer xDaystoFinish = (Integer) map.get("daysToDeadline"); + String[] lessonIds = (String[]) map.get("lessonIDs"); + Collection users = monitoringService.getUsersByEmailNotificationSearchType(searchType, lessonId, lessonIds, activityId, xDaystoFinish, orgId); + + JSONArray cellarray = new JSONArray(); - case COURSE_TYPE_HAVE_STARTED_X_LESSONS: - case COURSE_TYPE_HAVE_FINISHED_X_LESSONS: - case COURSE_TYPE_HAVE_FINISHED_PARTICULAR_LESSON: - case COURSE_TYPE_HAVE_FINISHED_THESE_LESSONS: - orgId = WebUtil.readLongParam(request, "orgId"); - Organisation org = (Organisation) learnerService.getUserManagementService().findById(Organisation.class, orgId); - break; + JSONObject responcedata = new JSONObject(); + responcedata.put("total", "" + users.size()); + responcedata.put("page", "" + 1); + responcedata.put("records", "" + users.size()); + + for (User user : users) { + JSONArray cell=new JSONArray(); + cell.put(user.getFirstName() + " " + user.getLastName() + " [" + user.getLogin() + "]"); + + JSONObject cellobj = new JSONObject(); + cellobj.put("id", "" + user.getUserId()); + cellobj.put("cell", cell); + cellarray.put(cellobj); } + responcedata.put("rows", cellarray); + response.setContentType("application/x-json"); + response.getWriter().print(responcedata); + return null; + } + + /** + * Copies search parameters from request to specified map. Validates parameters along the way. + * + * @param request + * @param map specified map + */ + private void copySearchParametersFromRequestToMap(HttpServletRequest request, Map map) { + int searchType = WebUtil.readIntParam(request, "searchType"); + Assert.notNull(searchType); + map.put("searchType", searchType); switch (searchType) { - case LESSON_TYPE_HAVENT_REACHED_PARTICULAR_ACTIVITY: - activityId = WebUtil.readLongParam(request, "activityId"); + case MonitoringConstants.LESSON_TYPE_ASSIGNED_TO_LESSON: + case MonitoringConstants.LESSON_TYPE_HAVENT_FINISHED_LESSON: + case MonitoringConstants.LESSON_TYPE_HAVE_FINISHED_LESSON: + case MonitoringConstants.LESSON_TYPE_HAVENT_STARTED_LESSON: + case MonitoringConstants.LESSON_TYPE_HAVE_STARTED_LESSON: + case MonitoringConstants.LESSON_TYPE_HAVENT_REACHED_PARTICULAR_ACTIVITY: + case MonitoringConstants.LESSON_TYPE_LESS_THAN_X_DAYS_TO_DEADLINE: + Long lessonId = (Long) WebUtil.readLongParam(request, AttributeNames.PARAM_LESSON_ID); + Assert.notNull(lessonId); + map.put(AttributeNames.PARAM_LESSON_ID, lessonId); break; - case LESSON_TYPE_LESS_THAN_X_DAYS_TO_DEADLINE: - xDaystoFinish = WebUtil.readIntParam(request, "daysToDeadline"); - break; - case COURSE_TYPE_HAVE_STARTED_X_LESSONS: - case COURSE_TYPE_HAVE_FINISHED_X_LESSONS: - numberLessons = WebUtil.readIntParam(request, "numberLessons"); + case MonitoringConstants.COURSE_TYPE_HAVENT_STARTED_ANY_LESSONS: + case MonitoringConstants.COURSE_TYPE_HAVE_FINISHED_THESE_LESSONS: + case MonitoringConstants.COURSE_TYPE_HAVE_FINISHED_PARTICULAR_LESSON: + case MonitoringConstants.COURSE_TYPE_HAVENT_STARTED_PARTICULAR_LESSON: + Integer organisationId = WebUtil.readIntParam(request, AttributeNames.PARAM_ORGANISATION_ID); + Assert.notNull(organisationId); + map.put(AttributeNames.PARAM_ORGANISATION_ID, organisationId); break; - case COURSE_TYPE_HAVE_FINISHED_PARTICULAR_LESSON: - Long lessonId = WebUtil.readLongParam(request, "lessonId"); - lesson = learnerService.getLesson(lessonId); - break; - case COURSE_TYPE_HAVE_FINISHED_THESE_LESSONS: - lessonIds = request.getParameterValues("lessonId"); - break; } - Collection users = getUsers(searchType, lesson, lessonIds, activityId, xDaystoFinish); - request.setAttribute("users", users); - - return mapping.findForward("userList"); - } - - public Collection getUsers(int searchType, Lesson lesson, String[] lessonIds, Long activityId, int xDaystoFinish) throws IOException, ServletException { - getLessonService(); - - ICoreLearnerService learnerService = MonitoringServiceProxy.getLearnerService(getServlet() - .getServletContext()); - - Long lessonId = lesson.getLessonId(); - - Collection users = new LinkedList(); switch (searchType) { - case LESSON_TYPE_ASSIGNED_TO_LESSON: - users = lesson.getAllLearners(); + case MonitoringConstants.LESSON_TYPE_HAVENT_REACHED_PARTICULAR_ACTIVITY: + Long activityId = WebUtil.readLongParam(request, AttributeNames.PARAM_ACTIVITY_ID); + Assert.notNull(activityId); + map.put(AttributeNames.PARAM_ACTIVITY_ID, activityId); break; - case LESSON_TYPE_HAVENT_FINISHED_LESSON: - Set allUsers = lesson.getAllLearners(); - List usersCompletedLesson = getUsersCompletedLesson(lessonId); - users = CollectionUtils.subtract(allUsers, usersCompletedLesson); + case MonitoringConstants.LESSON_TYPE_LESS_THAN_X_DAYS_TO_DEADLINE: + Integer xDaystoFinish = WebUtil.readIntParam(request, "daysToDeadline"); + Assert.notNull(xDaystoFinish); + map.put("daysToDeadline", xDaystoFinish); break; - - case LESSON_TYPE_HAVE_FINISHED_LESSON: - users = getUsersCompletedLesson(lessonId); - break; - - case LESSON_TYPE_HAVENT_STARTED_LESSON: - allUsers = lesson.getAllLearners(); - List usersStartedLesson = lessonService.getActiveLessonLearners(lessonId); - users = CollectionUtils.subtract(allUsers, usersStartedLesson); - break; - - case LESSON_TYPE_HAVE_STARTED_LESSON: - users = lessonService.getActiveLessonLearners(lessonId); - break; - case LESSON_TYPE_HAVENT_REACHED_PARTICULAR_ACTIVITY: - Activity activity = learnerService.getActivity(activityId); - allUsers = lesson.getAllLearners(); - List usersAttemptedActivity = lessonService.getLearnersHaveAttemptedActivity(activity); - users = CollectionUtils.subtract(allUsers, usersAttemptedActivity); + case MonitoringConstants.COURSE_TYPE_HAVE_FINISHED_PARTICULAR_LESSON: + case MonitoringConstants.COURSE_TYPE_HAVENT_STARTED_PARTICULAR_LESSON: + Long lessonId = (Long) WebUtil.readLongParam(request, AttributeNames.PARAM_LESSON_ID); + Assert.notNull(lessonId); + map.put(AttributeNames.PARAM_LESSON_ID, lessonId); break; - - case LESSON_TYPE_LESS_THAN_X_DAYS_TO_DEADLINE: - Date now = new Date(); - Calendar currentTimePlusXDays = Calendar.getInstance(); - currentTimePlusXDays.setTime(now); - currentTimePlusXDays.add(Calendar.DATE, xDaystoFinish); - - Date scheduleEndDate = lesson.getScheduleEndDate(); - if (scheduleEndDate != null) { - if (now.before(scheduleEndDate) && currentTimePlusXDays.getTime().after(scheduleEndDate)) { - users = lesson.getAllLearners(); - } - - } else if (lesson.isScheduledToCloseForIndividuals()) { - getGroupUserDAO().getUsersWithLessonEndingSoonerThan(lesson, currentTimePlusXDays.getTime()); - } + case MonitoringConstants.COURSE_TYPE_HAVE_FINISHED_THESE_LESSONS: + String[] lessonIds = request.getParameterValues(AttributeNames.PARAM_LESSON_ID); + Assert.notNull(lessonIds); + map.put("lessonIDs", lessonIds); break; - - case COURSE_TYPE_HAVE_STARTED_X_LESSONS: - break; - - case COURSE_TYPE_HAVE_FINISHED_X_LESSONS: - break; - - case COURSE_TYPE_HAVE_FINISHED_PARTICULAR_LESSON: - users = getUsersCompletedLesson(lessonId); - break; - - case COURSE_TYPE_HAVE_FINISHED_THESE_LESSONS: - int i = 0; - for (String lessonIdStr : lessonIds) { - lessonId = Long.parseLong(lessonIdStr); - List completedLesson = getUsersCompletedLesson(lessonId); - if (i++ == 0) { - users = completedLesson; - } else { - users = CollectionUtils.intersection(users, completedLesson); - } - } - break; } - - return users; + } - private List getUsersCompletedLesson(Long lessonId) { - List usersCompletedLesson = new LinkedList(); - - List completedLearnerProgresses = getLearnerProgressDAO().getCompletedLearnerProgressForLesson(lessonId); - for (LearnerProgress learnerProgress : completedLearnerProgresses) { - usersCompletedLesson.add(learnerProgress.getUser()); - } - return usersCompletedLesson; - } - - private ILessonService getLessonService() { - if (lessonService == null) { + private IEventNotificationService getEventNotificationService() { + if (eventNotificationService == null) { WebApplicationContext ctx = WebApplicationContextUtils.getRequiredWebApplicationContext(getServlet() .getServletContext()); - lessonService = (ILessonService) ctx.getBean("lessonService"); + eventNotificationService = (IEventNotificationService) ctx.getBean("eventNotificationService"); } - return lessonService; + return eventNotificationService; } - private IGroupUserDAO getGroupUserDAO() { - if (groupUserDAO == null) { + private IUserManagementService getUserManagementService() { + if (userManagementService == null) { WebApplicationContext ctx = WebApplicationContextUtils.getRequiredWebApplicationContext(getServlet() .getServletContext()); - groupUserDAO = (IGroupUserDAO) ctx.getBean("groupUserDAO"); + userManagementService = (IUserManagementService) ctx.getBean("userManagementService"); } - return groupUserDAO; + return userManagementService; } - private ILearnerProgressDAO getLearnerProgressDAO() { - if (learnerProgressDAO == null) { - WebApplicationContext ctx = WebApplicationContextUtils.getRequiredWebApplicationContext(getServlet() - .getServletContext()); - learnerProgressDAO = (ILearnerProgressDAO) ctx.getBean("learnerProgressDAO"); - } - return learnerProgressDAO; + /** + * + * @return the bean that defines emailScheduleMessageJob. + */ + private JobDetail getEmailScheduleMessageJob() { + WebApplicationContext ctx = WebApplicationContextUtils.getRequiredWebApplicationContext(getServlet() + .getServletContext()); + return (JobDetail) ctx.getBean(MonitoringConstants.JOB_EMAIL_MESSAGE); } + + /** + * + * @return the bean that defines Scheduler. + */ + private Scheduler getScheduler() { + WebApplicationContext ctx = WebApplicationContextUtils.getRequiredWebApplicationContext(getServlet() + .getServletContext()); + return (Scheduler) ctx.getBean("scheduler"); + } } Index: lams_monitoring/web/CloudWizard.swf =================================================================== diff -u -rdd4d44a08e68d690c1ca65156ff7d4378e71fb1e -r1af4378c901cea902392d4ef17f9d990f25e16f3 Binary files differ Index: lams_monitoring/web/WEB-INF/web.xml =================================================================== diff -u -r6710ffa47b5b99cb033f76dc5df2cc729cd34ce0 -r1af4378c901cea902392d4ef17f9d990f25e16f3 --- lams_monitoring/web/WEB-INF/web.xml (.../web.xml) (revision 6710ffa47b5b99cb033f76dc5df2cc729cd34ce0) +++ lams_monitoring/web/WEB-INF/web.xml (.../web.xml) (revision 1af4378c901cea902392d4ef17f9d990f25e16f3) @@ -82,13 +82,13 @@ - initializeLesson - org.lamsfoundation.lams.monitoring.web.InitializeLessonServlet + gateExportPortfolio + org.lamsfoundation.lams.monitoring.web.GateExportPortfolioServlet - performChosenGrouping - org.lamsfoundation.lams.monitoring.web.PerformChosenGroupingServlet + createLessonClass + org.lamsfoundation.lams.monitoring.web.CreateLessonServlet @@ -97,13 +97,13 @@ - branchingExportPortfolio - org.lamsfoundation.lams.monitoring.web.BranchingExportPortfolioServlet + performChosenGrouping + org.lamsfoundation.lams.monitoring.web.PerformChosenGroupingServlet - gateExportPortfolio - org.lamsfoundation.lams.monitoring.web.GateExportPortfolioServlet + branchingExportPortfolio + org.lamsfoundation.lams.monitoring.web.BranchingExportPortfolioServlet @@ -112,8 +112,8 @@ - createLessonClass - org.lamsfoundation.lams.monitoring.web.CreateLessonServlet + initializeLesson + org.lamsfoundation.lams.monitoring.web.InitializeLessonServlet @@ -145,32 +145,32 @@ - initializeLesson - /initializeLesson + gateExportPortfolio + /gateExportPortfolio - performChosenGrouping - /monitoring/performChosenGrouping + createLessonClass + /createLessonClass initializeAndCreateLessons /initializeAndCreateLessons + performChosenGrouping + /monitoring/performChosenGrouping + + branchingExportPortfolio /branchingExportPortfolio - gateExportPortfolio - /gateExportPortfolio - - sequenceExportPortfolio /sequenceExportPortfolio - createLessonClass - /createLessonClass + initializeLesson + /initializeLesson @@ -237,13 +237,6 @@ /WEB-INF/jstl/tlds/x.tld - - - - fck-editor - /WEB-INF/fckeditor/tlds/FCKeditor.tld - - Index: lams_monitoring/web/emailnotifications/additionalSettings.jsp =================================================================== diff -u --- lams_monitoring/web/emailnotifications/additionalSettings.jsp (revision 0) +++ lams_monitoring/web/emailnotifications/additionalSettings.jsp (revision 1af4378c901cea902392d4ef17f9d990f25e16f3) @@ -0,0 +1,45 @@ +<%@ taglib uri="tags-tiles" prefix="tiles" %> +<%@ taglib uri="tags-html" prefix="html" %> +<%@ taglib uri="tags-fmt" prefix="fmt" %> +<%@ taglib uri="tags-core" prefix="c" %> +<%@ taglib uri="tags-lams" prefix="lams" %> +<%@ taglib uri="tags-function" prefix="fn"%> + +

+

+ +

+
+
+
+
+ +

+ +

+
+
+ +
+ +
+ + + + + +
+ + + + lessonID=${lesson.lessonId} + + + organisationID=${org.organisationId} + + + + + +
+
Index: lams_monitoring/web/emailnotifications/scheduledEmailList.jsp =================================================================== diff -u --- lams_monitoring/web/emailnotifications/scheduledEmailList.jsp (revision 0) +++ lams_monitoring/web/emailnotifications/scheduledEmailList.jsp (revision 1af4378c901cea902392d4ef17f9d990f25e16f3) @@ -0,0 +1,88 @@ +<%@ taglib uri="tags-tiles" prefix="tiles" %> +<%@ taglib uri="tags-html" prefix="html" %> +<%@ taglib uri="tags-fmt" prefix="fmt" %> +<%@ taglib uri="tags-core" prefix="c" %> +<%@ taglib uri="tags-lams" prefix="lams" %> +<%@ taglib uri="tags-function" prefix="fn"%> +<%@ page import="org.lamsfoundation.lams.util.Configuration"%> +<%@ page import="org.lamsfoundation.lams.util.ConfigurationKeys"%> + + + + + <fmt:message key="title.lams"/> :: <fmt:message key="index.welcome" /> + + + + + + + + + + + + +

+ +

+ + + + + + + + + + + + + + + + +
+ + + Notify students that + + +
+ + + + + + + + + + + + + + + + + ${emailJob.emailBody} +
+ + + + ?method=getLessonView&lessonID=${lessonID} + + + ?method=getCourseView&organisationID=${organisationID} + + + + + + + + +