diff options
author | mkersten | 2006-08-24 04:17:54 +0000 |
---|---|---|
committer | mkersten | 2006-08-24 04:17:54 +0000 |
commit | c75c2f53ac8f9b431ff2fed49a528ff753cdf908 (patch) | |
tree | 7442daff377ea3f21276a9207931e6968b92e9e5 | |
parent | 9edf3526df85040bae894a0e762073b21b14e5a3 (diff) | |
download | org.eclipse.mylyn.tasks-c75c2f53ac8f9b431ff2fed49a528ff753cdf908.tar.gz org.eclipse.mylyn.tasks-c75c2f53ac8f9b431ff2fed49a528ff753cdf908.tar.xz org.eclipse.mylyn.tasks-c75c2f53ac8f9b431ff2fed49a528ff753cdf908.zip |
Progress on: 151899: Trac connector: migrate to using RepositoryTaskData
https://bugs.eclipse.org/bugs/show_bug.cgi?id=151899
11 files changed, 713 insertions, 5 deletions
diff --git a/org.eclipse.mylyn.trac.ui/src/org/eclipse/mylyn/internal/trac/TracAttributeFactory.java b/org.eclipse.mylyn.trac.ui/src/org/eclipse/mylyn/internal/trac/TracAttributeFactory.java new file mode 100644 index 000000000..8423c0d98 --- /dev/null +++ b/org.eclipse.mylyn.trac.ui/src/org/eclipse/mylyn/internal/trac/TracAttributeFactory.java @@ -0,0 +1,132 @@ +/******************************************************************************* + * Copyright (c) 2004 - 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.trac; + +import java.util.HashMap; +import java.util.Map; + +import org.eclipse.mylar.internal.trac.model.TracTicket.Key; +import org.eclipse.mylar.tasks.core.AbstractAttributeFactory; +import org.eclipse.mylar.tasks.core.RepositoryTaskAttribute; + +/** + * Provides a mapping from Mylar task keys to Trac ticket keys. + * + * @author Steffen Pingel + */ +public class TracAttributeFactory extends AbstractAttributeFactory { + + private static final long serialVersionUID = 5333211422546115138L; + + private static Map<String, Attribute> attributeByTracKey = new HashMap<String, Attribute>(); + + private static Map<String, String> tracKeyByTaskKey = new HashMap<String, String>(); + + public enum Attribute { + CC(Key.CC, "CC:", RepositoryTaskAttribute.USER_CC), + CHANGE_TIME(Key.CHANGE_TIME, "Last Modification:", RepositoryTaskAttribute.DATE_MODIFIED, true, true), + COMPONENT(Key.COMPONENT, "Component:", null), + DESCRIPTION(Key.DESCRIPTION, "Description:", RepositoryTaskAttribute.DESCRIPTION, true, false), + ID(Key.ID, "<used by search engine>", null, true), + KEYWORDS(Key.KEYWORDS, "Keywords:", RepositoryTaskAttribute.KEYWORDS), + MILESTONE(Key.MILESTONE, "Milestone:", null), + OWNER(Key.OWNER, "Owner:", RepositoryTaskAttribute.USER_OWNER, false, true), + PRIORITY(Key.PRIORITY, "Priority:", null), + REPORTER(Key.REPORTER, "Reporter:", RepositoryTaskAttribute.USER_REPORTER, false, true), + RESOLUTION(Key.RESOLUTION, "Resolution:", RepositoryTaskAttribute.RESOLUTION, false, true), + SEVERITY(Key.SEVERITY, "Severity:", null), + STATUS(Key.STATUS, "Status:", RepositoryTaskAttribute.STATUS, false, true), + SUMMARY(Key.SUMMARY, "Summary:", RepositoryTaskAttribute.SUMMARY, true), + TIME(Key.TIME, "Created:", RepositoryTaskAttribute.DATE_CREATION, true, true), + TYPE(Key.TYPE, "Type:", null), + VERSION(Key.VERSION, "Version:", null); + + private final boolean isHidden; + + private final boolean isReadOnly; + + private final String tracKey; + + private final String prettyName; + + private final String taskKey; + + Attribute(Key key, String prettyName, String taskKey, boolean hidden, boolean readonly) { + this.tracKey = key.getKey(); + this.taskKey = taskKey; + this.prettyName = prettyName; + this.isHidden = hidden; + this.isReadOnly = readonly; + + attributeByTracKey.put(tracKey, this); + if (taskKey != null) { + tracKeyByTaskKey.put(taskKey, tracKey); + } + } + + Attribute(Key key, String prettyName, String taskKey, boolean hidden) { + this(key, prettyName, taskKey, hidden, false); + } + + Attribute(Key key, String prettyName, String taskKey) { + this(key, prettyName, taskKey, false, false); + } + + public String getTaskKey() { + return taskKey; + } + + public String getTracKey() { + return tracKey; + } + + public boolean isHidden() { + return isHidden; + } + + public boolean isReadOnly() { + return isReadOnly; + } + + public String toString() { + return prettyName; + } + } + + + @Override + public boolean getIsHidden(String key) { + Attribute attribute = attributeByTracKey.get(key); + return (attribute != null) ? attribute.isHidden() : false; + } + + @Override + public String getName(String key) { + Attribute attribute = attributeByTracKey.get(key); + // TODO if attribute == null it is probably a custom field: need + // to query custom field information from repoository + return (attribute != null) ? attribute.toString() : key; + } + + @Override + public boolean isReadOnly(String key) { + Attribute attribute = attributeByTracKey.get(key); + return (attribute != null) ? attribute.isReadOnly() : false; + } + + @Override + public String mapCommonAttributeKey(String key) { + String tracKey = tracKeyByTaskKey.get(key); + return (tracKey != null) ? tracKey : key; + } + +} diff --git a/org.eclipse.mylyn.trac.ui/src/org/eclipse/mylyn/internal/trac/TracOfflineTaskHandler.java b/org.eclipse.mylyn.trac.ui/src/org/eclipse/mylyn/internal/trac/TracOfflineTaskHandler.java new file mode 100644 index 000000000..1804c5bfe --- /dev/null +++ b/org.eclipse.mylyn.trac.ui/src/org/eclipse/mylyn/internal/trac/TracOfflineTaskHandler.java @@ -0,0 +1,259 @@ +/******************************************************************************* + * Copyright (c) 2004 - 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.trac; + +import java.util.Date; +import java.util.HashSet; +import java.util.Map; +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.mylar.internal.trac.TracAttributeFactory.Attribute; +import org.eclipse.mylar.internal.trac.core.ITracClient; +import org.eclipse.mylar.internal.trac.core.TracUtils; +import org.eclipse.mylar.internal.trac.model.TracAttachment; +import org.eclipse.mylar.internal.trac.model.TracComment; +import org.eclipse.mylar.internal.trac.model.TracTicket; +import org.eclipse.mylar.tasks.core.AbstractAttributeFactory; +import org.eclipse.mylar.tasks.core.AbstractRepositoryTask; +import org.eclipse.mylar.tasks.core.IOfflineTaskHandler; +import org.eclipse.mylar.tasks.core.RepositoryAttachment; +import org.eclipse.mylar.tasks.core.RepositoryOperation; +import org.eclipse.mylar.tasks.core.RepositoryTaskAttribute; +import org.eclipse.mylar.tasks.core.RepositoryTaskData; +import org.eclipse.mylar.tasks.core.TaskComment; +import org.eclipse.mylar.tasks.core.TaskRepository; +import org.eclipse.mylar.tasks.ui.TasksUiPlugin; + +/** + * @author Steffen Pingel + */ +public class TracOfflineTaskHandler implements IOfflineTaskHandler { + + private AbstractAttributeFactory attributeFactory = new TracAttributeFactory(); + + private TracRepositoryConnector connector; + + public TracOfflineTaskHandler(TracRepositoryConnector connector) { + this.connector = connector; + } + + public RepositoryTaskData downloadTaskData(final AbstractRepositoryTask task) throws CoreException { + if (!connector.hasRichEditor(task)) { + // offline mode is only supported for XML-RPC + return null; + } + + TaskRepository repository = TasksUiPlugin.getRepositoryManager().getRepository(TracUiPlugin.REPOSITORY_KIND, + task.getRepositoryUrl()); + try { + int id = Integer.parseInt(AbstractRepositoryTask.getTaskId(task.getHandleIdentifier())); + RepositoryTaskData data = new RepositoryTaskData(attributeFactory, TracUiPlugin.REPOSITORY_KIND, repository + .getUrl(), id + ""); + ITracClient client = connector.getClientManager().getRepository(repository); + client.updateAttributes(new NullProgressMonitor(), false); + TracTicket ticket = client.getTicket(id); + createDefaultAttributes(attributeFactory, data, client); + updateTaskData(repository, attributeFactory, data, ticket); + return data; + } catch (Exception e) { + throw new CoreException(new Status(IStatus.ERROR, TracUiPlugin.PLUGIN_ID, 0, "Ticket download from " + + task.getRepositoryUrl() + " failed, please see details.", e)); + } + } + + public AbstractAttributeFactory getAttributeFactory() { + return attributeFactory; + } + + public Date getDateForAttributeType(String attributeKey, String dateString) { + if (dateString == null || dateString.length() == 0) { + return null; + } + + try { + String mappedKey = attributeFactory.mapCommonAttributeKey(attributeKey); + if (mappedKey.equals(Attribute.TIME.getTracKey()) || mappedKey.equals(Attribute.CHANGE_TIME.getTracKey())) { + return TracUtils.parseDate(Integer.valueOf(dateString)); + } + } catch (Exception e) { + } + return null; + } + + public static void updateTaskData(TaskRepository repository, AbstractAttributeFactory factory, + RepositoryTaskData data, TracTicket ticket) { + if (ticket.getCreated() != null) { + data.setAttributeValue(Attribute.TIME.getTracKey(), TracUtils.toTracTime(ticket.getCreated()) + ""); + } + if (ticket.getLastChanged() != null) { + data.setAttributeValue(Attribute.CHANGE_TIME.getTracKey(), TracUtils.toTracTime(ticket.getLastChanged()) + + ""); + } + Map<String, String> valueByKey = ticket.getValues(); + for (String key : valueByKey.keySet()) { + data.setAttributeValue(key, valueByKey.get(key)); + } + + TracComment[] comments = ticket.getComments(); + if (comments != null) { + for (int i = 0; i < comments.length; i++) { + if (!"comment".equals(comments[i].getField()) + || "".equals(comments[i].getNewValue())) { + continue; + } + + TaskComment taskComment = new TaskComment(factory, data, data.getComments().size() + 1); + taskComment.setAttributeValue(RepositoryTaskAttribute.USER_OWNER, comments[i].getAuthor()); + taskComment + .setAttributeValue(RepositoryTaskAttribute.COMMENT_DATE, comments[i].getCreated().toString()); + taskComment.setAttributeValue(RepositoryTaskAttribute.COMMENT_TEXT, comments[i].getNewValue()); + data.addComment(taskComment); + } + } + + TracAttachment[] attachments = ticket.getAttachments(); + if (attachments != null) { + for (int i = 0; i < attachments.length; i++) { + RepositoryAttachment taskAttachment = new RepositoryAttachment(factory); + taskAttachment.setCreator(attachments[i].getAuthor()); + taskAttachment.setAttributeValue(Attribute.DESCRIPTION.getTracKey(), attachments[i].getDescription()); + taskAttachment.setAttributeValue(RepositoryTaskAttribute.ATTACHMENT_FILENAME, attachments[i] + .getFilename()); + taskAttachment.setAttributeValue(RepositoryTaskAttribute.USER_OWNER, attachments[i].getAuthor()); + taskAttachment.setAttributeValue(RepositoryTaskAttribute.ATTACHMENT_DATE, attachments[i].getCreated() + .toString()); + taskAttachment.setAttributeValue(RepositoryTaskAttribute.ATTACHMENT_URL, repository.getUrl() + + ITracClient.TICKET_ATTACHMENT_URL + ticket.getId() + "/" + attachments[i].getFilename()); + taskAttachment.setAttributeValue(RepositoryTaskAttribute.ATTACHMENT_ID, i + ""); + data.addAttachment(taskAttachment); + } + } + + String[] actions = ticket.getActions(); + for (String action : actions) { + addOperation(repository, data, ticket, action); + } + } + + // TODO Reuse Labels from BugzillaServerFacade + private static void addOperation(TaskRepository repository, RepositoryTaskData data, TracTicket ticket, String action) { + RepositoryOperation operation = null; + if ("leave".equals(action)) { + operation = new RepositoryOperation(action, "Leave as " + data.getStatus() + " " + + data.getResolution()); + operation.setChecked(true); + } else if ("accept".equals(action)) { + operation = new RepositoryOperation(action, "Accept"); + } else if ("resolve".equals(action)) { + operation = new RepositoryOperation(action, "Resolve bug, changing resolution to"); + operation.setUpOptions("resolution"); + for (String resolution : ticket.getResolutions()) { + operation.addOption(resolution, resolution); + } + } else if ("reassign".equals(action)) { + String localUser = repository.getUserName(); + operation = new RepositoryOperation(action, "Reassing bug to"); + // FIXME owner? + operation.setInputName("assign_to"); + operation.setInputValue(localUser); + } else if ("reopen".equals(action)) { + operation = new RepositoryOperation(action, "Reopen"); + } + + if (operation != null) { + data.addOperation(operation); + } + } + + public static void createDefaultAttributes(AbstractAttributeFactory factory, RepositoryTaskData data, + ITracClient client) { + createAttribute(factory, data, Attribute.STATUS, client.getTicketStatus()); + createAttribute(factory, data, Attribute.RESOLUTION, client.getTicketResolutions()); + + createAttribute(factory, data, Attribute.COMPONENT, client.getComponents()); + createAttribute(factory, data, Attribute.VERSION, client.getVersions(), true); + createAttribute(factory, data, Attribute.PRIORITY, client.getPriorities()); + createAttribute(factory, data, Attribute.SEVERITY, client.getSeverities()); + + createAttribute(factory, data, Attribute.TYPE, client.getTicketTypes()); + createAttribute(factory, data, Attribute.OWNER); + createAttribute(factory, data, Attribute.MILESTONE, client.getMilestones(), true); + createAttribute(factory, data, Attribute.REPORTER); + + createAttribute(factory, data, Attribute.CC); + createAttribute(factory, data, Attribute.KEYWORDS); + } + + private static RepositoryTaskAttribute createAttribute(AbstractAttributeFactory factory, RepositoryTaskData data, + Attribute attribute, Object[] values, boolean allowEmtpy) { + RepositoryTaskAttribute attr = factory.createAttribute(attribute.getTracKey()); + if (values != null && values.length > 0) { + if (allowEmtpy) { + attr.addOptionValue("", ""); + } + for (int i = 0; i < values.length; i++) { + attr.addOptionValue(values[i].toString(), values[i].toString()); + } + } else { + //attr.setHidden(true); + attr.setReadOnly(true); + } + data.addAttribute(attribute.getTracKey(), attr); + return attr; + } + + private static RepositoryTaskAttribute createAttribute(AbstractAttributeFactory factory, RepositoryTaskData data, + Attribute attribute) { + RepositoryTaskAttribute attr = factory.createAttribute(attribute.getTracKey()); + data.addAttribute(attribute.getTracKey(), attr); + return attr; + } + + private static RepositoryTaskAttribute createAttribute(AbstractAttributeFactory factory, RepositoryTaskData data, + Attribute attribute, Object[] values) { + return createAttribute(factory, data, attribute, values, false); + } + + public Set<AbstractRepositoryTask> getChangedSinceLastSync(TaskRepository repository, + Set<AbstractRepositoryTask> tasks) throws Exception { + if (repository.getSyncTimeStamp() == null) { + return tasks; + } + + String dateString = repository.getSyncTimeStamp(); + if (dateString == null) { + dateString = "0"; + } + Date since = TracUtils.parseDate(Integer.parseInt(dateString)); + + ITracClient client = connector.getClientManager().getRepository(repository); + Set<Integer> ids = client.getChangedTickets(since); + if (ids == null) { + // the call is not supported, any task may have changed + return tasks; + } + + Set<AbstractRepositoryTask> result = new HashSet<AbstractRepositoryTask>(); + for (AbstractRepositoryTask task : tasks) { + Integer id = Integer.parseInt(AbstractRepositoryTask.getTaskId(task.getHandleIdentifier())); + if (ids.contains(id)) { + result.add(task); + } + } + return result; + } + +} diff --git a/org.eclipse.mylyn.trac.ui/src/org/eclipse/mylyn/internal/trac/TracRepositoryConnector.java b/org.eclipse.mylyn.trac.ui/src/org/eclipse/mylyn/internal/trac/TracRepositoryConnector.java index fa63b4276..5b6b9c366 100644 --- a/org.eclipse.mylyn.trac.ui/src/org/eclipse/mylyn/internal/trac/TracRepositoryConnector.java +++ b/org.eclipse.mylyn.trac.ui/src/org/eclipse/mylyn/internal/trac/TracRepositoryConnector.java @@ -61,13 +61,15 @@ public class TracRepositoryConnector extends AbstractRepositoryConnector { private List<String> supportedVersions; private TracClientManager clientManager; - + + private TracOfflineTaskHandler offlineTaskHandler = new TracOfflineTaskHandler(this); + private TracAttachmentHandler attachmentHandler = new TracAttachmentHandler(this); - + public TracRepositoryConnector() { TracUiPlugin.getDefault().setConnector(this); } - + @Override public boolean canCreateNewTask(TaskRepository repository) { return true; @@ -125,7 +127,7 @@ public class TracRepositoryConnector extends AbstractRepositoryConnector { @Override public IOfflineTaskHandler getOfflineTaskHandler() { - return null; + return offlineTaskHandler; } @Override diff --git a/org.eclipse.mylyn.trac.ui/src/org/eclipse/mylyn/internal/trac/core/AbstractTracClient.java b/org.eclipse.mylyn.trac.ui/src/org/eclipse/mylyn/internal/trac/core/AbstractTracClient.java index 528f2678c..914437ed8 100644 --- a/org.eclipse.mylyn.trac.ui/src/org/eclipse/mylyn/internal/trac/core/AbstractTracClient.java +++ b/org.eclipse.mylyn.trac.ui/src/org/eclipse/mylyn/internal/trac/core/AbstractTracClient.java @@ -101,4 +101,21 @@ public abstract class AbstractTracClient implements ITracClient { this.data = data; } + public String[] getDefaultTicketResolutions() { + return new String[] { "fixed", "invalid", "wontfix", "duplicat", "worksforme" }; + } + + public String[] getDefaultTicketActions(String status) { + if ("new".equals(status)) { + return new String[] { "leave", "resolve", "reassign", "accept" }; + } else if ("assigned".equals(status)) { + return new String[] { "leave", "resolve", "reassign" }; + } else if ("reopened".equals(status)) { + return new String[] { "leave", "resolve", "reassign" }; + } else if ("closed".equals(status)) { + return new String[] { "leave", "reopen" }; + } + return null; + } + } diff --git a/org.eclipse.mylyn.trac.ui/src/org/eclipse/mylyn/internal/trac/core/ITracClient.java b/org.eclipse.mylyn.trac.ui/src/org/eclipse/mylyn/internal/trac/core/ITracClient.java index 30effdab8..b7f7fdd89 100644 --- a/org.eclipse.mylyn.trac.ui/src/org/eclipse/mylyn/internal/trac/core/ITracClient.java +++ b/org.eclipse.mylyn.trac.ui/src/org/eclipse/mylyn/internal/trac/core/ITracClient.java @@ -11,7 +11,9 @@ package org.eclipse.mylar.internal.trac.core; +import java.util.Date; import java.util.List; +import java.util.Set; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.mylar.internal.trac.model.TracComponent; @@ -146,5 +148,7 @@ public interface ITracClient { * @param data cached repository attributes */ void setData(TracClientData data); + + Set<Integer> getChangedTickets(Date since) throws TracException; } diff --git a/org.eclipse.mylyn.trac.ui/src/org/eclipse/mylyn/internal/trac/core/Trac09Client.java b/org.eclipse.mylyn.trac.ui/src/org/eclipse/mylyn/internal/trac/core/Trac09Client.java index c1b571d97..beec213aa 100644 --- a/org.eclipse.mylyn.trac.ui/src/org/eclipse/mylyn/internal/trac/core/Trac09Client.java +++ b/org.eclipse.mylyn.trac.ui/src/org/eclipse/mylyn/internal/trac/core/Trac09Client.java @@ -18,9 +18,11 @@ import java.net.HttpURLConnection; import java.net.URL; import java.text.ParseException; import java.util.ArrayList; +import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Set; import java.util.StringTokenizer; import javax.security.auth.login.LoginException; @@ -470,4 +472,8 @@ public class Trac09Client extends AbstractTracClient { throw new TracException("Unsupported operation"); } + public Set<Integer> getChangedTickets(Date since) throws TracException { + throw new TracException("Unsupported operation"); + } + } diff --git a/org.eclipse.mylyn.trac.ui/src/org/eclipse/mylyn/internal/trac/core/TracUtils.java b/org.eclipse.mylyn.trac.ui/src/org/eclipse/mylyn/internal/trac/core/TracUtils.java index 5c6c16669..e414bcfc1 100644 --- a/org.eclipse.mylyn.trac.ui/src/org/eclipse/mylyn/internal/trac/core/TracUtils.java +++ b/org.eclipse.mylyn.trac.ui/src/org/eclipse/mylyn/internal/trac/core/TracUtils.java @@ -19,11 +19,18 @@ import java.util.TimeZone; */ public class TracUtils { - public static Date parseDate(int seconds) { + public static Date parseDate(long seconds) { Calendar c = Calendar.getInstance(); c.setTimeZone(TimeZone.getTimeZone(ITracClient.TIME_ZONE)); c.setTimeInMillis(seconds * 1000l); return c.getTime(); } + public static long toTracTime(Date date) { + Calendar c = Calendar.getInstance(); + c.setTime(date); + c.setTimeZone(TimeZone.getTimeZone(ITracClient.TIME_ZONE)); + return c.getTimeInMillis() / 1000l; + } + } diff --git a/org.eclipse.mylyn.trac.ui/src/org/eclipse/mylyn/internal/trac/core/TracXmlRpcClient.java b/org.eclipse.mylyn.trac.ui/src/org/eclipse/mylyn/internal/trac/core/TracXmlRpcClient.java index ad8f33027..ea618d6ef 100644 --- a/org.eclipse.mylyn.trac.ui/src/org/eclipse/mylyn/internal/trac/core/TracXmlRpcClient.java +++ b/org.eclipse.mylyn.trac.ui/src/org/eclipse/mylyn/internal/trac/core/TracXmlRpcClient.java @@ -4,9 +4,12 @@ import java.net.HttpURLConnection; import java.net.URL; import java.util.ArrayList; import java.util.Collections; +import java.util.Date; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Set; import org.apache.xmlrpc.XmlRpcException; import org.apache.xmlrpc.client.XmlRpcClient; @@ -15,6 +18,8 @@ import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.OperationCanceledException; import org.eclipse.mylar.context.core.MylarStatusHandler; import org.eclipse.mylar.internal.trac.core.TracHttpClientTransportFactory.TracHttpException; +import org.eclipse.mylar.internal.trac.model.TracAttachment; +import org.eclipse.mylar.internal.trac.model.TracComment; import org.eclipse.mylar.internal.trac.model.TracComponent; import org.eclipse.mylar.internal.trac.model.TracMilestone; import org.eclipse.mylar.internal.trac.model.TracPriority; @@ -151,9 +156,50 @@ public class TracXmlRpcClient extends AbstractTracClient { public TracTicket getTicket(int id) throws TracException { Object[] result = (Object[]) call("ticket.get", id); TracTicket ticket = parseTicket(result); + + result = (Object[]) call("ticket.changeLog", id, 0); + for (Object item : result) { + ticket.addComment(parseChangeLogEntry((Object[]) item)); + } + + result = (Object[]) call("ticket.listAttachments", id); + for (Object item : result) { + ticket.addAttachment(parseAttachment((Object[]) item)); + } + + try { + String[] actions = getActions(id); + ticket.setActions(actions); + } catch (TracException e) { + // remove this if getActions() has been implemented in XmlRpcPlugin + String status = ticket.getValue(Key.STATUS); + ticket.setActions(getDefaultTicketActions(status)); + } + + ticket.setResolutions(getDefaultTicketResolutions()); + return ticket; } + private TracAttachment parseAttachment(Object[] entry) { + TracAttachment attachment = new TracAttachment((String) entry[0]); + attachment.setDescription((String) entry[1]); + attachment.setSize((Integer) entry[2]); + attachment.setCreated(TracUtils.parseDate((Integer) entry[3])); + attachment.setAuthor((String) entry[4]); + return attachment; + } + + private TracComment parseChangeLogEntry(Object[] entry) { + TracComment comment = new TracComment(); + comment.setCreated(TracUtils.parseDate((Integer) entry[0])); + comment.setAuthor((String) entry[1]); + comment.setField((String) entry[2]); + comment.setOldValue((String) entry[3]); + comment.setNewValue((String) entry[4]); + return comment; + } + /* public for testing */ @SuppressWarnings("unchecked") public List<TracTicket> getTickets(int[] ids) throws TracException { @@ -377,4 +423,28 @@ public class TracXmlRpcClient extends AbstractTracClient { call("ticket.update", ticket.getId(), comment, attributes); } + public Set<Integer> getChangedTickets(Date since) throws TracException { + Object[] ids; + try { + ids = (Object[]) call("ticket.getRecentChanges", since); + } catch (TracException e) { + // TODO remove this once getRecentChanges is supported by the XmlRpcPlugin + return null; + } + Set<Integer> result = new HashSet<Integer>(); + for (Object id : ids) { + result.add((Integer) id); + } + return result; + } + + public String[] getActions(int id) throws TracException { + Object[] actions = (Object[]) call("ticket.getAvailableActions", id); + String[] result = new String[actions.length]; + for (int i = 0; i < result.length; i++) { + result[i] = (String) actions[i]; + } + return result; + } + } diff --git a/org.eclipse.mylyn.trac.ui/src/org/eclipse/mylyn/internal/trac/model/TracAttachment.java b/org.eclipse.mylyn.trac.ui/src/org/eclipse/mylyn/internal/trac/model/TracAttachment.java new file mode 100644 index 000000000..338fae2c0 --- /dev/null +++ b/org.eclipse.mylyn.trac.ui/src/org/eclipse/mylyn/internal/trac/model/TracAttachment.java @@ -0,0 +1,77 @@ +/******************************************************************************* + * Copyright (c) 2004 - 2006 Mylar committers 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 + *******************************************************************************/ + +package org.eclipse.mylar.internal.trac.model; + +import java.util.Date; + +/** + * @author Steffen Pingel + */ +public class TracAttachment { + + private String author; + + private Date created; + + private String description; + + private String filename; + + int size; + + public TracAttachment(String filename) { + this.filename = filename; + } + + public String getAuthor() { + return author; + } + + public Date getCreated() { + return created; + } + + public String getDescription() { + return description; + } + + public String getFilename() { + return filename; + } + + public int getSize() { + return size; + } + + public void setAuthor(String author) { + this.author = author; + } + + public void setCreated(Date created) { + this.created = created; + } + + public void setDescription(String description) { + this.description = description; + } + + public void setFilename(String filename) { + this.filename = filename; + } + + public void setSize(int size) { + this.size = size; + } + + @Override + public String toString() { + return filename; + } + +} diff --git a/org.eclipse.mylyn.trac.ui/src/org/eclipse/mylyn/internal/trac/model/TracComment.java b/org.eclipse.mylyn.trac.ui/src/org/eclipse/mylyn/internal/trac/model/TracComment.java new file mode 100644 index 000000000..14b534393 --- /dev/null +++ b/org.eclipse.mylyn.trac.ui/src/org/eclipse/mylyn/internal/trac/model/TracComment.java @@ -0,0 +1,86 @@ +/******************************************************************************* + * Copyright (c) 2004 - 2006 Mylar committers 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 + *******************************************************************************/ + +package org.eclipse.mylar.internal.trac.model; + +import java.util.Date; + +/** + * @author Steffen Pingel + */ +public class TracComment { + + private String author; + + private Date created; + + private String field; + + private String newValue; + + private String oldValue; + + private boolean permanent; + + public TracComment() { + } + + public String getAuthor() { + return author; + } + + public Date getCreated() { + return created; + } + + public String getField() { + return field; + } + + public String getNewValue() { + return newValue; + } + + public String getOldValue() { + return oldValue; + } + + public boolean isPermanent() { + return permanent; + } + + public void setAuthor(String author) { + this.author = author; + } + + public void setCreated(Date created) { + this.created = created; + } + + public void setField(String field) { + this.field = field; + } + + public void setNewValue(String newValue) { + this.newValue = newValue; + } + + public void setOldValue(String oldValue) { + this.oldValue = oldValue; + } + + public void setPermanent(boolean permanent) { + this.permanent = permanent; + } + + @Override + public String toString() { + return "[" + field + "] " + author + ": " + oldValue + " -> " + newValue; + } + +} diff --git a/org.eclipse.mylyn.trac.ui/src/org/eclipse/mylyn/internal/trac/model/TracTicket.java b/org.eclipse.mylyn.trac.ui/src/org/eclipse/mylyn/internal/trac/model/TracTicket.java index c08851cad..9b4959963 100644 --- a/org.eclipse.mylyn.trac.ui/src/org/eclipse/mylyn/internal/trac/model/TracTicket.java +++ b/org.eclipse.mylyn.trac.ui/src/org/eclipse/mylyn/internal/trac/model/TracTicket.java @@ -11,8 +11,10 @@ package org.eclipse.mylar.internal.trac.model; +import java.util.ArrayList; import java.util.Date; import java.util.HashMap; +import java.util.List; import java.util.Map; import org.eclipse.mylar.internal.trac.core.InvalidTicketException; @@ -78,6 +80,14 @@ public class TracTicket { /** Trac's built-in ticket properties. */ private Map<Key, String> valueByKey = new HashMap<Key, String>(); + private List<TracComment> comments; + + private List<TracAttachment> attachments; + + private String[] actions; + + private String[] resolutions; + public TracTicket() { } @@ -174,4 +184,42 @@ public class TracTicket { this.lastChanged = TracUtils.parseDate(lastChanged); } + public void addComment(TracComment comment) { + if (comments == null) { + comments = new ArrayList<TracComment>(); + } + comments.add(comment); + } + + public void addAttachment(TracAttachment attachment) { + if (attachments == null) { + attachments = new ArrayList<TracAttachment>(); + } + attachments.add(attachment); + } + + public TracComment[] getComments() { + return (comments != null) ? comments.toArray(new TracComment[0]) : null; + } + + public TracAttachment[] getAttachments() { + return (attachments != null) ? attachments.toArray(new TracAttachment[0]) : null; + } + + public void setActions(String[] actions) { + this.actions = actions; + } + + public String[] getActions() { + return actions; + } + + public void setResolutions(String[] resolutions) { + this.resolutions = resolutions; + } + + public String[] getResolutions() { + return resolutions; + } + } |