Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormkersten2006-06-21 03:40:36 +0000
committermkersten2006-06-21 03:40:36 +0000
commit9f89ae63642d902b398c51592c2e4b677a9ccc2a (patch)
tree7899811224fddbcfa1e8625cc7f3f7cdaf265927
parent7835063ee03b994b1b68aa552ec418ef25c64152 (diff)
downloadorg.eclipse.mylyn.tasks-9f89ae63642d902b398c51592c2e4b677a9ccc2a.tar.gz
org.eclipse.mylyn.tasks-9f89ae63642d902b398c51592c2e4b677a9ccc2a.tar.xz
org.eclipse.mylyn.tasks-9f89ae63642d902b398c51592c2e4b677a9ccc2a.zip
Progress on: 147816: Trac connector: implement core and model
https://bugs.eclipse.org/bugs/show_bug.cgi?id=147816
-rw-r--r--org.eclipse.mylyn.trac.tests/.classpath6
-rw-r--r--org.eclipse.mylyn.trac.tests/META-INF/MANIFEST.MF3
-rw-r--r--org.eclipse.mylyn.trac.tests/src/org/eclipse/mylyn/trac/tests/AllTracTests.java3
-rw-r--r--org.eclipse.mylyn.trac.tests/src/org/eclipse/mylyn/trac/tests/TracSearchTest.java133
-rw-r--r--org.eclipse.mylyn.trac.tests/src/org/eclipse/mylyn/trac/tests/TracTicketTest.java73
-rw-r--r--org.eclipse.mylyn.trac.ui/META-INF/MANIFEST.MF6
-rw-r--r--org.eclipse.mylyn.trac.ui/src/org/eclipse/mylyn/internal/trac/core/ITracRepository.java99
-rw-r--r--org.eclipse.mylyn.trac.ui/src/org/eclipse/mylyn/internal/trac/core/InvalidTicketException.java30
-rw-r--r--org.eclipse.mylyn.trac.ui/src/org/eclipse/mylyn/internal/trac/core/TracException.java38
-rw-r--r--org.eclipse.mylyn.trac.ui/src/org/eclipse/mylyn/internal/trac/core/TracLoginException.java30
-rw-r--r--org.eclipse.mylyn.trac.ui/src/org/eclipse/mylyn/internal/trac/model/TracSearch.java141
-rw-r--r--org.eclipse.mylyn.trac.ui/src/org/eclipse/mylyn/internal/trac/model/TracSearchFilter.java108
-rw-r--r--org.eclipse.mylyn.trac.ui/src/org/eclipse/mylyn/internal/trac/model/TracTicket.java169
13 files changed, 832 insertions, 7 deletions
diff --git a/org.eclipse.mylyn.trac.tests/.classpath b/org.eclipse.mylyn.trac.tests/.classpath
index 1c64a6d3f..751c8f2e5 100644
--- a/org.eclipse.mylyn.trac.tests/.classpath
+++ b/org.eclipse.mylyn.trac.tests/.classpath
@@ -1,11 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src"/>
- <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER">
- <accessrules>
- <accessrule kind="nonaccessible" pattern="com/sun/**"/>
- </accessrules>
- </classpathentry>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
<classpathentry kind="output" path="bin"/>
</classpath>
diff --git a/org.eclipse.mylyn.trac.tests/META-INF/MANIFEST.MF b/org.eclipse.mylyn.trac.tests/META-INF/MANIFEST.MF
index fa97ad28f..a0170f9ad 100644
--- a/org.eclipse.mylyn.trac.tests/META-INF/MANIFEST.MF
+++ b/org.eclipse.mylyn.trac.tests/META-INF/MANIFEST.MF
@@ -5,5 +5,6 @@ Bundle-SymbolicName: org.eclipse.mylar.trac.tests
Bundle-Version: 0.0.0
Bundle-Localization: plugin
Require-Bundle: org.junit,
- org.apache.xmlrpc
+ org.apache.xmlrpc,
+ org.eclipse.mylar.trac
Export-Package: org.eclipse.mylar.trac.tests
diff --git a/org.eclipse.mylyn.trac.tests/src/org/eclipse/mylyn/trac/tests/AllTracTests.java b/org.eclipse.mylyn.trac.tests/src/org/eclipse/mylyn/trac/tests/AllTracTests.java
index 4e193f669..ddd9fbbda 100644
--- a/org.eclipse.mylyn.trac.tests/src/org/eclipse/mylyn/trac/tests/AllTracTests.java
+++ b/org.eclipse.mylyn.trac.tests/src/org/eclipse/mylyn/trac/tests/AllTracTests.java
@@ -16,6 +16,7 @@ import junit.framework.TestSuite;
/**
* @author Mik Kersten
+ * @author Steffen Pingel
*/
public class AllTracTests {
@@ -23,6 +24,8 @@ public class AllTracTests {
TestSuite suite = new TestSuite("Test for org.eclipse.mylar.trac.tests");
//$JUnit-BEGIN$
suite.addTestSuite(TracXmlRpcTest.class);
+ suite.addTestSuite(TracSearchTest.class);
+ suite.addTestSuite(TracTicketTest.class);
//$JUnit-END$
return suite;
}
diff --git a/org.eclipse.mylyn.trac.tests/src/org/eclipse/mylyn/trac/tests/TracSearchTest.java b/org.eclipse.mylyn.trac.tests/src/org/eclipse/mylyn/trac/tests/TracSearchTest.java
new file mode 100644
index 000000000..19562c955
--- /dev/null
+++ b/org.eclipse.mylyn.trac.tests/src/org/eclipse/mylyn/trac/tests/TracSearchTest.java
@@ -0,0 +1,133 @@
+/*******************************************************************************
+ * Copyright (c) 2006 - 2006 Mylar eclipse.org project 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:
+ * Mylar project committers - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.mylar.trac.tests;
+
+import junit.framework.TestCase;
+
+import org.eclipse.mylar.internal.trac.model.TracSearch;
+
+/**
+ * @author Steffen Pingel
+ */
+public class TracSearchTest extends TestCase {
+
+ private static final String QUERY1 = "&status=new|assigned|reopened&milestone~=0.1";
+
+ private static final String URL1 = "&status=new&status=assigned&status=reopened&milestone=%7E0.1";
+
+ private TracSearch search1;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ search1 = new TracSearch();
+ search1.addFilter("status", "new");
+ search1.addFilter("status", "assigned");
+ search1.addFilter("status", "reopened");
+ search1.addFilter("milestone", "~0.1");
+ }
+
+ public void testToQuery() {
+ assertEquals(QUERY1, search1.toQuery());
+ }
+
+ public void testToQueryEmpty() {
+ assertEquals("", new TracSearch().toQuery());
+ }
+
+ public void testToQueryOperators1() {
+ TracSearch search = new TracSearch();
+ search.addFilter("is", "a");
+ search.addFilter("contains", "~b");
+ search.addFilter("starts", "^c");
+ search.addFilter("ends", "$d");
+ search.addFilter("nis", "!e");
+ search.addFilter("ncontains", "!~f");
+ search.addFilter("nstarts", "!^g");
+ search.addFilter("nends", "!$h");
+
+ assertEquals("&is=a&contains~=b&starts^=c&ends$=d&nis!=e&ncontains!~=f&nstarts!^=g&nends!$=h", search.toQuery());
+ }
+
+ public void testToQueryOperators2() {
+ TracSearch search = new TracSearch();
+ search.addFilter("nstarts", "!^g");
+ search.addFilter("nis", "!e");
+ search.addFilter("is", "a");
+
+ assertEquals("&nstarts!^=g&nis!=e&is=a", search.toQuery());
+ }
+
+ public void testToQuerySortOrder() {
+ search1.setOrderBy("id");
+ assertEquals("&order=id" + QUERY1, search1.toQuery());
+
+ search1.setAscending(false);
+ assertEquals("&order=id&desc=1" + QUERY1, search1.toQuery());
+
+ search1.setOrderBy("summary");
+ search1.setAscending(true);
+ assertEquals("&order=summary" + QUERY1, search1.toQuery());
+ }
+
+ public void testToUrl() {
+ assertEquals(URL1, search1.toUrl());
+ }
+
+ public void testToUrlEmpty() {
+ assertEquals("", new TracSearch().toUrl());
+ }
+
+ public void testToUrlEncoding() {
+ search1.addFilter("encoded", "&");
+ assertEquals(URL1 + "&encoded=%26", search1.toUrl());
+ }
+
+ public void testToUrlOperators1() {
+ TracSearch search = new TracSearch();
+ search.addFilter("is", "a");
+ search.addFilter("contains", "~b");
+ search.addFilter("starts", "^c");
+ search.addFilter("ends", "$d");
+ search.addFilter("nis", "!e");
+ search.addFilter("ncontains", "!~f");
+ search.addFilter("nstarts", "!^g");
+ search.addFilter("nends", "!$h");
+
+ assertEquals(
+ "&is=a&contains=%7Eb&starts=%5Ec&ends=%24d&nis=%21e&ncontains=%21%7Ef&nstarts=%21%5Eg&nends=%21%24h",
+ search.toUrl());
+ }
+
+ public void testToUrlOperators2() {
+ TracSearch search = new TracSearch();
+ search.addFilter("nstarts", "!^g");
+ search.addFilter("nis", "!e");
+ search.addFilter("is", "a");
+
+ assertEquals("&nstarts=%21%5Eg&nis=%21e&is=a", search.toUrl());
+ }
+
+ public void testToUrlSortOrder() {
+ search1.setOrderBy("id");
+ assertEquals("&order=id" + QUERY1, search1.toQuery());
+
+ search1.setAscending(false);
+ assertEquals("&order=id&desc=1" + QUERY1, search1.toQuery());
+
+ search1.setOrderBy("summary");
+ search1.setAscending(true);
+ assertEquals("&order=summary" + QUERY1, search1.toQuery());
+ }
+
+}
diff --git a/org.eclipse.mylyn.trac.tests/src/org/eclipse/mylyn/trac/tests/TracTicketTest.java b/org.eclipse.mylyn.trac.tests/src/org/eclipse/mylyn/trac/tests/TracTicketTest.java
new file mode 100644
index 000000000..395d81c6a
--- /dev/null
+++ b/org.eclipse.mylyn.trac.tests/src/org/eclipse/mylyn/trac/tests/TracTicketTest.java
@@ -0,0 +1,73 @@
+/*******************************************************************************
+ * Copyright (c) 2006 - 2006 Mylar eclipse.org project 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:
+ * Mylar project committers - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.mylar.trac.tests;
+
+import java.util.Calendar;
+import java.util.Date;
+import java.util.TimeZone;
+
+import org.eclipse.mylar.internal.trac.core.InvalidTicketException;
+import org.eclipse.mylar.internal.trac.model.TracTicket;
+import org.eclipse.mylar.internal.trac.model.TracTicket.Key;
+
+import junit.framework.TestCase;
+
+/**
+ * @author Steffen Pingel
+ */
+public class TracTicketTest extends TestCase {
+
+ public void testValid() {
+ TracTicket ticket = new TracTicket();
+ assertFalse(ticket.isValid());
+
+ ticket.setId(1);
+ assertTrue(ticket.isValid());
+ }
+
+ public void testPutTracValue() throws InvalidTicketException {
+ TracTicket ticket = new TracTicket(1);
+ ticket.putTracValue("summary", "a");
+ assertEquals("a", ticket.getValue(Key.SUMMARY));
+ assertEquals(null, ticket.getCustomValue("summary"));
+ assertEquals(null, ticket.getCustomValue("a"));
+
+ ticket.putTracValue("summary", "b");
+ ticket.putTracValue("custom", "c");
+ assertEquals("b", ticket.getValue(Key.SUMMARY));
+ assertEquals(null, ticket.getCustomValue("summary"));
+ assertEquals("c", ticket.getCustomValue("custom"));
+ }
+
+ public void testPutTracValueId() throws InvalidTicketException {
+ TracTicket ticket = new TracTicket();
+ try {
+ ticket.putTracValue("id", "1");
+ fail("Expected RuntimeException");
+ } catch (RuntimeException e) {
+ }
+ }
+
+ public void testSetCreated() throws InvalidTicketException {
+ TracTicket ticket = new TracTicket(1);
+ ticket.setCreated(0);
+ assertEquals(TimeZone.getTimeZone("GMT").getOffset(0) * 1000, ticket.getCreated().getTime());
+
+ Date date = new Date();
+ Calendar utc = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
+ utc.setTime(date);
+ ticket.setCreated((int) (utc.getTimeInMillis() / 1000));
+
+ assertEquals(date.getTime() / 1000, ticket.getCreated().getTime() / 1000);
+ }
+
+}
diff --git a/org.eclipse.mylyn.trac.ui/META-INF/MANIFEST.MF b/org.eclipse.mylyn.trac.ui/META-INF/MANIFEST.MF
index 7c7d64f77..9734f2f89 100644
--- a/org.eclipse.mylyn.trac.ui/META-INF/MANIFEST.MF
+++ b/org.eclipse.mylyn.trac.ui/META-INF/MANIFEST.MF
@@ -7,5 +7,9 @@ Bundle-Activator: org.eclipse.mylar.internal.trac.MylarTracPlugin
Bundle-Vendor: Eclipse.org
Bundle-Localization: plugin
Require-Bundle: org.eclipse.ui,
- org.eclipse.core.runtime
+ org.eclipse.core.runtime,
+ org.eclipse.mylar.core
Eclipse-LazyStart: true
+Export-Package: org.eclipse.mylar.internal.trac,
+ org.eclipse.mylar.internal.trac.core,
+ org.eclipse.mylar.internal.trac.model
diff --git a/org.eclipse.mylyn.trac.ui/src/org/eclipse/mylyn/internal/trac/core/ITracRepository.java b/org.eclipse.mylyn.trac.ui/src/org/eclipse/mylyn/internal/trac/core/ITracRepository.java
new file mode 100644
index 000000000..7f9011c5c
--- /dev/null
+++ b/org.eclipse.mylyn.trac.ui/src/org/eclipse/mylyn/internal/trac/core/ITracRepository.java
@@ -0,0 +1,99 @@
+/*******************************************************************************
+ * Copyright (c) 2006 - 2006 Mylar eclipse.org project 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:
+ * Mylar project committers - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.mylar.internal.trac.core;
+
+import java.util.List;
+
+import org.eclipse.mylar.internal.trac.model.TracSearch;
+import org.eclipse.mylar.internal.trac.model.TracTicket;
+
+/**
+ * Defines the requirements for classes that provide remote access to Trac
+ * repositories.
+ *
+ * @author Steffen Pingel
+ */
+public interface ITracRepository {
+
+ public enum Version {
+ TRAC_0_9, XML_RPC;
+
+ public static Version fromVersion(String version) {
+ try {
+ return Version.valueOf(version);
+ } catch (IllegalArgumentException e) {
+ return null;
+ }
+ }
+
+ @Override
+ public String toString() {
+ switch (this) {
+ case TRAC_0_9:
+ return "Trac 0.9 and higher";
+ case XML_RPC:
+ return "XML-RPC Plugin (Rev. 826)";
+ default:
+ return null;
+ }
+ }
+
+ }
+
+ public static final String CHARSET = "UTF-8";
+
+ public static final String TIME_ZONE = "UTC";
+
+ public static final String LOGIN_URL = "/login";
+
+ public static final String QUERY_URL = "/query?format=tab";
+
+ public static final String TICKET_URL = "/ticket/";
+
+ /**
+ * Gets ticket with <code>id</code> from repository.
+ *
+ * @param id
+ * the id of the ticket to get
+ * @return the ticket
+ * @throws TracException
+ * thrown in case of a connection error
+ */
+ TracTicket getTicket(int id) throws TracException;
+
+ /**
+ * Returns the access type.
+ */
+ Version getVersion();
+
+ /**
+ * Queries tickets from repository. All found tickets are added to
+ * <code>result</code>.
+ *
+ * @param query
+ * the search criteria
+ * @param result
+ * the list of found tickets
+ * @throws TracException
+ * thrown in case of a connection error
+ */
+ void search(TracSearch query, List<TracTicket> result) throws TracException;
+
+ /**
+ * Validates the repository connection.
+ *
+ * @throws TracException
+ * thrown in case of a connection error
+ */
+ void validate() throws TracException;
+
+}
diff --git a/org.eclipse.mylyn.trac.ui/src/org/eclipse/mylyn/internal/trac/core/InvalidTicketException.java b/org.eclipse.mylyn.trac.ui/src/org/eclipse/mylyn/internal/trac/core/InvalidTicketException.java
new file mode 100644
index 000000000..f5102eaa9
--- /dev/null
+++ b/org.eclipse.mylyn.trac.ui/src/org/eclipse/mylyn/internal/trac/core/InvalidTicketException.java
@@ -0,0 +1,30 @@
+/*******************************************************************************
+ * Copyright (c) 2006 - 2006 Mylar eclipse.org project 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:
+ * Mylar project committers - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.mylar.internal.trac.core;
+
+/**
+ * Indicates an error while parsing a ticket retrieved from a repository.
+ *
+ * @author Steffen Pingel
+ */
+public class InvalidTicketException extends TracException {
+
+ private static final long serialVersionUID = 7716941243394876876L;
+
+ public InvalidTicketException(String message) {
+ super(message);
+ }
+
+ public InvalidTicketException() {
+ }
+
+}
diff --git a/org.eclipse.mylyn.trac.ui/src/org/eclipse/mylyn/internal/trac/core/TracException.java b/org.eclipse.mylyn.trac.ui/src/org/eclipse/mylyn/internal/trac/core/TracException.java
new file mode 100644
index 000000000..f38b02a4a
--- /dev/null
+++ b/org.eclipse.mylyn.trac.ui/src/org/eclipse/mylyn/internal/trac/core/TracException.java
@@ -0,0 +1,38 @@
+/*******************************************************************************
+ * Copyright (c) 2006 - 2006 Mylar eclipse.org project 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:
+ * Mylar project committers - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.mylar.internal.trac.core;
+
+/**
+ * Indicates an error during repository access.
+ *
+ * @author Steffen Pingel
+ */
+public class TracException extends Exception {
+
+ private static final long serialVersionUID = 1929614326467463462L;
+
+ public TracException() {
+ }
+
+ public TracException(String message) {
+ super(message);
+ }
+
+ public TracException(Throwable cause) {
+ super(cause);
+ }
+
+ public TracException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+}
diff --git a/org.eclipse.mylyn.trac.ui/src/org/eclipse/mylyn/internal/trac/core/TracLoginException.java b/org.eclipse.mylyn.trac.ui/src/org/eclipse/mylyn/internal/trac/core/TracLoginException.java
new file mode 100644
index 000000000..d50aff94b
--- /dev/null
+++ b/org.eclipse.mylyn.trac.ui/src/org/eclipse/mylyn/internal/trac/core/TracLoginException.java
@@ -0,0 +1,30 @@
+/*******************************************************************************
+ * Copyright (c) 2006 - 2006 Mylar eclipse.org project 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:
+ * Mylar project committers - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.mylar.internal.trac.core;
+
+/**
+ * Indicates an authentication error during login.
+ *
+ * @author Steffen Pingel
+ */
+public class TracLoginException extends TracException {
+
+ private static final long serialVersionUID = -6128773690643367414L;
+
+ public TracLoginException() {
+ }
+
+ public TracLoginException(String message) {
+ super(message);
+ }
+
+}
diff --git a/org.eclipse.mylyn.trac.ui/src/org/eclipse/mylyn/internal/trac/model/TracSearch.java b/org.eclipse.mylyn.trac.ui/src/org/eclipse/mylyn/internal/trac/model/TracSearch.java
new file mode 100644
index 000000000..014584d48
--- /dev/null
+++ b/org.eclipse.mylyn.trac.ui/src/org/eclipse/mylyn/internal/trac/model/TracSearch.java
@@ -0,0 +1,141 @@
+/*******************************************************************************
+ * Copyright (c) 2006 - 2006 Mylar eclipse.org project 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:
+ * Mylar project committers - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.mylar.internal.trac.model;
+
+import java.io.UnsupportedEncodingException;
+import java.net.URLEncoder;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.mylar.internal.core.util.MylarStatusHandler;
+import org.eclipse.mylar.internal.trac.core.ITracRepository;
+import org.eclipse.mylar.internal.trac.model.TracSearchFilter.CompareOperator;
+
+/**
+ * Represents a Trac search. A search can have multiple {@link TracSearchFilter}s
+ * that all need to match.
+ *
+ * @author Steffen Pingel
+ */
+public class TracSearch {
+
+ /** Stores search criteria in the order entered by the user. */
+ private Map<String, TracSearchFilter> filterByFieldName = new LinkedHashMap<String, TracSearchFilter>();
+
+ /** The field the result is ordered by. */
+ private String orderBy;
+
+ private boolean ascending = true;
+
+ public TracSearch() {
+ }
+
+ public void addFilter(String key, String value) {
+ TracSearchFilter filter = filterByFieldName.get(key);
+ if (filter == null) {
+ filter = new TracSearchFilter(key);
+ CompareOperator operator = CompareOperator.fromUrl(value);
+ filter.setOperator(operator);
+ filterByFieldName.put(key, filter);
+ }
+
+ filter.addValue(value.substring(filter.getOperator().getQueryValue().length()));
+ }
+
+ public List<TracSearchFilter> getFilters() {
+ return new ArrayList<TracSearchFilter>(filterByFieldName.values());
+ }
+
+ public void setAscending(boolean ascending) {
+ this.ascending = ascending;
+ }
+
+ public boolean isAscending() {
+ return ascending;
+ }
+
+ public void setOrderBy(String orderBy) {
+ this.orderBy = orderBy;
+ }
+
+ public String getOrderBy() {
+ return orderBy;
+ }
+
+ /**
+ * Returns a Trac query string that conforms to the format defined at
+ * {@link http://projects.edgewall.com/trac/wiki/TracQuery#QueryLanguage}.
+ *
+ * @return the empty string, if no search order and criteria are defined; a
+ * string that starts with &amp;, otherwise
+ */
+ public String toQuery() {
+ StringBuilder sb = new StringBuilder();
+ if (orderBy != null) {
+ sb.append("&order=");
+ sb.append(orderBy);
+ if (!ascending) {
+ sb.append("&desc=1");
+ }
+ }
+ for (TracSearchFilter filter : filterByFieldName.values()) {
+ sb.append("&");
+ sb.append(filter.getFieldName());
+ sb.append(filter.getOperator().getQueryValue());
+ sb.append("=");
+ List<String> values = filter.getValues();
+ for (Iterator<String> it = values.iterator(); it.hasNext();) {
+ sb.append(it.next());
+ if (it.hasNext()) {
+ sb.append("|");
+ }
+ }
+ }
+ return sb.toString();
+ }
+
+ /**
+ * Returns a URL encoded string that can be passed as an argument to the
+ * Trac query script.
+ *
+ * @return the empty string, if no search order and criteria are defined; a
+ * string that starts with &amp;, otherwise
+ */
+ public String toUrl() {
+ StringBuilder sb = new StringBuilder();
+ if (orderBy != null) {
+ sb.append("&order=");
+ sb.append(orderBy);
+ if (!ascending) {
+ sb.append("&desc=1");
+ }
+ }
+ for (TracSearchFilter filter : filterByFieldName.values()) {
+ for (String value : filter.getValues()) {
+ sb.append("&");
+ sb.append(filter.getFieldName());
+ sb.append("=");
+ try {
+ sb.append(URLEncoder.encode(filter.getOperator().getQueryValue(), ITracRepository.CHARSET));
+ sb.append(URLEncoder.encode(value, ITracRepository.CHARSET));
+ } catch (UnsupportedEncodingException e) {
+ MylarStatusHandler.log(e, "Unexpected exception while decoding URL");
+ }
+ }
+ }
+ return sb.toString();
+ }
+
+}
diff --git a/org.eclipse.mylyn.trac.ui/src/org/eclipse/mylyn/internal/trac/model/TracSearchFilter.java b/org.eclipse.mylyn.trac.ui/src/org/eclipse/mylyn/internal/trac/model/TracSearchFilter.java
new file mode 100644
index 000000000..2702d90af
--- /dev/null
+++ b/org.eclipse.mylyn.trac.ui/src/org/eclipse/mylyn/internal/trac/model/TracSearchFilter.java
@@ -0,0 +1,108 @@
+/*******************************************************************************
+ * Copyright (c) 2006 - 2006 Mylar eclipse.org project 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:
+ * Mylar project committers - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.mylar.internal.trac.model;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Represents a search criterion. Each criterion is applied to a field such as
+ * milestone or priority. It has a compare operator and a list of values. The
+ * compare mode is <code>OR</code> for the operators <code>contains</code>,
+ * <code>starts with</code>, <code>ends with</code> and <code>is</code>.
+ * The compare mode is <code>AND</code> for all other (negated) operators.
+ *
+ * @author Steffen Pingel
+ */
+public class TracSearchFilter {
+
+ public enum CompareOperator {
+ CONTAINS("~"), CONTAINS_NOT("!~"), BEGINS_WITH("^"), NOT_BEGINS_WITH("!^"), ENDS_WITH("$"), NOT_ENDS_WITH("!$"), IS(
+ ""), IS_NOT("!");
+
+ public static CompareOperator fromUrl(String value) {
+ for (CompareOperator operator : values()) {
+ if (operator != IS && operator != IS_NOT && value.startsWith(operator.queryValue)) {
+ return operator;
+ }
+ }
+ if (value.startsWith(IS_NOT.queryValue)) {
+ return IS_NOT;
+ }
+ return IS;
+ }
+
+ /** The string that represent the operator in a Trac query. */
+ private String queryValue;
+
+ CompareOperator(String queryValue) {
+ this.queryValue = queryValue;
+ }
+
+ public String getQueryValue() {
+ return queryValue;
+ }
+
+ public String toString() {
+ switch (this) {
+ case CONTAINS:
+ return "contains";
+ case CONTAINS_NOT:
+ return "does not contain";
+ case BEGINS_WITH:
+ return "begins with";
+ case NOT_BEGINS_WITH:
+ return "does not begin with";
+ case ENDS_WITH:
+ return "ends with";
+ case NOT_ENDS_WITH:
+ return "does not end with";
+ case IS_NOT:
+ return "is not";
+ default:
+ return "is";
+ }
+ }
+
+ }
+
+ private String fieldName;
+
+ private CompareOperator operator;
+
+ private List<String> values = new ArrayList<String>();
+
+ public TracSearchFilter(String fieldName) {
+ this.fieldName = fieldName;
+ }
+
+ public void addValue(String value) {
+ values.add(value);
+ }
+
+ public String getFieldName() {
+ return fieldName;
+ }
+
+ public CompareOperator getOperator() {
+ return operator;
+ }
+
+ public List<String> getValues() {
+ return values;
+ }
+
+ public void setOperator(CompareOperator operator) {
+ this.operator = operator;
+ }
+
+}
diff --git a/org.eclipse.mylyn.trac.ui/src/org/eclipse/mylyn/internal/trac/model/TracTicket.java b/org.eclipse.mylyn.trac.ui/src/org/eclipse/mylyn/internal/trac/model/TracTicket.java
new file mode 100644
index 000000000..2673d20a6
--- /dev/null
+++ b/org.eclipse.mylyn.trac.ui/src/org/eclipse/mylyn/internal/trac/model/TracTicket.java
@@ -0,0 +1,169 @@
+/*******************************************************************************
+ * Copyright (c) 2006 - 2006 Mylar eclipse.org project 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:
+ * Mylar project committers - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.mylar.internal.trac.model;
+
+import java.util.Calendar;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.TimeZone;
+
+import org.eclipse.mylar.internal.trac.core.ITracRepository;
+import org.eclipse.mylar.internal.trac.core.InvalidTicketException;
+
+/**
+ * Represents a Trac ticket as it is retrieved from a Trac repository.
+ *
+ * @author Steffen Pingel
+ */
+public class TracTicket {
+
+ /**
+ * Represents the key of a string propertiy of a ticket.
+ *
+ * @author Steffen Pingel
+ */
+ public enum Key {
+ COMPONENT("component"), DESCRIPTION("description"), ID("id"), KEYWORDS("keywords"), MILESTONE("milestone"), OWNER(
+ "owner"), PRIORITY("priority"), REPORTER("reporter"), RESOLUTION("resolution"), STATUS("status"), SUMMARY(
+ "summary"), TYPE("type"), VERSION("version");
+
+ public static Key fromKey(String name) {
+ for (Key key : Key.values()) {
+ if (key.toString().equals(name)) {
+ return key;
+ }
+ }
+ return null;
+ }
+
+ private String key;
+
+ Key(String key) {
+ this.key = key;
+ }
+
+ public String toString() {
+ return key;
+ }
+ }
+
+ public static final int INVALID_ID = -1;
+
+ private Date created;
+
+ /**
+ * User defined custom ticket fields.
+ *
+ * @see http://projects.edgewall.com/trac/wiki/TracTicketsCustomFields
+ */
+ private Map<String, String> customValueByKey;
+
+ private int id = INVALID_ID;
+
+ private Date lastChanged;
+
+ /** Trac's built-in ticket properties. */
+ private Map<Key, String> valueByKey = new HashMap<Key, String>();
+
+ public TracTicket() {
+ }
+
+ /**
+ * Constructs a Trac ticket.
+ *
+ * @param id
+ * the nummeric Trac ticket id
+ */
+ public TracTicket(int id) {
+ this.id = id;
+ }
+
+ public Date getCreated() {
+ return created;
+ }
+
+ public int getId() {
+ return id;
+ }
+
+ public Date getLastChanged() {
+ return lastChanged;
+ }
+
+ public String getCustomValue(String key) {
+ if (customValueByKey == null){
+ return null;
+ }
+ return customValueByKey.get(key);
+ }
+
+ public String getValue(Key key) {
+ return valueByKey.get(key);
+ }
+
+ public boolean isValid() {
+ return getId() != TracTicket.INVALID_ID;
+ }
+
+ private Date parseTracDate(int seconds) {
+ Calendar c = Calendar.getInstance();
+ c.setTimeZone(TimeZone.getTimeZone(ITracRepository.TIME_ZONE));
+ c.setTimeInMillis(seconds * 1000l);
+ return c.getTime();
+ }
+
+ public void putBuiltinValue(Key key, String value) throws InvalidTicketException {
+ valueByKey.put(key, value);
+ }
+
+ public void putCustomValue(String key, String value) {
+ if (customValueByKey == null) {
+ customValueByKey = new HashMap<String, String>();
+ }
+ customValueByKey.put(key, value);
+ }
+
+ /**
+ * Stores a value as it is retrieved from the repository.
+ *
+ * @throws InvalidTicketException
+ * thrown if the type of <code>value</code> is not valid
+ */
+ public void putTracValue(String keyName, String value) throws InvalidTicketException {
+ Key key = Key.fromKey(keyName);
+ if (key != null) {
+ if (key == Key.ID) {
+ throw new RuntimeException("The ID field must be accessed through setId()");
+ }
+ putBuiltinValue(key, value);
+ } else if (value instanceof String) {
+ putCustomValue(keyName, (String) value);
+ } else {
+ throw new InvalidTicketException("Expected string value for custom key '" + keyName + "', got '" + value
+ + "'");
+ }
+ }
+
+ public void setCreated(int created) {
+ this.created = parseTracDate(created);
+ }
+
+ public void setId(int id) {
+ this.id = id;
+ }
+
+ public void setLastChanged(int lastChanged) {
+ this.lastChanged = parseTracDate(lastChanged);
+ }
+
+}

Back to the top