import java.io.Serializable;
/**
- * Created by gamars on 05/05/14.
*
* @since 4.4
*/
* if the format is not valid.
*/
public static QualityProfileKey parse(String s) {
- String[] split = s.split(":");
- Preconditions.checkArgument(split.length == 3, "Bad format of activeRule key: " + s);
+ String[] split = s.trim().split(":");
+ Preconditions.checkArgument(split.length == 2, "Bad format of QualityProfileKey: " + s);
return QualityProfileKey.of(split[0], split[1]);
}
}
/**
- * Format is "qProfile:lang", for example "Java:javascript"
+ * Format is "profile:lang", for example "Java:javascript"
*/
@Override
public String toString() {
.field("type", "object")
.startObject("properties")
.startObject("_id")
- .field("type","string")
+ .field("type", "string")
.endObject()
.startObject(ActiveRuleNormalizer.ActiveRuleParamField.NAME.key())
- .field("type", "string")
- .endObject()
- .startObject(ActiveRuleNormalizer.ActiveRuleParamField.VALUE.key())
- .field("type", "string")
- .endObject()
- .endObject();
+ .field("type", "string")
+ .endObject()
+ .startObject(ActiveRuleNormalizer.ActiveRuleParamField.VALUE.key())
+ .field("type", "string")
+ .endObject()
+ .endObject();
mapping.endObject();
mapping.endObject().endObject();
return new ActiveRuleDoc(response.getSource());
}
- /** finder methods */
- public List<ActiveRule> findByRule(RuleKey key){
+ /**
+ * finder methods
+ */
+ public List<ActiveRule> findByRule(RuleKey key) {
SearchRequestBuilder request = getClient().prepareSearch(this.getIndexName())
.setQuery(QueryBuilders
.hasParentQuery(this.getParentType(),
QueryBuilders.idsQuery(this.getParentType())
- .addIds(key.toString())))
+ .addIds(key.toString())
+ ))
.setRouting(key.toString());
SearchResponse response = request.get();
List<ActiveRule> activeRules = new ArrayList<ActiveRule>();
- for(SearchHit hit:response.getHits()){
+ for (SearchHit hit : response.getHits()) {
activeRules.add(new ActiveRuleDoc(hit.getSource()));
}
return new RuleIndexDefinition().getIndexType();
}
- public ActiveRule getByRuleKeyAndProfileKey(RuleKey ruleKey, QualityProfileKey qualityProfileKey){
- return null;
+ public ActiveRule getByRuleKeyAndProfileKey(RuleKey ruleKey, QualityProfileKey qualityProfileKey) {
+ return toDoc(getClient().prepareGet()
+ .setRouting(ruleKey.toString())
+ .setType(this.getIndexType())
+ .setIndex(this.getIndexName())
+ .setId(ActiveRuleKey.of(qualityProfileKey, ruleKey).toString())
+ .get());
}
}
import org.sonar.api.rule.RuleKey;
import org.sonar.core.permission.GlobalPermissions;
import org.sonar.core.persistence.DbSession;
+import org.sonar.core.qualityprofile.db.QualityProfileKey;
import org.sonar.core.rule.RuleDto;
import org.sonar.server.db.DbClient;
import org.sonar.server.qualityprofile.ActiveRule;
import javax.annotation.CheckForNull;
import javax.annotation.Nullable;
import java.util.Date;
+import java.util.List;
import java.util.Set;
/**
}
public RuleResult search(RuleQuery query, QueryOptions options) {
- // keep only supported fields and add the fields to always return
+
+ /** keep only supported fields and add the fields to always return */
options.filterFieldsToReturn(RuleIndex.PUBLIC_FIELDS);
- RuleResult result = index.search(query, options);
- for(Rule rule:result.getHits()){
- for(ActiveRule activeRule:activeRuleIndex.findByRule(rule.key())){
- result.getActiveRules().put(rule.key().toString(),activeRule);
+ RuleResult result = index.search(query, options);
+
+ /** Check for activation */
+ if (query.getActivation() != null && !query.getActivation().isEmpty()) {
+ if (query.getActivation().equalsIgnoreCase("true")) {
+ for (Rule rule : result.getHits()) {
+ if(query.getqProfileKey() == null){
+ throw new IllegalStateException("\"activation=true\" requires a profile key!");
+ }
+ QualityProfileKey qualityProfileKey = QualityProfileKey.parse(query.getqProfileKey());
+ result.getActiveRules().put(rule.key().toString(),
+ activeRuleIndex.getByRuleKeyAndProfileKey(rule.key(),qualityProfileKey));
+ }
+ } else if (query.getActivation().equalsIgnoreCase("all")) {
+ for (Rule rule : result.getHits()) {
+ List<ActiveRule> activeRules = activeRuleIndex.findByRule(rule.key());
+ for (ActiveRule activeRule : activeRules) {
+ result.getActiveRules().put(rule.key().toString(), activeRule);
+ }
+ }
}
}
+
return result;
}
/**
* Extend rule description by adding a note.
- * @param ruleKey the required key
+ *
+ * @param ruleKey the required key
* @param markdownNote markdown text. <code>null</code> to remove current note.
*/
public void setNote(RuleKey ruleKey, @Nullable String markdownNote) {
protected SearchRequestBuilder buildRequest(RuleQuery query, QueryOptions options) {
SearchRequestBuilder esSearch = getClient()
.prepareSearch(this.getIndexName())
+ .setTypes(this.getIndexType())
.setIndices(this.getIndexName());
/* Integrate Facets */
public class RuleQuery {
+
+
public static enum SortField {
KEY(RuleNormalizer.RuleField.KEY),
REPOSITORY(RuleNormalizer.RuleField.REPOSITORY),
private Boolean hasDebtCharacteristic;
private SortField sortField;
private boolean ascendingSort = true;
+ private String activation;
+ private String qProfileKey;
+
/**
* @see org.sonar.server.rule2.RuleService#newRuleQuery()
public RuleQuery() {
}
+ @CheckForNull
+ public String getqProfileKey() {
+ return qProfileKey;
+ }
+
+ public RuleQuery setqProfileKey(String qProfileKey) {
+ this.qProfileKey = qProfileKey;
+ return this;
+ }
+
+ public RuleQuery setActivation(String activation) {
+ this.activation = activation;
+ return this;
+ }
+
+ @CheckForNull
+ public String getActivation(){
+ return this.activation;
+ }
+
@CheckForNull
public String getKey() {
return key;
private static final String PARAM_TEXT_QUERY = "q";
private static final String PARAM_REPOSITORIES = "repositories";
+ private static final String PARAM_ACTIVATION = "activation";
+ private static final String PARAM_QPROFILE = "qprofile";
private static final String PARAM_SEVERITIES = "severities";
private static final String PARAM_STATUSES = "statuses";
private static final String PARAM_LANGUAGES = "languages";
.setExampleValue("security,java8");
action
- .createParam("qprofile")
+ .createParam(PARAM_QPROFILE)
.setDescription("Key of Quality profile")
.setExampleValue("java:Sonar way");
action
- .createParam("activation")
+ .createParam(PARAM_ACTIVATION)
.setDescription("Used only if 'qprofile' is set")
.setExampleValue("java:Sonar way")
.setPossibleValues("false", "true", "all");
query.setLanguages(request.paramAsStrings(PARAM_LANGUAGES));
query.setDebtCharacteristics(request.paramAsStrings(PARAM_DEBT_CHARACTERISTICS));
query.setHasDebtCharacteristic(request.paramAsBoolean(PARAM_HAS_DEBT_CHARACTERISTIC));
+ query.setActivation(request.param(PARAM_ACTIVATION));
+ query.setqProfileKey(request.param(PARAM_QPROFILE));
// TODO move to QueryOptions ?
query.setSortField(RuleQuery.SortField.valueOfOrNull(request.param(PARAM_SORT)));
import org.sonar.core.permission.GlobalPermissions;
import org.sonar.core.persistence.DbSession;
import org.sonar.core.persistence.MyBatis;
+import org.sonar.core.qualityprofile.db.ActiveRuleDto;
+import org.sonar.core.qualityprofile.db.QualityProfileDao;
+import org.sonar.core.qualityprofile.db.QualityProfileDto;
import org.sonar.core.rule.RuleDto;
import org.sonar.server.exceptions.ForbiddenException;
import org.sonar.server.exceptions.NotFoundException;
+import org.sonar.server.qualityprofile.persistence.ActiveRuleDao;
import org.sonar.server.rule2.index.RuleIndex;
+import org.sonar.server.rule2.index.RuleQuery;
+import org.sonar.server.rule2.index.RuleResult;
import org.sonar.server.rule2.persistence.RuleDao;
+import org.sonar.server.search.QueryOptions;
import org.sonar.server.tester.ServerTester;
import org.sonar.server.user.MockUserSession;
public class RuleServiceMediumTest {
@ClassRule
- public static ServerTester tester = new ServerTester();
+ public static ServerTester tester = new ServerTester()
+ .setProperty("sonar.es.http.port","9200");
RuleDao dao = tester.get(RuleDao.class);
RuleIndex index = tester.get(RuleIndex.class);
// assertThat(rule.getNoteUpdatedAt()).isNull();
// assertThat(rule.getNoteUserLogin()).isNull();
+ }
+
+ @Test
+ public void test_search_activation_on_rules() throws InterruptedException {
+
+ // 1. Create in DB
+ QualityProfileDto qprofile1 = QualityProfileDto.createFor("profile1","java");
+ QualityProfileDto qprofile2 = QualityProfileDto.createFor("profile2","java");
+ tester.get(QualityProfileDao.class).insert(qprofile1, dbSession);
+ tester.get(QualityProfileDao.class).insert(qprofile2, dbSession);
+
+ RuleDto rule1 = newRuleDto(RuleKey.of("test", "rule1"));
+ RuleDto rule2 = newRuleDto(RuleKey.of("test", "rule2"));
+ tester.get(RuleDao.class).insert(rule1, dbSession);
+ tester.get(RuleDao.class).insert(rule2, dbSession);
+
+ ActiveRuleDto activeRule1 = ActiveRuleDto.createFor(qprofile1, rule1)
+ .setSeverity(Severity.BLOCKER);
+ ActiveRuleDto activeRule2 = ActiveRuleDto.createFor(qprofile1, rule2)
+ .setSeverity(Severity.BLOCKER);
+ ActiveRuleDto activeRule3 = ActiveRuleDto.createFor(qprofile2, rule2)
+ .setSeverity(Severity.BLOCKER);
+ tester.get(ActiveRuleDao.class).insert(activeRule1, dbSession);
+ tester.get(ActiveRuleDao.class).insert(activeRule2, dbSession);
+ tester.get(ActiveRuleDao.class).insert(activeRule3, dbSession);
+
+ dbSession.commit();
+ service.refresh();
+
+
+ // 2. test in DB
+ assertThat(tester.get(RuleDao.class).findAll(dbSession)).hasSize(2);
+ assertThat(tester.get(ActiveRuleDao.class).findByRule(rule1, dbSession)).hasSize(1);
+ assertThat(tester.get(ActiveRuleDao.class).findByRule(rule2, dbSession)).hasSize(2);
+
+
+ // 3. Test for ALL activations
+ RuleQuery query = new RuleQuery()
+ .setActivation("all");
+ RuleResult result = service.search(query, new QueryOptions());
+ assertThat(result.getActiveRules().values()).hasSize(3);
+
+ // 4. Test for NO active rules
+ query = new RuleQuery()
+ .setActivation("false");
+ result = service.search(query, new QueryOptions());
+ assertThat(result.getActiveRules().values()).hasSize(0);
+
+ // 4. Test for active rules of QProfile
+ query = new RuleQuery()
+ .setActivation("true")
+ .setqProfileKey(qprofile1.getKey().toString());
+ result = service.search(query, new QueryOptions());
+ assertThat(result.getActiveRules().values()).hasSize(2);
+
+
}
private RuleDto newRuleDto(RuleKey ruleKey) {
@Test
- public void search_active_rules() throws Exception {
+ public void search_all_active_rules() throws Exception {
QualityProfileDto profile = newQualityProfile();
tester.get(QualityProfileDao.class).insert(profile, session);
MockUserSession.set();
WsTester.TestRequest request = wsTester.newGetRequest("api/rules", "search");
request.setParam("q","S001");
+ request.setParam("activation","all");
WsTester.Result result = request.execute();
result.assertJson(this.getClass(),"search_active_rules.json");
}
@Test
- public void search_active_rules_params() throws Exception {
+ public void search_no_active_rules() throws Exception {
QualityProfileDto profile = newQualityProfile();
tester.get(QualityProfileDao.class).insert(profile, session);
RuleDto rule = newRuleDto(RuleKey.of(profile.getLanguage(), "S001"));
- ruleDao.insert(rule, session);
+ ruleDao.insert(rule, session);
+
+ ActiveRuleDto activeRule = newActiveRule(profile, rule);
+ tester.get(ActiveRuleDao.class).insert(activeRule, session);
session.commit();
+ tester.get(RuleService.class).refresh();
+
+
+ MockUserSession.set();
+ WsTester.TestRequest request = wsTester.newGetRequest("api/rules2", "search");
+ request.setParam("q","S001");
+ request.setParam("activation","false");
+ WsTester.Result result = request.execute();
+
+ result.assertJson(this.getClass(),"search_no_active_rules.json");
+ }
+
+ @Test
+ public void search_profile_active_rules() throws Exception {
+ QualityProfileDto profile = newQualityProfile().setName("p1");
+ tester.get(QualityProfileDao.class).insert(profile, session);
+
+ QualityProfileDto profile2 = newQualityProfile().setName("p2");
+ tester.get(QualityProfileDao.class).insert(profile2, session);
+
+ session.commit();
+
+ RuleDto rule = newRuleDto(RuleKey.of(profile.getLanguage(), "S001"));
+ ruleDao.insert(rule, session);
+
+ ActiveRuleDto activeRule = newActiveRule(profile, rule);
+ tester.get(ActiveRuleDao.class).insert(activeRule, session);
+ ActiveRuleDto activeRule2 = newActiveRule(profile2, rule);
+ tester.get(ActiveRuleDao.class).insert(activeRule2, session);
+
+ session.commit();
+ tester.get(RuleService.class).refresh();
+
+
+ MockUserSession.set();
+ WsTester.TestRequest request = wsTester.newGetRequest("api/rules2", "search");
+ request.setParam("q","S001");
+ request.setParam("activation","true");
+ request.setParam("qprofile",profile2.getKey().toString());
+ WsTester.Result result = request.execute();
+
+ result.assertJson(this.getClass(),"search_profile_active_rules.json");
+ }
+
+ @Test
+ public void search_all_active_rules_params() throws Exception {
+ QualityProfileDto profile = newQualityProfile();
+ tester.get(QualityProfileDao.class).insert(profile, session);
+
+ RuleDto rule = newRuleDto(RuleKey.of(profile.getLanguage(), "S001"));
+ ruleDao.insert(rule, session);
+
+ session.commit();
RuleParamDto param = RuleParamDto.createFor(rule)
.setDefaultValue("some value")
MockUserSession.set();
WsTester.TestRequest request = wsTester.newGetRequest("api/rules", "search");
request.setParam("q", "S001");
+ request.setParam("activation", "all");
+
WsTester.Result result = request.execute();
+ System.out.println("result.outputAsString() = " + result.outputAsString());
result.assertJson(this.getClass(),"search_active_rules_params.json");
}
private ActiveRuleDto newActiveRule(QualityProfileDto profile, RuleDto rule) {
return ActiveRuleDto.createFor(profile, rule)
- .setInheritance("NONE")
+ .setInheritance("none")
.setSeverity("BLOCKER");
}
}
--- /dev/null
+{"total": 1, "p": 1, "ps": 25, "rules": [
+ {
+ "key": "java:S001",
+ "repo": "java",
+ "lang": "js",
+ "name": "Rule S001",
+ "htmlDesc": "Description S001",
+ "status": "READY",
+ "template": false,
+ "internalKey": "InternalKeyS001",
+ "severity": "INFO",
+ "tags": [],
+ "sysTags": [],
+ "debtRemediationFunctionType": "LINEAR",
+ "debtRemediationFunctionCoefficient": "1h",
+ "debtRemediationFunctionOffset": "5min",
+ "params": [],
+ "actives": []
+ }
+]}
--- /dev/null
+{
+ "p": 1,
+ "ps": 25,
+ "rules": [
+ {
+ "actives": [
+ {
+ "inherit": "NONE",
+ "key": "p2:java:java:S001",
+ "params": [],
+ "severity": "BLOCKER"
+ }
+ ],
+ "debtRemediationFunctionCoefficient": "1h",
+ "debtRemediationFunctionOffset": "5min",
+ "debtRemediationFunctionType": "LINEAR",
+ "htmlDesc": "Description S001",
+ "internalKey": "InternalKeyS001",
+ "key": "java:S001",
+ "lang": "js",
+ "name": "Rule S001",
+ "params": [],
+ "repo": "java",
+ "severity": "INFO",
+ "status": "READY",
+ "sysTags": [],
+ "tags": [],
+ "template": false
+ }
+ ],
+ "total": 1
+}