]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-3755 Add actionPlans in Issues Client WS
authorJulien Lancelot <julien.lancelot@gmail.com>
Thu, 30 May 2013 11:27:22 +0000 (13:27 +0200)
committerJulien Lancelot <julien.lancelot@gmail.com>
Thu, 30 May 2013 11:27:22 +0000 (13:27 +0200)
sonar-server/src/main/webapp/WEB-INF/app/controllers/api/action_plans_controller.rb
sonar-server/src/main/webapp/WEB-INF/app/models/action_plan.rb [new file with mode: 0644]
sonar-ws-client/src/main/java/org/sonar/wsclient/issue/Issue.java
sonar-ws-client/src/main/java/org/sonar/wsclient/issue/IssueJsonParser.java
sonar-ws-client/src/main/java/org/sonar/wsclient/issue/Issues.java
sonar-ws-client/src/test/java/org/sonar/wsclient/issue/IssueJsonParserTest.java
sonar-ws-client/src/test/resources/org/sonar/wsclient/issue/IssueParserTest/issue-with-action-plans.json [new file with mode: 0644]
sonar-ws-client/src/test/resources/org/sonar/wsclient/issue/IssueParserTest/search.json

index e0c67868374283ba172795b13db8fc0ade754ead..41ebd88eaa842af1d482c211880b0e03e0731bcb 100644 (file)
@@ -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 (file)
index 0000000..ec808b2
--- /dev/null
@@ -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
index ff9bad62e2c8a9bc3bf97a60e54a0cba40348383..7e8ca71744e57b4bfcb74a095de0d327790f55bc 100644 (file)
@@ -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");
   }
index fc1b1fb6cccedf18f433e50c0d6b48ad2a5ac09b..635a624758bb4e6ff068e18efe7fb5bfe9653e5e 100644 (file)
@@ -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<Map> jsonRules = (List) jsonRoot.get("actionPlans");
+    if (jsonRules != null) {
+      for (Map jsonRule : jsonRules) {
+        result.add(new ActionPlan(jsonRule));
+      }
+    }
+  }
+
   List<String> parseTransitions(String json) {
     List<String> transitions = new ArrayList<String>();
     Map jRoot = (Map) JSONValue.parse(json);
index 9dcd5926c94c1d358ee116fec94077ece650c7dd..ff761f26cdf6f5a2f5ca013e3510dacdcfef7abf 100644 (file)
@@ -37,6 +37,7 @@ public class Issues {
   private final Map<String, User> usersByKey = new HashMap<String, User>();
   private final Map<String, Component> componentsByKey = new HashMap<String, Component>();
   private final Map<String, Component> projectsByKey = new HashMap<String, Component>();
+  private final Map<String, ActionPlan> actionPlansByKey = new HashMap<String, ActionPlan>();
   private Paging paging;
   private Boolean maxResultsReached;
 
@@ -83,6 +84,15 @@ public class Issues {
     return projectsByKey.get(issue.projectKey());
   }
 
+  public Collection<ActionPlan> 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;
index 82c71f7446d5f02d31d91d04f8a22721668e2225..a33d60931905bbe697f1e5f374e9c3b47e298979 100644 (file)
@@ -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 (file)
index 0000000..46718d5
--- /dev/null
@@ -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": "<p>\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</p>\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
index 55ff5e79e5361ce88dbbd9d7242b468b0a5d35e4..40e1a7ab1444e7eec7b0a0aecf208512062e08cf 100644 (file)
@@ -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",