PageRenderTime 153ms CodeModel.GetById 49ms app.highlight 42ms RepoModel.GetById 59ms app.codeStats 0ms

/src/org/bitbucket/connectors/jetbrains/tasks/BitbucketIssueRepository.java

https://bitbucket.org/atlassian/jetbrains-bitbucket-connector/
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}