/*******************************************************************************
* Copyright (c) 2004, 2012 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
*******************************************************************************/
package org.eclipse.mylyn.internal.tasks.ui.notifications;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Status;
import org.eclipse.mylyn.commons.core.StatusHandler;
import org.eclipse.mylyn.commons.notifications.ui.AbstractUiNotification;
import org.eclipse.mylyn.internal.tasks.core.data.ITaskDataManagerListener;
import org.eclipse.mylyn.internal.tasks.core.data.SynchronizationManger;
import org.eclipse.mylyn.internal.tasks.core.data.TaskDataDiff;
import org.eclipse.mylyn.internal.tasks.core.data.TaskDataManager;
import org.eclipse.mylyn.internal.tasks.core.data.TaskDataManagerEvent;
import org.eclipse.mylyn.internal.tasks.core.sync.SynchronizeTasksJob;
import org.eclipse.mylyn.internal.tasks.ui.ITaskListNotificationProvider;
import org.eclipse.mylyn.internal.tasks.ui.TasksUiPlugin;
import org.eclipse.mylyn.internal.tasks.ui.views.PresentationFilter;
import org.eclipse.mylyn.tasks.core.ITask;
import org.eclipse.mylyn.tasks.core.ITask.SynchronizationState;
import org.eclipse.mylyn.tasks.core.data.ITaskDataWorkingCopy;
import org.eclipse.mylyn.tasks.ui.AbstractRepositoryConnectorUi;
import org.eclipse.mylyn.tasks.ui.TasksUi;
import com.google.common.base.Strings;
/**
* @author Steffen Pingel
*/
public class TaskListNotifier implements ITaskDataManagerListener, ITaskListNotificationProvider {
public final static String KEY_INCOMING_NOTIFICATION_TEXT = "org.eclipse.mylyn.tasks.ui.TaskNotificationText"; //$NON-NLS-1$
private final TaskDataManager taskDataManager;
private final List<TaskListNotification> notificationQueue = new ArrayList<TaskListNotification>();
public boolean enabled;
private final SynchronizationManger synchronizationManger;
public TaskListNotifier(TaskDataManager taskDataManager, SynchronizationManger synchronizationManger) {
this.taskDataManager = taskDataManager;
this.synchronizationManger = synchronizationManger;
}
public TaskListNotification getNotification(ITask task, Object token) {
if (task.getSynchronizationState() == SynchronizationState.INCOMING_NEW) {
TaskListNotification notification = new TaskListNotification(task, token);
notification.setDescription(Messages.TaskListNotifier_New_unread_task);
return notification;
} else if (task.getSynchronizationState().isIncoming()) {
String notificationText = task.getAttribute(KEY_INCOMING_NOTIFICATION_TEXT);
if (!Strings.isNullOrEmpty(notificationText)) {
TaskListNotification notification = new TaskListNotification(task, token);
notification.setDescription(notificationText);
return notification;
}
}
return null;
}
public TaskDataDiff getDiff(ITask task) {
ITaskDataWorkingCopy workingCopy;
try {
workingCopy = taskDataManager.getTaskDataState(task);
if (workingCopy != null) {
return synchronizationManger.createDiff(workingCopy.getRepositoryData(), workingCopy.getLastReadData(),
new NullProgressMonitor());
}
} catch (CoreException e) {
StatusHandler.log(new Status(IStatus.ERROR, TasksUiPlugin.ID_PLUGIN, "Failed to get task data for task: \"" //$NON-NLS-1$
+ task + "\"", e)); //$NON-NLS-1$
}
return null;
}
@Override
public void taskDataUpdated(TaskDataManagerEvent event) {
// Events from SynchronizeQueryJobs end up with incorrect diffs
// Only notify for the subsequent SynchronizeTasksJobs
if (event.getTaskChanged() && event.getData() instanceof SynchronizeTasksJob) {
// Always record the notification text, it may be read outside of the notification
// The text does not need a token to be recorded, and manually synchronized tasks will not have an associated token
recordNotificationText(event);
if (shouldDisplayNotification(event)) {
queueNotification(event);
}
}
}
private void recordNotificationText(TaskDataManagerEvent event) {
ITask task = event.getTask();
SynchronizationState state = task.getSynchronizationState();
String notificationText = null;
if (state.isIncoming()) {
notificationText = computeNotificationText(task);
}
task.setAttribute(KEY_INCOMING_NOTIFICATION_TEXT, notificationText);
}
public String computeNotificationText(ITask task) {
TaskDataDiff diff = getDiff(task);
if (diff != null && diff.hasChanged()) {
return TaskDiffUtil.toString(diff, true);
}
return null;
}
private boolean shouldDisplayNotification(TaskDataManagerEvent event) {
return event.getToken() != null && isEnabled()
&& PresentationFilter.getInstance().isInVisibleQuery(event.getTask());
}
private void queueNotification(TaskDataManagerEvent event) {
AbstractRepositoryConnectorUi connectorUi = TasksUi
.getRepositoryConnectorUi(event.getTaskData().getConnectorKind());
if (!connectorUi.hasCustomNotifications()) {
TaskListNotification notification = getNotification(event.getTask(), event.getToken());
if (notification != null) {
synchronized (notificationQueue) {
if (enabled) {
notificationQueue.add(notification);
}
}
}
}
}
public Set<AbstractUiNotification> getNotifications() {
synchronized (notificationQueue) {
if (notificationQueue.isEmpty()) {
return Collections.emptySet();
}
HashSet<AbstractUiNotification> result = new HashSet<AbstractUiNotification>(notificationQueue);
notificationQueue.clear();
return result;
}
}
@Override
public void editsDiscarded(TaskDataManagerEvent event) {
// ignore
}
public void setEnabled(boolean enabled) {
synchronized (notificationQueue) {
if (!enabled) {
notificationQueue.clear();
}
this.enabled = enabled;
}
}
public boolean isEnabled() {
synchronized (notificationQueue) {
return enabled;
}
}
}