diff options
author | relves | 2007-06-14 21:20:27 +0000 |
---|---|---|
committer | relves | 2007-06-14 21:20:27 +0000 |
commit | 024a0c4e4a82ce7ad5ee39a2a6e40e38667cb696 (patch) | |
tree | 44e169f73f3797995129213c411a96e02cbf2f94 | |
parent | fe5d2f52d079fdd2e099f8956b3bbad7fab1191b (diff) | |
download | org.eclipse.mylyn.tasks-024a0c4e4a82ce7ad5ee39a2a6e40e38667cb696.tar.gz org.eclipse.mylyn.tasks-024a0c4e4a82ce7ad5ee39a2a6e40e38667cb696.tar.xz org.eclipse.mylyn.tasks-024a0c4e4a82ce7ad5ee39a2a6e40e38667cb696.zip |
NEW - bug 191575: [api] optimize query synchronization
https://bugs.eclipse.org/bugs/show_bug.cgi?id=191575
26 files changed, 631 insertions, 538 deletions
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 53905ec76..b4aab562e 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 @@ -53,6 +53,7 @@ import org.eclipse.mylyn.core.MylarStatusHandler; import org.eclipse.mylyn.internal.bugzilla.core.history.BugzillaTaskHistoryParser; import org.eclipse.mylyn.internal.bugzilla.core.history.TaskHistory; import org.eclipse.mylyn.tasks.core.AbstractRepositoryQuery; +import org.eclipse.mylyn.tasks.core.ITaskCollector; import org.eclipse.mylyn.tasks.core.ITaskAttachment; import org.eclipse.mylyn.tasks.core.QueryHitCollector; import org.eclipse.mylyn.tasks.core.RepositoryOperation; @@ -436,53 +437,9 @@ public class BugzillaClient { // } // } -// public void getSearchHits(AbstractRepositoryQuery query, QueryHitCollector -// collector, TaskList taskList) -// throws IOException, CoreException { -// GetMethod method = null; -// try { -// String queryUrl = query.getUrl(); -// // Test that we don't specify content type twice. -// // Should only be specified here (not in passed in url if possible) -// if (!queryUrl.contains("ctype=rdf")) { -// queryUrl = queryUrl.concat(IBugzillaConstants.CONTENT_TYPE_RDF); -// } -// -// method = getConnect(queryUrl); -// if (method.getResponseHeader("Content-Type") != null) { -// Header responseTypeHeader = method.getResponseHeader("Content-Type"); -// for (String type : VALID_CONFIG_CONTENT_TYPES) { -// if (responseTypeHeader.getValue().toLowerCase(Locale.ENGLISH).contains(type)) -// { -// RepositoryQueryResultsFactory queryFactory = new -// RepositoryQueryResultsFactory(method -// .getResponseBodyAsStream(), characterEncoding); -// queryFactory.performQuery(taskList, repositoryUrl.toString(), collector, -// QueryHitCollector.MAX_HITS); -// -// -// -// -// //getTaskData(queryFactory.get) -// // pass t -// -// return; -// } -// } -// } -// parseHtmlError(new BufferedReader( -// new InputStreamReader(method.getResponseBodyAsStream(), characterEncoding))); -// } finally { -// if (method != null) { -// method.releaseConnection(); -// } -// } -// } - - /** - * Returns ids of bugs that match given query - */ - public Set<String> getSearchHits(AbstractRepositoryQuery query) throws IOException, CoreException { + public boolean getSearchHits(AbstractRepositoryQuery query, ITaskCollector + collector) + throws IOException, CoreException { GetMethod method = null; try { String queryUrl = query.getUrl(); @@ -496,12 +453,14 @@ public class BugzillaClient { if (method.getResponseHeader("Content-Type") != null) { Header responseTypeHeader = method.getResponseHeader("Content-Type"); for (String type : VALID_CONFIG_CONTENT_TYPES) { - if (responseTypeHeader.getValue().toLowerCase(Locale.ENGLISH).contains(type)) { - RepositoryQueryResultsFactory queryFactory = new RepositoryQueryResultsFactory(method + if (responseTypeHeader.getValue().toLowerCase(Locale.ENGLISH).contains(type)) + { + RepositoryQueryResultsFactory queryFactory = new + RepositoryQueryResultsFactory(method .getResponseBodyAsStream(), characterEncoding); - queryFactory.performQuery(repositoryUrl.toString(), QueryHitCollector.MAX_HITS); - - return queryFactory.getHits(); + queryFactory.performQuery(repositoryUrl.toString(), collector, + QueryHitCollector.MAX_HITS); + return !queryFactory.getHits().isEmpty(); } } } @@ -512,9 +471,45 @@ public class BugzillaClient { method.releaseConnection(); } } - return new HashSet<String>(); + return false; } +// /** +// * Returns ids of bugs that match given query +// */ +// public Set<String> getSearchHits(AbstractRepositoryQuery query) throws IOException, CoreException { +// GetMethod method = null; +// try { +// String queryUrl = query.getUrl(); +// // Test that we don't specify content type twice. +// // Should only be specified here (not in passed in url if possible) +// if (!queryUrl.contains("ctype=rdf")) { +// queryUrl = queryUrl.concat(IBugzillaConstants.CONTENT_TYPE_RDF); +// } +// +// method = getConnect(queryUrl); +// if (method.getResponseHeader("Content-Type") != null) { +// Header responseTypeHeader = method.getResponseHeader("Content-Type"); +// for (String type : VALID_CONFIG_CONTENT_TYPES) { +// if (responseTypeHeader.getValue().toLowerCase(Locale.ENGLISH).contains(type)) { +// RepositoryQueryResultsFactory queryFactory = new RepositoryQueryResultsFactory(method +// .getResponseBodyAsStream(), characterEncoding); +// queryFactory.performQuery(repositoryUrl.toString(), QueryHitCollector.MAX_HITS); +// +// return queryFactory.getHits(); +// } +// } +// } +// parseHtmlError(new BufferedReader( +// new InputStreamReader(method.getResponseBodyAsStream(), characterEncoding))); +// } finally { +// if (method != null) { +// method.releaseConnection(); +// } +// } +// return new HashSet<String>(); +// } + public static void setupExistingBugAttributes(String serverUrl, RepositoryTaskData existingReport) { // ordered list of elements as they appear in UI // and additional elements that may not appear in the incoming xml 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 353b7ab73..f3be5249b 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 @@ -21,7 +21,6 @@ import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Locale; -import java.util.Map; import java.util.Set; import org.eclipse.core.runtime.CoreException; @@ -34,6 +33,7 @@ import org.eclipse.mylyn.tasks.core.AbstractRepositoryConnector; import org.eclipse.mylyn.tasks.core.AbstractRepositoryQuery; import org.eclipse.mylyn.tasks.core.AbstractTask; import org.eclipse.mylyn.tasks.core.IAttachmentHandler; +import org.eclipse.mylyn.tasks.core.ITaskCollector; import org.eclipse.mylyn.tasks.core.ITaskDataHandler; import org.eclipse.mylyn.tasks.core.ITaskFactory; import org.eclipse.mylyn.tasks.core.QueryHitCollector; @@ -221,61 +221,79 @@ public class BugzillaRepositoryConnector extends AbstractRepositoryConnector { } } - @Override - public Set<AbstractTask> getChangedSinceLastSync(TaskRepository repository, - Set<AbstractTask> tasks, IProgressMonitor monitor) throws CoreException { + public boolean markStaleTasks(TaskRepository repository, Set<AbstractTask> tasks, IProgressMonitor monitor) + throws CoreException { try { - Set<AbstractTask> changedTasks = new HashSet<AbstractTask>(); + monitor.beginTask("Checking for changed tasks", IProgressMonitor.UNKNOWN); if (repository.getSyncTimeStamp() == null) { - return tasks; + for (AbstractTask task : tasks) { + task.setStale(true); + } + return true; } String dateString = repository.getSyncTimeStamp(); if (dateString == null) { dateString = ""; } - String urlQueryBase; - String urlQueryString; - urlQueryBase = repository.getUrl() + CHANGED_BUGS_CGI_QUERY + String urlQueryBase = repository.getUrl() + CHANGED_BUGS_CGI_QUERY + URLEncoder.encode(dateString, repository.getCharacterEncoding()) + CHANGED_BUGS_CGI_ENDDATE; - urlQueryString = urlQueryBase + BUG_ID; + String urlQueryString = urlQueryBase + BUG_ID; + + // Need to replace this with query that would return list of tasks since last sync + // the trouble is that bugzilla only have 1 hour granularity for "changed since" query + // so, we can't say that no tasks has changed in repository + Set<AbstractTask> changedTasks = new HashSet<AbstractTask>(); int queryCounter = -1; Iterator<AbstractTask> itr = tasks.iterator(); while (itr.hasNext()) { queryCounter++; AbstractTask task = itr.next(); String newurlQueryString = URLEncoder.encode(task.getTaskId() + ",", repository.getCharacterEncoding()); - if ((urlQueryString.length() + newurlQueryString.length() + IBugzillaConstants.CONTENT_TYPE_RDF - .length()) > IBugzillaConstants.MAX_URL_LENGTH) { + if ((urlQueryString.length() + newurlQueryString.length() + IBugzillaConstants.CONTENT_TYPE_RDF.length()) > IBugzillaConstants.MAX_URL_LENGTH) { queryForChanged(repository, changedTasks, urlQueryString); queryCounter = 0; urlQueryString = urlQueryBase + BUG_ID; - urlQueryString += newurlQueryString; - } else if (!itr.hasNext()) { - urlQueryString += newurlQueryString; + } + urlQueryString += newurlQueryString; + if (!itr.hasNext()) { queryForChanged(repository, changedTasks, urlQueryString); - } else { - urlQueryString += newurlQueryString; } } - return changedTasks; + + for (AbstractTask task : tasks) { + if (changedTasks.contains(task)) { + task.setStale(true); + } + } + +// for (AbstractTask task : changedTasks) { +// task.setStale(true); +// } + + // FIXME check if new tasks were added + //return changedTasks.isEmpty(); + return true; } catch (UnsupportedEncodingException e) { + // XXX throw CoreException instead? MylarStatusHandler.fail(e, "Repository configured with unsupported encoding: " + repository.getCharacterEncoding() + "\n\n Unable to determine changed tasks.", true); - return tasks; + return false; + } finally { + monitor.done(); } } - private void queryForChanged(final TaskRepository repository, Set<AbstractTask> changedTasks, - String urlQueryString) throws UnsupportedEncodingException, CoreException { + private void queryForChanged(final TaskRepository repository, Set<AbstractTask> changedTasks, String urlQueryString) + throws UnsupportedEncodingException, CoreException { QueryHitCollector collector = new QueryHitCollector(taskList, new ITaskFactory() { - public AbstractTask createTask(RepositoryTaskData taskData, boolean synchData, boolean forced, IProgressMonitor monitor) { + public AbstractTask createTask(RepositoryTaskData taskData, IProgressMonitor monitor) { // do not construct actual task objects here as query shouldn't result in new tasks return taskList.getTask(taskData.getRepositoryUrl(), taskData.getId()); } @@ -283,7 +301,7 @@ public class BugzillaRepositoryConnector extends AbstractRepositoryConnector { BugzillaRepositoryQuery query = new BugzillaRepositoryQuery(repository.getUrl(), urlQueryString, ""); - performQuery(query, repository, new NullProgressMonitor(), collector, false); + performQuery(query, repository, new NullProgressMonitor(), collector); for (AbstractTask taskHit : collector.getTaskHits()) { // String handle = @@ -332,49 +350,30 @@ public class BugzillaRepositoryConnector extends AbstractRepositoryConnector { @Override public IStatus performQuery(final AbstractRepositoryQuery query, TaskRepository repository, - IProgressMonitor monitor, QueryHitCollector resultCollector, boolean forced) { - IStatus queryStatus = Status.OK_STATUS; + IProgressMonitor monitor, ITaskCollector resultCollector) { try { + monitor.beginTask("Running query", IProgressMonitor.UNKNOWN); BugzillaClient client = getClientManager().getClient(repository); - resultCollector.clear(); - Set<String> ids = client.getSearchHits(query); - if (ids.size() == 0) { + boolean hitsReceived = client.getSearchHits(query, resultCollector); + if (!hitsReceived) { // XXX: HACK in case of ip change bugzilla can return 0 hits // due to invalid authorization token, forcing relogin fixes client.logout(); - ids = client.getSearchHits(query); - } - - if (!forced) { - // Only retrieve data for hits we don't already have - for (AbstractTask existingTask : query.getChildren()) { - AbstractTask repositoryTask = (AbstractTask) existingTask; - if (ids.contains(repositoryTask.getTaskId())) { - resultCollector.accept(repositoryTask); - ids.remove(repositoryTask.getTaskId()); - } - } - } - - Map<String, RepositoryTaskData> hits = client.getTaskData(ids); - for (RepositoryTaskData data : hits.values()) { - if (data != null) { - taskDataHandler.configureTaskData(repository, data); - resultCollector.accept(data); - } + client.getSearchHits(query, resultCollector); } + return Status.OK_STATUS; } catch (UnrecognizedReponseException e) { - queryStatus = new Status(IStatus.ERROR, BugzillaCorePlugin.PLUGIN_ID, Status.INFO, + return new Status(IStatus.ERROR, BugzillaCorePlugin.PLUGIN_ID, Status.INFO, "Unrecognized response from server", e); } catch (IOException e) { - queryStatus = new Status(IStatus.ERROR, BugzillaCorePlugin.PLUGIN_ID, Status.ERROR, + return new Status(IStatus.ERROR, BugzillaCorePlugin.PLUGIN_ID, Status.ERROR, "Check repository configuration: " + e.getMessage(), e); } catch (CoreException e) { - queryStatus = e.getStatus(); + return e.getStatus(); + } finally { + monitor.done(); } - return queryStatus; - } @Override diff --git a/org.eclipse.mylyn.bugzilla.core/src/org/eclipse/mylyn/internal/bugzilla/core/RepositoryQueryResultsFactory.java b/org.eclipse.mylyn.bugzilla.core/src/org/eclipse/mylyn/internal/bugzilla/core/RepositoryQueryResultsFactory.java index d8faa0fc1..e6099baa0 100644 --- a/org.eclipse.mylyn.bugzilla.core/src/org/eclipse/mylyn/internal/bugzilla/core/RepositoryQueryResultsFactory.java +++ b/org.eclipse.mylyn.bugzilla.core/src/org/eclipse/mylyn/internal/bugzilla/core/RepositoryQueryResultsFactory.java @@ -17,6 +17,9 @@ import java.security.GeneralSecurityException; import java.util.HashSet; import java.util.Set; +import org.eclipse.mylyn.tasks.core.ITaskCollector; +import org.eclipse.mylyn.tasks.core.QueryHitCollector; + /** * @author Rob Elves */ @@ -28,14 +31,23 @@ public class RepositoryQueryResultsFactory extends AbstractReportFactory { super(inStream, encoding); } - /** - * expects rdf returned from repository (ctype=rdf in url) - * - * @throws GeneralSecurityException - */ - public void performQuery(String repositoryUrl, int maxHits) throws IOException { - - SaxBugzillaQueryContentHandler contentHandler = new SaxBugzillaQueryContentHandler(repositoryUrl, hits, maxHits); +// /** +// * expects rdf returned from repository (ctype=rdf in url) +// * +// * @throws GeneralSecurityException +// */ +// public void performQuery(String repositoryUrl, int maxHits) throws IOException { +// +// SaxBugzillaQueryContentHandler contentHandler = new SaxBugzillaQueryContentHandler(repositoryUrl, hits, maxHits); +// collectResults(contentHandler, false); +// } + + /** expects rdf returned from repository (ctype=rdf in url) + * @throws GeneralSecurityException */ + public void performQuery(String repositoryUrl, ITaskCollector collector, int maxHits) throws IOException { + + SaxBugzillaQueryContentHandler contentHandler = new SaxBugzillaQueryContentHandler(repositoryUrl, + collector, hits, maxHits); collectResults(contentHandler, false); } diff --git a/org.eclipse.mylyn.bugzilla.core/src/org/eclipse/mylyn/internal/bugzilla/core/SaxBugzillaQueryContentHandler.java b/org.eclipse.mylyn.bugzilla.core/src/org/eclipse/mylyn/internal/bugzilla/core/SaxBugzillaQueryContentHandler.java index f36a640e0..0c7b1fbd0 100644 --- a/org.eclipse.mylyn.bugzilla.core/src/org/eclipse/mylyn/internal/bugzilla/core/SaxBugzillaQueryContentHandler.java +++ b/org.eclipse.mylyn.bugzilla.core/src/org/eclipse/mylyn/internal/bugzilla/core/SaxBugzillaQueryContentHandler.java @@ -14,6 +14,9 @@ package org.eclipse.mylyn.internal.bugzilla.core; import java.util.Locale; import java.util.Set; +import org.eclipse.mylyn.tasks.core.AbstractTask; +import org.eclipse.mylyn.tasks.core.ITaskCollector; +import org.eclipse.mylyn.tasks.core.QueryHitCollector; import org.eclipse.mylyn.web.core.HtmlStreamTokenizer; import org.xml.sax.Attributes; import org.xml.sax.SAXException; @@ -29,18 +32,20 @@ public class SaxBugzillaQueryContentHandler extends DefaultHandler { /** The bug id */ private String id; -// /** The summary of the bug */ -// private String description = ""; -// -// /** The priority of the bug */ -// private String priority = Task.PriorityLevel.getDefault().toString(); -// -// /** The state of the bug */ -// private String state = ""; + /** The summary of the bug */ + private String description = ""; + + /** The priority of the bug */ + private String priority = AbstractTask.PriorityLevel.getDefault().toString(); + + /** The state of the bug */ + private String state = ""; private StringBuffer characters; -// private String repositoryUrl; + private ITaskCollector collector; + + private String repositoryUrl; private Set<String> bugIds; @@ -48,9 +53,10 @@ public class SaxBugzillaQueryContentHandler extends DefaultHandler { private int numCollected = 0; - public SaxBugzillaQueryContentHandler(String repositoryUrl, Set<String> hits, int maxHits) { - //this.repositoryUrl = repositoryUrl; + public SaxBugzillaQueryContentHandler(String repositoryUrl, ITaskCollector collector, Set<String> hits, int maxHits) { + this.repositoryUrl = repositoryUrl; this.maxHits = maxHits; + this.collector = collector; this.bugIds = hits; } @@ -96,42 +102,42 @@ public class SaxBugzillaQueryContentHandler extends DefaultHandler { //System.err.println(">>> "+id); bugIds.add(id); numCollected++; - } + } break; -// // case BUG_SEVERITY: -// // severity = parsedText; -// // break; -// case PRIORITY: -// priority = parsedText; -// break; -// // case REP_PLATFORM: -// // platform = parsedText; -// // break; -// case ASSIGNED_TO: -// //hit.setOwner(parsedText); -// break; -// case BUG_STATUS: -// state = parsedText; -// break; -// // case RESOLUTION: -// // resolution = parsedText; -// // break; -// case SHORT_DESC: -// description = parsedText; -// break; -// case SHORT_SHORT_DESC: -// description = parsedText; -// break; -// case LI: -// if (numCollected < maxHits || maxHits == IBugzillaConstants.RETURN_ALL_HITS) -// { -// hit = new BugzillaQueryHit(taskList, description, priority, repositoryUrl, -// id, null, state); -// collector.accept(hit); -// numCollected++; -// } else { -// break; -// } + // case BUG_SEVERITY: + // severity = parsedText; + // break; + case PRIORITY: + priority = parsedText; + break; + // case REP_PLATFORM: + // platform = parsedText; + // break; + case ASSIGNED_TO: + //hit.setOwner(parsedText); + break; + case BUG_STATUS: + state = parsedText; + break; + // case RESOLUTION: + // resolution = parsedText; + // break; + case SHORT_DESC: + description = parsedText; + break; + case SHORT_SHORT_DESC: + description = parsedText; + break; + case LI: + if (numCollected < maxHits || maxHits == IBugzillaConstants.RETURN_ALL_HITS) { + BugzillaTask task = new BugzillaTask(repositoryUrl, id, description); + task.setPriority(priority); + // TODO set state + collector.accept(task); + numCollected++; + } else { + break; + } } } catch (RuntimeException e) { if (e instanceof IllegalArgumentException) { diff --git a/org.eclipse.mylyn.bugzilla.tests/src/org/eclipse/mylyn/bugzilla/tests/BugzillaRepositoryConnectorTest.java b/org.eclipse.mylyn.bugzilla.tests/src/org/eclipse/mylyn/bugzilla/tests/BugzillaRepositoryConnectorTest.java index 2c4f2a587..9f1270b28 100644 --- a/org.eclipse.mylyn.bugzilla.tests/src/org/eclipse/mylyn/bugzilla/tests/BugzillaRepositoryConnectorTest.java +++ b/org.eclipse.mylyn.bugzilla.tests/src/org/eclipse/mylyn/bugzilla/tests/BugzillaRepositoryConnectorTest.java @@ -386,9 +386,11 @@ public class BugzillaRepositoryConnectorTest extends AbstractBugzillaTest { TasksUiPlugin.getRepositoryManager().setSyncTime(repository, task5.getLastSyncDateStamp(), TasksUiPlugin.getDefault().getRepositoriesFilePath()); - Set<AbstractTask> changedTasks = connector.getChangedSinceLastSync(repository, tasks, new NullProgressMonitor()); + boolean changed = connector.markStaleTasks(repository, tasks, new NullProgressMonitor()); + assertTrue(changed); // Always last known changed returned - assertEquals(1, changedTasks.size()); + assertFalse(task4.isStale()); + assertTrue(task5.isStale()); String priority4 = null; if (task4.getPriority().equals("P1")) { @@ -414,14 +416,15 @@ public class BugzillaRepositoryConnectorTest extends AbstractBugzillaTest { submit(task4, taskData4); submit(task5, taskData5); - changedTasks = connector.getChangedSinceLastSync(repository, tasks, new NullProgressMonitor()); + changed = connector.markStaleTasks(repository, tasks, new NullProgressMonitor()); - assertEquals("Changed reports expected ", 2, changedTasks.size()); - assertTrue(tasks.containsAll(changedTasks)); + assertTrue(task4.isStale()); + assertTrue(task5.isStale()); - TasksUiPlugin.getSynchronizationManager().synchronize(connector, changedTasks, true, null); + TasksUiPlugin.getSynchronizationManager().synchronize(connector, tasks, true, null); - for (AbstractTask task : changedTasks) { + + for (AbstractTask task : tasks) { if (task.getTaskId() == "4") { assertEquals(priority4, task4.getPriority()); } diff --git a/org.eclipse.mylyn.bugzilla.tests/src/org/eclipse/mylyn/bugzilla/tests/BugzillaSearchEngineTest.java b/org.eclipse.mylyn.bugzilla.tests/src/org/eclipse/mylyn/bugzilla/tests/BugzillaSearchEngineTest.java index 493557319..9cc663dab 100644 --- a/org.eclipse.mylyn.bugzilla.tests/src/org/eclipse/mylyn/bugzilla/tests/BugzillaSearchEngineTest.java +++ b/org.eclipse.mylyn.bugzilla.tests/src/org/eclipse/mylyn/bugzilla/tests/BugzillaSearchEngineTest.java @@ -118,7 +118,7 @@ public class BugzillaSearchEngineTest extends TestCase { TaskList taskList = TasksUiPlugin.getTaskListManager().getTaskList(); QueryHitCollector collector = new QueryHitCollector(taskList, new TaskFactory(repository)); - connector.performQuery(repositoryQuery, repository, new NullProgressMonitor(), collector, false); + connector.performQuery(repositoryQuery, repository, new NullProgressMonitor(), collector); // results.addAll(connector.performQuery(repositoryQuery, new // NullProgressMonitor(), new MultiStatus(TasksUiPlugin.PLUGIN_ID, diff --git a/org.eclipse.mylyn.bugzilla.tests/src/org/eclipse/mylyn/bugzilla/tests/headless/BugzillaQueryTest.java b/org.eclipse.mylyn.bugzilla.tests/src/org/eclipse/mylyn/bugzilla/tests/headless/BugzillaQueryTest.java index 1c136ce4c..f20bd5c05 100644 --- a/org.eclipse.mylyn.bugzilla.tests/src/org/eclipse/mylyn/bugzilla/tests/headless/BugzillaQueryTest.java +++ b/org.eclipse.mylyn.bugzilla.tests/src/org/eclipse/mylyn/bugzilla/tests/headless/BugzillaQueryTest.java @@ -136,7 +136,7 @@ public class BugzillaQueryTest extends TestCase { BugzillaRepositoryConnector connector = new BugzillaRepositoryConnector(); connector.init(taskList); BugzillaRepositoryQuery query = new BugzillaRepositoryQuery(repository.getUrl(), queryUrlString, "summary"); - connector.performQuery(query, repository, new NullProgressMonitor(), collector, false); + connector.performQuery(query, repository, new NullProgressMonitor(), collector); assertEquals(2, collector.getTaskHits().size()); for (AbstractTask hit : collector.getTaskHits()) { assertTrue(hit.getSummary().contains("search-match-test")); diff --git a/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/internal/tasks/core/LocalRepositoryConnector.java b/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/internal/tasks/core/LocalRepositoryConnector.java index 331555779..1790c6a89 100644 --- a/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/internal/tasks/core/LocalRepositoryConnector.java +++ b/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/internal/tasks/core/LocalRepositoryConnector.java @@ -11,7 +11,7 @@ package org.eclipse.mylyn.internal.tasks.core; -import java.util.Collections; + import java.util.Set; import org.eclipse.core.runtime.CoreException; @@ -21,8 +21,8 @@ import org.eclipse.mylyn.tasks.core.AbstractRepositoryConnector; import org.eclipse.mylyn.tasks.core.AbstractRepositoryQuery; import org.eclipse.mylyn.tasks.core.AbstractTask; import org.eclipse.mylyn.tasks.core.IAttachmentHandler; +import org.eclipse.mylyn.tasks.core.ITaskCollector; import org.eclipse.mylyn.tasks.core.ITaskDataHandler; -import org.eclipse.mylyn.tasks.core.QueryHitCollector; import org.eclipse.mylyn.tasks.core.RepositoryTaskData; import org.eclipse.mylyn.tasks.core.TaskRepository; @@ -63,9 +63,9 @@ public class LocalRepositoryConnector extends AbstractRepositoryConnector { } @Override - public Set<AbstractTask> getChangedSinceLastSync(TaskRepository repository, - Set<AbstractTask> tasks, IProgressMonitor monitor) throws CoreException { - return Collections.emptySet(); + public boolean markStaleTasks(TaskRepository repository, + Set<AbstractTask> tasks, IProgressMonitor monitor) { + return false; } @Override @@ -104,7 +104,7 @@ public class LocalRepositoryConnector extends AbstractRepositoryConnector { @Override public IStatus performQuery(AbstractRepositoryQuery query, TaskRepository repository, IProgressMonitor monitor, - QueryHitCollector resultCollector, boolean forced) { + ITaskCollector resultCollector) { // ignore return null; } diff --git a/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/tasks/core/AbstractRepositoryConnector.java b/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/tasks/core/AbstractRepositoryConnector.java index 8eca91e4a..fad1df265 100644 --- a/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/tasks/core/AbstractRepositoryConnector.java +++ b/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/tasks/core/AbstractRepositoryConnector.java @@ -171,7 +171,7 @@ public abstract class AbstractRepositoryConnector { * IQueryHitCollector that collects the hits found */ public abstract IStatus performQuery(AbstractRepositoryQuery query, TaskRepository repository, - IProgressMonitor monitor, QueryHitCollector resultCollector, boolean forced); + IProgressMonitor monitor, ITaskCollector resultCollector); /** * The connector's summary i.e. "JIRA (supports 3.3.1 and later)" @@ -250,18 +250,23 @@ public abstract class AbstractRepositoryConnector { } /** - * Of <code>tasks</code> provided, return all that have changed since last - * synchronization of <code>repository</code> + * Of <code>tasks</code> provided, return all that have changed since last synchronization of + * <code>repository</code>. * - * All errors should be thrown as <code>CoreException</code> for the - * framework to handle, since background synchronizations fail silently when - * disconnected. + * Tasks that need to be synchronized (i.e. task data updated) should be passed to + * <code>collector.accept(Task)</code> method, or if repository connector can update task data, it can use + * <code>collector.accept(RepositoryTaskData)</code> call. * - * TODO: Add progress monitor as parameter + * All errors should be thrown as <code>CoreException</code> for the framework to handle, since background + * synchronizations fail silently when disconnected. + * @param tasks TODO + * + * @return null if there was no tasks changed in the repository, otherwise collection of updated tasks (within + * <code>tasks</code> collection), so empty collection means that there are some other tasks changed * * @throws CoreException */ - public abstract Set<AbstractTask> getChangedSinceLastSync(TaskRepository repository, + public abstract boolean markStaleTasks(TaskRepository repository, Set<AbstractTask> tasks, IProgressMonitor monitor) throws CoreException; /** @@ -392,7 +397,7 @@ public abstract class AbstractRepositoryConnector { * synchronization timestamp. Override to return actual timestamp from * repository. */ - public String getLastSyncTimestamp(TaskRepository repository, Set<AbstractTask> changedTasks) { + public String getSynchronizationTimestamp(TaskRepository repository, Set<AbstractTask> changedTasks) { Date mostRecent = new Date(0); String mostRecentTimeStamp = repository.getSyncTimeStamp(); for (AbstractTask task : changedTasks) { @@ -432,4 +437,5 @@ public abstract class AbstractRepositoryConnector { this.taskDataManager = taskDataManager; } + } diff --git a/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/tasks/core/AbstractTask.java b/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/tasks/core/AbstractTask.java index e1dfb29a7..ab8a3b448 100644 --- a/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/tasks/core/AbstractTask.java +++ b/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/tasks/core/AbstractTask.java @@ -66,6 +66,8 @@ public abstract class AbstractTask extends AbstractTaskContainer { // transient private IStatus errorStatus = null; + + private boolean stale = false; public enum RepositoryTaskSyncState { OUTGOING, SYNCHRONIZED, INCOMING, CONFLICT @@ -446,4 +448,13 @@ public abstract class AbstractTask extends AbstractTaskContainer { public void setDueDate(Date date) { this.dueDate = date; } + + public boolean isStale() { + return stale; + } + + public void setStale(boolean stale) { + this.stale = stale; + } + } diff --git a/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/tasks/core/DelegatingTaskExternalizer.java b/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/tasks/core/DelegatingTaskExternalizer.java index 8f38aed49..a2995d956 100644 --- a/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/tasks/core/DelegatingTaskExternalizer.java +++ b/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/tasks/core/DelegatingTaskExternalizer.java @@ -126,6 +126,8 @@ public class DelegatingTaskExternalizer implements ITaskListExternalizer { public static final String KEY_SYNC_STATE = "offlineSyncState"; public static final String KEY_OWNER = "Owner"; + + public static final String KEY_STALE = "Stale"; private List<ITaskListExternalizer> delegateExternalizers = new ArrayList<ITaskListExternalizer>(); @@ -204,6 +206,11 @@ public class DelegatingTaskExternalizer implements ITaskListExternalizer { } else { node.setAttribute(KEY_REMINDED, VAL_FALSE); } + if (task.isStale()) { + node.setAttribute(KEY_STALE, VAL_TRUE); + } else { + node.setAttribute(KEY_STALE, VAL_FALSE); + } if (task instanceof AbstractTask) { AbstractTask abstractTask = (AbstractTask) task; @@ -483,6 +490,11 @@ public class DelegatingTaskExternalizer implements ITaskListExternalizer { } else { task.setReminded(false); } + if (element.hasAttribute(KEY_STALE) && element.getAttribute(KEY_STALE).compareTo(VAL_TRUE) == 0) { + task.setStale(true); + } else { + task.setStale(false); + } if (task instanceof AbstractTask) { AbstractTask abstractTask = (AbstractTask) task; diff --git a/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/tasks/core/ITaskCollector.java b/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/tasks/core/ITaskCollector.java new file mode 100644 index 000000000..2aad2db65 --- /dev/null +++ b/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/tasks/core/ITaskCollector.java @@ -0,0 +1,22 @@ +/******************************************************************************* + * 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.mylyn.tasks.core; + +import org.eclipse.core.runtime.CoreException; + +public interface ITaskCollector { + + void accept(AbstractTask task); + + void accept(RepositoryTaskData taskData) throws CoreException; + +} diff --git a/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/tasks/core/ITaskFactory.java b/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/tasks/core/ITaskFactory.java index 834e0947e..68583a7ad 100644 --- a/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/tasks/core/ITaskFactory.java +++ b/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/tasks/core/ITaskFactory.java @@ -23,6 +23,6 @@ public interface ITaskFactory { * @param forced - * user requested synchronization */ - public abstract AbstractTask createTask(RepositoryTaskData taskData, boolean synchData, boolean forced, IProgressMonitor monitor) throws CoreException; + public abstract AbstractTask createTask(RepositoryTaskData taskData, IProgressMonitor monitor) throws CoreException; }
\ No newline at end of file diff --git a/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/tasks/core/QueryHitCollector.java b/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/tasks/core/QueryHitCollector.java index b68a980b8..310e337c3 100644 --- a/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/tasks/core/QueryHitCollector.java +++ b/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/tasks/core/QueryHitCollector.java @@ -10,131 +10,64 @@ *******************************************************************************/ package org.eclipse.mylyn.tasks.core; -import java.text.MessageFormat; import java.util.HashSet; import java.util.Set; import org.eclipse.core.runtime.CoreException; -import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.NullProgressMonitor; -import org.eclipse.core.runtime.SubProgressMonitor; /** * Collects QueryHits resulting from repository search * * @author Shawn Minto * @author Rob Elves (generalized from bugzilla) + * @author Steffen Pingel */ -public class QueryHitCollector { +public class QueryHitCollector implements ITaskCollector { public static final int MAX_HITS = 5000; public static final String MAX_HITS_REACHED = "Max allowed number of hits returned exceeded. Some hits may not be displayed. Please narrow query scope."; - protected Set<AbstractTask> taskResults = new HashSet<AbstractTask>(); + private final Set<AbstractTask> taskResults = new HashSet<AbstractTask>(); - /** The progress monitor for the search operation */ - private IProgressMonitor monitor = new NullProgressMonitor(); + private final TaskList taskList; - /** The number of matches found */ - private int matchCount; - - /** The string to display to the user while querying */ - private static final String STARTING = "querying the server"; - - /** The string to display to the user when we have 1 match */ - private static final String MATCH = "1 match"; - - /** The string to display to the user when we have multiple or no matches */ - private static final String MATCHES = "{0} matches"; - - /** The string to display to the user when the query is done */ - private static final String DONE = "done"; - - protected TaskList taskList; - - protected ITaskFactory taskFactory; + private final ITaskFactory taskFactory; public QueryHitCollector(TaskList tasklist, ITaskFactory taskFactory) { this.taskList = tasklist; this.taskFactory = taskFactory; } - public void aboutToStart(int startMatchCount) throws CoreException { - taskResults.clear(); - matchCount = startMatchCount; - monitor.setTaskName(STARTING); - } - public void accept(AbstractTask task) { - - if (!getProgressMonitor().isCanceled()) { - getProgressMonitor().subTask(getFormattedMatchesString(matchCount)); - getProgressMonitor().worked(1); + if (task == null) { + throw new IllegalArgumentException(); } - - if (task == null) - return; - - AbstractTask hitTask = taskList.getTask(task.getHandleIdentifier()); - if (hitTask == null) { - hitTask = task; - // task is new, add to tasklist - taskList.addTask(hitTask); + + AbstractTask existingTask = taskList.getTask(task.getHandleIdentifier()); + if (existingTask == null) { + task.setStale(true); + } else { + // preserve meta attributes of existing task + task.setLastSyncDateStamp(existingTask.getLastSyncDateStamp()); + task.setStale(existingTask.isStale()); } - taskResults.add((AbstractTask) hitTask); - matchCount++; + + taskResults.add((AbstractTask) task); } public void accept(RepositoryTaskData taskData) throws CoreException { - if (taskData == null) - return; - - if (!getProgressMonitor().isCanceled()) { - getProgressMonitor().subTask(getFormattedMatchesString(matchCount)); - getProgressMonitor().worked(1); + if (taskData == null) { + throw new IllegalArgumentException(); } - AbstractTask task = taskFactory.createTask(taskData, true, false, new SubProgressMonitor(monitor, 1)); + AbstractTask task = taskFactory.createTask(taskData, new NullProgressMonitor()); taskResults.add(task); - matchCount++; - } - - public void done() { - if (monitor != null && !monitor.isCanceled()) { - // if the operation is cancelled, finish with the data that we - // already have - String matchesString = getFormattedMatchesString(matchCount); - monitor.setTaskName(MessageFormat.format(DONE, new Object[] { matchesString })); - monitor.done(); - } - - // Cut no longer used references because the collector might be re-used - monitor = null; - } - - protected String getFormattedMatchesString(int count) { - if (count == 1) { - return MATCH; - } - Object[] messageFormatArgs = { new Integer(count) }; - return MessageFormat.format(MATCHES, messageFormatArgs); - } - - public IProgressMonitor getProgressMonitor() { - return monitor; - } - - public void setProgressMonitor(IProgressMonitor monitor) { - this.monitor = monitor; } public Set<AbstractTask> getTaskHits() { return taskResults; } - public void clear() { - taskResults.clear(); - } - } diff --git a/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/tasks/core/TaskRepository.java b/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/tasks/core/TaskRepository.java index 70c727789..7d81e8de3 100644 --- a/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/tasks/core/TaskRepository.java +++ b/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/tasks/core/TaskRepository.java @@ -294,8 +294,23 @@ public class TaskRepository { @Override public boolean equals(Object object) { - if (object instanceof TaskRepository && getUrl() != null) { - return getUrl().equals(((TaskRepository) object).getUrl()); + if (object instanceof TaskRepository) { + TaskRepository repository = (TaskRepository) object; + if (getUrl() == null) { + if (repository.getUrl() != null) { + return false; + } + } else { + if(!getUrl().equals(repository.getUrl())) { + return false; + } + } + if (getKind() == null) { + return repository.getKind() == null; + } else { + return getKind().equals(repository.getKind()); + } + } else { return super.equals(object); } @@ -303,11 +318,8 @@ public class TaskRepository { @Override public int hashCode() { - if (getUrl() != null) { - return getUrl().hashCode(); - } else { - return super.hashCode(); - } + int res = getUrl()==null ? 1 : getUrl().hashCode(); + return res * 31 + (getKind()==null ? 1 : getKind().hashCode()); } @Override diff --git a/org.eclipse.mylyn.tasks.tests/src/org/eclipse/mylyn/tasks/tests/connector/MockRepositoryConnector.java b/org.eclipse.mylyn.tasks.tests/src/org/eclipse/mylyn/tasks/tests/connector/MockRepositoryConnector.java index f2c2e8e8a..184920bfe 100644 --- a/org.eclipse.mylyn.tasks.tests/src/org/eclipse/mylyn/tasks/tests/connector/MockRepositoryConnector.java +++ b/org.eclipse.mylyn.tasks.tests/src/org/eclipse/mylyn/tasks/tests/connector/MockRepositoryConnector.java @@ -22,8 +22,8 @@ import org.eclipse.mylyn.tasks.core.AbstractRepositoryConnector; import org.eclipse.mylyn.tasks.core.AbstractRepositoryQuery; import org.eclipse.mylyn.tasks.core.AbstractTask; import org.eclipse.mylyn.tasks.core.IAttachmentHandler; +import org.eclipse.mylyn.tasks.core.ITaskCollector; import org.eclipse.mylyn.tasks.core.ITaskDataHandler; -import org.eclipse.mylyn.tasks.core.QueryHitCollector; import org.eclipse.mylyn.tasks.core.RepositoryTaskData; import org.eclipse.mylyn.tasks.core.TaskRepository; @@ -133,9 +133,10 @@ public class MockRepositoryConnector extends AbstractRepositoryConnector { } @Override - public Set<AbstractTask> getChangedSinceLastSync(TaskRepository repository, - Set<AbstractTask> tasks, IProgressMonitor monitor) throws CoreException { - return Collections.emptySet(); + public boolean markStaleTasks(TaskRepository repository, + Set<AbstractTask> tasks, IProgressMonitor monitor) { + // ignore + return false; } @Override @@ -153,7 +154,7 @@ public class MockRepositoryConnector extends AbstractRepositoryConnector { @Override public IStatus performQuery(AbstractRepositoryQuery query, TaskRepository repository, IProgressMonitor monitor, - QueryHitCollector resultCollector, boolean forced) { + ITaskCollector resultCollector) { // ignore return null; } diff --git a/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/ScheduledTaskListSynchJob.java b/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/ScheduledTaskListSynchJob.java index 1cae5a004..fa1a7a6fc 100644 --- a/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/ScheduledTaskListSynchJob.java +++ b/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/ScheduledTaskListSynchJob.java @@ -11,23 +11,20 @@ package org.eclipse.mylyn.internal.tasks.ui; -import java.util.Collections; import java.util.List; import java.util.Set; 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.Status; import org.eclipse.core.runtime.SubProgressMonitor; -import org.eclipse.core.runtime.jobs.IJobChangeEvent; import org.eclipse.core.runtime.jobs.Job; -import org.eclipse.core.runtime.jobs.JobChangeAdapter; import org.eclipse.mylyn.tasks.core.AbstractRepositoryConnector; import org.eclipse.mylyn.tasks.core.AbstractRepositoryQuery; import org.eclipse.mylyn.tasks.core.TaskList; import org.eclipse.mylyn.tasks.core.TaskRepository; +import org.eclipse.mylyn.tasks.ui.RepositorySynchronizationManager; import org.eclipse.mylyn.tasks.ui.TaskListManager; import org.eclipse.mylyn.tasks.ui.TasksUiPlugin; @@ -68,12 +65,8 @@ public class ScheduledTaskListSynchJob extends Job { } @Override - public IStatus run(IProgressMonitor monitor) { + public IStatus run(final IProgressMonitor monitor) { try { - if (monitor == null) { - monitor = new NullProgressMonitor(); - } - taskList = taskListManager.getTaskList(); if (repositories == null) { repositories = TasksUiPlugin.getRepositoryManager().getAllRepositories(); @@ -113,22 +106,11 @@ public class ScheduledTaskListSynchJob extends Job { updateJob.schedule(); } - Set<AbstractRepositoryQuery> queries = Collections.unmodifiableSet(taskList - .getRepositoryQueries(repository.getUrl())); - if (queries.size() > 0) { - if (connector != null) { - JobChangeAdapter jobAdapter = new JobChangeAdapter() { - @Override - public void done(IJobChangeEvent event) { - TasksUiPlugin.getSynchronizationManager().synchronizeChanged(connector, repository); - } - }; - TasksUiPlugin.getSynchronizationManager().synchronize(connector, queries, jobAdapter, - Job.DECORATE, 0, false, false); - } - } else { - TasksUiPlugin.getSynchronizationManager().synchronizeChanged(connector, repository); - } + RepositorySynchronizationManager synchronizationManager = TasksUiPlugin.getSynchronizationManager(); + Set<AbstractRepositoryQuery> queries = taskList.getRepositoryQueries(repository.getUrl()); + synchronizationManager.synchronize(connector, repository, queries, null, + Job.DECORATE, 0, false); + monitor.worked(1); } } finally { diff --git a/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/actions/SynchronizeSelectedAction.java b/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/actions/SynchronizeSelectedAction.java index 13c0c9d38..dd8fdbaa3 100644 --- a/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/actions/SynchronizeSelectedAction.java +++ b/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/actions/SynchronizeSelectedAction.java @@ -29,6 +29,7 @@ import org.eclipse.mylyn.tasks.core.AbstractRepositoryQuery; import org.eclipse.mylyn.tasks.core.AbstractTask; import org.eclipse.mylyn.tasks.core.TaskCategory; import org.eclipse.mylyn.tasks.core.TaskRepository; +import org.eclipse.mylyn.tasks.ui.RepositorySynchronizationManager; import org.eclipse.mylyn.tasks.ui.TasksUiPlugin; import org.eclipse.ui.IActionBars; import org.eclipse.ui.IViewActionDelegate; @@ -68,11 +69,9 @@ public class SynchronizeSelectedAction extends ActionDelegate implements IViewAc } else if (obj instanceof TaskCategory) { TaskCategory cat = (TaskCategory) obj; for (AbstractTask task : cat.getChildren()) { - if (task instanceof AbstractTask) { - AbstractRepositoryConnector client = TasksUiPlugin.getRepositoryManager() - .getRepositoryConnector(((AbstractTask) task).getRepositoryKind()); - addTaskToSync(client, (AbstractTask) task); - } + AbstractRepositoryConnector client = TasksUiPlugin.getRepositoryManager() + .getRepositoryConnector(((AbstractTask) task).getRepositoryKind()); + addTaskToSync(client, (AbstractTask) task); } } else if (obj instanceof AbstractTask) { AbstractTask repositoryTask = (AbstractTask) obj; @@ -82,41 +81,41 @@ public class SynchronizeSelectedAction extends ActionDelegate implements IViewAc } } + RepositorySynchronizationManager syncManager = TasksUiPlugin.getSynchronizationManager(); if (!queriesToSyncMap.isEmpty()) { // determine which repositories to synch changed tasks for - HashMap<String, Set<TaskRepository>> repositoriesToSync = new HashMap<String, Set<TaskRepository>>(); + HashMap<TaskRepository, Set<AbstractRepositoryQuery>> repositoriesToSync = new HashMap<TaskRepository, Set<AbstractRepositoryQuery>>(); for (AbstractRepositoryConnector connector : queriesToSyncMap.keySet()) { List<AbstractRepositoryQuery> queriesToSync = queriesToSyncMap.get(connector); + if(queriesToSync==null || queriesToSync.isEmpty()) { + continue; + } + for (AbstractRepositoryQuery query : queriesToSync) { TaskRepository repos = TasksUiPlugin.getRepositoryManager().getRepository(query.getRepositoryKind(), query.getRepositoryUrl()); - Set<TaskRepository> repositories = repositoriesToSync.get(connector.getRepositoryType()); - if(repositories == null) { - repositories = new HashSet<TaskRepository>(); - repositoriesToSync.put(connector.getRepositoryType(), repositories); + Set<AbstractRepositoryQuery> queries = repositoriesToSync.get(repos); + if(queries == null) { + queries = new HashSet<AbstractRepositoryQuery>(); + repositoriesToSync.put(repos, queries); } - repositories.add(repos); + queries.add(query); } } - // synch the queries followed by the repositories - for (AbstractRepositoryConnector connector : queriesToSyncMap.keySet()) { - List<AbstractRepositoryQuery> queriesToSync = queriesToSyncMap.get(connector); - if (queriesToSync != null && queriesToSync.size() > 0) { - TasksUiPlugin.getSynchronizationManager().synchronize(connector, new HashSet<AbstractRepositoryQuery>(queriesToSync), null, Job.LONG, 0, - false, true); - } - //XXX enable? -// for (TaskRepository taskRepository : repositoriesToSync.get(connector.getRepositoryType())) { -// TasksUiPlugin.getSynchronizationManager().synchronizeChanged(connector, taskRepository); -// } - } + for (Map.Entry<TaskRepository, Set<AbstractRepositoryQuery>> entry : repositoriesToSync.entrySet()) { + TaskRepository repository = entry.getKey(); + AbstractRepositoryConnector connector = TasksUiPlugin.getRepositoryManager() + .getRepositoryConnector(repository.getKind()); + Set<AbstractRepositoryQuery> queries = entry.getValue(); + syncManager.synchronize(connector, repository, queries, null, Job.LONG, 0L, true); + } } if (!tasksToSyncMap.isEmpty()) { for (AbstractRepositoryConnector connector : tasksToSyncMap.keySet()) { List<AbstractTask> tasksToSync = tasksToSyncMap.get(connector); if (tasksToSync != null && tasksToSync.size() > 0) { - TasksUiPlugin.getSynchronizationManager().synchronize(connector, new HashSet<AbstractTask>(tasksToSync), true, null); + syncManager.synchronize(connector, new HashSet<AbstractTask>(tasksToSync), true, null); } } } diff --git a/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/tasks/ui/RepositorySynchronizationManager.java b/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/tasks/ui/RepositorySynchronizationManager.java index abf321820..4632e8a23 100644 --- a/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/tasks/ui/RepositorySynchronizationManager.java +++ b/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/tasks/ui/RepositorySynchronizationManager.java @@ -12,17 +12,10 @@ import java.util.Collections; import java.util.HashSet; import java.util.Set; -import org.eclipse.core.runtime.CoreException; -import org.eclipse.core.runtime.IProgressMonitor; -import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.NullProgressMonitor; -import org.eclipse.core.runtime.Platform; -import org.eclipse.core.runtime.Status; -import org.eclipse.core.runtime.jobs.IJobChangeEvent; import org.eclipse.core.runtime.jobs.IJobChangeListener; import org.eclipse.core.runtime.jobs.ISchedulingRule; import org.eclipse.core.runtime.jobs.Job; -import org.eclipse.core.runtime.jobs.JobChangeAdapter; import org.eclipse.mylyn.core.MylarStatusHandler; import org.eclipse.mylyn.internal.tasks.core.TaskDataManager; import org.eclipse.mylyn.tasks.core.AbstractRepositoryConnector; @@ -103,22 +96,23 @@ public class RepositorySynchronizationManager { */ public final Job synchronize(AbstractRepositoryConnector connector, final AbstractRepositoryQuery repositoryQuery, IJobChangeListener listener, boolean forceSync) { - HashSet<AbstractRepositoryQuery> items = new HashSet<AbstractRepositoryQuery>(); - items.add(repositoryQuery); - return synchronize(connector, items, listener, Job.LONG, 0, true, forceSync); + TaskRepository repository = TasksUiPlugin.getRepositoryManager().getRepository( + repositoryQuery.getRepositoryKind(), repositoryQuery.getRepositoryUrl()); + return synchronize(connector, repository, Collections.singleton(repositoryQuery), listener, Job.LONG, 0, forceSync); } - public final Job synchronize(AbstractRepositoryConnector connector, + public final Job synchronize(AbstractRepositoryConnector connector, TaskRepository repository, final Set<AbstractRepositoryQuery> repositoryQueries, final IJobChangeListener listener, int priority, - long delay, boolean syncChangedTasks, boolean userForcedSync) { + long delay, boolean userForcedSync) { TaskList taskList = TasksUiPlugin.getTaskListManager().getTaskList(); - final SynchronizeQueryJob job = new SynchronizeQueryJob(this, connector, repositoryQueries, taskList); - job.setSynchChangedTasks(syncChangedTasks); - job.setForced(userForcedSync); for (AbstractRepositoryQuery repositoryQuery : repositoryQueries) { repositoryQuery.setCurrentlySynchronizing(true); // TasksUiPlugin.getTaskListManager().getTaskList().notifyContainerUpdated(repositoryQuery); } + + final SynchronizeQueryJob job = new SynchronizeQueryJob(connector, repository, repositoryQueries, taskList); + job.setSynchronizeChangedTasks(true); + job.setForced(userForcedSync); if (listener != null) { job.addJobChangeListener(listener); } @@ -145,70 +139,20 @@ public class RepositorySynchronizationManager { * TaskRepository.syncTime. */ public final void synchronizeChanged(final AbstractRepositoryConnector connector, final TaskRepository repository) { - if (connector.getTaskDataHandler() != null) { - final SynchronizeChangedTasksJob getChangedTasksJob = new SynchronizeChangedTasksJob(connector, repository); - getChangedTasksJob.setSystem(true); - getChangedTasksJob.setRule(new RepositoryMutexRule(repository)); - if (!forceSyncExecForTesting) { - getChangedTasksJob.schedule(); - } else { - PlatformUI.getWorkbench().getDisplay().syncExec(new Runnable() { - public void run() { - getChangedTasksJob.run(new NullProgressMonitor()); - } - }); - } + final SynchronizeChangedTasksJob synchronizeChangedTasksJob = new SynchronizeChangedTasksJob(connector, repository); + synchronizeChangedTasksJob.setSystem(true); + synchronizeChangedTasksJob.setRule(new RepositoryMutexRule(repository)); + if (!forceSyncExecForTesting) { + synchronizeChangedTasksJob.schedule(); + } else { + PlatformUI.getWorkbench().getDisplay().syncExec(new Runnable() { + public void run() { + synchronizeChangedTasksJob.run(new NullProgressMonitor()); + } + }); } } - private class SynchronizeChangedTasksJob extends Job { - - private AbstractRepositoryConnector connector; - - private TaskRepository repository; - - private Set<AbstractTask> changedTasks; - - public SynchronizeChangedTasksJob(AbstractRepositoryConnector connector, TaskRepository repository) { - super("Get Changed Tasks"); - this.connector = connector; - this.repository = repository; - } - - @Override - public IStatus run(IProgressMonitor monitor) { - TaskList taskList = TasksUiPlugin.getTaskListManager().getTaskList(); - Set<AbstractTask> repositoryTasks = Collections.unmodifiableSet(taskList - .getRepositoryTasks(repository.getUrl())); - - try { - changedTasks = connector.getChangedSinceLastSync(repository, repositoryTasks, monitor); - - if (changedTasks == null || changedTasks.size() == 0) { - return Status.OK_STATUS; - } - - synchronize(connector, changedTasks, false, new JobChangeAdapter() { - - @Override - public void done(IJobChangeEvent event) { - if (!Platform.isRunning() || TasksUiPlugin.getRepositoryManager() == null) { - return; - } - TasksUiPlugin.getRepositoryManager().setSyncTime(repository, - connector.getLastSyncTimestamp(repository, changedTasks), - TasksUiPlugin.getDefault().getRepositoriesFilePath()); - } - }); - - } catch (final CoreException e) { - // ignore, indicates working offline - // error reported in ui (tooltip and warning icon) - } - return Status.OK_STATUS; - }; - }; - /** * @param repositoryTask * task that changed diff --git a/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/tasks/ui/SynchronizeChangedTasksJob.java b/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/tasks/ui/SynchronizeChangedTasksJob.java new file mode 100644 index 000000000..2faa09b21 --- /dev/null +++ b/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/tasks/ui/SynchronizeChangedTasksJob.java @@ -0,0 +1,89 @@ +/******************************************************************************* + * 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.mylyn.tasks.ui; + +import java.util.Iterator; +import java.util.Set; + +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.core.runtime.SubProgressMonitor; +import org.eclipse.core.runtime.jobs.Job; +import org.eclipse.mylyn.core.MylarStatusHandler; +import org.eclipse.mylyn.tasks.core.AbstractRepositoryConnector; +import org.eclipse.mylyn.tasks.core.AbstractTask; +import org.eclipse.mylyn.tasks.core.TaskList; +import org.eclipse.mylyn.tasks.core.TaskRepository; + +public class SynchronizeChangedTasksJob extends Job { + + private final AbstractRepositoryConnector connector; + + private final TaskRepository repository; + + private boolean forced; + + public SynchronizeChangedTasksJob(AbstractRepositoryConnector connector, TaskRepository repository) { + super("Get Changed Tasks"); + + this.connector = connector; + this.repository = repository; + } + + /** + * Returns true, if synchronization was triggered manually and not by an automatic background job. + */ + public boolean isForced() { + return forced; + } + + /** + * Indicates a manual synchronization (User initiated). If set to true, a dialog will be displayed in case of + * errors. Any tasks with missing data will be retrieved. + */ + public void setForced(boolean forced) { + this.forced = forced; + } + + @Override + public IStatus run(IProgressMonitor monitor) { + try { + monitor.beginTask("Synchronizing changed tasks", IProgressMonitor.UNKNOWN); + + TaskList taskList = TasksUiPlugin.getTaskListManager().getTaskList(); + Set<AbstractTask> tasks = taskList.getRepositoryTasks(repository.getUrl()); + + boolean changed = connector.markStaleTasks(repository, tasks, new SubProgressMonitor(monitor, 1)); + if (!changed) { + return Status.OK_STATUS; + } + + for (Iterator<AbstractTask> it = tasks.iterator(); it.hasNext();) { + if (!it.next().isStale()) { + it.remove(); + } + } + + if (!tasks.isEmpty()) { + return Status.OK_STATUS; + } + + TasksUiPlugin.getSynchronizationManager().synchronize(connector, tasks, forced, null); + } catch (final CoreException e) { + MylarStatusHandler.log(e.getStatus()); + } finally { + monitor.done(); + } + + return Status.OK_STATUS; + }; + +} diff --git a/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/tasks/ui/SynchronizeQueryJob.java b/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/tasks/ui/SynchronizeQueryJob.java index 4783e7ba3..9bd21352a 100644 --- a/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/tasks/ui/SynchronizeQueryJob.java +++ b/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/tasks/ui/SynchronizeQueryJob.java @@ -11,24 +11,26 @@ package org.eclipse.mylyn.tasks.ui; +import java.util.Collections; import java.util.Date; import java.util.HashSet; import java.util.Set; +import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Platform; import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.SubProgressMonitor; import org.eclipse.core.runtime.jobs.Job; import org.eclipse.mylyn.core.MylarStatusHandler; import org.eclipse.mylyn.internal.tasks.ui.TasksUiImages; +import org.eclipse.mylyn.internal.tasks.ui.views.TaskListView; import org.eclipse.mylyn.monitor.core.DateUtil; import org.eclipse.mylyn.tasks.core.AbstractRepositoryConnector; import org.eclipse.mylyn.tasks.core.AbstractRepositoryQuery; import org.eclipse.mylyn.tasks.core.AbstractTask; import org.eclipse.mylyn.tasks.core.QueryHitCollector; -import org.eclipse.mylyn.tasks.core.RepositoryStatus; -import org.eclipse.mylyn.tasks.core.TaskContainerDelta; import org.eclipse.mylyn.tasks.core.TaskList; import org.eclipse.mylyn.tasks.core.TaskRepository; import org.eclipse.ui.PlatformUI; @@ -37,52 +39,48 @@ import org.eclipse.ui.progress.IProgressConstants; /** * @author Mik Kersten * @author Rob Elves + * @author Steffen Pingel */ class SynchronizeQueryJob extends Job { private final AbstractRepositoryConnector connector; - private static final String JOB_LABEL = "Synchronizing queries"; + private final TaskRepository repository; - private Set<AbstractRepositoryQuery> queries; + private final Set<AbstractRepositoryQuery> queries; - private Set<TaskRepository> repositories; + private final TaskList taskList; - private boolean synchChangedTasks; + private boolean synchronizeChangedTasks; - private TaskList taskList; + private boolean forced = false; -// private RepositorySynchronizationManager synchronizationManager; + private HashSet<AbstractTask> tasksToBeSynchronized = new HashSet<AbstractTask>(); - private boolean forced = false; + public SynchronizeQueryJob(AbstractRepositoryConnector connector, TaskRepository repository, + Set<AbstractRepositoryQuery> queries, TaskList taskList) { + super("Synchronizying queries for " + repository.getRepositoryLabel()); - public SynchronizeQueryJob(RepositorySynchronizationManager synchronizationManager, - AbstractRepositoryConnector connector, Set<AbstractRepositoryQuery> queries, TaskList taskList) { - super(JOB_LABEL + ": " + connector.getRepositoryType()); this.connector = connector; + this.repository = repository; this.queries = queries; this.taskList = taskList; - this.repositories = new HashSet<TaskRepository>(); - // TODO: remove once architecture established - // this.synchronizationManager = synchronizationManager; } - public void setSynchChangedTasks(boolean syncChangedTasks) { - this.synchChangedTasks = syncChangedTasks; + public void setSynchronizeChangedTasks(boolean synchronizeChangedTasks) { + this.synchronizeChangedTasks = synchronizeChangedTasks; } /** - * Returns true, if synchronization was triggered manually and not by an - * automatic background job. + * Returns true, if synchronization was triggered manually and not by an automatic background job. */ public boolean isForced() { return forced; } /** - * Indicates a manual synchronization (User initiated). If set to true, a - * dialog will be displayed in case of errors. Any tasks with missing data - * will be retrieved. + * Indicates a manual synchronization (User initiated). If set to true, a dialog will be displayed in case of + * errors. Any tasks with missing data will be retrieved. */ public void setForced(boolean forced) { this.forced = forced; @@ -90,72 +88,121 @@ class SynchronizeQueryJob extends Job { @Override protected IStatus run(IProgressMonitor monitor) { - monitor.beginTask(JOB_LABEL, queries.size()); - - taskList.notifyContainersUpdated(queries); - for (AbstractRepositoryQuery repositoryQuery : queries) { -// taskList.notifyContainerUpdated(repositoryQuery); - repositoryQuery.setStatus(null); - - monitor.setTaskName("Synchronizing: " + repositoryQuery.getSummary()); - setProperty(IProgressConstants.ICON_PROPERTY, TasksUiImages.REPOSITORY_SYNCHRONIZE); - TaskRepository repository = TasksUiPlugin.getRepositoryManager().getRepository( - repositoryQuery.getRepositoryKind(), repositoryQuery.getRepositoryUrl()); - if (repository == null) { - repositoryQuery.setStatus(RepositoryStatus.createNotFoundError(repositoryQuery.getRepositoryUrl(), - TasksUiPlugin.PLUGIN_ID)); - } else { - - QueryHitCollector collector = new QueryHitCollector(taskList, new TaskFactory(repository)); - SubProgressMonitor collectorMonitor = new SubProgressMonitor(monitor, 1); - collector.setProgressMonitor(collectorMonitor); - final IStatus resultingStatus = connector.performQuery(repositoryQuery, repository, collectorMonitor, - collector, forced); - - if (resultingStatus.getSeverity() == IStatus.CANCEL) { - // do nothing - } else if (resultingStatus.isOK()) { - - if (collector.getTaskHits().size() >= QueryHitCollector.MAX_HITS) { - MylarStatusHandler.log( - QueryHitCollector.MAX_HITS_REACHED + "\n" + repositoryQuery.getSummary(), this); + try { + monitor.beginTask("Synchronizing " + queries.size() + " queries", 20 + queries.size() * 10 + 40); + + Set<AbstractTask> allTasks = Collections.unmodifiableSet(taskList.getRepositoryTasks(repository.getUrl())); + + // check if the repository has changed at all and have the connector mark tasks that need synchronization + try { + monitor.subTask("Checking for changed tasks"); + boolean hasChangedOrNew = connector.markStaleTasks(repository, allTasks, + new SubProgressMonitor(monitor, 20)); + if (!hasChangedOrNew && !forced) { + for (AbstractRepositoryQuery repositoryQuery : queries) { + repositoryQuery.setStatus(null); + repositoryQuery.setCurrentlySynchronizing(false); + taskList.notifyContainersUpdated(queries); } + return Status.OK_STATUS; + } + } catch (CoreException e) { + // there is no good way of informing the user at this point, just log the error + MylarStatusHandler.log(e.getStatus()); + } - repositoryQuery.clear(); - for (AbstractTask hit : collector.getTaskHits()) { - taskList.addTask(hit, repositoryQuery); - } + // synchronize queries + int n = 0; + for (AbstractRepositoryQuery repositoryQuery : queries) { + repositoryQuery.setStatus(null); + taskList.notifyContainersUpdated(Collections.singleton(repositoryQuery)); - if (synchChangedTasks) { - repositories.add(repository); - } + monitor.setTaskName("Synchronizing " + ++n + "/" + queries.size() + ": " + repositoryQuery.getSummary()); + synchronizeQuery(repositoryQuery, new SubProgressMonitor(monitor, 10)); - repositoryQuery.setLastRefreshTimeStamp(DateUtil.getFormattedDate(new Date(), "MMM d, H:mm:ss")); - } else { - repositoryQuery.setStatus(resultingStatus); - if (isForced()) { - PlatformUI.getWorkbench().getDisplay().asyncExec(new Runnable() { - public void run() { - MylarStatusHandler.displayStatus("Query Synchronization Failed", resultingStatus); - } - }); + repositoryQuery.setCurrentlySynchronizing(false); + taskList.notifyContainersUpdated(Collections.singleton(repositoryQuery)); + } + + // for background synchronizations all changed tasks are synchronized including the ones that are not part of a query + if (forced) { + for (AbstractTask task : allTasks) { + if (task.isStale()) { + tasksToBeSynchronized.add(task); + task.setCurrentlySynchronizing(true); } } } - repositoryQuery.setCurrentlySynchronizing(false); - taskList.notifyContainersUpdated(queries); -// taskList.notifyContainerUpdated(repositoryQuery); - } + // synchronize tasks that were marked by the connector + if (!tasksToBeSynchronized.isEmpty()) { + monitor.setTaskName("Synchronizing " + tasksToBeSynchronized.size() + " changed tasks"); + SynchronizeTaskJob job = new SynchronizeTaskJob(connector, tasksToBeSynchronized); + job.setForced(forced); + job.run(new SubProgressMonitor(monitor, 40)); + + if (Platform.isRunning() && !(TasksUiPlugin.getRepositoryManager() == null)) { + TasksUiPlugin.getRepositoryManager().setSyncTime(repository, + connector.getSynchronizationTimestamp(repository, tasksToBeSynchronized), + TasksUiPlugin.getDefault().getRepositoriesFilePath()); + } + } + + + taskList.notifyContainersUpdated(null); - for (TaskRepository repository : repositories) { - TasksUiPlugin.getSynchronizationManager().synchronizeChanged(connector, repository); +// // HACK: force entire Task List to refresh in case containers need to +// // appear or disappear +// PlatformUI.getWorkbench().getDisplay().syncExec(new Runnable() { +// public void run() { +// TaskListView view = TaskListView.getFromActivePerspective(); +// if (view != null) { +// // TODO: remove explicit refresh +// view.getViewer().refresh(); +// } +// } +// }); + + return Status.OK_STATUS; + } finally { + monitor.done(); } - taskList.notifyContainersUpdated(null); + } + + private void synchronizeQuery(AbstractRepositoryQuery repositoryQuery, IProgressMonitor monitor) { + setProperty(IProgressConstants.ICON_PROPERTY, TasksUiImages.REPOSITORY_SYNCHRONIZE); + + QueryHitCollector collector = new QueryHitCollector(taskList, new TaskFactory(repository)); + + final IStatus resultingStatus = connector.performQuery(repositoryQuery, repository, monitor, collector); + if (resultingStatus.getSeverity() == IStatus.CANCEL) { + // do nothing + } else if (resultingStatus.isOK()) { + if (collector.getTaskHits().size() >= QueryHitCollector.MAX_HITS) { + MylarStatusHandler.log(QueryHitCollector.MAX_HITS_REACHED + "\n" + repositoryQuery.getSummary(), this); + } - monitor.done(); + repositoryQuery.clear(); - return Status.OK_STATUS; + for (AbstractTask hit : collector.getTaskHits()) { + taskList.addTask(hit, repositoryQuery); + if (synchronizeChangedTasks && hit.isStale()) { + tasksToBeSynchronized.add(hit); + hit.setCurrentlySynchronizing(true); + } + } + + repositoryQuery.setLastRefreshTimeStamp(DateUtil.getFormattedDate(new Date(), "MMM d, H:mm:ss")); + } else { + repositoryQuery.setStatus(resultingStatus); + if (isForced()) { + PlatformUI.getWorkbench().getDisplay().asyncExec(new Runnable() { + public void run() { + MylarStatusHandler.displayStatus("Query Synchronization Failed", resultingStatus); + } + }); + } + } } }
\ No newline at end of file diff --git a/org.eclipse.mylyn.trac.core/src/org/eclipse/mylyn/internal/trac/core/TracRepositoryConnector.java b/org.eclipse.mylyn.trac.core/src/org/eclipse/mylyn/internal/trac/core/TracRepositoryConnector.java index 199ed9deb..96eeb70a8 100644 --- a/org.eclipse.mylyn.trac.core/src/org/eclipse/mylyn/internal/trac/core/TracRepositoryConnector.java +++ b/org.eclipse.mylyn.trac.core/src/org/eclipse/mylyn/internal/trac/core/TracRepositoryConnector.java @@ -13,9 +13,7 @@ package org.eclipse.mylyn.internal.trac.core; import java.io.File; import java.util.ArrayList; -import java.util.Collections; import java.util.Date; -import java.util.HashSet; import java.util.List; import java.util.Set; @@ -33,8 +31,8 @@ import org.eclipse.mylyn.tasks.core.AbstractRepositoryConnector; import org.eclipse.mylyn.tasks.core.AbstractRepositoryQuery; import org.eclipse.mylyn.tasks.core.AbstractTask; import org.eclipse.mylyn.tasks.core.IAttachmentHandler; +import org.eclipse.mylyn.tasks.core.ITaskCollector; import org.eclipse.mylyn.tasks.core.ITaskDataHandler; -import org.eclipse.mylyn.tasks.core.QueryHitCollector; import org.eclipse.mylyn.tasks.core.RepositoryOperation; import org.eclipse.mylyn.tasks.core.RepositoryStatus; import org.eclipse.mylyn.tasks.core.RepositoryTaskAttribute; @@ -126,7 +124,7 @@ public class TracRepositoryConnector extends AbstractRepositoryConnector { @Override public IStatus performQuery(AbstractRepositoryQuery query, TaskRepository repository, IProgressMonitor monitor, - QueryHitCollector resultCollector, boolean force) { + ITaskCollector resultCollector) { final List<TracTicket> tickets = new ArrayList<TracTicket>(); @@ -150,41 +148,51 @@ public class TracRepositoryConnector extends AbstractRepositoryConnector { } @Override - public Set<AbstractTask> getChangedSinceLastSync(TaskRepository repository, + public boolean markStaleTasks(TaskRepository repository, Set<AbstractTask> tasks, IProgressMonitor monitor) throws CoreException { - if (repository.getSyncTimeStamp() == null) { - return tasks; - } + try { + monitor.beginTask("Getting changed tasks", IProgressMonitor.UNKNOWN); + + if (!TracRepositoryConnector.hasChangedSince(repository)) { + // always run the queries for web mode + return true; + } - if (!TracRepositoryConnector.hasChangedSince(repository)) { - // return an empty list to avoid causing all tasks to synchronized - return Collections.emptySet(); - } + if (repository.getSyncTimeStamp() == null) { + for (AbstractTask task : tasks) { + task.setStale(true); + } + return true; + } - Date since = new Date(0); - try { - since = TracUtils.parseDate(Integer.parseInt(repository.getSyncTimeStamp())); - } catch (NumberFormatException e) { - } + Date since = new Date(0); + try { + since = TracUtils.parseDate(Integer.parseInt(repository.getSyncTimeStamp())); + } catch (NumberFormatException e) { + } - ITracClient client; - try { - client = getClientManager().getRepository(repository); - Set<Integer> ids = client.getChangedTickets(since); + try { + ITracClient client = getClientManager().getRepository(repository); + Set<Integer> ids = client.getChangedTickets(since); + if (ids.isEmpty()) { + // repository is unchanged + return false; + } - Set<AbstractTask> result = new HashSet<AbstractTask>(); - if (!ids.isEmpty()) { for (AbstractTask task : tasks) { Integer id = getTicketId(task.getTaskId()); if (ids.contains(id)) { - result.add(task); + task.setStale(true); } } + + return true; + } catch (Exception e) { + throw new CoreException(new Status(IStatus.ERROR, TracCorePlugin.PLUGIN_ID, IStatus.OK, + "Could not determine changed tasks", e)); } - return result; - } catch (Exception e) { - throw new CoreException(new Status(IStatus.ERROR, TracCorePlugin.PLUGIN_ID, IStatus.OK, - "could not determine changed tasks", e)); + } finally { + monitor.done(); } } diff --git a/org.eclipse.mylyn.trac.tests/src/org/eclipse/mylyn/trac/tests/RepositorySearchQueryTest.java b/org.eclipse.mylyn.trac.tests/src/org/eclipse/mylyn/trac/tests/RepositorySearchQueryTest.java index af318c588..7ccd00c14 100644 --- a/org.eclipse.mylyn.trac.tests/src/org/eclipse/mylyn/trac/tests/RepositorySearchQueryTest.java +++ b/org.eclipse.mylyn.trac.tests/src/org/eclipse/mylyn/trac/tests/RepositorySearchQueryTest.java @@ -78,7 +78,7 @@ public class RepositorySearchQueryTest extends TestCase { String queryUrl = repository.getUrl() + ITracClient.QUERY_URL + search.toUrl(); TracRepositoryQuery query = new TracRepositoryQuery(repository.getUrl(), queryUrl, "description"); SearchHitCollector collector = new SearchHitCollector(TasksUiPlugin.getTaskListManager() - .getTaskList(), repository, query, new TaskFactory(repository)); + .getTaskList(), repository, query, new TaskFactory(repository, false, false)); collector.run(new NullProgressMonitor()); for (AbstractTask task : collector.getTaskHits()) { diff --git a/org.eclipse.mylyn.trac.tests/src/org/eclipse/mylyn/trac/tests/TracRepositoryConnectorTest.java b/org.eclipse.mylyn.trac.tests/src/org/eclipse/mylyn/trac/tests/TracRepositoryConnectorTest.java index 00cf18b9e..b11bf9c0d 100644 --- a/org.eclipse.mylyn.trac.tests/src/org/eclipse/mylyn/trac/tests/TracRepositoryConnectorTest.java +++ b/org.eclipse.mylyn.trac.tests/src/org/eclipse/mylyn/trac/tests/TracRepositoryConnectorTest.java @@ -217,7 +217,7 @@ public class TracRepositoryConnectorTest extends TestCase { public void accept(AbstractTask hit) { result.add(hit); }}; - IStatus queryStatus = connector.performQuery(query, repository, new NullProgressMonitor(), hitCollector, false); + IStatus queryStatus = connector.performQuery(query, repository, new NullProgressMonitor(), hitCollector); assertTrue(queryStatus.isOK()); assertEquals(3, result.size()); diff --git a/org.eclipse.mylyn.trac.tests/src/org/eclipse/mylyn/trac/tests/TracTaskDataHandlerTest.java b/org.eclipse.mylyn.trac.tests/src/org/eclipse/mylyn/trac/tests/TracTaskDataHandlerTest.java index 5d238227e..bc8c00c19 100644 --- a/org.eclipse.mylyn.trac.tests/src/org/eclipse/mylyn/trac/tests/TracTaskDataHandlerTest.java +++ b/org.eclipse.mylyn.trac.tests/src/org/eclipse/mylyn/trac/tests/TracTaskDataHandlerTest.java @@ -79,19 +79,23 @@ public class TracTaskDataHandlerTest extends TestCase { public void testGetChangedSinceLastSyncWeb096() throws Exception { init(TracTestConstants.TEST_TRAC_096_URL, Version.TRAC_0_9); - TracTask task = (TracTask) connector.createTaskFromExistingId(repository, data.offlineHandlerTicketId + "", new NullProgressMonitor()); + TracTask task = (TracTask) connector.createTaskFromExistingId(repository, data.offlineHandlerTicketId + "", + new NullProgressMonitor()); Set<AbstractTask> tasks = new HashSet<AbstractTask>(); tasks.add(task); - + assertEquals(null, repository.getSyncTimeStamp()); - Set<AbstractTask> result = connector.getChangedSinceLastSync(repository, tasks, new NullProgressMonitor()); - assertEquals(tasks, result); + boolean changed = connector.markStaleTasks(repository, tasks, new NullProgressMonitor()); + assertEquals(true, changed); assertEquals(null, repository.getSyncTimeStamp()); - - int time = (int)(System.currentTimeMillis() / 1000) + 1; + assertFalse(task.isStale()); + + int time = (int) (System.currentTimeMillis() / 1000) + 1; repository.setSyncTimeStamp(time + ""); - assertEquals(tasks, result); + changed = connector.markStaleTasks(repository, tasks, new NullProgressMonitor()); + assertEquals(true, changed); + assertFalse(task.isStale()); } public void testGetChangedSinceLastSyncXmlRpc010() throws Exception { @@ -105,28 +109,35 @@ public class TracTaskDataHandlerTest extends TestCase { } private void getChangedSinceLastSync() throws Exception { - TracTask task = (TracTask) connector.createTaskFromExistingId(repository, data.offlineHandlerTicketId + "", new NullProgressMonitor()); + TracTask task = (TracTask) connector.createTaskFromExistingId(repository, data.offlineHandlerTicketId + "", + new NullProgressMonitor()); TasksUiPlugin.getSynchronizationManager().synchronize(connector, task, true, null); - RepositoryTaskData taskData = TasksUiPlugin.getDefault().getTaskDataManager().getNewTaskData(task.getHandleIdentifier()); - + RepositoryTaskData taskData = TasksUiPlugin.getDefault().getTaskDataManager().getNewTaskData( + task.getHandleIdentifier()); + int lastModified = Integer.parseInt(taskData.getLastModified()); - + Set<AbstractTask> tasks = new HashSet<AbstractTask>(); tasks.add(task); assertEquals(null, repository.getSyncTimeStamp()); - Set<AbstractTask> result = connector.getChangedSinceLastSync(repository, tasks, new NullProgressMonitor()); - assertEquals(tasks, result); + boolean changed = connector.markStaleTasks(repository, tasks, new NullProgressMonitor()); + assertTrue(changed); + assertTrue(task.isStale()); // always returns the ticket because time comparison mode is >= + task.setStale(false); repository.setSyncTimeStamp(lastModified + ""); - result = connector.getChangedSinceLastSync(repository, tasks, new NullProgressMonitor()); - assertEquals(tasks, result); + changed = connector.markStaleTasks(repository, tasks, new NullProgressMonitor()); + assertTrue(changed); + assertTrue(task.isStale()); + task.setStale(false); repository.setSyncTimeStamp((lastModified + 1) + ""); - result = connector.getChangedSinceLastSync(repository, tasks, new NullProgressMonitor()); - assertTrue(result.isEmpty()); - + changed = connector.markStaleTasks(repository, tasks, new NullProgressMonitor()); + assertTrue(changed); + assertFalse(task.isStale()); + // change ticket making sure it gets a new change time Thread.sleep(1000); ITracClient client = connector.getClientManager().getRepository(repository); @@ -138,11 +149,13 @@ public class TracTaskDataHandlerTest extends TestCase { } client.updateTicket(ticket, "comment"); + task.setStale(false); repository.setSyncTimeStamp((lastModified + 1) + ""); - result = connector.getChangedSinceLastSync(repository, tasks, new NullProgressMonitor()); - assertEquals(tasks, result); + changed = connector.markStaleTasks(repository, tasks, new NullProgressMonitor()); + assertTrue(changed); + assertTrue(task.isStale()); } - + public void testNonNumericTaskId() { try { connector.getTaskDataHandler().getTaskData(repository, "abc", new NullProgressMonitor()); @@ -150,6 +163,5 @@ public class TracTaskDataHandlerTest extends TestCase { } catch (CoreException e) { } } - } diff --git a/org.eclipse.mylyn.trac.ui/src/org/eclipse/mylyn/internal/trac/ui/editor/NewTracTaskEditor.java b/org.eclipse.mylyn.trac.ui/src/org/eclipse/mylyn/internal/trac/ui/editor/NewTracTaskEditor.java index 7d81e0c33..6d3a7bacb 100644 --- a/org.eclipse.mylyn.trac.ui/src/org/eclipse/mylyn/internal/trac/ui/editor/NewTracTaskEditor.java +++ b/org.eclipse.mylyn.trac.ui/src/org/eclipse/mylyn/internal/trac/ui/editor/NewTracTaskEditor.java @@ -49,7 +49,7 @@ public class NewTracTaskEditor extends AbstractNewRepositoryTaskEditor { TracRepositoryQuery query = new TracRepositoryQuery(repository.getUrl(), sb.toString(), "<Duplicate Search>"); SearchHitCollector collector = new SearchHitCollector(TasksUiPlugin.getTaskListManager().getTaskList(), - repository, query, new TaskFactory(repository)); + repository, query, new TaskFactory(repository, false, false)); return collector; } |