/src/org/bitbucket/connectors/jetbrains/tasks/BitbucketIssueRepository.java
Java | 300 lines | 234 code | 61 blank | 5 comment | 19 complexity | d62ca4a33fdb09d8bccc8766daa80c49 MD5 | raw file
1package org.bitbucket.connectors.jetbrains.tasks; 2 3import com.intellij.openapi.diagnostic.Logger; 4import com.intellij.openapi.util.Ref; 5import com.intellij.tasks.*; 6import com.intellij.tasks.impl.BaseRepository; 7import com.intellij.tasks.impl.BaseRepositoryImpl; 8import com.intellij.tasks.impl.LocalTaskImpl; 9import com.intellij.tasks.impl.TaskUtil; 10import com.intellij.tasks.pivotal.PivotalTrackerRepository; 11import com.intellij.util.NullableFunction; 12import com.intellij.util.containers.ContainerUtil; 13import com.intellij.util.xmlb.annotations.Attribute; 14import com.intellij.util.xmlb.annotations.Tag; 15import org.bitbucket.connectors.jetbrains.BitbucketSettings; 16import org.bitbucket.connectors.jetbrains.BitbucketUtil; 17import org.jdom.Element; 18import org.jetbrains.annotations.NotNull; 19import org.jetbrains.annotations.Nullable; 20 21import javax.swing.*; 22import java.lang.reflect.Method; 23import java.text.MessageFormat; 24import java.text.ParseException; 25import java.util.Arrays; 26import java.util.Date; 27import java.util.List; 28 29 30@Tag("Bitbucket") 31public class BitbucketIssueRepository extends BaseRepositoryImpl { 32 private static final Logger log = 33 Logger.getInstance("#org.bitbucket.connectors.jetbrains.tasks.BitbucketIssueRepository"); 34 35 36 @SuppressWarnings({"UnusedDeclaration"}) 37 public BitbucketIssueRepository() {} 38 39 protected BitbucketIssueRepository(BitbucketIssueRepositoryType type) { 40 super(type); 41 } 42 43 public BitbucketIssueRepository(BitbucketIssueRepository other) { 44 super(other); 45 setRepositoryName(other.getRepositoryName()); 46 setRepositoryOwner(other.getRepositoryOwner()); 47 } 48 49 protected String myRepoName = null; 50 51 @Attribute("repo") 52 public String getRepositoryName() { 53 return myRepoName; 54 } 55 56 public void setRepositoryName(String s) { 57 myRepoName = s; 58 } 59 60 protected String myRepoOwner = null; 61 62 @Attribute("owner") 63 public String getRepositoryOwner() { 64 return myRepoOwner; 65 } 66 67 public void setRepositoryOwner(String s) { 68 myRepoOwner = s; 69 } 70 @Override 71 public Task[] getIssues(@Nullable String query, int max, long since) throws Exception { 72 log.debug("getIssues: " + query); 73 74 @SuppressWarnings({"unchecked"}) List<Object> children = getIssues(query); 75 if (children == null) return Task.EMPTY_ARRAY; 76 77 List<Task> taskList = ContainerUtil.mapNotNull(children, new NullableFunction<Object, Task>() { 78 public Task fun(Object o) { 79 final Task issue = createIssue((Element) o); 80 log.debug("Loaded Issue: " + issue); 81 return issue; 82 } 83 }); 84 85 return taskList.toArray(new Task[taskList.size()]); 86 } 87 88 // https://api.bitbucket.org/1.0/repositories/sylvanaar2/lua-for-idea/issues/?format=xml&status=new&status=open 89 // sylvanaar2/lua-for-idea/issues?status=new&status=open status=new&status=open 90 private List getIssues(String query) throws Exception { 91 log.debug(query); 92 final BitbucketSettings settings = BitbucketSettings.getInstance(); 93 94 95 String url = "/repositories/" + getRepositoryOwner() + "/" + getRepositoryName() + "/issues"; 96 97 log.debug("getIssues for : " + url); 98 String queryParameters = "status=new&status=open"; 99 100 Element element = 101 BitbucketUtil.request(settings.getLogin(), settings.getPassword(), url, false, null, queryParameters); 102 103 return element.getChild("issues").getChildren("resource"); 104 } 105 106 TaskState mapState(String state) { 107 if (state.equals("new")) return TaskState.SUBMITTED; 108 if (state.equals("open")) return TaskState.OPEN; 109 return TaskState.RESOLVED; 110 } 111 112 113 @Nullable 114 private Task createIssue(final Element element) { 115 if (element != null) log.debug(element.getText()); 116 else { 117 log.debug("NULL element"); 118 return null; 119 } 120 121 122 final String id = element.getChildText("local_id"); 123 if (id == null) { 124 return null; 125 } 126 final String summary = element.getChildText("title"); 127 if (summary == null) { 128 return null; 129 } 130 final String description = element.getChildText("content"); 131 final Ref<Date> created = new Ref<Date>(); 132 try { 133 created.set(parseDate(element, "created_on")); 134 } catch (ParseException e) { 135 log.warn(e); 136 } 137 138 final String kind = element.getChild("metadata").getChildText("kind"); 139 final TaskType taskType = 140 kind.equals("bug") ? TaskType.BUG : (kind.equals("enhancement") ? TaskType.FEATURE : TaskType.OTHER); 141 142 final String state = element.getChildText("status"); 143 final TaskState taskState = mapState(state); 144 145 final boolean isClosed = taskState.equals(TaskState.RESOLVED); 146 147 // /1.0/repositories/sylvanaar2/lua-for-idea/issues/79 148 final String issueUrl = element.getChildText("resource_uri").replace("/1.0/repositories", "").replace("/issues/", "/issue/"); 149 150 151 return new LocalTaskImpl(new Task() { 152 153 public String getCustomIcon() { 154 return null; 155 } 156 157 @Override 158 public boolean isIssue() { 159 return true; 160 } 161 162 //https://bitbucket.org/sylvanaar2/lua-for-idea/issue/80 163 @Override 164 public String getIssueUrl() { 165 return "https://" + BitbucketUtil.BITBUCKET_DN + issueUrl; 166 } 167 168 @NotNull 169 @Override 170 public String getId() { 171 return id; 172 } 173 174 @NotNull 175 @Override 176 public String getSummary() { 177 return summary; 178 } 179 180 public String getDescription() { 181 return description; 182 } 183 184 @Override 185 public TaskState getState() { 186 return taskState; 187 } 188 189 @NotNull 190 @Override 191 public Comment[] getComments() { 192 return new Comment[0]; 193 } 194 195 @Override 196 public Icon getIcon() { 197 return BitbucketUtil.ICON; 198 } 199 200 @NotNull 201 @Override 202 public TaskType getType() { 203 return taskType; 204 } 205 206 @Override 207 public Date getUpdated() { 208 return created.get(); 209 } 210 211 @Override 212 public Date getCreated() { 213 return created.get(); 214 } 215 216 @Override 217 public boolean isClosed() { 218 return isClosed; 219 } 220 221 @Override 222 public TaskRepository getRepository() { 223 return BitbucketIssueRepository.this; 224 } 225 226 @Override 227 public String getPresentableName() { 228 return MessageFormat.format("#{0}: {1}", getId(), getSummary()); 229 } 230 }); 231 } 232 233 private static Date parseDate(final Element element, final String name) throws ParseException { 234 try { 235 Method parseDateMethod = getParseDateMethod(); 236 if (parseDateMethod != null) { 237 return (Date) parseDateMethod.invoke(null, element, name); 238 } else { // fix for newer versions without PivotalTrackerRepository.parseDate() method 239 String val = element.getChildText(name); 240 return TaskUtil.parseDate(val); 241 } 242 } catch (Exception e) { 243 throw new RuntimeException(e); 244 } 245 } 246 247 private static Method getParseDateMethod() { 248 final Class[] PARAMETER_TYPES = new Class[] { Element.class, String.class }; 249 for (Method method: PivotalTrackerRepository.class.getMethods()) { 250 if ("parseDate".equals(method.getName()) && Arrays.equals(PARAMETER_TYPES, method.getParameterTypes())) { 251 method.setAccessible(true); 252 return method; 253 } 254 } 255 return null; 256 } 257 258 //https://api.bitbucket.org/1.0/repositories/sylvanaar2/lua-for-idea/issues/1 259 @Override 260 public Task findTask(String s) throws Exception { 261 log.debug("Find Task:" + s); 262 final BitbucketSettings settings = BitbucketSettings.getInstance(); 263 264 String url = "/repositories/" + getRepositoryOwner() + "/" + getRepositoryName() + "/issues/" + s; 265 266 Element element = BitbucketUtil.request(settings.getLogin(), settings.getPassword(), url, false, null); 267 268 if (element == null) return null; 269 270 return createIssue(element); 271 } 272 273 @Override 274 public BaseRepository clone() { 275 return new BitbucketIssueRepository(this); 276 } 277 278 @Nullable 279 public String extractId(String taskName) { 280 return taskName; 281 } 282 283 @Override 284 @Nullable 285 public String getTaskComment(Task task) { 286 return MessageFormat.format("#{0}: {1}", task.getId(), task.getSummary()); 287 } 288 289 @Override 290 public String toString() { 291 return "BitbucketIssueRepository{" + "myRepoName='" + myRepoName + '\'' + ", myRepoOwner='" + myRepoOwner + 292 '\'' + '}'; 293 } 294 295 @Override 296 public String getUrl() { 297 return BitbucketUtil.API_URL_BASE + "/" + "repositories" + "/" + getRepositoryOwner() + "/" + 298 getRepositoryName(); 299 } 300}