aboutsummaryrefslogtreecommitdiffstats
path: root/sonar-plugin-api
diff options
context:
space:
mode:
authorSimon Brandhof <simon.brandhof@gmail.com>2013-04-17 18:29:35 +0200
committerSimon Brandhof <simon.brandhof@gmail.com>2013-04-17 18:36:56 +0200
commit7660b174b186527b5df5354295886c42dec2109d (patch)
tree0ed5f14607232f9161741a486e5d67ca48440e93 /sonar-plugin-api
parent398c82a5810e446a22b31d204a87ad7fd806a068 (diff)
downloadsonarqube-7660b174b186527b5df5354295886c42dec2109d.tar.gz
sonarqube-7660b174b186527b5df5354295886c42dec2109d.zip
SONAR-3755 support the parameter "rules" in /api/issues/search
Diffstat (limited to 'sonar-plugin-api')
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/issue/IssueChange.java146
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/issue/IssueQuery.java93
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/issue/JRubyIssues.java2
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/rule/RuleKey.java22
-rw-r--r--sonar-plugin-api/src/test/java/org/sonar/api/issue/IssueChangeTest.java41
-rw-r--r--sonar-plugin-api/src/test/java/org/sonar/api/issue/IssueQueryTest.java29
-rw-r--r--sonar-plugin-api/src/test/java/org/sonar/api/rule/RuleKeyTest.java40
7 files changed, 304 insertions, 69 deletions
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/issue/IssueChange.java b/sonar-plugin-api/src/main/java/org/sonar/api/issue/IssueChange.java
new file mode 100644
index 00000000000..1587ca25453
--- /dev/null
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/issue/IssueChange.java
@@ -0,0 +1,146 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2008-2012 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar 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.
+ *
+ * Sonar 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 Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.api.issue;
+
+import javax.annotation.Nullable;
+import java.util.Collections;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+/**
+ * @since 3.6
+ */
+public class IssueChange {
+ private String severity = null;
+ private String comment = null;
+ private Boolean manualSeverity = null;
+ private String message = null;
+ private boolean lineChanged = false;
+ private Integer line = null;
+ private boolean costChanged = false;
+ private Double cost = null;
+ private String resolution = null;
+ private boolean assigneeLoginChanged = false;
+ private String assigneeLogin = null;
+ private Map<String, String> attributes = null;
+
+ private IssueChange() {
+ }
+
+ public static IssueChange create() {
+ return new IssueChange();
+ }
+
+ public boolean hasChanges() {
+ return severity != null || comment != null || manualSeverity != null || message != null ||
+ lineChanged || costChanged || resolution != null || assigneeLoginChanged || attributes != null;
+ }
+
+ public IssueChange setSeverity(String severity) {
+ this.severity = severity;
+ return this;
+ }
+
+ public IssueChange setComment(String comment) {
+ this.comment = comment;
+ return this;
+ }
+
+ public IssueChange setManualSeverity(boolean b) {
+ this.manualSeverity = b;
+ return this;
+ }
+
+ public IssueChange setMessage(String message) {
+ this.message = message;
+ return this;
+ }
+
+ public IssueChange setLine(@Nullable Integer line) {
+ this.lineChanged = true;
+ this.line = line;
+ return this;
+ }
+
+ public IssueChange setCost(@Nullable Double cost) {
+ this.costChanged = true;
+ this.cost = cost;
+ return this;
+ }
+
+ public IssueChange setResolution(String resolution) {
+ this.resolution = resolution;
+ return this;
+ }
+
+ public IssueChange setAssigneeLogin(@Nullable String assigneeLogin) {
+ this.assigneeLoginChanged = true;
+ this.assigneeLogin = assigneeLogin;
+ return this;
+ }
+
+ public IssueChange setAttribute(String key, @Nullable String value) {
+ if (attributes == null && value != null) {
+ attributes = new LinkedHashMap<String, String>();
+ }
+ if (value != null) {
+ attributes.put(key, value);
+ } else if (attributes != null) {
+ attributes.remove(key);
+ }
+ return this;
+ }
+
+ public String severity() {
+ return severity;
+ }
+
+ public String comment() {
+ return comment;
+ }
+
+ public Boolean manualSeverity() {
+ return manualSeverity;
+ }
+
+ public String message() {
+ return message;
+ }
+
+ public Integer line() {
+ return line;
+ }
+
+ public Double cost() {
+ return cost;
+ }
+
+ public String resolution() {
+ return resolution;
+ }
+
+ public String assigneeLogin() {
+ return assigneeLogin;
+ }
+
+ public Map<String, String> attributes() {
+ return attributes == null ? Collections.<String, String>emptyMap() : new LinkedHashMap<String, String>(attributes);
+ }
+}
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/issue/IssueQuery.java b/sonar-plugin-api/src/main/java/org/sonar/api/issue/IssueQuery.java
index ab6ec98a9cd..9ab187dab22 100644
--- a/sonar-plugin-api/src/main/java/org/sonar/api/issue/IssueQuery.java
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/issue/IssueQuery.java
@@ -22,9 +22,10 @@ package org.sonar.api.issue;
import com.google.common.base.Preconditions;
import org.apache.commons.lang.builder.ReflectionToStringBuilder;
+import org.sonar.api.rule.RuleKey;
import java.util.Date;
-import java.util.List;
+import java.util.Collection;
/**
* TODO add javadoc
@@ -33,16 +34,15 @@ import java.util.List;
*/
public class IssueQuery {
- private final List<String> keys;
- private final List<String> severities;
- private final List<String> statuses;
- private final List<String> resolutions;
- private final List<String> components;
- private final List<String> componentRoots;
- private final String ruleRepository;
- private final String rule;
- private final List<String> userLogins;
- private final List<String> assigneeLogins;
+ private final Collection<String> keys;
+ private final Collection<String> severities;
+ private final Collection<String> statuses;
+ private final Collection<String> resolutions;
+ private final Collection<String> components;
+ private final Collection<String> componentRoots;
+ private final Collection<RuleKey> rules;
+ private final Collection<String> userLogins;
+ private final Collection<String> assigneeLogins;
private final Date createdAfter;
private final Date createdBefore;
private final int limit, offset;
@@ -54,8 +54,7 @@ public class IssueQuery {
this.resolutions = builder.resolutions;
this.components = builder.components;
this.componentRoots = builder.componentRoots;
- this.ruleRepository = builder.ruleRepository;
- this.rule = builder.rule;
+ this.rules = builder.rules;
this.userLogins = builder.userLogins;
this.assigneeLogins = builder.assigneeLogins;
this.createdAfter = builder.createdAfter;
@@ -64,43 +63,39 @@ public class IssueQuery {
this.offset = builder.offset;
}
- public List<String> keys() {
+ public Collection<String> keys() {
return keys;
}
- public List<String> severities() {
+ public Collection<String> severities() {
return severities;
}
- public List<String> statuses() {
+ public Collection<String> statuses() {
return statuses;
}
- public List<String> resolutions() {
+ public Collection<String> resolutions() {
return resolutions;
}
- public List<String> components() {
+ public Collection<String> components() {
return components;
}
- public List<String> componentRoots() {
+ public Collection<String> componentRoots() {
return componentRoots;
}
- public String ruleRepository() {
- return ruleRepository;
+ public Collection<RuleKey> rules() {
+ return rules;
}
- public String rule() {
- return rule;
- }
-
- public List<String> userLogins() {
+ public Collection<String> userLogins() {
return userLogins;
}
- public List<String> assigneeLogins() {
+ public Collection<String> assigneeLogins() {
return assigneeLogins;
}
@@ -138,16 +133,15 @@ public class IssueQuery {
private static final int MAX_LIMIT = 5000;
private static final int DEFAULT_OFFSET = 0;
- private List<String> keys;
- private List<String> severities;
- private List<String> statuses;
- private List<String> resolutions;
- private List<String> components;
- private List<String> componentRoots;
- private String ruleRepository;
- private String rule;
- private List<String> userLogins;
- private List<String> assigneeLogins;
+ private Collection<String> keys;
+ private Collection<String> severities;
+ private Collection<String> statuses;
+ private Collection<String> resolutions;
+ private Collection<String> components;
+ private Collection<String> componentRoots;
+ private Collection<RuleKey> rules;
+ private Collection<String> userLogins;
+ private Collection<String> assigneeLogins;
private Date createdAfter;
private Date createdBefore;
private int limit = DEFAULT_LIMIT;
@@ -156,52 +150,47 @@ public class IssueQuery {
private Builder() {
}
- public Builder keys(List<String> l) {
+ public Builder keys(Collection<String> l) {
this.keys = l;
return this;
}
- public Builder severities(List<String> l) {
+ public Builder severities(Collection<String> l) {
this.severities = l;
return this;
}
- public Builder statuses(List<String> l) {
+ public Builder statuses(Collection<String> l) {
this.statuses = l;
return this;
}
- public Builder resolutions(List<String> l) {
+ public Builder resolutions(Collection<String> l) {
this.resolutions = l;
return this;
}
- public Builder components(List<String> l) {
+ public Builder components(Collection<String> l) {
this.components = l;
return this;
}
- public Builder componentRoots(List<String> l) {
+ public Builder componentRoots(Collection<String> l) {
this.componentRoots = l;
return this;
}
- public Builder ruleRepository(String ruleRepository) {
- this.ruleRepository = ruleRepository;
- return this;
- }
-
- public Builder rule(String rule) {
- this.rule = rule;
+ public Builder rules(Collection<RuleKey> rules) {
+ this.rules = rules;
return this;
}
- public Builder userLogins(List<String> l) {
+ public Builder userLogins(Collection<String> l) {
this.userLogins = l;
return this;
}
- public Builder assigneeLogins(List<String> l) {
+ public Builder assigneeLogins(Collection<String> l) {
this.assigneeLogins = l;
return this;
}
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/issue/JRubyIssues.java b/sonar-plugin-api/src/main/java/org/sonar/api/issue/JRubyIssues.java
index af3a0a0bffc..6ec537a8399 100644
--- a/sonar-plugin-api/src/main/java/org/sonar/api/issue/JRubyIssues.java
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/issue/JRubyIssues.java
@@ -24,7 +24,7 @@ import org.sonar.api.ServerComponent;
import java.util.Map;
/**
- * Facade for JRuby on Rails extensions.
+ * Facade for JRuby on Rails extensions to request issues.
* <p>
* Reference from Ruby code : <code>Api.issues</code>
* </p>
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/rule/RuleKey.java b/sonar-plugin-api/src/main/java/org/sonar/api/rule/RuleKey.java
index 6227d717646..a286b0f5750 100644
--- a/sonar-plugin-api/src/main/java/org/sonar/api/rule/RuleKey.java
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/rule/RuleKey.java
@@ -20,9 +20,14 @@
package org.sonar.api.rule;
import com.google.common.base.Preconditions;
+import com.google.common.base.Strings;
import java.io.Serializable;
+/**
+ * Key of a rule. Unique among all the rule repositories.
+ * @since 3.6
+ */
public class RuleKey implements Serializable {
private final String repository, rule;
@@ -31,20 +36,35 @@ public class RuleKey implements Serializable {
this.rule = rule;
}
+ /**
+ * Create a key. Parameters are NOT null.
+ */
public static RuleKey of(String repository, String rule) {
+ Preconditions.checkArgument(!Strings.isNullOrEmpty(repository), "Repository must be set");
+ Preconditions.checkArgument(!Strings.isNullOrEmpty(rule), "Rule must be set");
return new RuleKey(repository, rule);
}
+ /**
+ * Create a key from a string representation (see {@link #toString()}. An {@link IllegalArgumentException} is raised
+ * if the format is not valid.
+ */
public static RuleKey parse(String s) {
String[] split = s.split(":");
Preconditions.checkArgument(split.length == 2, "Bad format of rule key: " + s);
return RuleKey.of(split[0], split[1]);
}
+ /**
+ * Never null
+ */
public String repository() {
return repository;
}
+ /**
+ * Never null
+ */
public String rule() {
return rule;
}
@@ -75,7 +95,7 @@ public class RuleKey implements Serializable {
}
/**
- * Do not change this format because it's used by customers of the API (rails, ...)
+ * Format is "repository:rule", for example "squid:AvoidCycle"
*/
@Override
public String toString() {
diff --git a/sonar-plugin-api/src/test/java/org/sonar/api/issue/IssueChangeTest.java b/sonar-plugin-api/src/test/java/org/sonar/api/issue/IssueChangeTest.java
new file mode 100644
index 00000000000..bd51b76127a
--- /dev/null
+++ b/sonar-plugin-api/src/test/java/org/sonar/api/issue/IssueChangeTest.java
@@ -0,0 +1,41 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2008-2012 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar 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.
+ *
+ * Sonar 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 Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.api.issue;
+
+import org.junit.Test;
+
+import static org.fest.assertions.Assertions.assertThat;
+
+public class IssueChangeTest {
+ @Test
+ public void should_not_have_changes_by_default() throws Exception {
+ IssueChange change = IssueChange.create();
+ assertThat(change.hasChanges()).isFalse();
+ assertThat(change.severity()).isNull();
+ assertThat(change.cost()).isNull();
+ assertThat(change.assigneeLogin()).isNull();
+ assertThat(change.line()).isNull();
+ assertThat(change.comment()).isNull();
+ assertThat(change.message()).isNull();
+ assertThat(change.resolution()).isNull();
+ assertThat(change.manualSeverity()).isNull();
+ assertThat(change.attributes()).isEmpty();
+ }
+}
diff --git a/sonar-plugin-api/src/test/java/org/sonar/api/issue/IssueQueryTest.java b/sonar-plugin-api/src/test/java/org/sonar/api/issue/IssueQueryTest.java
index 5b3c4491ee4..324d2d78c3c 100644
--- a/sonar-plugin-api/src/test/java/org/sonar/api/issue/IssueQueryTest.java
+++ b/sonar-plugin-api/src/test/java/org/sonar/api/issue/IssueQueryTest.java
@@ -21,6 +21,7 @@ package org.sonar.api.issue;
import com.google.common.collect.Lists;
import org.junit.Test;
+import org.sonar.api.rule.RuleKey;
import org.sonar.api.rule.Severity;
import java.util.Date;
@@ -36,27 +37,25 @@ public class IssueQueryTest {
.severities(Lists.newArrayList(Severity.BLOCKER))
.statuses(Lists.newArrayList(Issue.STATUS_RESOLVED))
.resolutions(Lists.newArrayList(Issue.RESOLUTION_FALSE_POSITIVE))
- .components(Lists.newArrayList("components"))
- .componentRoots(Lists.newArrayList("componentRoots"))
- .ruleRepository("ruleRepository")
- .rule("rule")
- .userLogins(Lists.newArrayList("user"))
+ .components(Lists.newArrayList("org/struts/Action.java"))
+ .componentRoots(Lists.newArrayList("org.struts:core"))
+ .rules(Lists.newArrayList(RuleKey.of("squid", "AvoidCycle")))
+ .userLogins(Lists.newArrayList("crunky"))
.assigneeLogins(Lists.newArrayList("gargantua"))
.createdAfter(new Date())
.createdBefore(new Date())
.limit(125)
.offset(33)
.build();
- assertThat(query.keys()).containsExactly("ABCDE");
- assertThat(query.severities()).containsExactly(Severity.BLOCKER);
- assertThat(query.statuses()).containsExactly(Issue.STATUS_RESOLVED);
- assertThat(query.resolutions()).containsExactly(Issue.RESOLUTION_FALSE_POSITIVE);
- assertThat(query.components()).containsExactly("components");
- assertThat(query.componentRoots()).containsExactly("componentRoots");
- assertThat(query.userLogins()).containsExactly("user");
- assertThat(query.assigneeLogins()).containsExactly("gargantua");
- assertThat(query.ruleRepository()).isEqualTo("ruleRepository");
- assertThat(query.rule()).isEqualTo("rule");
+ assertThat(query.keys()).containsOnly("ABCDE");
+ assertThat(query.severities()).containsOnly(Severity.BLOCKER);
+ assertThat(query.statuses()).containsOnly(Issue.STATUS_RESOLVED);
+ assertThat(query.resolutions()).containsOnly(Issue.RESOLUTION_FALSE_POSITIVE);
+ assertThat(query.components()).containsOnly("org/struts/Action.java");
+ assertThat(query.componentRoots()).containsOnly("org.struts:core");
+ assertThat(query.userLogins()).containsOnly("crunky");
+ assertThat(query.assigneeLogins()).containsOnly("gargantua");
+ assertThat(query.rules()).containsOnly(RuleKey.of("squid", "AvoidCycle"));
assertThat(query.createdAfter()).isNotNull();
assertThat(query.createdBefore()).isNotNull();
assertThat(query.limit()).isEqualTo(125);
diff --git a/sonar-plugin-api/src/test/java/org/sonar/api/rule/RuleKeyTest.java b/sonar-plugin-api/src/test/java/org/sonar/api/rule/RuleKeyTest.java
index d4411fb860f..aee99313bbc 100644
--- a/sonar-plugin-api/src/test/java/org/sonar/api/rule/RuleKeyTest.java
+++ b/sonar-plugin-api/src/test/java/org/sonar/api/rule/RuleKeyTest.java
@@ -33,6 +33,46 @@ public class RuleKeyTest {
}
@Test
+ public void repository_must_not_be_null() throws Exception {
+ try {
+ RuleKey.of(null, "NullDeref");
+ fail();
+ } catch (IllegalArgumentException e) {
+ assertThat(e).hasMessage("Repository must be set");
+ }
+ }
+
+ @Test
+ public void repository_must_not_be_empty() throws Exception {
+ try {
+ RuleKey.of("", "NullDeref");
+ fail();
+ } catch (IllegalArgumentException e) {
+ assertThat(e).hasMessage("Repository must be set");
+ }
+ }
+
+ @Test
+ public void rule_must_not_be_null() throws Exception {
+ try {
+ RuleKey.of("squid", null);
+ fail();
+ } catch (IllegalArgumentException e) {
+ assertThat(e).hasMessage("Rule must be set");
+ }
+ }
+
+ @Test
+ public void rule_must_not_be_empty() throws Exception {
+ try {
+ RuleKey.of("squid", "");
+ fail();
+ } catch (IllegalArgumentException e) {
+ assertThat(e).hasMessage("Rule must be set");
+ }
+ }
+
+ @Test
public void should_encode_and_decode_string() throws Exception {
RuleKey key = RuleKey.of("squid", "NullDeref");
String serialized = key.toString();