From a49b0c598c69d3b4b095f5b583368db4b6708282 Mon Sep 17 00:00:00 2001 From: Julien Lancelot Date: Thu, 30 May 2013 13:27:22 +0200 Subject: [PATCH] SONAR-3755 Add actionPlans in Issues Client WS --- .../api/action_plans_controller.rb | 11 +-- .../webapp/WEB-INF/app/models/action_plan.rb | 36 ++++++++++ .../java/org/sonar/wsclient/issue/Issue.java | 5 ++ .../sonar/wsclient/issue/IssueJsonParser.java | 10 +++ .../java/org/sonar/wsclient/issue/Issues.java | 15 ++++ .../wsclient/issue/IssueJsonParserTest.java | 18 +++++ .../issue-with-action-plans.json | 71 +++++++++++++++++++ .../issue/IssueParserTest/search.json | 1 + 8 files changed, 157 insertions(+), 10 deletions(-) create mode 100644 sonar-server/src/main/webapp/WEB-INF/app/models/action_plan.rb create mode 100644 sonar-ws-client/src/test/resources/org/sonar/wsclient/issue/IssueParserTest/issue-with-action-plans.json diff --git a/sonar-server/src/main/webapp/WEB-INF/app/controllers/api/action_plans_controller.rb b/sonar-server/src/main/webapp/WEB-INF/app/controllers/api/action_plans_controller.rb index e0c67868374..41ebd88eaa8 100644 --- a/sonar-server/src/main/webapp/WEB-INF/app/controllers/api/action_plans_controller.rb +++ b/sonar-server/src/main/webapp/WEB-INF/app/controllers/api/action_plans_controller.rb @@ -164,16 +164,7 @@ class Api::ActionPlansController < Api::ApiController private def action_plan_to_hash(action_plan) - hash = {:key => action_plan.key(), :name => action_plan.name(), :status => action_plan.status()} - hash[:project] = action_plan.projectKey() if action_plan.projectKey() && !action_plan.projectKey().blank? - hash[:desc] = action_plan.description() if action_plan.description() && !action_plan.description().blank? - hash[:userLogin] = action_plan.userLogin() if action_plan.userLogin() - hash[:deadLine] = Api::Utils.format_datetime(action_plan.deadLine()) if action_plan.deadLine() - hash[:totalIssues] = action_plan.totalIssues() if action_plan.respond_to?('totalIssues') - hash[:unresolvedIssues] = action_plan.unresolvedIssues() if action_plan.respond_to?('unresolvedIssues') - hash[:createdAt] = Api::Utils.format_datetime(action_plan.createdAt()) if action_plan.createdAt() - hash[:updatedAt] = Api::Utils.format_datetime(action_plan.updatedAt()) if action_plan.updatedAt() - hash + ActionPlan.to_hash(action_plan) end def error_to_hash(msg) diff --git a/sonar-server/src/main/webapp/WEB-INF/app/models/action_plan.rb b/sonar-server/src/main/webapp/WEB-INF/app/models/action_plan.rb new file mode 100644 index 00000000000..ec808b21c1a --- /dev/null +++ b/sonar-server/src/main/webapp/WEB-INF/app/models/action_plan.rb @@ -0,0 +1,36 @@ +# +# Sonar, entreprise quality control tool. +# Copyright (C) 2008-2013 SonarSource +# mailto:contact AT sonarsource DOT com +# +# SonarQube is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 3 of the License, or (at your option) any later version. +# +# SonarQube is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# + +class ActionPlan + + def self.to_hash(action_plan) + hash = {:key => action_plan.key(), :name => action_plan.name(), :status => action_plan.status()} + hash[:project] = action_plan.projectKey() if action_plan.projectKey() && !action_plan.projectKey().blank? + hash[:desc] = action_plan.description() if action_plan.description() && !action_plan.description().blank? + hash[:userLogin] = action_plan.userLogin() if action_plan.userLogin() + hash[:deadLine] = Api::Utils.format_datetime(action_plan.deadLine()) if action_plan.deadLine() + hash[:totalIssues] = action_plan.totalIssues() if action_plan.respond_to?('totalIssues') + hash[:unresolvedIssues] = action_plan.unresolvedIssues() if action_plan.respond_to?('unresolvedIssues') + hash[:createdAt] = Api::Utils.format_datetime(action_plan.createdAt()) if action_plan.createdAt() + hash[:updatedAt] = Api::Utils.format_datetime(action_plan.updatedAt()) if action_plan.updatedAt() + hash + end + +end \ No newline at end of file diff --git a/sonar-ws-client/src/main/java/org/sonar/wsclient/issue/Issue.java b/sonar-ws-client/src/main/java/org/sonar/wsclient/issue/Issue.java index ff9bad62e2c..7e8ca71744e 100644 --- a/sonar-ws-client/src/main/java/org/sonar/wsclient/issue/Issue.java +++ b/sonar-ws-client/src/main/java/org/sonar/wsclient/issue/Issue.java @@ -99,6 +99,11 @@ public class Issue { return JsonUtils.getString(json, "assignee"); } + @CheckForNull + public String actionPlan() { + return JsonUtils.getString(json, "actionPlan"); + } + public Date creationDate() { return JsonUtils.getDateTime(json, "creationDate"); } diff --git a/sonar-ws-client/src/main/java/org/sonar/wsclient/issue/IssueJsonParser.java b/sonar-ws-client/src/main/java/org/sonar/wsclient/issue/IssueJsonParser.java index fc1b1fb6ccc..635a624758b 100644 --- a/sonar-ws-client/src/main/java/org/sonar/wsclient/issue/IssueJsonParser.java +++ b/sonar-ws-client/src/main/java/org/sonar/wsclient/issue/IssueJsonParser.java @@ -47,6 +47,7 @@ class IssueJsonParser { parseUsers(result, jsonRoot); parseComponents(result, jsonRoot); parseProjects(result, jsonRoot); + parseActionPlans(result, jsonRoot); parsePaging(result, jsonRoot); return result; } @@ -93,6 +94,15 @@ class IssueJsonParser { } } + private void parseActionPlans(Issues result, Map jsonRoot) { + List jsonRules = (List) jsonRoot.get("actionPlans"); + if (jsonRules != null) { + for (Map jsonRule : jsonRules) { + result.add(new ActionPlan(jsonRule)); + } + } + } + List parseTransitions(String json) { List transitions = new ArrayList(); Map jRoot = (Map) JSONValue.parse(json); diff --git a/sonar-ws-client/src/main/java/org/sonar/wsclient/issue/Issues.java b/sonar-ws-client/src/main/java/org/sonar/wsclient/issue/Issues.java index 9dcd5926c94..ff761f26cdf 100644 --- a/sonar-ws-client/src/main/java/org/sonar/wsclient/issue/Issues.java +++ b/sonar-ws-client/src/main/java/org/sonar/wsclient/issue/Issues.java @@ -37,6 +37,7 @@ public class Issues { private final Map usersByKey = new HashMap(); private final Map componentsByKey = new HashMap(); private final Map projectsByKey = new HashMap(); + private final Map actionPlansByKey = new HashMap(); private Paging paging; private Boolean maxResultsReached; @@ -83,6 +84,15 @@ public class Issues { return projectsByKey.get(issue.projectKey()); } + public Collection actionPlans() { + return actionPlansByKey.values(); + } + + @CheckForNull + public ActionPlan actionPlans(Issue issue) { + return actionPlansByKey.get(issue.actionPlan()); + } + public Paging paging() { return paging; } @@ -106,6 +116,11 @@ public class Issues { return this; } + Issues add(ActionPlan actionPlan) { + actionPlansByKey.put(actionPlan.key(), actionPlan); + return this; + } + Issues addComponent(Component c) { componentsByKey.put(c.key(), c); return this; diff --git a/sonar-ws-client/src/test/java/org/sonar/wsclient/issue/IssueJsonParserTest.java b/sonar-ws-client/src/test/java/org/sonar/wsclient/issue/IssueJsonParserTest.java index 82c71f7446d..a33d6093190 100644 --- a/sonar-ws-client/src/test/java/org/sonar/wsclient/issue/IssueJsonParserTest.java +++ b/sonar-ws-client/src/test/java/org/sonar/wsclient/issue/IssueJsonParserTest.java @@ -49,6 +49,7 @@ public class IssueJsonParserTest { assertThat(first.message()).isEqualTo("the message"); assertThat(first.effortToFix()).isEqualTo(4.2); assertThat(first.reporter()).isEqualTo("perceval"); + assertThat(first.actionPlan()).isEqualTo("9450b10c-e725-48b8-bf01-acdec751c491"); assertThat(first.creationDate()).isNotNull(); assertThat(first.updateDate()).isNotNull(); assertThat(first.closeDate()).isNotNull(); @@ -170,4 +171,21 @@ public class IssueJsonParserTest { assertThat(component.name()).isEqualTo("Struts"); assertThat(component.longName()).isEqualTo("org.struts"); } + + @Test + public void should_parse_action_plans() throws Exception { + String json = IOUtils.toString(getClass().getResourceAsStream("/org/sonar/wsclient/issue/IssueParserTest/issue-with-action-plans.json")); + Issues issues = new IssueJsonParser().parseIssues(json); + + assertThat(issues.actionPlans()).hasSize(1); + + ActionPlan actionPlan = issues.actionPlans(issues.list().get(0)); + assertThat(actionPlan.key()).isEqualTo("9450b10c-e725-48b8-bf01-acdec751c491"); + assertThat(actionPlan.name()).isEqualTo("3.6"); + assertThat(actionPlan.status()).isEqualTo("OPEN"); + assertThat(actionPlan.project()).isEqualTo("struts"); + assertThat(actionPlan.deadLine().getTime()).isEqualTo(1369951200000l); + assertThat(actionPlan.createdAt().getTime()).isEqualTo(1369828520000l); + assertThat(actionPlan.updatedAt().getTime()).isEqualTo(1369828520000l); + } } diff --git a/sonar-ws-client/src/test/resources/org/sonar/wsclient/issue/IssueParserTest/issue-with-action-plans.json b/sonar-ws-client/src/test/resources/org/sonar/wsclient/issue/IssueParserTest/issue-with-action-plans.json new file mode 100644 index 00000000000..46718d5b39f --- /dev/null +++ b/sonar-ws-client/src/test/resources/org/sonar/wsclient/issue/IssueParserTest/issue-with-action-plans.json @@ -0,0 +1,71 @@ +{ + "issues": [ + { + "key": "ABCDE", + "component": "struts:Action.java", + "project": "struts", + "rule": "squid:CycleBetweenPackages", + "severity": "CRITICAL", + "status": "OPEN", + "actionPlan": "9450b10c-e725-48b8-bf01-acdec751c491", + "comments": [ + { + "key": "COMMENT-1", + "login": "morgan", + "htmlText": "the first comment", + "createdAt": "2013-05-18T13:45:34+0200" + }, + { + "key": "COMMENT-2", + "login": "arthur", + "htmlText": "the second comment", + "createdAt": "2013-06-19T00:02:03+0100" + } + ] + } + ], + "rules": [ + { + + "key": "squid:CycleBetweenPackages", + "name": "Avoid cycle between java packages", + "desc": "

\nWhen several packages are involved in a cycle (package A > package B > package C > package A where \">\" means \"depends upon\"),\nthat means that those packages are highly coupled and that there is no way to reuse/extract one of those packages without importing all the other packages.\nSuch cycle could quickly increase the effort required to maintain an application and to embrace business change.\nSonar not only detect cycles between packages but also determines what is the minimum effort to break those cycles.\nThis rule log a violation on each source file having an outgoing dependency to be but in order to break a cycle.\n

\n" + + } + ], + "components": [ + { + "key": "struts:Action.java", + "name": "Action", + "qualifier": "CLA", + "longName": "org.struts.Action" + } + ], + "projects": [ + { + "key": "struts", + "name": "Struts", + "qualifier": "TRK", + "longName": "org.struts" + } + ], + "actionPlans": [ + { + "key": "9450b10c-e725-48b8-bf01-acdec751c491", + "name": "3.6", + "status": "OPEN", + "project": "struts", + "userLogin": "arthur", + "deadLine": "2013-05-31T00:00:00+0200", + "createdAt": "2013-05-29T13:55:20+0200", + "updatedAt": "2013-05-29T13:55:20+0200" + } + ], + "paging": { + "pageIndex": 1, + "pageSize": 100, + "total": 2, + "pages": 1 + }, + "maxResultsReached": false +} \ No newline at end of file diff --git a/sonar-ws-client/src/test/resources/org/sonar/wsclient/issue/IssueParserTest/search.json b/sonar-ws-client/src/test/resources/org/sonar/wsclient/issue/IssueParserTest/search.json index 55ff5e79e53..40e1a7ab144 100644 --- a/sonar-ws-client/src/test/resources/org/sonar/wsclient/issue/IssueParserTest/search.json +++ b/sonar-ws-client/src/test/resources/org/sonar/wsclient/issue/IssueParserTest/search.json @@ -14,6 +14,7 @@ "message": "the message", "title": "the title", "reporter": "perceval", + "actionPlan": "9450b10c-e725-48b8-bf01-acdec751c491", "creationDate": "2013-05-18T12:45:34+0200", "updateDate": "2013-05-18T13:45:34+0200", "closeDate": "2013-05-18T14:45:34+0200", -- 2.39.5