blob: f3af722dddad066c3ad2f1900da6cc1a7a332030 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2004 - 2005 University Of British Columbia 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:
* University Of British Columbia - initial API and implementation
*******************************************************************************/
/*
* Created on 14-Jan-2005
*/
package org.eclipse.mylar.tasks;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import javax.security.auth.login.LoginException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.IJobChangeEvent;
import org.eclipse.core.runtime.jobs.IJobChangeListener;
import org.eclipse.core.runtime.jobs.ISchedulingRule;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.mylar.bugzilla.BugzillaPlugin;
import org.eclipse.mylar.bugzilla.core.BugReport;
import org.eclipse.mylar.bugzilla.core.BugzillaRepository;
import org.eclipse.mylar.bugzilla.core.IBugzillaBug;
import org.eclipse.mylar.bugzilla.offlineReports.OfflineReportsFile;
import org.eclipse.mylar.bugzilla.ui.OfflineView;
import org.eclipse.mylar.core.MylarPlugin;
import org.eclipse.mylar.tasks.ui.BugzillaTaskEditorInput;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.internal.Workbench;
/**
* @author Mik Kersten
*/
public class BugzillaTask extends Task {
/**
* Comment for <code>serialVersionUID</code>
*/
private static final long serialVersionUID = 3257007648544469815L;
public static final String FILE_EXTENSION = ".bug_reports";
public enum BugTaskState {FREE, WAITING, DOWNLOADING, COMPARING, OPENING}
private transient BugTaskState state;
/**
* The bug report for this BugzillaTask. This is <code>null</code> if the
* bug report with the specified ID was unable to download.
*/
protected transient BugReport bugReport = null;
/**
* Value is <code>true</code> if the bug report has saved changes that
* need synchronizing with the Bugzilla server.
*/
private boolean isDirty;
/** The last time this task's bug report was downloaded from the server. */
protected Date lastRefresh;
public static final ISchedulingRule rule = new ISchedulingRule() {
public boolean isConflicting(ISchedulingRule schedulingRule) {
return schedulingRule == this;
}
public boolean contains(ISchedulingRule schedulingRule) {
return schedulingRule == this;
}
};
public BugzillaTask(String id, String label) {
super(id, label);
isDirty = false;
GetBugReportJob job = new GetBugReportJob("Downloading from Bugzilla server...");
job.schedule();
}
public BugzillaTask(String id, String label, boolean noDownload) {
super(id, label);
isDirty = false;
if (!noDownload) {
GetBugReportJob job = new GetBugReportJob("Downloading from Bugzilla server...");
job.schedule();
}
}
@Override
public String getLabel() {
return MylarTasksPlugin.getDefault().getBugzillaProvider().getBugzillaDescription(this);
}
/**
* @return Returns the bugReport.
*/
public BugReport getBugReport() {
return bugReport;
}
/**
* @param bugReport The bugReport to set.
*/
public void setBugReport(BugReport bugReport) {
this.bugReport = bugReport;
}
/**
* @return Returns the serialVersionUID.
*/
public static long getSerialVersionUID() {
return serialVersionUID;
}
/**
* @return Returns the lastRefresh.
*/
public Date getLastRefresh() {
return lastRefresh;
}
/**
* @param lastRefresh The lastRefresh to set.
*/
public void setLastRefresh(Date lastRefresh) {
this.lastRefresh = lastRefresh;
}
/**
* @param state The state to set.
*/
public void setState(BugTaskState state) {
this.state = state;
}
/**
* @return Returns <code>true</code> if the bug report has saved changes
* that need synchronizing with the Bugzilla server.
*/
public boolean isDirty() {
return isDirty;
}
/**
* @param isDirty The isDirty to set.
*/
public void setDirty(boolean isDirty) {
this.isDirty = isDirty;
notifyTaskDataChange();
}
/**
* @return Returns the state of the Bugzilla task.
*/
public BugTaskState getState() {
return state;
}
/**
* Try to download the bug from the server.
* @param bugId The ID of the bug report to download.
*
* @return The bug report, or <code>null</code> if it was unsuccessfully
* downloaded.
*/
public BugReport downloadReport() {
// BugzillaTaskEditorInput input = new BugzillaTaskEditorInput(this);
try {
// XXX make sure to send in the server name if there are multiple repositories
return BugzillaRepository.getInstance().getBug(getBugId(getHandle()));
} catch (LoginException e) {
MylarPlugin.log(e, "download failed");
} catch (IOException e) {
MylarPlugin.log(e, "download failed");
}
return null;
}
@Override
public void openTaskInEditor(){
openTask(-1);
}
/**
* Opens this task's bug report in an editor revealing the selected comment.
* @param commentNumber The comment number to reveal
*/
public void openTask(int commentNumber) {
if (state != BugTaskState.FREE) {
return;
}
state = BugTaskState.OPENING;
notifyTaskDataChange();
OpenBugTaskJob job = new OpenBugTaskJob("Opening Bugzilla task in editor...", this);
job.schedule();
job.addJobChangeListener(new IJobChangeListener(){
public void aboutToRun(IJobChangeEvent event) {
// don't care about this event
}
public void awake(IJobChangeEvent event) {
// don't care about this event
}
public void done(IJobChangeEvent event) {
state = BugTaskState.FREE;
notifyTaskDataChange();
}
public void running(IJobChangeEvent event) {
// don't care about this event
}
public void scheduled(IJobChangeEvent event) {
// don't care about this event
}
public void sleeping(IJobChangeEvent event) {
// don't care about this event
}
});
}
/**
* @return <code>true</code> if the bug report for this BugzillaTask was
* successfully downloaded.
*/
public boolean isBugDownloaded() {
return bugReport != null;
}
@Override
public String toString() {
return "bugzilla report id: " + getHandle();
}
protected void openTaskEditor(final IEditorInput input) {
if (isBugDownloaded()) {
Workbench.getInstance().getDisplay().asyncExec(new Runnable() {
public void run() {
// get the active workbench page
IWorkbenchPage page = MylarTasksPlugin.getDefault().getWorkbench().getActiveWorkbenchWindow().getActivePage();
// if we couldn't get the page, get out of here
if (page == null)
return;
try {
// try to open an editor on the input bug
//page.openEditor(input, IBugzillaConstants.EXISTING_BUG_EDITOR_ID);
page.openEditor(input, "org.eclipse.mylar.tasks.ui.bugzillaTaskEditor");
}
catch (PartInitException ex) {
MylarPlugin.log(ex, "couldn't open");
return;
}
}
});
}
else {
Workbench.getInstance().getDisplay().asyncExec(new Runnable() {
public void run() {
MessageDialog.openInformation(Workbench.getInstance().getActiveWorkbenchWindow().getShell(),
"Could not open bug.", "Bug #" + getHandle()
+ " could not be read from the server. Try refreshing the bug task.");
}
});
}
}
/**
* @return Returns the last time this task's bug report was downloaded from
* the server.
*/
public Date getLastRefreshTime() {
return lastRefresh;
}
/**
* @return The number of seconds ago that this task's bug report was
* downloaded from the server.
*/
public long getTimeSinceLastRefresh() {
Date timeNow = new Date();
return (timeNow.getTime() - lastRefresh.getTime())/1000;
}
private class GetBugReportJob extends Job {
public GetBugReportJob(String name) {
super(name);
setRule(rule);
state = BugTaskState.WAITING;
notifyTaskDataChange();
}
@Override
protected IStatus run(IProgressMonitor monitor) {
state = BugTaskState.DOWNLOADING;
notifyTaskDataChange();
// Update time this bugtask was last downloaded.
lastRefresh = new Date();
bugReport = downloadReport();
state = BugTaskState.FREE;
updateTaskDetails();
notifyTaskDataChange();
saveBugReport(true);
return new Status(IStatus.OK, MylarPlugin.IDENTIFIER, IStatus.OK, "", null);
}
}
public void updateTaskDetails() {
setPriority(bugReport.getAttribute("Priority").getValue());
String status = bugReport.getAttribute("Status").getValue();
if (status.equals("RESOLVED")) {
setCompleted(true);
}
}
private class OpenBugTaskJob extends Job {
protected BugzillaTask bugTask;
public OpenBugTaskJob(String name, BugzillaTask bugTask) {
super(name);
this.bugTask = bugTask;
}
@Override
protected IStatus run(IProgressMonitor monitor) {
try{
final IEditorInput input = new BugzillaTaskEditorInput(bugTask);
state = BugTaskState.OPENING;
notifyTaskDataChange();
openTaskEditor(input);
state = BugTaskState.FREE;
notifyTaskDataChange();
return new Status(IStatus.OK, MylarPlugin.IDENTIFIER, IStatus.OK, "", null);
}catch(Exception e){
MylarPlugin.log(e, "couldn't open");
}
return Status.CANCEL_STATUS;
}
}
/**
* Refreshes the bug report with the Bugzilla server.
*/
public void refresh() {
// The bug report must be untouched, and this task must not be busy.
if (isDirty() || (state != BugTaskState.FREE)) {
return;
}
GetBugReportJob job = new GetBugReportJob("Refreshing with Bugzilla server...");
job.schedule();
}
@Override
public String getToolTipText() {
// Get the current time.
Date timeNow = new Date();
// Get the number of minutes between the current time
// and the last time the bug report was downloaded
long timeDifference = (timeNow.getTime() - lastRefresh.getTime())/60000;
// Calculate the number of minutes and hours.
// The amount left in "timeDifference" is the
// days' difference.
long minutes = timeDifference % 60;
timeDifference /= 60;
long hours = timeDifference % 24;
timeDifference /= 24;
// Gradually generate the tooltip string...
String toolTip;
if (bugReport == null) {
toolTip = "Last attempted download ";
}
else {
toolTip = "Last downloaded ";
}
if (timeDifference > 0) {
toolTip += timeDifference + ((timeDifference == 1) ? " day " : " days ");
}
if (hours > 0 || timeDifference > 0) {
toolTip += hours + ((hours == 1) ? " hour " : " hours ");
}
toolTip += minutes + ((minutes == 1) ? " minute " : " minutes ") + "ago";
return toolTip;
}
public boolean readBugReport() {
// XXX server name needs to be with the bug report
int location = BugzillaPlugin.getDefault().getOfflineReports().find(getBugId(getHandle()));
if(location == -1){
bugReport = null;
return true;
}
bugReport = (BugReport)BugzillaPlugin.getDefault().getOfflineReports().elements().get(location);
return true;
}
public void saveBugReport(boolean refresh) {
if(bugReport == null)
return;
// XXX use the server name for multiple repositories
OfflineReportsFile offlineReports = BugzillaPlugin.getDefault().getOfflineReports();
int location = offlineReports.find(getBugId(getHandle()));
if(location != -1){
IBugzillaBug tmpBugReport = offlineReports.elements().get(location);
List<IBugzillaBug> l = new ArrayList<IBugzillaBug>(1);
l.add(tmpBugReport);
offlineReports.remove(l);
}
offlineReports.add(bugReport);
if(refresh){
final IWorkbench workbench = PlatformUI.getWorkbench();
workbench.getDisplay().asyncExec(new Runnable() {
public void run() {
OfflineView.refresh();
}
});
}
}
public static String getServerName(String handle) {
int index = handle.lastIndexOf('-');
if(index != -1){
return handle.substring(0, index);
}
return null;
}
public static int getBugId(String handle) {
int index = handle.lastIndexOf('-');
if(index != -1){
String id = handle.substring(index+1);
return Integer.parseInt(id);
}
return -1;
}
}