Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorrelves2007-02-13 02:28:16 -0500
committerrelves2007-02-13 02:28:16 -0500
commit5ddc687e18141108ae52812ee74cd067db340e66 (patch)
tree5a409ea7cf917ab02af4c8473a0bbe1c4ec4bd90
parent1d8c2973398fb86cdf00713a135ba286fca91107 (diff)
downloadorg.eclipse.mylyn.tasks-5ddc687e18141108ae52812ee74cd067db340e66.tar.gz
org.eclipse.mylyn.tasks-5ddc687e18141108ae52812ee74cd067db340e66.tar.xz
org.eclipse.mylyn.tasks-5ddc687e18141108ae52812ee74cd067db340e66.zip
RESOLVED - bug 173575: Adding the report history to the report
https://bugs.eclipse.org/bugs/show_bug.cgi?id=173575
-rw-r--r--org.eclipse.mylyn.bugzilla.core/META-INF/MANIFEST.MF3
-rw-r--r--org.eclipse.mylyn.bugzilla.core/src/org/eclipse/mylyn/internal/bugzilla/core/BugzillaClient.java60
-rw-r--r--org.eclipse.mylyn.bugzilla.core/src/org/eclipse/mylyn/internal/bugzilla/core/BugzillaRepositoryConnector.java36
-rw-r--r--org.eclipse.mylyn.bugzilla.core/src/org/eclipse/mylyn/internal/bugzilla/core/IBugzillaConstants.java2
-rw-r--r--org.eclipse.mylyn.bugzilla.core/src/org/eclipse/mylyn/internal/bugzilla/core/history/AssignmentEvent.java37
-rw-r--r--org.eclipse.mylyn.bugzilla.core/src/org/eclipse/mylyn/internal/bugzilla/core/history/AttachmentEvent.java183
-rw-r--r--org.eclipse.mylyn.bugzilla.core/src/org/eclipse/mylyn/internal/bugzilla/core/history/AttachmentFlag.java45
-rw-r--r--org.eclipse.mylyn.bugzilla.core/src/org/eclipse/mylyn/internal/bugzilla/core/history/AttachmentFlagState.java18
-rw-r--r--org.eclipse.mylyn.bugzilla.core/src/org/eclipse/mylyn/internal/bugzilla/core/history/AttachmentFlagStatus.java29
-rw-r--r--org.eclipse.mylyn.bugzilla.core/src/org/eclipse/mylyn/internal/bugzilla/core/history/BugzillaTaskHistoryParser.java224
-rw-r--r--org.eclipse.mylyn.bugzilla.core/src/org/eclipse/mylyn/internal/bugzilla/core/history/ResolutionEvent.java41
-rw-r--r--org.eclipse.mylyn.bugzilla.core/src/org/eclipse/mylyn/internal/bugzilla/core/history/ResolutionType.java97
-rw-r--r--org.eclipse.mylyn.bugzilla.core/src/org/eclipse/mylyn/internal/bugzilla/core/history/StatusEvent.java34
-rw-r--r--org.eclipse.mylyn.bugzilla.core/src/org/eclipse/mylyn/internal/bugzilla/core/history/StatusType.java105
-rw-r--r--org.eclipse.mylyn.bugzilla.core/src/org/eclipse/mylyn/internal/bugzilla/core/history/TaskHistory.java115
-rw-r--r--org.eclipse.mylyn.bugzilla.core/src/org/eclipse/mylyn/internal/bugzilla/core/history/TaskRevision.java113
-rw-r--r--org.eclipse.mylyn.bugzilla.tests/src/org/eclipse/mylyn/bugzilla/tests/AllBugzillaTests.java6
-rw-r--r--org.eclipse.mylyn.bugzilla.tests/src/org/eclipse/mylyn/bugzilla/tests/headless/BugzillaTaskHistoryTest.java59
18 files changed, 1178 insertions, 29 deletions
diff --git a/org.eclipse.mylyn.bugzilla.core/META-INF/MANIFEST.MF b/org.eclipse.mylyn.bugzilla.core/META-INF/MANIFEST.MF
index 6cbfacf80..872f6c4e9 100644
--- a/org.eclipse.mylyn.bugzilla.core/META-INF/MANIFEST.MF
+++ b/org.eclipse.mylyn.bugzilla.core/META-INF/MANIFEST.MF
@@ -10,5 +10,6 @@ Require-Bundle: org.eclipse.core.runtime,
Eclipse-AutoStart: true
Bundle-Vendor: Eclipse.org
Bundle-ClassPath: .
-Export-Package: org.eclipse.mylar.internal.bugzilla.core
+Export-Package: org.eclipse.mylar.internal.bugzilla.core,
+ org.eclipse.mylar.internal.bugzilla.core.history
Bundle-RequiredExecutionEnvironment: J2SE-1.5
diff --git a/org.eclipse.mylyn.bugzilla.core/src/org/eclipse/mylyn/internal/bugzilla/core/BugzillaClient.java b/org.eclipse.mylyn.bugzilla.core/src/org/eclipse/mylyn/internal/bugzilla/core/BugzillaClient.java
index b73b65761..20884e950 100644
--- a/org.eclipse.mylyn.bugzilla.core/src/org/eclipse/mylyn/internal/bugzilla/core/BugzillaClient.java
+++ b/org.eclipse.mylyn.bugzilla.core/src/org/eclipse/mylyn/internal/bugzilla/core/BugzillaClient.java
@@ -28,6 +28,8 @@ import java.util.List;
import java.util.Locale;
import java.util.Map;
+import javax.security.auth.login.LoginException;
+
import org.apache.commons.httpclient.ConnectTimeoutException;
import org.apache.commons.httpclient.Header;
import org.apache.commons.httpclient.HttpClient;
@@ -54,6 +56,8 @@ import org.eclipse.mylar.core.net.HtmlStreamTokenizer;
import org.eclipse.mylar.core.net.HtmlTag;
import org.eclipse.mylar.core.net.WebClientUtil;
import org.eclipse.mylar.core.net.HtmlStreamTokenizer.Token;
+import org.eclipse.mylar.internal.bugzilla.core.history.BugzillaTaskHistoryParser;
+import org.eclipse.mylar.internal.bugzilla.core.history.TaskHistory;
import org.eclipse.mylar.tasks.core.AbstractRepositoryQuery;
import org.eclipse.mylar.tasks.core.IMylarStatusConstants;
import org.eclipse.mylar.tasks.core.MylarStatus;
@@ -447,8 +451,9 @@ public class BugzillaClient {
BugzillaCorePlugin.REPOSITORY_KIND, repositoryUrl.toString(), "" + id);
setupExistingBugAttributes(repositoryUrl.toString(), taskData);
RepositoryReportFactory reportFactory = new RepositoryReportFactory(method
- .getResponseBodyAsStream(), characterEncoding);
+ .getResponseBodyAsStream(), characterEncoding);
reportFactory.populateReport(taskData);
+
return taskData;
}
}
@@ -509,14 +514,14 @@ public class BugzillaClient {
// ordered list of elements as they appear in UI
// and additional elements that may not appear in the incoming xml
// stream but need to be present for bug submission
- BugzillaReportElement[] reportElements = { BugzillaReportElement.SHORT_DESC, BugzillaReportElement.BUG_STATUS, BugzillaReportElement.RESOLUTION,
- BugzillaReportElement.BUG_ID, BugzillaReportElement.REP_PLATFORM, BugzillaReportElement.PRODUCT,
- BugzillaReportElement.OP_SYS, BugzillaReportElement.COMPONENT, BugzillaReportElement.VERSION,
- BugzillaReportElement.PRIORITY, BugzillaReportElement.BUG_SEVERITY, BugzillaReportElement.ASSIGNED_TO,
- BugzillaReportElement.TARGET_MILESTONE, BugzillaReportElement.REPORTER,
- BugzillaReportElement.DEPENDSON, BugzillaReportElement.BLOCKED, BugzillaReportElement.BUG_FILE_LOC,
- BugzillaReportElement.NEWCC, BugzillaReportElement.KEYWORDS, BugzillaReportElement.CC,
- BugzillaReportElement.NEW_COMMENT, BugzillaReportElement.QA_CONTACT };
+ BugzillaReportElement[] reportElements = { BugzillaReportElement.SHORT_DESC, BugzillaReportElement.BUG_STATUS,
+ BugzillaReportElement.RESOLUTION, BugzillaReportElement.BUG_ID, BugzillaReportElement.REP_PLATFORM,
+ BugzillaReportElement.PRODUCT, BugzillaReportElement.OP_SYS, BugzillaReportElement.COMPONENT,
+ BugzillaReportElement.VERSION, BugzillaReportElement.PRIORITY, BugzillaReportElement.BUG_SEVERITY,
+ BugzillaReportElement.ASSIGNED_TO, BugzillaReportElement.TARGET_MILESTONE,
+ BugzillaReportElement.REPORTER, BugzillaReportElement.DEPENDSON, BugzillaReportElement.BLOCKED,
+ BugzillaReportElement.BUG_FILE_LOC, BugzillaReportElement.NEWCC, BugzillaReportElement.KEYWORDS,
+ BugzillaReportElement.CC, BugzillaReportElement.NEW_COMMENT, BugzillaReportElement.QA_CONTACT };
for (BugzillaReportElement element : reportElements) {
RepositoryTaskAttribute reportAttribute = BugzillaClient.makeNewAttribute(element);
@@ -604,7 +609,7 @@ public class BugzillaClient {
try {
postMethod = new PostMethod(WebClientUtil.getRequestPath(repositoryUrl
- + IBugzillaConstants.URL_POST_ATTACHMENT_UPLOAD));
+ + IBugzillaConstants.URL_POST_ATTACHMENT_UPLOAD));
// This option causes the client to first
// check
// with the server to see if it will in fact receive the post before
@@ -981,4 +986,39 @@ public class BugzillaClient {
}
}
+ public TaskHistory getHistory(String taskId) throws IOException, CoreException {
+ WebClientUtil.setupHttpClient(httpClient, proxy, repositoryUrl.toString(), htAuthUser, htAuthPass);
+ if (!authenticated && hasAuthenticationCredentials()) {
+ authenticate();
+ }
+ GetMethod method = null;
+ try {
+ String url = repositoryUrl + IBugzillaConstants.SHOW_ACTIVITY + taskId;
+ method = getConnect(url);
+ if (method != null) {
+ BugzillaTaskHistoryParser parser = new BugzillaTaskHistoryParser(method.getResponseBodyAsStream(),
+ characterEncoding);
+ try {
+ return parser.retrieveHistory();
+ } catch (LoginException e) {
+ authenticated = false;
+ throw new CoreException(new MylarStatus(Status.ERROR, BugzillaCorePlugin.PLUGIN_ID,
+ IMylarStatusConstants.REPOSITORY_LOGIN_ERROR, repositoryUrl.toString(),
+ IBugzillaConstants.INVALID_CREDENTIALS));
+ } catch (ParseException e) {
+ authenticated = false;
+ throw new CoreException(new MylarStatus(Status.ERROR, BugzillaCorePlugin.PLUGIN_ID,
+ IMylarStatusConstants.INTERNAL_ERROR, "Unable to parse response from "
+ + repositoryUrl.toString() + "."));
+ }
+ }
+
+ } finally {
+ if (method != null) {
+ method.releaseConnection();
+ }
+ }
+ return null;
+ }
+
}
diff --git a/org.eclipse.mylyn.bugzilla.core/src/org/eclipse/mylyn/internal/bugzilla/core/BugzillaRepositoryConnector.java b/org.eclipse.mylyn.bugzilla.core/src/org/eclipse/mylyn/internal/bugzilla/core/BugzillaRepositoryConnector.java
index 117074596..65fa56932 100644
--- a/org.eclipse.mylyn.bugzilla.core/src/org/eclipse/mylyn/internal/bugzilla/core/BugzillaRepositoryConnector.java
+++ b/org.eclipse.mylyn.bugzilla.core/src/org/eclipse/mylyn/internal/bugzilla/core/BugzillaRepositoryConnector.java
@@ -50,13 +50,13 @@ import org.eclipse.mylar.tasks.core.UnrecognizedReponseException;
public class BugzillaRepositoryConnector extends AbstractRepositoryConnector {
private static final int MAX_URL_LENGTH = 2000;
-
+
private static final String BUG_ID = "&bug_id=";
private static final String CHANGED_BUGS_CGI_ENDDATE = "&chfieldto=Now";
private static final String CHANGED_BUGS_CGI_QUERY = "/buglist.cgi?query_format=advanced&chfieldfrom=";
-
+
private static final String CLIENT_LABEL = "Bugzilla (supports uncustomized 2.18-2.22)";
private BugzillaAttachmentHandler attachmentHandler;
@@ -113,14 +113,15 @@ public class BugzillaRepositoryConnector extends AbstractRepositoryConnector {
return null;
}
-// String handle = AbstractRepositoryTask.getHandle();
+ // String handle = AbstractRepositoryTask.getHandle();
ITask task = taskList.getTask(repository.getUrl(), id);
AbstractRepositoryTask repositoryTask = null;
if (task == null) {
RepositoryTaskData taskData = null;
taskData = taskDataHandler.getTaskData(repository, id);
if (taskData != null) {
- repositoryTask = new BugzillaTask(repository.getUrl(), ""+bugId, taskData.getId() + ": " + taskData.getDescription(), true);
+ repositoryTask = new BugzillaTask(repository.getUrl(), "" + bugId, taskData.getId() + ": "
+ + taskData.getDescription(), true);
repositoryTask.setTaskData(taskData);
taskList.addTask(repositoryTask);
}
@@ -129,7 +130,7 @@ public class BugzillaRepositoryConnector extends AbstractRepositoryConnector {
}
return repositoryTask;
}
-
+
@Override
public Set<AbstractRepositoryTask> getChangedSinceLastSync(TaskRepository repository,
Set<AbstractRepositoryTask> tasks) throws CoreException {
@@ -157,8 +158,7 @@ public class BugzillaRepositoryConnector extends AbstractRepositoryConnector {
while (itr.hasNext()) {
queryCounter++;
AbstractRepositoryTask task = itr.next();
- String newurlQueryString = URLEncoder.encode(task.getTaskId()
- + ",", repository.getCharacterEncoding());
+ String newurlQueryString = URLEncoder.encode(task.getTaskId() + ",", repository.getCharacterEncoding());
if ((urlQueryString.length() + newurlQueryString.length() + IBugzillaConstants.CONTENT_TYPE_RDF
.length()) > MAX_URL_LENGTH) {
queryForChanged(repository, changedTasks, urlQueryString);
@@ -179,7 +179,7 @@ public class BugzillaRepositoryConnector extends AbstractRepositoryConnector {
return tasks;
}
}
-
+
private void queryForChanged(TaskRepository repository, Set<AbstractRepositoryTask> changedTasks,
String urlQueryString) throws UnsupportedEncodingException, CoreException {
QueryHitCollector collector = new QueryHitCollector(taskList);
@@ -187,9 +187,11 @@ public class BugzillaRepositoryConnector extends AbstractRepositoryConnector {
taskList);
performQuery(query, repository, new NullProgressMonitor(), collector);
-
+
for (AbstractQueryHit hit : collector.getHits()) {
-// String handle = AbstractRepositoryTask.getHandle(repository.getUrl(), hit.getId());
+ // String handle =
+ // AbstractRepositoryTask.getHandle(repository.getUrl(),
+ // hit.getId());
ITask correspondingTask = taskList.getTask(repository.getUrl(), hit.getTaskId());
if (correspondingTask != null && correspondingTask instanceof AbstractRepositoryTask) {
AbstractRepositoryTask repositoryTask = (AbstractRepositoryTask) correspondingTask;
@@ -203,8 +205,10 @@ public class BugzillaRepositoryConnector extends AbstractRepositoryConnector {
// currently it doesn't return a proper modified date string)
if (repositoryTask.getTaskData() != null
&& repositoryTask.getTaskData().getLastModified().equals(repository.getSyncTimeStamp())) {
-// String taskId = RepositoryTaskHandleUtil.getTaskId(repositoryTask.getHandleIdentifier());
- RepositoryTaskData taskData = getTaskDataHandler().getTaskData(repository, repositoryTask.getTaskId());
+ // String taskId =
+ // RepositoryTaskHandleUtil.getTaskId(repositoryTask.getHandleIdentifier());
+ RepositoryTaskData taskData = getTaskDataHandler().getTaskData(repository,
+ repositoryTask.getTaskId());
if (taskData != null && taskData.getLastModified().equals(repository.getSyncTimeStamp())) {
continue;
}
@@ -321,7 +325,8 @@ public class BugzillaRepositoryConnector extends AbstractRepositoryConnector {
throws CoreException {
String product = existingReport.getAttributeValue(BugzillaReportElement.PRODUCT.getKeyString());
for (RepositoryTaskAttribute attribute : existingReport.getAttributes()) {
- BugzillaReportElement element = BugzillaReportElement.valueOf(attribute.getID().trim().toUpperCase(Locale.ENGLISH));
+ BugzillaReportElement element = BugzillaReportElement.valueOf(attribute.getID().trim().toUpperCase(
+ Locale.ENGLISH));
attribute.clearOptions();
List<String> optionValues = BugzillaCorePlugin.getRepositoryConfiguration(taskRepository, false)
.getOptionValues(element, product);
@@ -391,10 +396,9 @@ public class BugzillaRepositoryConnector extends AbstractRepositoryConnector {
newTaskData.addAttribute(BugzillaReportElement.BUG_STATUS.getKeyString(), a);
-
- a = BugzillaClient.makeNewAttribute(BugzillaReportElement.SHORT_DESC);
+ a = BugzillaClient.makeNewAttribute(BugzillaReportElement.SHORT_DESC);
newTaskData.addAttribute(BugzillaReportElement.SHORT_DESC.getKeyString(), a);
-
+
a = BugzillaClient.makeNewAttribute(BugzillaReportElement.VERSION);
optionValues = repositoryConfiguration.getVersions(newTaskData.getProduct());
Collections.sort(optionValues);
diff --git a/org.eclipse.mylyn.bugzilla.core/src/org/eclipse/mylyn/internal/bugzilla/core/IBugzillaConstants.java b/org.eclipse.mylyn.bugzilla.core/src/org/eclipse/mylyn/internal/bugzilla/core/IBugzillaConstants.java
index e5acacd07..aa51d9d56 100644
--- a/org.eclipse.mylyn.bugzilla.core/src/org/eclipse/mylyn/internal/bugzilla/core/IBugzillaConstants.java
+++ b/org.eclipse.mylyn.bugzilla.core/src/org/eclipse/mylyn/internal/bugzilla/core/IBugzillaConstants.java
@@ -238,4 +238,6 @@ public interface IBugzillaConstants {
public static final String CHANGES_SUBMITTED = "changes submitted";
+ public static final String SHOW_ACTIVITY = "/show_activity.cgi?id=";
+
}
diff --git a/org.eclipse.mylyn.bugzilla.core/src/org/eclipse/mylyn/internal/bugzilla/core/history/AssignmentEvent.java b/org.eclipse.mylyn.bugzilla.core/src/org/eclipse/mylyn/internal/bugzilla/core/history/AssignmentEvent.java
new file mode 100644
index 000000000..5230fc306
--- /dev/null
+++ b/org.eclipse.mylyn.bugzilla.core/src/org/eclipse/mylyn/internal/bugzilla/core/history/AssignmentEvent.java
@@ -0,0 +1,37 @@
+/*******************************************************************************
+ * Copyright (c) 2003 - 2006 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
+ *******************************************************************************/
+package org.eclipse.mylar.internal.bugzilla.core.history;
+
+/**
+ * @author John Anvik
+ */
+public class AssignmentEvent extends TaskRevision {
+
+ private static final long serialVersionUID = 3258693199936631348L;
+
+ private final String assigned;
+
+ public AssignmentEvent(String change){
+ this.what = TaskRevision.ASSIGNMENT;
+ this.assigned = change;
+ this.added = change;
+ }
+
+ public String getAssigned() {
+ return this.assigned;
+ }
+
+ @Override
+ public String toString() {
+ return this.getName() + " | " + this.getDate() + " | " + this.getWhat() + " | " + this.getRemoved() + " | "
+ + this.getAssigned();
+ }
+} \ No newline at end of file
diff --git a/org.eclipse.mylyn.bugzilla.core/src/org/eclipse/mylyn/internal/bugzilla/core/history/AttachmentEvent.java b/org.eclipse.mylyn.bugzilla.core/src/org/eclipse/mylyn/internal/bugzilla/core/history/AttachmentEvent.java
new file mode 100644
index 000000000..25b67beae
--- /dev/null
+++ b/org.eclipse.mylyn.bugzilla.core/src/org/eclipse/mylyn/internal/bugzilla/core/history/AttachmentEvent.java
@@ -0,0 +1,183 @@
+/*******************************************************************************
+ * Copyright (c) 2003 - 2006 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
+ *******************************************************************************/
+package org.eclipse.mylar.internal.bugzilla.core.history;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * @author John Anvik
+ */
+public class AttachmentEvent extends TaskRevision {
+
+ private static final long serialVersionUID = 3258693199936631348L;
+
+ private static final Pattern id = Pattern.compile("\\d+");
+
+ private final int attachmentId;
+
+ private List<AttachmentFlag> flags;
+
+ public AttachmentEvent(int id, List<AttachmentFlag> flags) {
+ this.what = TaskRevision.ATTACHMENT;
+ this.attachmentId = id;
+ this.flags = flags;
+ }
+
+ public String getFlagsString() {
+ String flagString = "";
+ for (AttachmentFlag flag : this.flags) {
+ flagString += flag + " ";
+ }
+ return flagString;
+ }
+
+ public static int parseId(String attachment) {
+ Matcher matcher = AttachmentEvent.id.matcher(attachment);
+ if (matcher.find()) {
+ return Integer.parseInt(matcher.group());
+ }
+
+ // Error situation
+ System.err.println("WARNING: Cannot find attachment id in "
+ + attachment);
+ return -1;
+ }
+
+ public static List<AttachmentFlag> parseFlags(String attachmentFlags) {
+ List<AttachmentFlag> flags = new ArrayList<AttachmentFlag>();
+ AttachmentFlagStatus flagStatus = AttachmentFlagStatus.UNKNOWN;
+ AttachmentFlagState flagState = AttachmentFlagState.UNKNOWN;
+
+ String[] flagToken = attachmentFlags.split(", ");
+ for (int i = 0; i < flagToken.length; i++) {
+ String token = flagToken[i];
+ if (token.indexOf("(") != -1) {
+ int end = token.indexOf("(");
+ String substr = token.substring(0, end);
+ token = substr;
+ }
+
+ /* Handle the case of the obsolete status 'needs-work' */
+ if (token.startsWith("needs-work")) {
+ /*
+ * Since we don't know if 'needs-work' applies to 'review' or
+ * 'superreview', deny both
+ */
+ flags.add(new AttachmentFlag(AttachmentFlagStatus.REVIEW,
+ AttachmentFlagState.DENIED));
+ flags.add(new AttachmentFlag(AttachmentFlagStatus.SUPERREVIEW,
+ AttachmentFlagState.DENIED));
+ } else {
+ boolean startsWithReview = token.toLowerCase().startsWith(
+ AttachmentFlagStatus.REVIEW.name().toLowerCase());
+ boolean firstOrSecondReview = token.toLowerCase().contains(
+ AttachmentFlagStatus.REVIEW.name().toLowerCase())
+ && (token.toLowerCase().startsWith("first-") || token
+ .toLowerCase().startsWith("second-"));
+ /*
+ * if(firstOrSecondReview){ System.err.println("First/second
+ * activated"); }
+ */
+ if (startsWithReview || firstOrSecondReview) {
+ flagStatus = AttachmentFlagStatus.REVIEW;
+ } else if (token.toLowerCase().startsWith(
+ AttachmentFlagStatus.SUPERREVIEW.name().toLowerCase())) {
+ flagStatus = AttachmentFlagStatus.SUPERREVIEW;
+ } else if (token.toLowerCase().startsWith(
+ AttachmentFlagStatus.APPROVAL.name().toLowerCase())) {
+ flagStatus = AttachmentFlagStatus.APPROVAL;
+ } else if (token.toLowerCase().startsWith(
+ AttachmentFlagStatus.UI.name().toLowerCase())) {
+ flagStatus = AttachmentFlagStatus.UI;
+ } else if (token.toLowerCase().startsWith(
+ AttachmentFlagStatus.BRANCH.name().toLowerCase())) {
+ flagStatus = AttachmentFlagStatus.BRANCH;
+ } else if (token.toLowerCase().startsWith(
+ AttachmentFlagStatus.COMMITTED.name().toLowerCase())) {
+ flagStatus = AttachmentFlagStatus.COMMITTED;
+ } else if (token.toLowerCase().startsWith(
+ AttachmentFlagStatus.ACCEPTED.name().toLowerCase())) {
+ flagStatus = AttachmentFlagStatus.ACCEPTED;
+ } else if (token.toLowerCase().startsWith(
+ AttachmentFlagStatus.COMMENTED.name().toLowerCase())) {
+ flagStatus = AttachmentFlagStatus.COMMENTED;
+ } else if (token.toLowerCase().startsWith(
+ AttachmentFlagStatus.NONE.name().toLowerCase())) {
+ flagStatus = AttachmentFlagStatus.NONE;
+ } else if (token.toLowerCase().startsWith(
+ AttachmentFlagStatus.REJECTED.name().toLowerCase())) {
+ flagStatus = AttachmentFlagStatus.REJECTED;
+ } else if (token.equals("1")
+ || token.toLowerCase().startsWith(
+ AttachmentFlagStatus.OBSOLETE.name()
+ .toLowerCase())) {
+ flagStatus = AttachmentFlagStatus.OBSOLETE;
+ }
+
+ // Assure that flag was set to something meaningful
+ if (flagStatus.equals(AttachmentFlagStatus.UNKNOWN)
+ && token.equals("") == false) {
+ System.err
+ .println("WARNING: Attachment flag status unknown: "
+ + token);
+ }
+
+ if (token.length() > 0) {
+ if (token.charAt(token.length() - 1) == '?') {
+ flagState = AttachmentFlagState.REQUESTED;
+ } else if (token.charAt(token.length() - 1) == '+') {
+ flagState = AttachmentFlagState.GRANTED;
+ } else if (token.charAt(token.length() - 1) == '-') {
+ flagState = AttachmentFlagState.DENIED;
+ } else if (flagStatus.equals(AttachmentFlagStatus.OBSOLETE)
+ || flagStatus
+ .equals(AttachmentFlagStatus.COMMITTED)
+ || flagStatus.equals(AttachmentFlagStatus.ACCEPTED)
+ || flagStatus
+ .equals(AttachmentFlagStatus.COMMENTED)
+ || flagStatus.equals(AttachmentFlagStatus.NONE)
+ || flagStatus.equals(AttachmentFlagStatus.REJECTED)
+ || flagStatus.equals(AttachmentFlagStatus.REVIEW)){
+ flagState = AttachmentFlagState.OFF;
+ }
+ }
+ // Assure that flag state was set to something meaningful
+ if (flagState.equals(AttachmentFlagState.UNKNOWN)
+ && token.equals("") == false) {
+ System.err
+ .println("WARNING: Attachment flag state unknown: "
+ + token);
+ }
+
+ flags.add(new AttachmentFlag(flagStatus, flagState));
+ }
+ }
+ return flags;
+ }
+
+ @Override
+ public String toString() {
+ return this.getName() + " | " + this.getDate() + " | " + this.getWhat()
+ + " | " + this.attachmentId + " | " + this.getFlagsString();
+ }
+
+ public List<AttachmentFlag> getFlags() {
+ return this.flags;
+ }
+
+ public int getAttachmentId() {
+ return this.attachmentId;
+ }
+
+}
diff --git a/org.eclipse.mylyn.bugzilla.core/src/org/eclipse/mylyn/internal/bugzilla/core/history/AttachmentFlag.java b/org.eclipse.mylyn.bugzilla.core/src/org/eclipse/mylyn/internal/bugzilla/core/history/AttachmentFlag.java
new file mode 100644
index 000000000..c5624271c
--- /dev/null
+++ b/org.eclipse.mylyn.bugzilla.core/src/org/eclipse/mylyn/internal/bugzilla/core/history/AttachmentFlag.java
@@ -0,0 +1,45 @@
+/*******************************************************************************
+ * Copyright (c) 2003 - 2006 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
+ *******************************************************************************/
+package org.eclipse.mylar.internal.bugzilla.core.history;
+
+import java.io.Serializable;
+
+/**
+ * @author John Anvik
+ */
+public class AttachmentFlag implements Serializable {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 1L;
+
+ private final AttachmentFlagStatus status;
+ private final AttachmentFlagState state;
+
+ public AttachmentFlag(AttachmentFlagStatus status, AttachmentFlagState state) {
+ this.status = status;
+ this.state = state;
+ }
+
+ public AttachmentFlagState getState() {
+ return this.state;
+ }
+
+ public AttachmentFlagStatus getStatus() {
+ return this.status;
+ }
+
+ @Override
+ public String toString() {
+ return this.status.name() + "[" + (this.state.equals(AttachmentFlagState.UNKNOWN) ? "" : this.state.name()) + "]";
+ }
+} \ No newline at end of file
diff --git a/org.eclipse.mylyn.bugzilla.core/src/org/eclipse/mylyn/internal/bugzilla/core/history/AttachmentFlagState.java b/org.eclipse.mylyn.bugzilla.core/src/org/eclipse/mylyn/internal/bugzilla/core/history/AttachmentFlagState.java
new file mode 100644
index 000000000..696fe1fae
--- /dev/null
+++ b/org.eclipse.mylyn.bugzilla.core/src/org/eclipse/mylyn/internal/bugzilla/core/history/AttachmentFlagState.java
@@ -0,0 +1,18 @@
+/*******************************************************************************
+ * Copyright (c) 2003 - 2006 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
+ *******************************************************************************/
+package org.eclipse.mylar.internal.bugzilla.core.history;
+
+/**
+ * @author John Anvik
+ */
+public enum AttachmentFlagState{
+ OFF, GRANTED, DENIED, REQUESTED, UNKNOWN;
+}
diff --git a/org.eclipse.mylyn.bugzilla.core/src/org/eclipse/mylyn/internal/bugzilla/core/history/AttachmentFlagStatus.java b/org.eclipse.mylyn.bugzilla.core/src/org/eclipse/mylyn/internal/bugzilla/core/history/AttachmentFlagStatus.java
new file mode 100644
index 000000000..afd3d9de9
--- /dev/null
+++ b/org.eclipse.mylyn.bugzilla.core/src/org/eclipse/mylyn/internal/bugzilla/core/history/AttachmentFlagStatus.java
@@ -0,0 +1,29 @@
+/*******************************************************************************
+ * Copyright (c) 2003 - 2006 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
+ *******************************************************************************/
+package org.eclipse.mylar.internal.bugzilla.core.history;
+
+/**
+ * @author John Anvik
+ */
+public enum AttachmentFlagStatus {
+ REVIEW /* Firefox */,
+ SUPERREVIEW /* Firefox */,
+ APPROVAL /* Firefox */,
+ UI /* Firefox */,
+ BRANCH /* Firefox */,
+ OBSOLETE,
+ UNKNOWN,
+ COMMITTED /* Gnome */,
+ ACCEPTED /* Gnome accepted-committ_now*/,
+ COMMENTED /* Gnome */,
+ NONE /* Gnome */,
+ REJECTED/* Gnome */ ;
+}
diff --git a/org.eclipse.mylyn.bugzilla.core/src/org/eclipse/mylyn/internal/bugzilla/core/history/BugzillaTaskHistoryParser.java b/org.eclipse.mylyn.bugzilla.core/src/org/eclipse/mylyn/internal/bugzilla/core/history/BugzillaTaskHistoryParser.java
new file mode 100644
index 000000000..e60e4431c
--- /dev/null
+++ b/org.eclipse.mylyn.bugzilla.core/src/org/eclipse/mylyn/internal/bugzilla/core/history/BugzillaTaskHistoryParser.java
@@ -0,0 +1,224 @@
+/*******************************************************************************
+ * Copyright (c) 2003 - 2006 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
+ *******************************************************************************/
+package org.eclipse.mylar.internal.bugzilla.core.history;
+
+/**
+ * @author John Anvik
+ */
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.text.ParseException;
+
+import javax.security.auth.login.LoginException;
+
+import org.eclipse.mylar.core.net.HtmlStreamTokenizer;
+import org.eclipse.mylar.core.net.HtmlTag;
+import org.eclipse.mylar.core.net.HtmlStreamTokenizer.Token;
+
+/**
+ * Parses Bugzilla bug activity page to fill in a BugActivity object
+ *
+ * @author John Anvik
+ */
+
+public class BugzillaTaskHistoryParser {
+
+ private InputStream inStream;
+
+ private String characterEncoding;
+
+ public BugzillaTaskHistoryParser(InputStream inStream, String characterEncoding) {
+ this.inStream = inStream;
+ this.characterEncoding = characterEncoding;
+ }
+
+ /**
+ * Parse the activity page for events
+ *
+ * @return A BugActivity object containing the activity history
+ */
+ public TaskHistory retrieveHistory() throws IOException, ParseException, LoginException {
+ TaskHistory activity = new TaskHistory();
+ HtmlStreamTokenizer tokenizer = new HtmlStreamTokenizer(new BufferedReader(new InputStreamReader(inStream,
+ characterEncoding)), null);
+
+ boolean isTitle = false;
+ boolean possibleBadLogin = false;
+ String title = "";
+
+ for (Token token = tokenizer.nextToken(); token.getType() != Token.EOF; token = tokenizer.nextToken()) {
+
+ // make sure that bugzilla doesn't want us to login
+ if (token.getType() == Token.TAG && ((HtmlTag) (token.getValue())).getTagType() == HtmlTag.Type.TITLE
+ && !((HtmlTag) (token.getValue())).isEndTag()) {
+ isTitle = true;
+ continue;
+ }
+
+ if (isTitle) {
+ // get all of the data from inside of the title tag
+ if (token.getType() != Token.TAG) {
+ title += ((StringBuffer) token.getValue()).toString().toLowerCase() + " ";
+ continue;
+ } else if (token.getType() == Token.TAG
+ && ((HtmlTag) token.getValue()).getTagType() == HtmlTag.Type.TITLE
+ && ((HtmlTag) token.getValue()).isEndTag()) {
+ // check if we may have a problem with login by looking
+ // at
+ // the title of the page
+ if ((title.indexOf("login") != -1
+ || (title.indexOf("invalid") != -1 && title.indexOf("password") != -1)
+ || title.indexOf("check e-mail") != -1 || title.indexOf("error") != -1))
+ possibleBadLogin = true;
+ isTitle = false;
+ title = "";
+ }
+ continue;
+ }
+
+ if (token.getType() == Token.TAG) {
+ HtmlTag tag = (HtmlTag) token.getValue();
+ // Skip till find <br> - "there can be only one"
+ if (tag.getTagType() == HtmlTag.Type.BR && !tag.isEndTag()) {
+ // skip tags until start of real data
+ while (true) {
+ token = tokenizer.nextToken();
+ if (token.getType() == Token.TAG) {
+ tag = (HtmlTag) token.getValue();
+ if ((tag.isEndTag() && tag.getTagType() == HtmlTag.Type.TR)
+ || tag.getTagType() == HtmlTag.Type.P)
+ break;
+ }
+ }
+ parseActivity(tokenizer, activity);
+ }
+ }
+ }
+
+ // if we don't have any keywords and suspect that there was a login
+ // problem, assume we had a login problem
+ if (activity.size() == 0 && possibleBadLogin)
+ throw new LoginException("Bugzilla login information incorrect");
+ return activity;
+ }
+
+ /**
+ * Parse the events that have happened to the bug
+ *
+ * @param tokenizer
+ * the token stream
+ * @param activity
+ * the activity object to store the events in
+ * @return
+ */
+ private void parseActivity(HtmlStreamTokenizer tokenizer, TaskHistory activity) throws IOException, ParseException {
+ HtmlTag tag;
+
+ for (Token token = tokenizer.nextToken(); token.getType() != Token.EOF; token = tokenizer.nextToken()) {
+ if (token.getType() == Token.TAG) {
+ tag = (HtmlTag) token.getValue();
+
+ // End of events
+ if (tag.getTagType() == HtmlTag.Type.TABLE && tag.isEndTag())
+ break;
+
+ // Get event entry
+ this.parseEvent(tokenizer, activity);
+ }
+ }
+ }
+
+ /**
+ * Parse an activity entry
+ *
+ * @param tokenizer
+ * the stream of tokens
+ * @param activity
+ * the activity object to store events in
+ */
+ private void parseEvent(HtmlStreamTokenizer tokenizer, TaskHistory activity) {
+
+ HtmlTag tag;
+ int numChanges = 0;
+
+ try {
+ // Discover how many changes for this entry
+ for (Token token = tokenizer.nextToken(); token.getType() != Token.EOF; token = tokenizer.nextToken()) {
+ if (token.getType() == Token.TAG) {
+ tag = (HtmlTag) token.getValue();
+ if (tag.getTagType() == HtmlTag.Type.TD && tag.hasAttribute("rowspan")) {
+ numChanges = tag.getIntAttribute("rowspan");
+ break;
+ }
+ }
+ }
+ } catch (NumberFormatException e) {
+ e.printStackTrace();
+ } catch (IOException e) {
+ e.printStackTrace();
+ } catch (ParseException e) {
+ e.printStackTrace();
+ }
+
+ String name = getData(tokenizer);
+ String date = getData(tokenizer);
+
+ String what, removed, added;
+ TaskRevision event;
+ for (int change = 0; change < numChanges; change++) {
+ what = getData(tokenizer);
+ removed = getData(tokenizer);
+ added = getData(tokenizer);
+
+ event = TaskRevision.createEvent(what, added);
+ event.setName(name);
+ event.setDate(date);
+ event.setRemoved(removed);
+
+ activity.addEvent(event);
+ }
+ }
+
+ private String getData(HtmlStreamTokenizer tokenizer) {
+
+ Token token;
+ HtmlTag tag;
+ StringBuffer sb = new StringBuffer();
+
+ try {
+ for (token = tokenizer.nextToken(); token.getType() != Token.EOF; token = tokenizer.nextToken()) {
+ if (token.getType() == Token.TAG) {
+ tag = (HtmlTag) token.getValue();
+ if (tag.getTagType() == HtmlTag.Type.TD && tag.isEndTag()) {
+ String data = HtmlStreamTokenizer.unescape(sb.toString());
+ if (data.startsWith("\n") && (data.contains("Attachment") == false)) {
+ data = ""; // empty field
+ }
+ return data;
+ }
+ }
+ if (token.getType() == Token.TEXT) {
+ sb.append(token.toString());
+ }
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ } catch (ParseException e) {
+ e.printStackTrace();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
+
+}
diff --git a/org.eclipse.mylyn.bugzilla.core/src/org/eclipse/mylyn/internal/bugzilla/core/history/ResolutionEvent.java b/org.eclipse.mylyn.bugzilla.core/src/org/eclipse/mylyn/internal/bugzilla/core/history/ResolutionEvent.java
new file mode 100644
index 000000000..034e196fb
--- /dev/null
+++ b/org.eclipse.mylyn.bugzilla.core/src/org/eclipse/mylyn/internal/bugzilla/core/history/ResolutionEvent.java
@@ -0,0 +1,41 @@
+/*******************************************************************************
+ * Copyright (c) 2003 - 2006 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
+ *******************************************************************************/
+package org.eclipse.mylar.internal.bugzilla.core.history;
+
+/**
+ * @author John Anvik
+ */
+public class ResolutionEvent extends TaskRevision {
+
+ private static final long serialVersionUID = 3258693199936631348L;
+
+ private final ResolutionType type;
+
+ public ResolutionEvent(ResolutionType type) {
+ this.what = TaskRevision.RESOLUTION;
+ this.type = type;
+ }
+
+ public ResolutionType getType() {
+ return this.type;
+ }
+
+ public String getResolvedBy() {
+ return this.getName();
+ }
+
+ @Override
+ public String toString() {
+ return this.getName() + " | " + this.getDate() + " | " + this.getWhat()
+ + " | " + this.getRemoved() + " | " + (this.getType().equals(ResolutionType.UNKNOWN) ? "" : this.getType());
+ }
+
+}
diff --git a/org.eclipse.mylyn.bugzilla.core/src/org/eclipse/mylyn/internal/bugzilla/core/history/ResolutionType.java b/org.eclipse.mylyn.bugzilla.core/src/org/eclipse/mylyn/internal/bugzilla/core/history/ResolutionType.java
new file mode 100644
index 000000000..33b67e005
--- /dev/null
+++ b/org.eclipse.mylyn.bugzilla.core/src/org/eclipse/mylyn/internal/bugzilla/core/history/ResolutionType.java
@@ -0,0 +1,97 @@
+/*******************************************************************************
+ * Copyright (c) 2003 - 2006 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
+ *******************************************************************************/
+package org.eclipse.mylar.internal.bugzilla.core.history;
+
+/**
+ * @author John Anvik
+ */
+public enum ResolutionType {
+
+ FIXED, DUPLICATE, WONTFIX, INVALID, WORKSFORME, REOPENED, LATER,
+ REMIND, MOVED, UNKNOWN, NOTABUG, NOTGNOME, INCOMPLETE, OBSOLETE, EXPIRED,
+ NOTXIMIAN, NEXTRELEASE, ERRATA, RAWHIDE, UPSTREAM, CANTFIX, CURRENTRELEASE, INSUFFICIENT_DATA, DEFERRED;
+
+ public static ResolutionType convert(String change) {
+ if (change.equals("FIXED")) {
+ return ResolutionType.FIXED;
+ }
+ if (change.contains("DUPLICATE")) {
+ return ResolutionType.DUPLICATE;
+ }
+ if (change.equals("INVALID")) {
+ return ResolutionType.INVALID;
+ }
+ if (change.equals("LATER")) {
+ return ResolutionType.LATER;
+ }
+ if (change.equals("WORKSFORME")) {
+ return ResolutionType.WORKSFORME;
+ }
+ if (change.equals("REOPENED")) {
+ return ResolutionType.REOPENED;
+ }
+ if (change.equals("WONTFIX")) {
+ return ResolutionType.WONTFIX;
+ }
+ if (change.equals("REMIND")) {
+ return ResolutionType.REMIND;
+ }
+ if (change.equals("MOVED")) {
+ return ResolutionType.MOVED;
+ }
+ if (change.equals("EXPIRED")) {
+ return ResolutionType.EXPIRED;
+ }
+ if (change.equals("NOTABUG")) { // Gnome
+ return ResolutionType.NOTABUG;
+ }
+ if (change.equals("NOTGNOME")) { // Gnome
+ return ResolutionType.NOTGNOME;
+ }
+ if (change.equals("INCOMPLETE")) { // Gnome
+ return ResolutionType.INCOMPLETE;
+ }
+ if (change.equals("OBSOLETE")) { // Gnome
+ return ResolutionType.OBSOLETE;
+ }
+ if(change.equals("NOTXIMIAN")){ // Gnome
+ return ResolutionType.NOTXIMIAN;
+ }
+ if(change.equals("NEXTRELEASE")){ // Redhat
+ return ResolutionType.NEXTRELEASE;
+ }
+ if(change.equals("ERRATA")){// Redhat
+ return ResolutionType.ERRATA;
+ }
+ if(change.equals("RAWHIDE")){// Redhat
+ return ResolutionType.RAWHIDE;
+ }
+ if(change.equals("UPSTREAM")){// Redhat
+ return ResolutionType.UPSTREAM;
+ }
+ if(change.equals("CANTFIX")){// Redhat
+ return ResolutionType.CANTFIX;
+ }
+ if(change.equals("CURRENTRELEASE")){// Redhat
+ return ResolutionType.CURRENTRELEASE;
+ }
+ if(change.equals("INSUFFICIENT_DATA")){// Redhat
+ return ResolutionType.INSUFFICIENT_DATA;
+ }
+ if(change.equals("DEFERRED")){// Redhat
+ return ResolutionType.DEFERRED;
+ }
+ if (change.equals("") == false) {
+ System.err.println("Unknown resolution type: " + change);
+ }
+ return ResolutionType.UNKNOWN;
+ }
+}
diff --git a/org.eclipse.mylyn.bugzilla.core/src/org/eclipse/mylyn/internal/bugzilla/core/history/StatusEvent.java b/org.eclipse.mylyn.bugzilla.core/src/org/eclipse/mylyn/internal/bugzilla/core/history/StatusEvent.java
new file mode 100644
index 000000000..91fc06451
--- /dev/null
+++ b/org.eclipse.mylyn.bugzilla.core/src/org/eclipse/mylyn/internal/bugzilla/core/history/StatusEvent.java
@@ -0,0 +1,34 @@
+/*******************************************************************************
+ * Copyright (c) 2003 - 2006 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
+ *******************************************************************************/
+package org.eclipse.mylar.internal.bugzilla.core.history;
+
+/**
+ * @author John Anvik
+ */
+public class StatusEvent extends TaskRevision {
+
+ private final StatusType type;
+
+ public StatusEvent(StatusType type) {
+ this.what = TaskRevision.STATUS;
+ this.type = type;
+ }
+
+ public StatusType getType() {
+ return this.type;
+ }
+
+ @Override
+ public String toString() {
+ return this.getName() + " | " + this.getDate() + " | " + this.getWhat()
+ + " | " + this.getRemoved() + " | " + this.getType();
+ }
+}
diff --git a/org.eclipse.mylyn.bugzilla.core/src/org/eclipse/mylyn/internal/bugzilla/core/history/StatusType.java b/org.eclipse.mylyn.bugzilla.core/src/org/eclipse/mylyn/internal/bugzilla/core/history/StatusType.java
new file mode 100644
index 000000000..7483a7f1a
--- /dev/null
+++ b/org.eclipse.mylyn.bugzilla.core/src/org/eclipse/mylyn/internal/bugzilla/core/history/StatusType.java
@@ -0,0 +1,105 @@
+/*******************************************************************************
+ * Copyright (c) 2003 - 2006 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
+ *******************************************************************************/
+package org.eclipse.mylar.internal.bugzilla.core.history;
+
+/**
+ * @author John Anvik
+ */
+public enum StatusType {
+ VERIFIED,
+ RESOLVED,
+ CLOSED,
+ REOPENED,
+ ASSIGNED,
+ NEW,
+ UNCONFIRMED,
+ NEEDINFO, /* ANT? */
+ WAITING , /* GCC */
+ SUSPENDED, /* GCC */
+ MODIFIED, /* Redhat */
+ POST, /* Redhat */
+ INVESTIGATE, /* Redhat */
+ PASSES_QA, /* Redhat */
+ PROD_READY, /* Redhat */
+ RELEASE_PENDING, /* Redhat */
+ ON_QA, /* Redhat */
+ QA_READY, /* Redhat */
+ FAILS_QA, /* Redhat */
+ SPEC, /* Redhat */
+ UNKNOWN;
+
+ public static StatusType convert(String change) {
+ if (change.equals("RESOLVED")) {
+ return RESOLVED;
+ }
+ if (change.equals("ASSIGNED")) {
+ return ASSIGNED;
+ }
+ if (change.equals("NEW")) {
+ return NEW;
+ }
+ if (change.equals("REOPENED")) {
+ return REOPENED;
+ }
+ if (change.equals("CLOSED")) {
+ return CLOSED;
+ }
+ if (change.equals("VERIFIED")) {
+ return VERIFIED;
+ }
+ if (change.equals("UNCONFIRMED")) {
+ return UNCONFIRMED;
+ }
+ if(change.startsWith("NEEDINFO")){
+ return NEEDINFO;
+ }
+ if(change.equals("WAITING")){
+ return WAITING;
+ }
+ if(change.equals("SUSPENDED")){
+ return SUSPENDED;
+ }
+ if(change.equals("MODIFIED")){
+ return MODIFIED;
+ }
+ if(change.equals("POST")){
+ return POST;
+ }
+ if(change.equals("INVESTIGATE")){
+ return INVESTIGATE;
+ }
+ if(change.equals("PASSES_QA")){
+ return PASSES_QA;
+ }
+ if(change.equals("PROD_READY")){
+ return PROD_READY;
+ }
+ if(change.equals("RELEASE_PENDING")){
+ return RELEASE_PENDING;
+ }
+ if(change.equals("ON_QA")){
+ return ON_QA;
+ }
+ if(change.equals("QA_READY")){
+ return QA_READY;
+ }
+ if(change.equals("FAILS_QA")){
+ return FAILS_QA;
+ }
+ if(change.equals("SPEC")){
+ return SPEC;
+ }
+ if (change.equals("") == false) {
+ System.err.println("Unknown status type: " + change);
+ }
+ return UNKNOWN;
+ }
+} \ No newline at end of file
diff --git a/org.eclipse.mylyn.bugzilla.core/src/org/eclipse/mylyn/internal/bugzilla/core/history/TaskHistory.java b/org.eclipse.mylyn.bugzilla.core/src/org/eclipse/mylyn/internal/bugzilla/core/history/TaskHistory.java
new file mode 100644
index 000000000..54ea8566c
--- /dev/null
+++ b/org.eclipse.mylyn.bugzilla.core/src/org/eclipse/mylyn/internal/bugzilla/core/history/TaskHistory.java
@@ -0,0 +1,115 @@
+/*******************************************************************************
+ * Copyright (c) 2003 - 2006 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
+ *******************************************************************************/
+package org.eclipse.mylar.internal.bugzilla.core.history;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+
+
+/**
+ * @author John Anvik
+ */
+public class TaskHistory implements Iterable<TaskRevision> {
+
+ private final List<StatusEvent> statusEvents;
+
+ private final List<ResolutionEvent> resolutionEvents;
+
+ private final List<AssignmentEvent> assignmentEvents;
+
+ private final List<TaskRevision> otherEvents;
+
+ private final List<AttachmentEvent> attachmentEvents;
+
+ public TaskHistory() {
+ this.statusEvents = new ArrayList<StatusEvent>();
+ this.resolutionEvents = new ArrayList<ResolutionEvent>();
+ this.assignmentEvents = new ArrayList<AssignmentEvent>();
+ this.attachmentEvents = new ArrayList<AttachmentEvent>();
+ this.otherEvents = new ArrayList<TaskRevision>();
+ }
+
+ public void addEvent(TaskRevision event) {
+ if (event instanceof StatusEvent) {
+ this.statusEvents.add((StatusEvent) event);
+ return;
+ }
+
+ if (event instanceof ResolutionEvent) {
+ this.resolutionEvents.add((ResolutionEvent) event);
+ return;
+ }
+
+ if (event instanceof AssignmentEvent) {
+ this.assignmentEvents.add((AssignmentEvent) event);
+ return;
+ }
+
+ if (event instanceof AttachmentEvent) {
+ this.attachmentEvents.add((AttachmentEvent) event);
+ return;
+ }
+ this.otherEvents.add(event);
+ }
+
+ private List<TaskRevision> getEvents() {
+ List<TaskRevision> events = new ArrayList<TaskRevision>();
+ events.addAll(this.statusEvents);
+ events.addAll(this.resolutionEvents);
+ events.addAll(this.assignmentEvents);
+ events.addAll(this.attachmentEvents);
+ events.addAll(this.otherEvents);
+ Collections.sort(events);
+ return events;
+ }
+
+ public Iterator<TaskRevision> iterator() {
+ return getEvents().iterator();
+ }
+
+ public int size() {
+ return this.otherEvents.size() + this.statusEvents.size()
+ + this.resolutionEvents.size() + this.assignmentEvents.size();
+ }
+
+ @Override
+ public String toString() {
+ StringBuffer sb = new StringBuffer();
+ for (Object event : this) {
+ sb.append(event);
+ sb.append("\n");
+ }
+ return sb.toString();
+ }
+
+ public List<StatusEvent> getStatusEvents() {
+ return statusEvents;
+ }
+
+ public List<ResolutionEvent> getResolutionEvents() {
+ return resolutionEvents;
+ }
+
+ public List<TaskRevision> getOtherEvents() {
+ return otherEvents;
+ }
+
+ public List<AttachmentEvent> getAttachmentEvents() {
+ return attachmentEvents;
+ }
+
+ public List<AssignmentEvent> getAssignmentEvents() {
+ return assignmentEvents;
+ }
+
+}
diff --git a/org.eclipse.mylyn.bugzilla.core/src/org/eclipse/mylyn/internal/bugzilla/core/history/TaskRevision.java b/org.eclipse.mylyn.bugzilla.core/src/org/eclipse/mylyn/internal/bugzilla/core/history/TaskRevision.java
new file mode 100644
index 000000000..1ebbc2dd7
--- /dev/null
+++ b/org.eclipse.mylyn.bugzilla.core/src/org/eclipse/mylyn/internal/bugzilla/core/history/TaskRevision.java
@@ -0,0 +1,113 @@
+/*******************************************************************************
+ * Copyright (c) 2003 University Of British Columbia and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * University Of British Columbia - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.mylar.internal.bugzilla.core.history;
+
+
+/**
+ * @author John Anvik
+ */
+public class TaskRevision implements Comparable<TaskRevision> {
+
+ protected final static String STATUS = "Status";
+
+ protected final static String RESOLUTION = "Resolution";
+
+ protected final static String ASSIGNMENT = "AssignedTo";
+
+ protected final static String ATTACHMENT = "Attachment";
+
+ protected String name;
+
+ protected String date;
+
+ protected String what;
+
+ protected String removed;
+
+ protected String added;
+
+ protected TaskRevision() {
+ this.added = "";
+ }
+
+ public static TaskRevision createEvent(String type, String change) {
+ TaskRevision event = new TaskRevision();
+
+ if (STATUS.equals(type)) {
+ return new StatusEvent(StatusType.convert(change));
+ }
+
+ if (RESOLUTION.equals(type)) {
+ return new ResolutionEvent(ResolutionType.convert(change));
+ }
+
+ if (ASSIGNMENT.equals(type)) {
+ return new AssignmentEvent(change);
+ }
+
+ if (type.contains(ATTACHMENT) && type.contains("Flag")) {
+ return new AttachmentEvent(AttachmentEvent.parseId(type), AttachmentEvent.parseFlags(change));
+ }
+
+ event.setWhat(type);
+ event.setAdded(change);
+ return event;
+ }
+
+ private void setAdded(String added) {
+ this.added = added;
+ }
+
+ public void setRemoved(String removed) {
+ this.removed = removed;
+ }
+
+ private void setWhat(String what) {
+ this.what = what;
+ }
+
+ public void setDate(String date) {
+ this.date = date;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getAdded() {
+ return this.added;
+ }
+
+ public String getRemoved() {
+ return this.removed;
+ }
+
+ public String getWhat() {
+ return this.what;
+ }
+
+ public String getDate() {
+ return this.date;
+ }
+
+ public String getName() {
+ return this.name;
+ }
+
+ @Override
+ public String toString() {
+ return this.name + " | " + this.date + " | " + this.what + " | " + this.removed + " | " + this.added;
+ }
+
+ public int compareTo(TaskRevision o) {
+ return this.date.compareTo(o.getDate());
+ }
+}
diff --git a/org.eclipse.mylyn.bugzilla.tests/src/org/eclipse/mylyn/bugzilla/tests/AllBugzillaTests.java b/org.eclipse.mylyn.bugzilla.tests/src/org/eclipse/mylyn/bugzilla/tests/AllBugzillaTests.java
index 2f4417baf..6fdb60c93 100644
--- a/org.eclipse.mylyn.bugzilla.tests/src/org/eclipse/mylyn/bugzilla/tests/AllBugzillaTests.java
+++ b/org.eclipse.mylyn.bugzilla.tests/src/org/eclipse/mylyn/bugzilla/tests/AllBugzillaTests.java
@@ -14,6 +14,7 @@ import junit.framework.Test;
import junit.framework.TestSuite;
import org.eclipse.mylar.bugzilla.tests.headless.BugzillaQueryTest;
+import org.eclipse.mylar.bugzilla.tests.headless.BugzillaTaskHistoryTest;
/**
* @author Mik Kersten
@@ -22,7 +23,7 @@ public class AllBugzillaTests {
public static Test suite() {
TestSuite suite = new TestSuite("Test for org.eclipse.mylar.bugzilla.tests");
- // $JUnit-BEGIN$
+ // $JUnit-BEGIN$
suite.addTestSuite(RepositoryTaskHandleTest.class);
suite.addTestSuite(TaskListNotificationManagerTest.class);
suite.addTestSuite(BugzillaTaskTest.class);
@@ -34,7 +35,7 @@ public class AllBugzillaTests {
suite.addTestSuite(RepositoryEditorWizardTest.class);
suite.addTestSuite(RepositoryReportFactoryTest.class);
suite.addTestSuite(BugzillaConfigurationTest.class);
- suite.addTestSuite(BugzillaTaskHyperlinkDetectorTest.class);
+ suite.addTestSuite(BugzillaTaskHyperlinkDetectorTest.class);
suite.addTestSuite(BugzillaSearchEngineTest.class);
// suite.addTestSuite(Bugzilla220ParserTest.class);
suite.addTestSuite(BugzillaRepositoryConnectorTest.class);
@@ -52,6 +53,7 @@ public class AllBugzillaTests {
// suite.addTest(new TestSuite(BugzillaParserTest.class));
suite.addTestSuite(BugzillaSearchDialogTest.class);
suite.addTestSuite(DuplicateDetetionTest.class);
+ suite.addTestSuite(BugzillaTaskHistoryTest.class);
// $JUnit-END$
return suite;
}
diff --git a/org.eclipse.mylyn.bugzilla.tests/src/org/eclipse/mylyn/bugzilla/tests/headless/BugzillaTaskHistoryTest.java b/org.eclipse.mylyn.bugzilla.tests/src/org/eclipse/mylyn/bugzilla/tests/headless/BugzillaTaskHistoryTest.java
new file mode 100644
index 000000000..6669ad4ee
--- /dev/null
+++ b/org.eclipse.mylyn.bugzilla.tests/src/org/eclipse/mylyn/bugzilla/tests/headless/BugzillaTaskHistoryTest.java
@@ -0,0 +1,59 @@
+/*******************************************************************************
+ * Copyright (c) 2003 - 2006 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
+ *******************************************************************************/
+package org.eclipse.mylar.bugzilla.tests.headless;
+
+import org.eclipse.mylar.bugzilla.tests.AbstractBugzillaTest;
+import org.eclipse.mylar.context.tests.support.MylarTestUtils;
+import org.eclipse.mylar.context.tests.support.MylarTestUtils.Credentials;
+import org.eclipse.mylar.internal.bugzilla.core.BugzillaClient;
+import org.eclipse.mylar.internal.bugzilla.core.BugzillaCorePlugin;
+import org.eclipse.mylar.internal.bugzilla.core.BugzillaRepositoryConnector;
+import org.eclipse.mylar.internal.bugzilla.core.IBugzillaConstants;
+import org.eclipse.mylar.internal.bugzilla.core.history.AssignmentEvent;
+import org.eclipse.mylar.internal.bugzilla.core.history.TaskHistory;
+import org.eclipse.mylar.tasks.core.TaskList;
+import org.eclipse.mylar.tasks.core.TaskRepository;
+
+public class BugzillaTaskHistoryTest extends AbstractBugzillaTest {
+
+ private TaskRepository repository;
+
+ private BugzillaRepositoryConnector connector;
+
+ public void setUp() throws Exception {
+ super.setUp();
+ connector = new BugzillaRepositoryConnector();
+ connector.init(new TaskList());
+ repository = new TaskRepository(BugzillaCorePlugin.REPOSITORY_KIND, IBugzillaConstants.TEST_BUGZILLA_222_URL);
+ Credentials credentials = MylarTestUtils.readCredentials();
+ repository.setAuthenticationCredentials(credentials.username, credentials.password);
+ }
+
+ public void testGetBugHistory() throws Exception {
+
+ BugzillaClient client = connector.getClientManager().getClient(repository);
+ assertNotNull(client);
+ TaskHistory history = client.getHistory("1");
+ assertNotNull(history);
+
+ assertEquals(1, history.getAssignmentEvents().size());
+ assertEquals(1, history.getStatusEvents().size());
+ assertEquals(12, history.getOtherEvents().size());
+ AssignmentEvent assignment = history.getAssignmentEvents().get(0);
+ assertEquals("nhapke@cs.ubc.ca", assignment.getName());
+ assertEquals("user@mylar.eclipse.org", assignment.getAssigned());
+ assertEquals("2006-08-25 17:48:02", assignment.getDate());
+ assertEquals("nhapke@cs.ubc.ca", assignment.getRemoved());
+ assertEquals("user@mylar.eclipse.org", assignment.getAdded());
+ assertEquals("AssignedTo", assignment.getWhat());
+ }
+
+}

Back to the top