/******************************************************************************* * Copyright (c) 2004, 2010 Tasktop Technologies and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Tasktop Technologies - initial API and implementation * Manuel Doninger - fixes for bug 349924 *******************************************************************************/ package org.eclipse.mylyn.internal.tasks.core; import java.util.ArrayList; import java.util.Calendar; import java.util.Collection; import java.util.Collections; import java.util.Date; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import java.util.SortedMap; import java.util.TreeMap; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.CopyOnWriteArraySet; import org.eclipse.core.runtime.Assert; import org.eclipse.core.runtime.IConfigurationElement; import org.eclipse.core.runtime.IExtension; import org.eclipse.core.runtime.IExtensionPoint; import org.eclipse.core.runtime.IExtensionRegistry; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Platform; import org.eclipse.core.runtime.Status; import org.eclipse.mylyn.commons.core.StatusHandler; import org.eclipse.mylyn.internal.tasks.core.TaskContainerDelta.Kind; import org.eclipse.mylyn.tasks.core.ITask; import org.eclipse.mylyn.tasks.core.ITaskActivationListener; import org.eclipse.mylyn.tasks.core.ITaskActivityListener; import org.eclipse.mylyn.tasks.core.ITaskActivityManager2; import org.eclipse.osgi.util.NLS; /** * Manages task elapsed time, scheduling, due dates, and the date ranges * * @since 2.1 * @author Rob Elves */ public class TaskActivityManager implements ITaskActivityManager2 { private final TaskActivationHistory taskActivationHistory = new TaskActivationHistory(); private final List activityListeners = new ArrayList(); private final List activationListeners = new ArrayList(); private final Set allScheduledTasks = new HashSet(); private final Set allDueTasks = new HashSet(); private final SortedMap> scheduledTasks = Collections.synchronizedSortedMap(new TreeMap>()); private final SortedMap> dueTasks = Collections.synchronizedSortedMap(new TreeMap>()); // Map of Calendar (hour) to Tasks active during that hour private final SortedMap> activeTasks = Collections.synchronizedSortedMap(new TreeMap>()); // For a given task maps Calendar Hour to duration of time spent (milliseconds) with task active private final Map> taskElapsedTimeMap = new ConcurrentHashMap>(); private final Map> workingSetElapsedTimeMap = new ConcurrentHashMap>(); private final TaskList taskList; private final TaskRepositoryManager repositoryManager; private ITask activeTask; private int startDay = Calendar.MONDAY; private boolean listenersInitialized = false; private final ITaskListChangeListener TASKLIST_CHANGE_LISTENER = new ITaskListChangeListener() { public void containersChanged(Set containers) { for (TaskContainerDelta taskContainerDelta : containers) { if (taskContainerDelta.getKind() == TaskContainerDelta.Kind.ROOT) { reloadPlanningData(); } else if (!taskContainerDelta.isTransient() && Kind.DELETED == taskContainerDelta.getKind() && taskContainerDelta.getElement() instanceof ITask && taskActivationHistory != null) { taskActivationHistory.removeTask((ITask) taskContainerDelta.getElement()); } } } }; private static final String ID_EXTENSION_TASK_ACTIVATION_LISTENERS = ITasksCoreConstants.ID_PLUGIN + ".taskActivationListeners"; //$NON-NLS-1$ public TaskActivityManager(TaskRepositoryManager repositoryManager, TaskList taskList) { this.taskList = taskList; this.repositoryManager = repositoryManager; this.taskList.addChangeListener(TASKLIST_CHANGE_LISTENER); clear(); } /** * Reads task activation listeners from an extension point. *

* Note: The method is not synchronizes since task activation and de-activation are expected to occur sequentially. */ private void initTaskListeners() { if (!listenersInitialized) { listenersInitialized = true; IExtensionRegistry registry = Platform.getExtensionRegistry(); IExtensionPoint listenerExtensionPoint = registry.getExtensionPoint(TaskActivityManager.ID_EXTENSION_TASK_ACTIVATION_LISTENERS); IExtension[] listenerExtensions = listenerExtensionPoint.getExtensions(); for (IExtension extension : listenerExtensions) { IConfigurationElement[] elements = extension.getConfigurationElements(); for (IConfigurationElement element : elements) { if ("listener".equals(element.getName())) { //$NON-NLS-1$ try { Object object = element.createExecutableExtension("class"); //$NON-NLS-1$ if (object instanceof ITaskActivationListener) { addActivationListener((ITaskActivationListener) object); } else { StatusHandler.log(new Status( IStatus.ERROR, ITasksCoreConstants.ID_PLUGIN, NLS.bind( "Unexpected error registering listener contributed by {0}: ''{1}'' does not extend expected class", //$NON-NLS-1$ element.getContributor().getName(), object.getClass() .getCanonicalName()))); } } catch (Throwable e) { StatusHandler.log(new Status(IStatus.ERROR, ITasksCoreConstants.ID_PLUGIN, NLS.bind( "Unexpected error registering listener contributed by {0}", //$NON-NLS-1$ element.getContributor().getName()), e)); } } } } } } /** * Get the user specified first day of the week (Calendar.SUNDAY | Calendar.MONDAY) * * @see http://en.wikipedia.org/wiki/Days_of_the_week#First_day_of_the_week */ public int getWeekStartDay() { return startDay; } /** * Set the first day of the week (Calendar.SUNDAY | Calendar.MONDAY) * * @see http://en.wikipedia.org/wiki/Days_of_the_week#First_day_of_the_week * @param startDay * (Calendar.SUNDAY | Calendar.MONDAY) */ public void setWeekStartDay(int startDay) { TaskActivityUtil.setStartDay(startDay); this.startDay = startDay; for (ITaskActivityListener listener : activityListeners) { listener.activityReset(); } } public void addActivityListener(ITaskActivityListener listener) { activityListeners.add(listener); } public void removeActivityListener(ITaskActivityListener listener) { activityListeners.remove(listener); } public void addActivationListener(ITaskActivationListener listener) { activationListeners.add(listener); } public void removeActivationListener(ITaskActivationListener listener) { activationListeners.remove(listener); } public void clear() { dueTasks.clear(); allDueTasks.clear(); scheduledTasks.clear(); allScheduledTasks.clear(); clearActivity(); } public void clearActivity() { activeTasks.clear(); // handled in TaskActivationExternalizationParticipant now //taskActivationHistory.clear(); taskElapsedTimeMap.clear(); workingSetElapsedTimeMap.clear(); } public void reloadPlanningData() { reloadScheduledData(); for (ITaskActivityListener listener : activityListeners) { listener.activityReset(); } } public void removeElapsedTime(ITask task, Date startDate, Date endDate) { Assert.isNotNull(task); Assert.isNotNull(startDate); Assert.isNotNull(endDate); // remove any time that has already accumulated in data structures SortedMap activityMap = taskElapsedTimeMap.get(task); if (activityMap != null) { Calendar start = TaskActivityUtil.getCalendar(); start.setTime(startDate); TaskActivityUtil.snapStartOfHour(start); Calendar end = TaskActivityUtil.getCalendar(); end.setTime(endDate); TaskActivityUtil.snapEndOfHour(end); activityMap = activityMap.subMap(start, end); for (Calendar cal : new HashSet(activityMap.keySet())) { activityMap.remove(cal); } long elapsedTime = getElapsedTime(task); for (ITaskActivityListener listener : new ArrayList(activityListeners)) { try { listener.elapsedTimeUpdated(task, elapsedTime); } catch (Throwable t) { StatusHandler.log(new Status(IStatus.ERROR, ITasksCoreConstants.ID_PLUGIN, "Task activity listener failed: \"" + listener + "\"", t)); //$NON-NLS-1$ //$NON-NLS-2$ } } } } /** * @param workingSetIds * working set ids */ public void addWorkingSetElapsedTime(String workingSetName, Date startDate, Date endDate) { Assert.isNotNull(workingSetName); Assert.isNotNull(startDate); Assert.isNotNull(endDate); long attentionSpan = endDate.getTime() - startDate.getTime(); // Ignore any potential negative or zero times if (attentionSpan <= 0) { return; } // granularity to the hour Calendar hourOfDay = TaskActivityUtil.getCalendar(); hourOfDay.setTime(startDate); snapToStartOfHour(hourOfDay); SortedMap noTaskActiveMap = workingSetElapsedTimeMap.get(workingSetName); if (noTaskActiveMap == null) { noTaskActiveMap = Collections.synchronizedSortedMap(new TreeMap()); workingSetElapsedTimeMap.put(workingSetName, noTaskActiveMap); } Long daysActivity = noTaskActiveMap.get(hourOfDay); if (daysActivity == null) { daysActivity = new Long(0); } daysActivity = daysActivity.longValue() + attentionSpan; noTaskActiveMap.put(hourOfDay, daysActivity); } public long getElapsedForWorkingSet(String workingSetId, Calendar startDate, Calendar endDate) { Calendar startRange = snapToStartOfHour(getNewInstance(startDate)); Calendar endRange = snapToEndOfHour(getNewInstance(endDate)); long result = 0; SortedMap noTaskActiveMap = workingSetElapsedTimeMap.get(workingSetId); if (noTaskActiveMap != null) { Map subMap = noTaskActiveMap.subMap(startRange, endRange); for (Long time : subMap.values()) { if (time != null && time > 0) { result += time.longValue(); } } } return result; } public Set getWorkingSets() { return workingSetElapsedTimeMap.keySet(); } public void addElapsedTime(AbstractTask task, Date startDate, Date endDate) { Assert.isNotNull(task); Assert.isNotNull(startDate); Assert.isNotNull(endDate); SortedMap activityMap = taskElapsedTimeMap.get(task); if (activityMap == null) { activityMap = Collections.synchronizedSortedMap(new TreeMap()); taskElapsedTimeMap.put(task, activityMap); } long attentionSpan = endDate.getTime() - startDate.getTime(); // Ignore any potential negative or zero times if (attentionSpan <= 0) { return; } // granularity to the hour Calendar hourOfDay = TaskActivityUtil.getCalendar(); hourOfDay.setTime(startDate); snapToStartOfHour(hourOfDay); Long daysActivity = activityMap.get(hourOfDay); if (daysActivity == null) { daysActivity = new Long(0); } daysActivity = daysActivity.longValue() + attentionSpan; activityMap.put(hourOfDay, daysActivity); Set active = activeTasks.get(hourOfDay); if (active == null) { active = new HashSet(); activeTasks.put(hourOfDay, active); } active.add(task); long totalElapsed = getElapsedTime(activityMap); for (ITaskActivityListener listener : new ArrayList(activityListeners)) { try { listener.elapsedTimeUpdated(task, totalElapsed); } catch (Throwable t) { StatusHandler.log(new Status(IStatus.ERROR, ITasksCoreConstants.ID_PLUGIN, "Task activity listener failed: \"" + listener + "\"", t)); //$NON-NLS-1$ //$NON-NLS-2$ } } } private Calendar getNewInstance(Calendar cal) { Calendar newCal = TaskActivityUtil.getCalendar(); newCal.setTimeInMillis(cal.getTimeInMillis()); return newCal; } public void addScheduledTask(AbstractTask task) { DateRange range = task.getScheduledForDate(); if (range != null) { Set tasks = scheduledTasks.get(range); if (tasks == null) { tasks = new CopyOnWriteArraySet(); scheduledTasks.put(range, tasks); } tasks.add(task); allScheduledTasks.add(task); } else { removeScheduledTask(task); } } public void removeScheduledTask(ITask task) { synchronized (scheduledTasks) { for (Set setOfTasks : scheduledTasks.values()) { setOfTasks.remove(task); } allScheduledTasks.remove(task); } } public Set getScheduledTasks(DateRange range) { Set resultingTasks = new HashSet(); synchronized (scheduledTasks) { Set result = scheduledTasks.get(range); if (result != null && !result.isEmpty()) { resultingTasks.addAll(result); } else if (!(range instanceof WeekDateRange)) { return getScheduledTasks(range.getStartDate(), range.getEndDate()); } if (range instanceof WeekDateRange && TaskActivityUtil.getNextWeek().next().compareTo(range) == 0) { resultingTasks.addAll(getScheduledTasks(range.getStartDate(), range.getEndDate())); } } return resultingTasks; } public Set getScheduledTasks(Calendar start, Calendar end) { Set resultingTasks = new HashSet(); synchronized (scheduledTasks) { DateRange startRange = new DateRange(start); Calendar endExclusive = TaskActivityUtil.getCalendar(); endExclusive.setTimeInMillis(end.getTimeInMillis() + 1); DateRange endRange = new DateRange(endExclusive); SortedMap> result = scheduledTasks.subMap(startRange, endRange); for (Entry> entry : result.entrySet()) { DateRange range = entry.getKey(); if (start.compareTo(range.getStartDate()) > 0 || end.compareTo(range.getEndDate()) < 0) { continue; } resultingTasks.addAll(entry.getValue()); } } return resultingTasks; } public void addDueTask(ITask task) { if (task.getDueDate() == null) { removeDueTask(task); return; } Calendar time = TaskActivityUtil.getCalendar(); time.setTime(task.getDueDate()); snapToStartOfHour(time); synchronized (dueTasks) { Set tasks = dueTasks.get(time); if (tasks == null) { tasks = new CopyOnWriteArraySet(); dueTasks.put(time, tasks); } tasks.add(task); allDueTasks.add(task); } } public void removeDueTask(ITask task) { synchronized (dueTasks) { for (Set setOfTasks : dueTasks.values()) { setOfTasks.remove(task); } allDueTasks.remove(task); } } public Set getDueTasks(Calendar start, Calendar end) { Set resultingTasks = new HashSet(); SortedMap> result = dueTasks.subMap(start, end); synchronized (dueTasks) { for (Set set : result.values()) { resultingTasks.addAll(set); } } return resultingTasks; } public void activateTask(ITask task) { deactivateActiveTask(); taskList.addTaskIfAbsent(task); initTaskListeners(); // notify that a task is about to be activated for (ITaskActivationListener listener : new ArrayList(activationListeners)) { try { listener.preTaskActivated(task); } catch (Throwable t) { StatusHandler.log(new Status(IStatus.ERROR, ITasksCoreConstants.ID_PLUGIN, "Task activity listener failed: " + listener, t)); //$NON-NLS-1$ } } activeTask = task; ((AbstractTask) activeTask).setActive(true); for (ITaskActivationListener listener : new ArrayList(activationListeners)) { try { listener.taskActivated(task); } catch (Throwable t) { StatusHandler.log(new Status(IStatus.ERROR, ITasksCoreConstants.ID_PLUGIN, "Task activity listener failed: " + listener, t)); //$NON-NLS-1$ } } } public void deactivateActiveTask() { if (activeTask != null) { deactivateTask(activeTask); } } public void deactivateTask(ITask task) { if (task == null) { return; } if (task.isActive() && task == activeTask) { // notify that a task is about to be deactivated initTaskListeners(); for (ITaskActivationListener listener : new ArrayList(activationListeners)) { try { listener.preTaskDeactivated(task); } catch (Throwable t) { StatusHandler.log(new Status(IStatus.ERROR, ITasksCoreConstants.ID_PLUGIN, "Notification failed for: " + listener, t)); //$NON-NLS-1$ } } ((AbstractTask) activeTask).setActive(false); activeTask = null; for (ITaskActivationListener listener : new ArrayList(activationListeners)) { try { listener.taskDeactivated(task); } catch (Throwable t) { StatusHandler.log(new Status(IStatus.ERROR, ITasksCoreConstants.ID_PLUGIN, "Notification failed for: " + listener, t)); //$NON-NLS-1$ } } } else { ((AbstractTask) task).setActive(false); } } /** * returns active tasks from start to end (exclusive) where both are snapped to the beginning of the hour */ public Set getActiveTasks(Calendar start, Calendar end) { Set resultingTasks = new HashSet(); Calendar startInternal = TaskActivityUtil.getCalendar(); startInternal.setTimeInMillis(start.getTimeInMillis()); TaskActivityUtil.snapStartOfHour(startInternal); Calendar endInternal = TaskActivityUtil.getCalendar(); endInternal.setTimeInMillis(end.getTimeInMillis()); TaskActivityUtil.snapStartOfHour(endInternal); synchronized (activeTasks) { SortedMap> result = activeTasks.subMap(startInternal, endInternal); for (Set set : result.values()) { resultingTasks.addAll(set); } } return resultingTasks; } /** total elapsed time based on activation history */ public long getElapsedTime(ITask task) { SortedMap activityMap = taskElapsedTimeMap.get(task); return getElapsedTime(activityMap); } private long getElapsedTime(SortedMap activityMap) { // TODO: Keep a running total instead of recalculating all the time long result = 0; if (activityMap != null) { synchronized (activityMap) { for (Long time : activityMap.values()) { if (time != null) { result += time.longValue(); } } } } return result; } /** * total elapsed time based on activation history */ public long getElapsedTime(ITask task, Calendar start, Calendar end) { if (task == null) { // TODO: return total elapsed with no task active return 0; } long result = 0; Calendar startRange = snapToStartOfHour(getNewInstance(start)); Calendar endRange = snapToEndOfHour(getNewInstance(end)); SortedMap activityMap = taskElapsedTimeMap.get(task); if (activityMap != null) { synchronized (activityMap) { activityMap = activityMap.subMap(startRange, endRange); for (Long time : activityMap.values()) { if (time != null) { result += time.longValue(); } } } } return result; } /** total elapsed time based on activation history */ public long getElapsedTime(ITask task, DateRange range) { return getElapsedTime(task, range.getStartDate(), range.getEndDate()); } // TODO: remove, copied from TaskListManager private Calendar snapToStartOfHour(Calendar cal) { cal.set(Calendar.MINUTE, 0); cal.set(Calendar.SECOND, 0); cal.set(Calendar.MILLISECOND, 0); cal.getTime(); return cal; } // TODO: remove, copied from TaskListManager private Calendar snapToEndOfHour(Calendar cal) { cal.set(Calendar.MINUTE, cal.getMaximum(Calendar.MINUTE)); cal.set(Calendar.SECOND, cal.getMaximum(Calendar.SECOND)); cal.set(Calendar.MILLISECOND, cal.getMaximum(Calendar.MILLISECOND)); cal.getTime(); return cal; } public ITask getActiveTask() { return activeTask; } private void reloadScheduledData() { for (AbstractTask task : taskList.getAllTasks()) { if (task.getScheduledForDate() != null) { addScheduledTask(task); } if (task.getDueDate() != null) { addDueTask(task); } } } public void setScheduledFor(AbstractTask task, DateRange reminderDate) { Assert.isNotNull(task); if (reminderDate != null && !reminderDate.equals(task.getScheduledForDate())) { (task).setReminded(false); } (task).setScheduledForDate(reminderDate); if (reminderDate == null) { removeScheduledTask(task); } else { removeScheduledTask(task); addScheduledTask(task); } taskList.notifyElementChanged(task); } public void setDueDate(ITask task, Date dueDate) { task.setDueDate(dueDate); if (dueDate == null) { removeDueTask(task); } else { removeDueTask(task); addDueTask(task); } taskList.notifyElementChanged(task); } /** * @return if a repository task, will only return true if the user is a */ public boolean isCompletedToday(ITask task) { if (task != null) { boolean isOwnedByUser = repositoryManager.isOwnedByUser(task); if (!isOwnedByUser) { return false; } else { Date completionDate = task.getCompletionDate(); if (completionDate != null) { Calendar completedTime = TaskActivityUtil.getCalendar(); completedTime.setTime(completionDate); return TaskActivityUtil.isToday(completedTime); } } } return false; } public boolean isPastReminder(AbstractTask task) { if (task == null || task.isCompleted() || task.getScheduledForDate() == null) { return false; } else { return isPastReminder(task.getScheduledForDate(), task.isCompleted()); } } public boolean isPastReminder(DateRange date, boolean isComplete) { if (date == null || isComplete) { return false; } else { if (date.getEndDate().compareTo(TaskActivityUtil.getCalendar()) < 0 && date instanceof DayDateRange) { return true; } else { return false; } } } public boolean isDueToday(ITask task) { if (repositoryManager.isOwnedByUser(task) && !task.isCompleted() && task.getDueDate() != null) { Calendar cal = TaskActivityUtil.getCalendar(); cal.setTimeInMillis(task.getDueDate().getTime()); if (TaskActivityUtil.isToday(cal)) { return true; } } return false; } /** * Tests if the task is owned by the current user and overdue. */ public boolean isOverdue(ITask task) { return (!task.isCompleted() && task.getDueDate() != null && new Date().after(task.getDueDate())) && repositoryManager.isOwnedByUser(task); } /** * Tests whether the task is owned by another user and overdue. */ public boolean isOverdueForOther(ITask task) { return (!task.isCompleted() && task.getDueDate() != null && new Date().after(task.getDueDate())) && !repositoryManager.isOwnedByUser(task); } public boolean isOwnedByUser(ITask task) { return repositoryManager.isOwnedByUser(task); } public boolean isActiveThisWeek(ITask task) { Calendar calStart = TaskActivityUtil.getCalendar(); TaskActivityUtil.snapStartOfWorkWeek(calStart); Calendar calEnd = TaskActivityUtil.getCalendar(); TaskActivityUtil.snapEndOfWeek(calEnd); return getElapsedTime(task, calStart, calEnd) > 0; } public boolean isScheduledForToday(AbstractTask task) { if (task != null && task.getScheduledForDate() != null) { return isScheduledForToday(task.getScheduledForDate()); } return false; } public boolean isScheduledForToday(DateRange range) { if (range != null) { return TaskActivityUtil.getCurrentWeek().getToday().compareTo(range) == 0; } return false; } public boolean isScheduledAfterThisWeek(AbstractTask task) { if (task != null && task.getScheduledForDate() != null) { return isScheduledAfterThisWeek(task.getScheduledForDate()); } return false; } public boolean isScheduledAfterThisWeek(DateRange range) { if (range != null) { return TaskActivityUtil.isAfterCurrentWeek(range.getStartDate()); } return false; } public boolean isScheduledForFuture(AbstractTask task) { if (task != null && task.getScheduledForDate() != null) { return isScheduledForFuture(task.getScheduledForDate()); } return false; } public boolean isScheduledForFuture(DateRange reminder) { if (reminder != null) { return TaskActivityUtil.isFuture(reminder.getStartDate()); } return false; } public boolean isScheduledForThisWeek(AbstractTask task) { boolean result = false; if (task != null && task.getScheduledForDate() != null) { result = isScheduledForThisWeek(task.getScheduledForDate()); } return result; } public boolean isScheduledForThisWeek(DateRange range) { if (range != null) { return TaskActivityUtil.getCurrentWeek().isCurrentWeekDay(range) || TaskActivityUtil.getCurrentWeek().compareTo(range) == 0; } return false; } public boolean isSheduledForPastWeek(AbstractTask task) { boolean result = false; if (task != null && task.getScheduledForDate() != null) { result = isSheduledForPastWeek(task.getScheduledForDate()); } return result; } private boolean isSheduledForPastWeek(DateRange range) { if (range != null) { return (range instanceof WeekDateRange && range.isPast()); } return false; } public boolean isScheduledForNextWeek(AbstractTask task) { if (task != null) { DateRange range = task.getScheduledForDate(); if (range != null) { return TaskActivityUtil.isNextWeek(range.getStartDate()); } } return false; } public void scheduleNewTask(AbstractTask newTask) { newTask.setCreationDate(new Date()); // TODO: set based on preference? see bug#158461 setScheduledFor(newTask, TaskActivityUtil.getCurrentWeek()); } public boolean isDueThisWeek(ITask task) { Date due = task.getDueDate(); if (due != null && repositoryManager.isOwnedByUser(task)) { Calendar cal = TaskActivityUtil.getCalendar(); cal.setTime(due); return TaskActivityUtil.isThisWeek(cal); } return false; } /** * Note: Returns all task scheduled for a SPECIFIC day this week. Not those in the "This Week" / Someday bin */ public Set getScheduledForADayThisWeek() { DateRange current = TaskActivityUtil.getCurrentWeek(); return getScheduledTasks(current.getStartDate(), current.getEndDate()); } public TaskActivationHistory getTaskActivationHistory() { return taskActivationHistory; } public Date getFirstActivity(ITask task) { SortedMap activityMap = taskElapsedTimeMap.get(task); if (activityMap != null && !activityMap.isEmpty()) { return activityMap.firstKey().getTime(); } return null; } public Date getLastActivity(ITask task) { SortedMap activityMap = taskElapsedTimeMap.get(task); if (activityMap != null && !activityMap.isEmpty()) { return activityMap.lastKey().getTime(); } return null; } public Set getAllScheduledTasks() { return new HashSet(allScheduledTasks); } public Set getAllScheduledTasksInternal() { Set tasks = new HashSet(); synchronized (scheduledTasks) { for (ITask task : allScheduledTasks) { if (task instanceof AbstractTask) { tasks.add((AbstractTask) task); } } } return tasks; } public Set getAllDueTasks() { return new HashSet(allDueTasks); } public Set getOverScheduledTasks() { Set children = new HashSet(); Calendar start = TaskActivityUtil.getCalendar(); start.setTimeInMillis(0); Calendar end = TaskActivityUtil.getCalendar(); TaskActivityUtil.snapStartOfDay(end); for (ITask task : getScheduledTasks(start, end)) { if (!task.isCompleted()) { children.add(task); } } return children; } public Collection getOverDueTasks() { Set children = new HashSet(); Calendar start = TaskActivityUtil.getCalendar(); start.setTimeInMillis(0); Calendar end = TaskActivityUtil.getCalendar(); TaskActivityUtil.snapStartOfHour(end); for (ITask task : getDueTasks(start, end)) { if (!task.isCompleted() && repositoryManager.isOwnedByUser(task)) { children.add(task); } } return children; } public Collection getUnscheduled() { Set allTasks = new HashSet(taskList.getAllTasks()); for (ITask abstractTask : getAllScheduledTasks()) { allTasks.remove(abstractTask); } return allTasks; } public boolean isActive(ITask task) { Assert.isNotNull(task); return task.equals(getActiveTask()); } }