diff options
13 files changed, 387 insertions, 81 deletions
diff --git a/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/editors/TaskEditorActionContributor.java b/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/editors/TaskEditorActionContributor.java index 2374153dc..eae0050fd 100644 --- a/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/editors/TaskEditorActionContributor.java +++ b/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/editors/TaskEditorActionContributor.java @@ -128,7 +128,6 @@ public class TaskEditorActionContributor extends MultiPageEditorActionBarContrib } public void contextMenuAboutToShow(IMenuManager manager, boolean addClipboard) { - actionGroup.getSynchronizeEditorAction().selectionChanged(new StructuredSelection(this.getEditor())); actionGroup.fillContextMenu(manager, editor, addClipboard); } @@ -181,8 +180,10 @@ public class TaskEditorActionContributor extends MultiPageEditorActionBarContrib if (activeEditor instanceof TaskEditor) { this.editor = (TaskEditor) activeEditor; this.editor.getSite().getSelectionProvider().addSelectionChangedListener(selectionProvider); + actionGroup.getSynchronizeEditorAction().selectionChanged(new StructuredSelection(this.editor)); updateSelectableActions(selectionProvider.getSelection()); } else { + actionGroup.getSynchronizeEditorAction().selectionChanged(StructuredSelection.EMPTY); this.editor = null; } } diff --git a/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/tasks/ui/editors/AbstractTaskEditorPage.java b/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/tasks/ui/editors/AbstractTaskEditorPage.java index 94e5c88bd..56192efa9 100644 --- a/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/tasks/ui/editors/AbstractTaskEditorPage.java +++ b/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/tasks/ui/editors/AbstractTaskEditorPage.java @@ -1243,7 +1243,9 @@ public abstract class AbstractTaskEditorPage extends TaskFormPage implements ISe for (Control control : editorComposite.getChildren()) { control.dispose(); } - focusTracker.reset(); + if (focusTracker != null) { + focusTracker.reset(); + } lastSelection = null; for (IFormPart part : getManagedForm().getParts()) { part.dispose(); diff --git a/org.eclipse.mylyn.trac.core/.options b/org.eclipse.mylyn.trac.core/.options new file mode 100644 index 000000000..aed10398c --- /dev/null +++ b/org.eclipse.mylyn.trac.core/.options @@ -0,0 +1,3 @@ + +# TracXmlRpcClient +org.eclipse.mylyn.trac.core/debug/xmlrpc=false diff --git a/org.eclipse.mylyn.trac.core/src/org/eclipse/mylyn/internal/trac/core/Messages.java b/org.eclipse.mylyn.trac.core/src/org/eclipse/mylyn/internal/trac/core/Messages.java index b1269dce0..61259f013 100644 --- a/org.eclipse.mylyn.trac.core/src/org/eclipse/mylyn/internal/trac/core/Messages.java +++ b/org.eclipse.mylyn.trac.core/src/org/eclipse/mylyn/internal/trac/core/Messages.java @@ -77,6 +77,18 @@ public class Messages extends NLS { public static String TracRepositoryConnector_TRAC_SUPPORTS_0_9_OR_0_10_THROUGH_WEB_AND_XML_RPC; + public static String TracTaskDataHandler_Accept; + + public static String TracTaskDataHandler_Leave; + + public static String TracTaskDataHandler_Leave_as_Status; + + public static String TracTaskDataHandler_Leave_as_Status_Resolution; + + public static String TracTaskDataHandler_Reopen; + + public static String TracTaskDataHandler_Resolve_as; + public static String TracWikiHandler_Download_Wiki_Page; public static String TracWikiHandler_Download_Wiki_Page_Names; diff --git a/org.eclipse.mylyn.trac.core/src/org/eclipse/mylyn/internal/trac/core/TracTaskDataHandler.java b/org.eclipse.mylyn.trac.core/src/org/eclipse/mylyn/internal/trac/core/TracTaskDataHandler.java index 25ab803ef..9ed732ccf 100644 --- a/org.eclipse.mylyn.trac.core/src/org/eclipse/mylyn/internal/trac/core/TracTaskDataHandler.java +++ b/org.eclipse.mylyn.trac.core/src/org/eclipse/mylyn/internal/trac/core/TracTaskDataHandler.java @@ -12,7 +12,6 @@ package org.eclipse.mylyn.internal.trac.core; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collection; import java.util.Date; import java.util.HashSet; @@ -28,6 +27,7 @@ import org.eclipse.core.runtime.OperationCanceledException; import org.eclipse.mylyn.commons.net.Policy; import org.eclipse.mylyn.internal.trac.core.client.ITracClient; import org.eclipse.mylyn.internal.trac.core.client.InvalidTicketException; +import org.eclipse.mylyn.internal.trac.core.model.TracAction; import org.eclipse.mylyn.internal.trac.core.model.TracAttachment; import org.eclipse.mylyn.internal.trac.core.model.TracComment; import org.eclipse.mylyn.internal.trac.core.model.TracTicket; @@ -49,6 +49,7 @@ import org.eclipse.mylyn.tasks.core.data.TaskCommentMapper; import org.eclipse.mylyn.tasks.core.data.TaskData; import org.eclipse.mylyn.tasks.core.data.TaskMapper; import org.eclipse.mylyn.tasks.core.data.TaskOperation; +import org.eclipse.osgi.util.NLS; /** * @author Steffen Pingel @@ -208,45 +209,62 @@ public class TracTaskDataHandler extends AbstractTaskDataHandler { } } - String[] actions = ticket.getActions(); + TracAction[] actions = ticket.getActions(); if (actions != null) { - // add operations in a defined order - List<String> actionList = new ArrayList<String>(Arrays.asList(actions)); - addOperation(repository, data, ticket, actionList, "leave"); //$NON-NLS-1$ - addOperation(repository, data, ticket, actionList, "accept"); //$NON-NLS-1$ - addOperation(repository, data, ticket, actionList, "resolve"); //$NON-NLS-1$ - addOperation(repository, data, ticket, actionList, "reopen"); //$NON-NLS-1$ + // add actions and set first as default + for (TracAction action : actions) { + addOperation(repository, data, ticket, action, action == actions[0]); + } } return changedAttributes; } - private static void addOperation(TaskRepository repository, TaskData data, TracTicket ticket, List<String> actions, - String action) { - if (!actions.remove(action)) { - return; - } - - String label = null; - if ("leave".equals(action)) { //$NON-NLS-1$ - // TODO provide better label for Leave action - //label = "Leave as " + data.getStatus() + " " + data.getResolution(); - label = "Leave"; //$NON-NLS-1$ - } else if ("accept".equals(action)) { //$NON-NLS-1$ - label = "Accept"; //$NON-NLS-1$ - } else if ("resolve".equals(action)) { //$NON-NLS-1$ - label = "Resolve as"; //$NON-NLS-1$ - } else if ("reopen".equals(action)) { //$NON-NLS-1$ - label = "Reopen"; //$NON-NLS-1$ + private static void addOperation(TaskRepository repository, TaskData data, TracTicket ticket, TracAction action, + boolean setAsDefault) { + String label = action.getLabel(); + if (label == null) { + if ("leave".equals(action.getId())) { //$NON-NLS-1$ + String status = ticket.getValue(Key.STATUS); + if (status != null) { + String resolution = ticket.getValue(Key.RESOLUTION); + if (resolution != null) { + label = NLS.bind(Messages.TracTaskDataHandler_Leave_as_Status_Resolution, status, resolution); + } else { + label = NLS.bind(Messages.TracTaskDataHandler_Leave_as_Status, status); + } + } else { + label = Messages.TracTaskDataHandler_Leave; + } + } else if ("accept".equals(action.getId())) { //$NON-NLS-1$ + label = Messages.TracTaskDataHandler_Accept; + } else if ("resolve".equals(action.getId())) { //$NON-NLS-1$ + label = Messages.TracTaskDataHandler_Resolve_as; + } else if ("reopen".equals(action.getId())) { //$NON-NLS-1$ + label = Messages.TracTaskDataHandler_Reopen; + } else { + label = action.getId(); + } } if (label != null) { - TaskAttribute attribute = data.getRoot().createAttribute(TaskAttribute.PREFIX_OPERATION + action); - TaskOperation.applyTo(attribute, action, label); - if ("resolve".equals(action)) { //$NON-NLS-1$ + TaskAttribute attribute = data.getRoot().createAttribute(TaskAttribute.PREFIX_OPERATION + action.getId()); + TaskOperation.applyTo(attribute, action.getId(), label); + if (!action.getFields().isEmpty()) { + // TODO support more than one field + TracTicketField field = action.getFields().get(0); + TaskAttribute fieldAttribute = createAttribute(data, field); + fieldAttribute.getMetaData().setKind(null); + attribute.getMetaData().putValue(TaskAttribute.META_ASSOCIATED_ATTRIBUTE_ID, fieldAttribute.getId()); + } else if ("resolve".equals(action)) { //$NON-NLS-1$ attribute.getMetaData().putValue(TaskAttribute.META_ASSOCIATED_ATTRIBUTE_ID, TracAttribute.RESOLUTION.getTracKey()); } + + if (setAsDefault) { + TaskAttribute operationAttribute = data.getRoot().createAttribute(TaskAttribute.OPERATION); + TaskOperation.applyTo(operationAttribute, action.getId(), label); + } } } @@ -293,7 +311,7 @@ public class TracTaskDataHandler extends AbstractTaskDataHandler { data.getRoot().createAttribute(TaskAttribute.OPERATION).getMetaData().setType(TaskAttribute.TYPE_OPERATION); } - private static void createAttribute(TaskData data, TracTicketField field) { + private static TaskAttribute createAttribute(TaskData data, TracTicketField field) { TaskAttribute attr = data.getRoot().createAttribute(field.getName()); TaskAttributeMetaData metaData = attr.getMetaData(); metaData.defaults(); @@ -347,6 +365,7 @@ public class TracTaskDataHandler extends AbstractTaskDataHandler { attr.setValue(field.getDefaultValue()); } } + return attr; } public static TaskAttribute createAttribute(TaskData data, TracAttribute tracAttribute) { @@ -551,6 +570,7 @@ public class TracTaskDataHandler extends AbstractTaskDataHandler { ticket.putValue("status", TracRepositoryConnector.TaskStatus.NEW.toStatusString()); //$NON-NLS-1$ } } + ticket.putValue("action", action); //$NON-NLS-1$ } return ticket; diff --git a/org.eclipse.mylyn.trac.core/src/org/eclipse/mylyn/internal/trac/core/client/TracWebClient.java b/org.eclipse.mylyn.trac.core/src/org/eclipse/mylyn/internal/trac/core/client/TracWebClient.java index bd8b4b822..f96bd434c 100644 --- a/org.eclipse.mylyn.trac.core/src/org/eclipse/mylyn/internal/trac/core/client/TracWebClient.java +++ b/org.eclipse.mylyn.trac.core/src/org/eclipse/mylyn/internal/trac/core/client/TracWebClient.java @@ -428,7 +428,7 @@ public class TracWebClient extends AbstractTracClient { if (version.startsWith("Trac 0.9")) { //$NON-NLS-1$ return new TracRepositoryInfo(0, 0, 0, version); } else if (version.startsWith("Trac 0.10")) { //$NON-NLS-1$ - return new TracRepositoryInfo(0, 1, 0, version); + return new TracRepositoryInfo(0, 0, 1, version); } else if (version.startsWith("Trac 0.11")) { //$NON-NLS-1$ return new TracRepositoryInfo(1, 0, 0, version); } else { diff --git a/org.eclipse.mylyn.trac.core/src/org/eclipse/mylyn/internal/trac/core/client/TracXmlRpcClient.java b/org.eclipse.mylyn.trac.core/src/org/eclipse/mylyn/internal/trac/core/client/TracXmlRpcClient.java index 0a57eb27e..7b389516c 100644 --- a/org.eclipse.mylyn.trac.core/src/org/eclipse/mylyn/internal/trac/core/client/TracXmlRpcClient.java +++ b/org.eclipse.mylyn.trac.core/src/org/eclipse/mylyn/internal/trac/core/client/TracXmlRpcClient.java @@ -46,6 +46,7 @@ import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.core.runtime.OperationCanceledException; +import org.eclipse.core.runtime.Platform; import org.eclipse.core.runtime.Status; import org.eclipse.mylyn.commons.core.StatusHandler; import org.eclipse.mylyn.commons.net.AbstractWebLocation; @@ -55,11 +56,13 @@ import org.eclipse.mylyn.commons.net.Policy; import org.eclipse.mylyn.commons.net.UnsupportedRequestException; import org.eclipse.mylyn.commons.net.WebUtil; import org.eclipse.mylyn.internal.trac.core.TracCorePlugin; +import org.eclipse.mylyn.internal.trac.core.model.TracAction; import org.eclipse.mylyn.internal.trac.core.model.TracAttachment; import org.eclipse.mylyn.internal.trac.core.model.TracComment; import org.eclipse.mylyn.internal.trac.core.model.TracComponent; import org.eclipse.mylyn.internal.trac.core.model.TracMilestone; import org.eclipse.mylyn.internal.trac.core.model.TracPriority; +import org.eclipse.mylyn.internal.trac.core.model.TracRepositoryInfo; import org.eclipse.mylyn.internal.trac.core.model.TracSearch; import org.eclipse.mylyn.internal.trac.core.model.TracSeverity; import org.eclipse.mylyn.internal.trac.core.model.TracTicket; @@ -71,11 +74,13 @@ import org.eclipse.mylyn.internal.trac.core.model.TracVersion; import org.eclipse.mylyn.internal.trac.core.model.TracWikiPage; import org.eclipse.mylyn.internal.trac.core.model.TracWikiPageInfo; import org.eclipse.mylyn.internal.trac.core.model.TracTicket.Key; +import org.eclipse.mylyn.internal.trac.core.model.TracTicketField.Type; import org.eclipse.mylyn.internal.trac.core.util.HttpMethodInterceptor; import org.eclipse.mylyn.internal.trac.core.util.TracHttpClientTransportFactory; import org.eclipse.mylyn.internal.trac.core.util.TracUtil; import org.eclipse.mylyn.internal.trac.core.util.TracXmlRpcClientRequest; import org.eclipse.mylyn.internal.trac.core.util.TracHttpClientTransportFactory.TracHttpException; +import org.eclipse.osgi.util.NLS; /** * Represents a Trac repository that is accessed through the Trac XmlRpcPlugin. @@ -146,7 +151,9 @@ public class TracXmlRpcClient extends AbstractTracClient implements ITracWikiCli if (isTracd && digestScheme != null) { probeAuthenticationScheme(monitor); } - + if (DEBUG) { + System.err.println("Calling " + location.getUrl() + ": " + method + " " + TracUtil.toString(parameters)); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + } TracXmlRpcClientRequest request = new TracXmlRpcClientRequest(xmlrpc.getClientConfig(), method, parameters, monitor); return xmlrpc.execute(request); @@ -177,6 +184,8 @@ public class TracXmlRpcClient extends AbstractTracClient implements ITracWikiCli } + private static final boolean DEBUG = Boolean.valueOf(Platform.getDebugOption("org.eclipse.mylyn.trac.core/debug/xmlrpc")); //$NON-NLS-1$ + public static final String XMLRPC_URL = "/xmlrpc"; //$NON-NLS-1$ public static final String REQUIRED_REVISION = "1950"; //$NON-NLS-1$ @@ -197,12 +206,6 @@ public class TracXmlRpcClient extends AbstractTracClient implements ITracWikiCli private TracHttpClientTransportFactory factory; - private int majorAPIVersion = -1; - - private int minorAPIVersion = -1; - - private int epochAPIVersion = -1; - private boolean accountMangerAuthenticationFailed; private XmlRpcClientConfigImpl config; @@ -217,6 +220,8 @@ public class TracXmlRpcClient extends AbstractTracClient implements ITracWikiCli private boolean isTracd; + private TracRepositoryInfo info = new TracRepositoryInfo(); + public TracXmlRpcClient(AbstractWebLocation location, Version version) { super(location, version); this.httpClient = createHttpClient(); @@ -386,7 +391,7 @@ public class TracXmlRpcClient extends AbstractTracClient implements ITracWikiCli private void checkForException(Object result) throws NumberFormatException, XmlRpcException { if (result instanceof Map<?, ?>) { Map<?, ?> exceptionData = (Map<?, ?>) result; - if (exceptionData.containsKey("faultCode") && exceptionData.containsKey("faultString")) { //$NON-NLS-1$ //$NON-NLS-2$ + if (exceptionData.containsKey("faultCode") && exceptionData.containsKey("faultString")) { //$NON-NLS-1$ //$NON-NLS-2$ throw new XmlRpcException(Integer.parseInt(exceptionData.get("faultCode").toString()), //$NON-NLS-1$ (String) exceptionData.get("faultString")); //$NON-NLS-1$ } @@ -404,7 +409,10 @@ public class TracXmlRpcClient extends AbstractTracClient implements ITracWikiCli return ((Object[]) item)[0]; } - public void validate(IProgressMonitor monitor) throws TracException { + public TracRepositoryInfo validate(IProgressMonitor monitor) throws TracException { + Integer epochAPIVersion; + Integer majorAPIVersion; + Integer minorAPIVersion; try { Object[] result = (Object[]) call(monitor, "system.getAPIVersion"); //$NON-NLS-1$ if (result.length >= 3) { @@ -416,35 +424,32 @@ public class TracXmlRpcClient extends AbstractTracClient implements ITracWikiCli majorAPIVersion = (Integer) result[0]; minorAPIVersion = (Integer) result[1]; } else { - throw new TracException( - "The API version is unsupported, please update your Trac XML-RPC Plugin to revision " //$NON-NLS-1$ - + REQUIRED_REVISION + " or later"); //$NON-NLS-1$ + throw new TracException(NLS.bind(Messages.TracXmlRpcClient_API_version_unsupported_Error, + REQUIRED_REVISION)); } } catch (TracNoSuchMethodException e) { - throw new TracException( - "Required API calls are missing, please update your Trac XML-RPC Plugin to revision " //$NON-NLS-1$ - + REQUIRED_REVISION + " or later"); //$NON-NLS-1$ + throw new TracException(NLS.bind(Messages.TracXmlRpcClient_Required_API_calls_missing_Error, + REQUIRED_REVISION)); } - if (!isAPIVersionOrHigher(REQUIRED_EPOCH, REQUIRED_MAJOR, REQUIRED_MINOR, monitor)) { - throw new TracException("The API version " + majorAPIVersion + "." + minorAPIVersion //$NON-NLS-1$ //$NON-NLS-2$ - + " is unsupported, please update your Trac XML-RPC Plugin to revision " + REQUIRED_REVISION //$NON-NLS-1$ - + " or later"); //$NON-NLS-1$ + info = new TracRepositoryInfo(epochAPIVersion, majorAPIVersion, minorAPIVersion); + if (!info.isApiVersionOrHigher(REQUIRED_EPOCH, REQUIRED_MAJOR, REQUIRED_MINOR)) { + throw new TracException(NLS.bind(Messages.TracXmlRpcClient_API_version_X_unsupported_Error, + info.toString(), REQUIRED_REVISION)); } + return info; } private void updateAPIVersion(IProgressMonitor monitor) throws TracException { - if (epochAPIVersion == -1 || majorAPIVersion == -1 || minorAPIVersion == -1) { + if (info.isStale()) { validate(monitor); } } - private boolean isAPIVersionOrHigher(int epoch, int major, int minor, IProgressMonitor monitor) + private boolean isApiVersionOrHigher(int epoch, int major, int minor, IProgressMonitor monitor) throws TracException { updateAPIVersion(monitor); - return epochAPIVersion > epoch // - || epochAPIVersion == epoch && (majorAPIVersion > major // - || majorAPIVersion == major && minorAPIVersion >= minor); + return info.isApiVersionOrHigher(epoch, major, minor); } public TracTicket getTicket(int id, IProgressMonitor monitor) throws TracException { @@ -461,7 +466,7 @@ public class TracXmlRpcClient extends AbstractTracClient implements ITracWikiCli ticket.addAttachment(parseAttachment((Object[]) item)); } - String[] actions = getActions(id, monitor); + TracAction[] actions = getActions(id, monitor); ticket.setActions(actions); updateAttributes(new NullProgressMonitor(), false); @@ -547,11 +552,11 @@ public class TracXmlRpcClient extends AbstractTracClient implements ITracWikiCli } private boolean supportsWorkFlow(IProgressMonitor monitor) throws TracException { - return isAPIVersionOrHigher(2, 0, 0, monitor); + return isApiVersionOrHigher(1, 0, 1, monitor); } private boolean supportsMaxSearchResults(IProgressMonitor monitor) throws TracException { - return isAPIVersionOrHigher(2, 0, 0, monitor); + return isApiVersionOrHigher(1, 0, 0, monitor); } private TracTicket parseTicket(Object[] ticketResult) throws InvalidTicketException { @@ -616,18 +621,14 @@ public class TracXmlRpcClient extends AbstractTracClient implements ITracWikiCli Collections.sort(data.severities); advance(monitor, 1); - if (supportsWorkFlow(monitor)) { - data.ticketStatus = new ArrayList<TracTicketStatus>(); - } else { - boolean assignValues = isAPIVersionOrHigher(1, 0, 0, monitor); - attributes = getTicketAttributes("ticket.status", assignValues, monitor); //$NON-NLS-1$ - data.ticketStatus = new ArrayList<TracTicketStatus>(result.length); - for (TicketAttributeResult attribute : attributes) { - data.ticketStatus.add(new TracTicketStatus(attribute.name, attribute.value)); - } - Collections.sort(data.ticketStatus); - advance(monitor, 1); + boolean assignValues = isApiVersionOrHigher(1, 0, 0, monitor); + attributes = getTicketAttributes("ticket.status", assignValues, monitor); //$NON-NLS-1$ + data.ticketStatus = new ArrayList<TracTicketStatus>(result.length); + for (TicketAttributeResult attribute : attributes) { + data.ticketStatus.add(new TracTicketStatus(attribute.name, attribute.value)); } + Collections.sort(data.ticketStatus); + advance(monitor, 1); attributes = getTicketAttributes("ticket.type", monitor); //$NON-NLS-1$ data.ticketTypes = new ArrayList<TracTicketType>(result.length); @@ -832,18 +833,22 @@ public class TracXmlRpcClient extends AbstractTracClient implements ITracWikiCli if (summary == null || description == null) { throw new InvalidTicketException(); } - if (isAPIVersionOrHigher(0, 0, 2, monitor)) { + if (supportsNotifications(monitor)) { return (Integer) call(monitor, "ticket.create", summary, description, attributes, true); //$NON-NLS-1$ } else { return (Integer) call(monitor, "ticket.create", summary, description, attributes); //$NON-NLS-1$ } } + private boolean supportsNotifications(IProgressMonitor monitor) throws TracException { + return isApiVersionOrHigher(0, 0, 2, monitor); + } + public void updateTicket(TracTicket ticket, String comment, IProgressMonitor monitor) throws TracException { updateAPIVersion(monitor); Map<String, String> attributes = ticket.getValues(); - if (isAPIVersionOrHigher(0, 0, 2, monitor)) { + if (supportsNotifications(monitor)) { call(monitor, "ticket.update", ticket.getId(), comment, attributes, true); //$NON-NLS-1$ } else { call(monitor, "ticket.update", ticket.getId(), comment, attributes); //$NON-NLS-1$ @@ -860,13 +865,45 @@ public class TracXmlRpcClient extends AbstractTracClient implements ITracWikiCli return result; } - public String[] getActions(int id, IProgressMonitor monitor) throws TracException { - Object[] actions = (Object[]) call(monitor, "ticket.getAvailableActions", id); //$NON-NLS-1$ - String[] result = new String[actions.length]; - for (int i = 0; i < result.length; i++) { - result[i] = (String) actions[i]; + public TracAction[] getActions(int id, IProgressMonitor monitor) throws TracException { + if (supportsWorkFlow(monitor)) { + Object[] actions = (Object[]) call(monitor, "ticket.getActions", id); //$NON-NLS-1$ + TracAction[] result = new TracAction[actions.length]; + for (int i = 0; i < result.length; i++) { + Object[] entry = (Object[]) actions[i]; + TracAction action = new TracAction((String) entry[0]); + action.setLabel((String) entry[1]); + action.setHint((String) entry[2]); + Object[] inputs = (Object[]) entry[3]; + // each action can be associated with fields + for (Object inputArray : inputs) { + Object[] inputEntry = (Object[]) inputArray; + TracTicketField field = new TracTicketField((String) inputEntry[0]); + field.setDefaultValue((String) inputEntry[1]); + Object[] optionEntry = (Object[]) inputEntry[2]; + if (optionEntry.length == 0) { + field.setType(Type.TEXT); + } else { + field.setType(Type.SELECT); + String[] options = new String[optionEntry.length]; + for (int j = 0; j < options.length; j++) { + options[j] = (String) optionEntry[j]; + } + field.setOptions(options); + } + action.addField(field); + } + result[i] = action; + } + return result; + } else { + Object[] actions = (Object[]) call(monitor, "ticket.getAvailableActions", id); //$NON-NLS-1$ + TracAction[] result = new TracAction[actions.length]; + for (int i = 0; i < result.length; i++) { + result[i] = new TracAction((String) actions[i]); + } + return result; } - return result; } public Date getTicketLastChanged(Integer id, IProgressMonitor monitor) throws TracException { diff --git a/org.eclipse.mylyn.trac.core/src/org/eclipse/mylyn/internal/trac/core/client/messages.properties b/org.eclipse.mylyn.trac.core/src/org/eclipse/mylyn/internal/trac/core/client/messages.properties index 039a0bf78..516300688 100644 --- a/org.eclipse.mylyn.trac.core/src/org/eclipse/mylyn/internal/trac/core/client/messages.properties +++ b/org.eclipse.mylyn.trac.core/src/org/eclipse/mylyn/internal/trac/core/client/messages.properties @@ -1 +1,4 @@ TracWebClient_Updating_attributes=Updating attributes +TracXmlRpcClient_API_version_unsupported_Error=The API version is unsupported, update the Trac XML-RPC Plugin to revision {0} or later +TracXmlRpcClient_API_version_X_unsupported_Error=The API version {0} is unsupported, update the Trac XML-RPC Plugin to revision {1} or later +TracXmlRpcClient_Required_API_calls_missing_Error=Required API calls are missing, update the Trac XML-RPC Plugin to revision {0} or later diff --git a/org.eclipse.mylyn.trac.core/src/org/eclipse/mylyn/internal/trac/core/messages.properties b/org.eclipse.mylyn.trac.core/src/org/eclipse/mylyn/internal/trac/core/messages.properties index 94a9caf16..cecf43ac6 100644 --- a/org.eclipse.mylyn.trac.core/src/org/eclipse/mylyn/internal/trac/core/messages.properties +++ b/org.eclipse.mylyn.trac.core/src/org/eclipse/mylyn/internal/trac/core/messages.properties @@ -27,6 +27,12 @@ TracCorePlugin_Unexpected_server_response_=Unexpected server response: TracRepositoryConnector_Getting_changed_tasks=Getting changed tasks TracRepositoryConnector_Querying_repository=Querying repository TracRepositoryConnector_TRAC_SUPPORTS_0_9_OR_0_10_THROUGH_WEB_AND_XML_RPC=Trac (supports 0.9 or 0.10 through Web and XML-RPC) +TracTaskDataHandler_Accept=Accept +TracTaskDataHandler_Leave=Leave +TracTaskDataHandler_Leave_as_Status=Leave as {0} +TracTaskDataHandler_Leave_as_Status_Resolution=Leave as {0} {1} +TracTaskDataHandler_Reopen=Reopen +TracTaskDataHandler_Resolve_as=Resolve as TracWikiHandler_Download_Wiki_Page=Download Wiki Page TracWikiHandler_Download_Wiki_Page_Names=Download Wiki Page Names diff --git a/org.eclipse.mylyn.trac.core/src/org/eclipse/mylyn/internal/trac/core/model/TracAction.java b/org.eclipse.mylyn.trac.core/src/org/eclipse/mylyn/internal/trac/core/model/TracAction.java new file mode 100644 index 000000000..632c73916 --- /dev/null +++ b/org.eclipse.mylyn.trac.core/src/org/eclipse/mylyn/internal/trac/core/model/TracAction.java @@ -0,0 +1,79 @@ +/******************************************************************************* + * Copyright (c) 2009 Steffen Pingel 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: + * Steffen Pingel - initial API and implementation + *******************************************************************************/ + +package org.eclipse.mylyn.internal.trac.core.model; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +/** + * @author Steffen Pingel + */ +public class TracAction { + + private List<TracTicketField> fields; + + private String hint; + + private String id; + + private String label; + + public TracAction(String id) { + this.id = id; + } + + public void addField(TracTicketField field) { + if (fields == null) { + fields = new ArrayList<TracTicketField>(); + } + fields.add(field); + } + + public List<TracTicketField> getFields() { + if (fields == null) { + return Collections.emptyList(); + } + return new ArrayList<TracTicketField>(fields); + } + + public String getHint() { + return hint; + } + + public String getId() { + return id; + } + + public String getLabel() { + return label; + } + + public void removeField(TracTicketField field) { + if (fields != null) { + fields.remove(field); + } + } + + public void setHint(String hint) { + this.hint = hint; + } + + public void setId(String id) { + this.id = id; + } + + public void setLabel(String label) { + this.label = label; + } + +} diff --git a/org.eclipse.mylyn.trac.core/src/org/eclipse/mylyn/internal/trac/core/model/TracRepositoryInfo.java b/org.eclipse.mylyn.trac.core/src/org/eclipse/mylyn/internal/trac/core/model/TracRepositoryInfo.java new file mode 100644 index 000000000..974357129 --- /dev/null +++ b/org.eclipse.mylyn.trac.core/src/org/eclipse/mylyn/internal/trac/core/model/TracRepositoryInfo.java @@ -0,0 +1,105 @@ +/******************************************************************************* + * Copyright (c) 2009 Steffen Pingel 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: + * Steffen Pingel - initial API and implementation + *******************************************************************************/ + +package org.eclipse.mylyn.internal.trac.core.model; + +/** + * The version of the Trac repository is defined by three numbers: epoch.major.minor. The default value is + * <code>-1.-1.-1</code> which indicates the version is not known. + * + * <pre> + * [0.0.0] Trac 0.9.6 + * [0.0.1, 1.0.0) Trac 0.10 + * [1.0.0, 2.0.0) Trac 0.11 + * </pre> + * + * @author Steffen Pingel + */ +public class TracRepositoryInfo { + + private final int apiEpoch; + + private final int apiMajor; + + private final int apiMinor; + + private String version; + + public TracRepositoryInfo() { + this(null); + } + + public TracRepositoryInfo(int apiEpoch, int apiMajor, int apiMinor) { + this(apiEpoch, apiMajor, apiMinor, null); + } + + public TracRepositoryInfo(int apiEpoch, int apiMajor, int apiMinor, String version) { + this.apiEpoch = apiEpoch; + this.apiMajor = apiMajor; + this.apiMinor = apiMinor; + this.version = version; + } + + public TracRepositoryInfo(String version) { + this(-1, -1, -1, version); + } + + public int getApiEpoch() { + return apiEpoch; + } + + public int getApiMajor() { + return apiMajor; + } + + public int getApiMinor() { + return apiMinor; + } + + public String getVersion() { + return version; + } + + public boolean isApiVersion(int epoch, int major, int minor) { + return apiEpoch == epoch && apiMajor == major && apiMinor == minor; + } + + public boolean isApiVersionOrHigher(int epoch, int major, int minor) { + return apiEpoch > epoch // + || apiEpoch == epoch && (apiMajor > major // + || apiMajor == major && apiMinor >= minor); + } + + public boolean isStale() { + return apiEpoch == -1 || apiMajor == -1 || apiMinor == -1; + } + + public void setVersion(String version) { + this.version = version; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append(apiEpoch); + sb.append("."); //$NON-NLS-1$ + sb.append(apiMajor); + sb.append("."); //$NON-NLS-1$ + sb.append(apiMinor); + if (version != null) { + sb.append(" ("); //$NON-NLS-1$ + sb.append(version); + sb.append(")"); //$NON-NLS-1$ + } + return sb.toString(); + } + +} diff --git a/org.eclipse.mylyn.trac.core/src/org/eclipse/mylyn/internal/trac/core/model/TracTicket.java b/org.eclipse.mylyn.trac.core/src/org/eclipse/mylyn/internal/trac/core/model/TracTicket.java index 4fe44673c..dbd8b604a 100644 --- a/org.eclipse.mylyn.trac.core/src/org/eclipse/mylyn/internal/trac/core/model/TracTicket.java +++ b/org.eclipse.mylyn.trac.core/src/org/eclipse/mylyn/internal/trac/core/model/TracTicket.java @@ -84,7 +84,7 @@ public class TracTicket { private List<TracAttachment> attachments; - private String[] actions; + private TracAction[] actions; private String[] resolutions; @@ -206,11 +206,11 @@ public class TracTicket { return (attachments != null) ? attachments.toArray(new TracAttachment[0]) : null; } - public void setActions(String[] actions) { + public void setActions(TracAction[] actions) { this.actions = actions; } - public String[] getActions() { + public TracAction[] getActions() { return actions; } diff --git a/org.eclipse.mylyn.trac.core/src/org/eclipse/mylyn/internal/trac/core/util/TracUtil.java b/org.eclipse.mylyn.trac.core/src/org/eclipse/mylyn/internal/trac/core/util/TracUtil.java index 782956bb0..8a5c86b89 100644 --- a/org.eclipse.mylyn.trac.core/src/org/eclipse/mylyn/internal/trac/core/util/TracUtil.java +++ b/org.eclipse.mylyn.trac.core/src/org/eclipse/mylyn/internal/trac/core/util/TracUtil.java @@ -15,6 +15,7 @@ package org.eclipse.mylyn.internal.trac.core.util; import java.io.UnsupportedEncodingException; import java.net.URLEncoder; import java.util.Date; +import java.util.Map; import org.eclipse.core.runtime.IStatus; import org.eclipse.mylyn.internal.trac.core.TracCorePlugin; @@ -91,4 +92,41 @@ public class TracUtil { } } + public static String toString(Object object) { + StringBuilder sb = new StringBuilder(); + toString(sb, object); + return sb.toString(); + } + + public static void toString(StringBuilder sb, Object object) { + if (object instanceof Object[]) { + sb.append("["); //$NON-NLS-1$ + Object[] entries = (Object[]) object; + boolean prependSeparator = false; + for (Object entry : entries) { + if (prependSeparator) { + sb.append(", "); //$NON-NLS-1$ + } + toString(sb, entry); + prependSeparator = true; + } + sb.append("]"); //$NON-NLS-1$ + } else if (object instanceof Map) { + sb.append("{"); //$NON-NLS-1$ + boolean prependSeparator = false; + for (Map.Entry<?, ?> entry : ((Map<?, ?>) object).entrySet()) { + if (prependSeparator) { + sb.append(", "); //$NON-NLS-1$ + } + toString(sb, entry.getKey()); + sb.append("="); //$NON-NLS-1$ + toString(sb, entry.getValue()); + prependSeparator = true; + } + sb.append("}"); //$NON-NLS-1$ + } else { + sb.append(object); + } + } + } |