*/
package org.sonar.server.qualityprofile;
+import org.elasticsearch.common.collect.Lists;
+import org.elasticsearch.common.collect.Maps;
+import org.sonar.api.rules.RulePriority;
+
+import java.util.List;
+import java.util.Map;
+
public class QProfileRule {
- private final String ruleSource;
- private final String activeRuleSource;
+ private final Map<String, Object> ruleSource;
+ private final Map<String, Object> activeRuleSource;
+
+ private final String key;
+ private final String name;
+ private final String description;
+ private final String status;
- public QProfileRule(String ruleSource, String activeRuleSource) {
+ private final RulePriority severity;
+ private final List<Param> params;
+
+ public QProfileRule(Map<String, Object> ruleSource, Map<String, Object> activeRuleSource) {
this.ruleSource = ruleSource;
this.activeRuleSource = activeRuleSource;
+
+ key = (String) ruleSource.get("key");
+ name = (String) ruleSource.get("name");
+ description = (String) ruleSource.get("description");
+ status = (String) ruleSource.get("status");
+
+ severity = RulePriority.valueOf((String) activeRuleSource.get("severity"));
+ params = Lists.newArrayList();
+ if (ruleSource.containsKey("params")) {
+ Map<String, Map<String, Object>> ruleParams = Maps.newHashMap();
+ for (Map<String, Object> ruleParam: (List<Map<String, Object>>) ruleSource.get("params")) {
+ ruleParams.put((String) ruleParam.get("key"), ruleParam);
+ }
+ Map<String, Map<String, Object>> activeRuleParams = Maps.newHashMap();
+ for (Map<String, Object> activeRuleParam: (List<Map<String, Object>>) activeRuleSource.get("params")) {
+ activeRuleParams.put((String) activeRuleParam.get("key"), activeRuleParam);
+ }
+ for(Map.Entry<String, Map<String, Object>> ruleParam: ruleParams.entrySet()) {
+ params.add(new Param(
+ (String) ruleParam.getValue().get("key"),
+ activeRuleParams.containsKey(ruleParam.getKey()) ? (String) activeRuleParams.get(ruleParam.getKey())
+ .get("value") : null,
+ (String) ruleParam.getValue().get("description"),
+ (String) ruleParam.getValue().get("defaultValue"),
+ (String) ruleParam.getValue().get("type")
+ ));
+ }
+ }
+ }
+
+ public Map<String, Object> ruleSource() {
+ return ruleSource;
+ }
+
+ public Map<String, Object> activeRuleSource() {
+ return activeRuleSource;
+ }
+
+ public String key() {
+ return key;
+ }
+
+ public String name() {
+ return name;
+ }
+
+ public String description() {
+ return description;
+ }
+
+ public String status() {
+ return status;
+ }
+
+ public RulePriority severity() {
+ return severity;
+ }
+
+ public List<Param> params() {
+ return params;
+ }
+
+ class Param {
+ private final String key;
+ private final String value;
+ private final String description;
+ private final String defaultValue;
+ private final String type;
+ public Param(String key, String value, String description, String defaultValue, String type) {
+ super();
+ this.key = key;
+ this.value = value;
+ this.description = description;
+ this.defaultValue = defaultValue;
+ this.type = type;
+ }
+ public String key() {
+ return key;
+ }
+ public String value() {
+ return value;
+ }
+ public String description() {
+ return description;
+ }
+ public String defaultValue() {
+ return defaultValue;
+ }
+ public String type() {
+ return type;
+ }
}
@Override
*/
package org.sonar.server.qualityprofile;
-import java.util.Collection;
import java.util.List;
public class QProfileRuleResult {
this.paging = paging;
}
- public Collection<QProfileRule> rules() {
+ public List<QProfileRule> rules() {
return rules;
}
import java.util.Collection;
import java.util.List;
+import java.util.Map;
import static org.elasticsearch.index.query.FilterBuilders.*;
import static org.elasticsearch.index.query.QueryBuilders.multiMatchQuery;
.setFrom(paging.offset());
SearchHits hits = index.executeRequest(builder);
- String[] activeRuleSources = new String[hits.getHits().length];
+ List<Map<String, Object>> activeRuleSources = Lists.newArrayList();
String[] parentIds = new String[hits.getHits().length];
int hitCounter = 0;
List<QProfileRule> result = Lists.newArrayList();
for (SearchHit hit: hits.getHits()) {
- activeRuleSources[hitCounter] = hit.sourceAsString();
+ activeRuleSources.add(hit.sourceAsMap());
parentIds[hitCounter] = hit.field("_parent").value();
hitCounter ++;
}
.execute().actionGet().getResponses();
for (int i = 0; i < hitCounter; i ++) {
- result.add(new QProfileRule(responses[i].getResponse().getSourceAsString(), activeRuleSources[i]));
+ result.add(new QProfileRule(responses[i].getResponse().getSourceAsMap(), activeRuleSources.get(i)));
}
}
import org.junit.Before;
import org.junit.Test;
import org.sonar.api.config.Settings;
+import org.sonar.api.rules.RulePriority;
import org.sonar.core.profiling.Profiling;
import org.sonar.server.qualityprofile.Paging;
+import org.sonar.server.qualityprofile.QProfileRule;
import org.sonar.server.search.SearchIndex;
import org.sonar.server.search.SearchNode;
import org.sonar.test.TestUtils;
+import java.util.List;
+
import static org.fest.assertions.Assertions.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
esSetup.client().prepareBulk()
.add(Requests.indexRequest().index("rules").type("rule").source(testFileAsString("should_find_active_rules/rule25.json")))
.add(Requests.indexRequest().index("rules").type("rule").source(testFileAsString("should_find_active_rules/rule759.json")))
+ .add(Requests.indexRequest().index("rules").type("rule").source(testFileAsString("should_find_active_rules/rule1482.json")))
.add(Requests.indexRequest().index("rules").type("active_rule").parent("25").source(testFileAsString("should_find_active_rules/active_rule25.json")))
.add(Requests.indexRequest().index("rules").type("active_rule").parent("759").source(testFileAsString("should_find_active_rules/active_rule391.json")))
.add(Requests.indexRequest().index("rules").type("active_rule").parent("759").source(testFileAsString("should_find_active_rules/active_rule523.json")))
+ .add(Requests.indexRequest().index("rules").type("active_rule").parent("1482").source(testFileAsString("should_find_active_rules/active_rule2702.json")))
.setRefresh(true).execute().actionGet();
Paging paging = Paging.create(10, 1);
// All rules for profile 1
- assertThat(profileRules.searchActiveRules(ProfileRuleQuery.create(1), paging).rules()).hasSize(2);
+ List<QProfileRule> rules1 = profileRules.searchActiveRules(ProfileRuleQuery.create(1), paging).rules();
+ assertThat(rules1).hasSize(3);
+ assertThat(rules1.get(0).key()).isEqualTo("DM_CONVERT_CASE");
+ assertThat(rules1.get(0).severity()).isEqualTo(RulePriority.MINOR);
// All rules for profile 2
- assertThat(profileRules.searchActiveRules(ProfileRuleQuery.create(2), paging).rules()).hasSize(1);
+ List<QProfileRule> rules2 = profileRules.searchActiveRules(ProfileRuleQuery.create(2), paging).rules();
+ assertThat(rules2).hasSize(1);
+ assertThat(rules2.get(0).ruleSource().get("id")).isEqualTo(759);
+ assertThat(rules2.get(0).activeRuleSource().get("id")).isEqualTo(523);
// Inexistent profile
assertThat(profileRules.searchActiveRules(ProfileRuleQuery.create(3), paging).rules()).hasSize(0);
// Match on repositoryKey
assertThat(profileRules.searchActiveRules(ProfileRuleQuery.create(1).addRepositoryKeys("findbugs"), paging).rules()).hasSize(1);
+
+ // Match on key, rule has parameters
+ List<QProfileRule> rulesWParam = profileRules.searchActiveRules(ProfileRuleQuery.create(1).setNameOrKey("ArchitecturalConstraint"), paging).rules();
+ assertThat(rulesWParam).hasSize(1);
+ assertThat(rulesWParam.get(0).params()).hasSize(2);
}
private String testFileAsString(String testFile) throws Exception {
-{"id": 25, "severity": "INFO", "profileId": 1, "inheritance": null}
\ No newline at end of file
+{"id": 25, "severity": "MINOR", "profileId": 1, "inheritance": null}
--- /dev/null
+{"id":2702,"severity":"CRITICAL","profileId":1,"inheritance":null,"params":[{"key":"fromClasses","value":"**.core.**"},{"key":"toClasses","value":"**.server.**"}]}
--- /dev/null
+{"id":1482,"key":"ArchitecturalConstraint","language":"java","name":"Architectural constraint","description":"<p>A source code comply to an architectural model when it fully\n\tadheres to a set of architectural constraints. A constraint allows to\n\tdeny references between classes by pattern.</p>\n<p>You can for instance use this rule to :</p>\n<ul>\n\t<li>forbid access to **.web.** from **.dao.** classes</li>\n\t<li>forbid access to java.util.Vector, java.util.Hashtable and\n\t\tjava.util.Enumeration from any classes</li>\n\t<li>forbid access to java.sql.** from **.ui.** and **.web.**\n\t\tclasses</li>\n</ul>","parentKey":null,"repositoryKey":"squid","severity":"MAJOR","status":"READY","createdAt":"2013-12-11T13:48:00.799Z","updatedAt":"2013-12-13T17:26:35.767Z","params":[{"key":"toClasses","type":"STRING","defaultValue":"","description":"Mandatory. Ex : java.util.Vector, java.util.Hashtable, java.util.Enumeration"},{"key":"fromClasses","type":"STRING","defaultValue":"","description":"Optional. If this property is not defined, all classes should adhere to this constraint. Ex : **.web.**"}]}