1 /* 2 * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 package org.openjdk.skara.issuetracker.jira; 24 25 import org.openjdk.skara.issuetracker.*; 26 import org.openjdk.skara.json.*; 27 import org.openjdk.skara.network.*; 28 29 import java.net.URI; 30 import java.util.*; 31 32 public class JiraProject implements IssueProject { 33 private final JiraHost jiraHost; 34 private final String projectName; 35 private final RestRequest request; 36 37 private JSONObject projectMetadataCache = null; 38 39 JiraProject(JiraHost host, RestRequest request, String projectName) { 40 this.jiraHost = host; 41 this.projectName = projectName; 42 this.request = request; 43 } 44 45 private JSONObject project() { 46 if (projectMetadataCache == null) { 47 projectMetadataCache = request.get("project/" + projectName).execute().asObject(); 48 } 49 return projectMetadataCache; 50 } 51 52 private Map<String, String> issueTypes() { 53 var ret = new HashMap<String, String>(); 54 for (var type : project().get("issueTypes").asArray()) { 55 ret.put(type.get("name").asString(), type.get("id").asString()); 56 } 57 return ret; 58 } 59 60 private Map<String, String> components() { 61 var ret = new HashMap<String, String>(); 62 for (var type : project().get("components").asArray()) { 63 ret.put(type.get("name").asString(), type.get("id").asString()); 64 } 65 return ret; 66 } 67 68 private String projectId() { 69 return project().get("id").asString(); 70 } 71 72 private String defaultIssueType() { 73 return issueTypes().values().stream() 74 .min(Comparator.naturalOrder()).orElseThrow(); 75 } 76 77 private String defaultComponent() { 78 return components().values().stream() 79 .min(Comparator.naturalOrder()).orElseThrow(); 80 } 81 82 @Override 83 public IssueTracker issueTracker() { 84 return jiraHost; 85 } 86 87 @Override 88 public URI webUrl() { 89 return URIBuilder.base(jiraHost.getUri()).setPath("/projects/" + projectName).build(); 90 } 91 92 @Override 93 public Issue createIssue(String title, List<String> body) { 94 var query = JSON.object() 95 .put("fields", JSON.object() 96 .put("project", JSON.object() 97 .put("id", projectId())) 98 .put("issuetype", JSON.object() 99 .put("id", defaultIssueType())) 100 .put("components", JSON.array() 101 .add(JSON.object().put("id", defaultComponent()))) 102 .put("summary", title) 103 .put("description", String.join("\n", body))); 104 105 var data = request.post("issue") 106 .body(query) 107 .execute(); 108 109 return issue(data.get("key").asString()).orElseThrow(); 110 } 111 112 @Override 113 public Optional<Issue> issue(String id) { 114 if (id.indexOf('-') < 0) { 115 id = projectName.toUpperCase() + "-" + id; 116 } 117 var issueRequest = request.restrict("issue/" + id); 118 var issue = issueRequest.get("") 119 .onError(r -> r.statusCode() == 404 ? JSON.object().put("NOT_FOUND", true) : null) 120 .execute(); 121 if (!issue.contains("NOT_FOUND")) { 122 return Optional.of(new JiraIssue(this, issueRequest, issue)); 123 } else { 124 return Optional.empty(); 125 } 126 } 127 128 @Override 129 public List<Issue> issues() { 130 var ret = new ArrayList<Issue>(); 131 var issues = request.post("search") 132 .body("jql", "project = " + projectName + " AND status in (Open, New)") 133 .execute(); 134 for (var issue : issues.get("issues").asArray()) { 135 ret.add(new JiraIssue(this, request, issue)); 136 } 137 return ret; 138 } 139 }