summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJulien Lancelot <julien.lancelot@sonarsource.com>2016-05-04 17:31:53 +0200
committerJulien Lancelot <julien.lancelot@sonarsource.com>2016-05-10 10:57:16 +0200
commit3254f4804263e94f81d696e717322c1460d5b737 (patch)
treed14deaaf6b331954cb98eff70edf88b1117bf0a1
parent66bf90cce772687e4301b821ecc25a8aaa6ae036 (diff)
downloadsonarqube-3254f4804263e94f81d696e717322c1460d5b737.tar.gz
sonarqube-3254f4804263e94f81d696e717322c1460d5b737.zip
SONAR-6906 Filter rules on profile language when bulk active rules
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevel4.java2
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/BulkRuleActivationActions.java65
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/rule/ws/RuleQueryFactory.java114
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/rule/ws/SearchAction.java70
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/QProfilesWsMediumTest.java55
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/QProfilesWsTest.java31
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/rule/index/RuleIndexTest.java57
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/rule/ws/RuleQueryFactoryTest.java200
-rw-r--r--server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/QProfilesWsMediumTest/bulk_activate_rule.json4
-rw-r--r--server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/QProfilesWsMediumTest/bulk_activate_rule_not_all.json4
-rw-r--r--server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/QProfilesWsMediumTest/does_not_return_warnings_when_bulk_activate_on_profile_and_rules_exist_on_another_language_than_profile.json4
-rw-r--r--sonar-ws/src/main/java/org/sonarqube/ws/client/rule/RulesService.java2
-rw-r--r--sonar-ws/src/test/java/org/sonarqube/ws/client/rule/RulesServiceTest.java2
13 files changed, 437 insertions, 173 deletions
diff --git a/server/sonar-server/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevel4.java b/server/sonar-server/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevel4.java
index b617008eb74..40de8952056 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevel4.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevel4.java
@@ -251,6 +251,7 @@ import org.sonar.server.rule.index.RuleIndexer;
import org.sonar.server.rule.ws.ActiveRuleCompleter;
import org.sonar.server.rule.ws.RepositoriesAction;
import org.sonar.server.rule.ws.RuleMapper;
+import org.sonar.server.rule.ws.RuleQueryFactory;
import org.sonar.server.rule.ws.RulesWs;
import org.sonar.server.rule.ws.TagsAction;
import org.sonar.server.source.HtmlSourceDecorator;
@@ -442,6 +443,7 @@ public class PlatformLevel4 extends PlatformLevel {
RuleMapper.class,
ActiveRuleCompleter.class,
RepositoriesAction.class,
+ RuleQueryFactory.class,
org.sonar.server.rule.ws.AppAction.class,
// languages
diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/BulkRuleActivationActions.java b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/BulkRuleActivationActions.java
index 82fc1c3ce76..bb48610221a 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/BulkRuleActivationActions.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/BulkRuleActivationActions.java
@@ -20,38 +20,19 @@
package org.sonar.server.qualityprofile.ws;
import org.sonar.api.i18n.I18n;
-import org.sonar.api.rule.RuleStatus;
import org.sonar.api.rule.Severity;
-import org.sonar.api.rules.RuleType;
import org.sonar.api.server.ServerSide;
import org.sonar.api.server.ws.Request;
import org.sonar.api.server.ws.RequestHandler;
import org.sonar.api.server.ws.Response;
import org.sonar.api.server.ws.WebService;
-import org.sonar.api.server.ws.WebService.Param;
import org.sonar.api.utils.text.JsonWriter;
-import org.sonar.db.DbClient;
import org.sonar.server.qualityprofile.BulkChangeResult;
import org.sonar.server.qualityprofile.QProfileService;
-import org.sonar.server.rule.RuleService;
-import org.sonar.server.rule.index.RuleQuery;
-import org.sonar.server.rule.ws.SearchAction;
+import org.sonar.server.rule.ws.RuleQueryFactory;
import org.sonar.server.user.UserSession;
-import static org.sonarqube.ws.client.rule.RulesWsParameters.PARAM_ACTIVATION;
-import static org.sonarqube.ws.client.rule.RulesWsParameters.PARAM_ACTIVE_SEVERITIES;
-import static org.sonarqube.ws.client.rule.RulesWsParameters.PARAM_AVAILABLE_SINCE;
-import static org.sonarqube.ws.client.rule.RulesWsParameters.PARAM_INHERITANCE;
-import static org.sonarqube.ws.client.rule.RulesWsParameters.PARAM_IS_TEMPLATE;
-import static org.sonarqube.ws.client.rule.RulesWsParameters.PARAM_LANGUAGES;
-import static org.sonarqube.ws.client.rule.RulesWsParameters.PARAM_QPROFILE;
-import static org.sonarqube.ws.client.rule.RulesWsParameters.PARAM_REPOSITORIES;
-import static org.sonarqube.ws.client.rule.RulesWsParameters.PARAM_RULE_KEY;
-import static org.sonarqube.ws.client.rule.RulesWsParameters.PARAM_SEVERITIES;
-import static org.sonarqube.ws.client.rule.RulesWsParameters.PARAM_STATUSES;
-import static org.sonarqube.ws.client.rule.RulesWsParameters.PARAM_TAGS;
-import static org.sonarqube.ws.client.rule.RulesWsParameters.PARAM_TEMPLATE_KEY;
-import static org.sonarqube.ws.client.rule.RulesWsParameters.PARAM_TYPES;
+import static org.sonar.server.rule.ws.SearchAction.defineRuleSearchParameters;
@ServerSide
public class BulkRuleActivationActions {
@@ -62,16 +43,14 @@ public class BulkRuleActivationActions {
public static final String BULK_ACTIVATE_ACTION = "activate_rules";
public static final String BULK_DEACTIVATE_ACTION = "deactivate_rules";
- private final DbClient dbClient;
private final QProfileService profileService;
- private final RuleService ruleService;
+ private final RuleQueryFactory ruleQueryFactory;
private final I18n i18n;
private final UserSession userSession;
- public BulkRuleActivationActions(DbClient dbClient, QProfileService profileService, RuleService ruleService, I18n i18n, UserSession userSession) {
- this.dbClient = dbClient;
+ public BulkRuleActivationActions(QProfileService profileService, RuleQueryFactory ruleQueryFactory, I18n i18n, UserSession userSession) {
this.profileService = profileService;
- this.ruleService = ruleService;
+ this.ruleQueryFactory = ruleQueryFactory;
this.i18n = i18n;
this.userSession = userSession;
}
@@ -94,7 +73,7 @@ public class BulkRuleActivationActions {
}
});
- SearchAction.defineRuleSearchParameters(activate);
+ defineRuleSearchParameters(activate);
defineProfileKeyParameter(activate);
activate.createParam(SEVERITY)
@@ -115,7 +94,7 @@ public class BulkRuleActivationActions {
}
});
- SearchAction.defineRuleSearchParameters(deactivate);
+ defineRuleSearchParameters(deactivate);
defineProfileKeyParameter(deactivate);
}
@@ -128,45 +107,19 @@ public class BulkRuleActivationActions {
private void bulkActivate(Request request, Response response) {
BulkChangeResult result = profileService.bulkActivate(
- createRuleQuery(ruleService.newRuleQuery(), request),
+ ruleQueryFactory.createRuleQuery(request),
request.mandatoryParam(PROFILE_KEY),
request.param(SEVERITY));
writeResponse(result, response);
}
private void bulkDeactivate(Request request, Response response) {
- // TODO filter on rule language
BulkChangeResult result = profileService.bulkDeactivate(
- createRuleQuery(ruleService.newRuleQuery(), request),
+ ruleQueryFactory.createRuleQuery(request),
request.mandatoryParam(PROFILE_KEY));
writeResponse(result, response);
}
- private static RuleQuery createRuleQuery(RuleQuery query, Request request) {
- query.setQueryText(request.param(Param.TEXT_QUERY));
- query.setSeverities(request.paramAsStrings(PARAM_SEVERITIES));
- query.setRepositories(request.paramAsStrings(PARAM_REPOSITORIES));
- query.setAvailableSince(request.hasParam(PARAM_AVAILABLE_SINCE) ? request.paramAsDate(PARAM_AVAILABLE_SINCE).getTime() : null);
- query.setStatuses(request.paramAsEnums(PARAM_STATUSES, RuleStatus.class));
- query.setLanguages(request.paramAsStrings(PARAM_LANGUAGES));
- query.setActivation(request.paramAsBoolean(PARAM_ACTIVATION));
- query.setQProfileKey(request.param(PARAM_QPROFILE));
- query.setTags(request.paramAsStrings(PARAM_TAGS));
- query.setInheritance(request.paramAsStrings(PARAM_INHERITANCE));
- query.setActiveSeverities(request.paramAsStrings(PARAM_ACTIVE_SEVERITIES));
- query.setIsTemplate(request.paramAsBoolean(PARAM_IS_TEMPLATE));
- query.setTemplateKey(request.param(PARAM_TEMPLATE_KEY));
- query.setTypes(request.paramAsEnums(PARAM_TYPES, RuleType.class));
- query.setKey(request.param(PARAM_RULE_KEY));
-
- String sortParam = request.param(Param.SORT);
- if (sortParam != null) {
- query.setSortField(sortParam);
- query.setAscendingSort(request.mandatoryParamAsBoolean(Param.ASCENDING));
- }
- return query;
- }
-
private void writeResponse(BulkChangeResult result, Response response) {
JsonWriter json = response.newJsonWriter().beginObject();
json.prop("succeeded", result.countSucceeded());
diff --git a/server/sonar-server/src/main/java/org/sonar/server/rule/ws/RuleQueryFactory.java b/server/sonar-server/src/main/java/org/sonar/server/rule/ws/RuleQueryFactory.java
new file mode 100644
index 00000000000..746bd3c6381
--- /dev/null
+++ b/server/sonar-server/src/main/java/org/sonar/server/rule/ws/RuleQueryFactory.java
@@ -0,0 +1,114 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program 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.
+ *
+ * This program 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.
+ */
+
+package org.sonar.server.rule.ws;
+
+import com.google.common.collect.ImmutableList;
+import java.util.Date;
+import javax.annotation.CheckForNull;
+import org.sonar.api.rule.RuleStatus;
+import org.sonar.api.rules.RuleType;
+import org.sonar.api.server.ServerSide;
+import org.sonar.api.server.ws.Request;
+import org.sonar.api.server.ws.WebService;
+import org.sonar.db.DbClient;
+import org.sonar.db.DbSession;
+import org.sonar.db.qualityprofile.QualityProfileDto;
+import org.sonar.server.rule.index.RuleQuery;
+
+import static org.sonar.server.util.EnumUtils.toEnums;
+import static org.sonarqube.ws.client.rule.RulesWsParameters.PARAM_ACTIVATION;
+import static org.sonarqube.ws.client.rule.RulesWsParameters.PARAM_ACTIVE_SEVERITIES;
+import static org.sonarqube.ws.client.rule.RulesWsParameters.PARAM_AVAILABLE_SINCE;
+import static org.sonarqube.ws.client.rule.RulesWsParameters.PARAM_INHERITANCE;
+import static org.sonarqube.ws.client.rule.RulesWsParameters.PARAM_IS_TEMPLATE;
+import static org.sonarqube.ws.client.rule.RulesWsParameters.PARAM_LANGUAGES;
+import static org.sonarqube.ws.client.rule.RulesWsParameters.PARAM_QPROFILE;
+import static org.sonarqube.ws.client.rule.RulesWsParameters.PARAM_REPOSITORIES;
+import static org.sonarqube.ws.client.rule.RulesWsParameters.PARAM_RULE_KEY;
+import static org.sonarqube.ws.client.rule.RulesWsParameters.PARAM_SEVERITIES;
+import static org.sonarqube.ws.client.rule.RulesWsParameters.PARAM_STATUSES;
+import static org.sonarqube.ws.client.rule.RulesWsParameters.PARAM_TAGS;
+import static org.sonarqube.ws.client.rule.RulesWsParameters.PARAM_TEMPLATE_KEY;
+import static org.sonarqube.ws.client.rule.RulesWsParameters.PARAM_TYPES;
+
+@ServerSide
+public class RuleQueryFactory {
+
+ private final DbClient dbClient;
+
+ public RuleQueryFactory(DbClient dbClient) {
+ this.dbClient = dbClient;
+ }
+
+ /**
+ * Create a {@link RuleQuery} from a {@link Request}.
+ * When a profile key is set, the language of the profile is automatically set in the query
+ */
+ public RuleQuery createRuleQuery(Request request) {
+ RuleQuery ruleQuery = createRuleQuery(new RuleQuery(), request);
+
+ String qProfileKey = ruleQuery.getQProfileKey();
+ if (qProfileKey != null) {
+ QualityProfileDto qProfile = getProfileByKey(qProfileKey);
+ if (qProfile != null) {
+ ruleQuery.setLanguages(ImmutableList.of(qProfile.getLanguage()));
+ }
+ }
+ return ruleQuery;
+ }
+
+ private static RuleQuery createRuleQuery(RuleQuery query, Request request) {
+ query.setQueryText(request.param(WebService.Param.TEXT_QUERY));
+ query.setSeverities(request.paramAsStrings(PARAM_SEVERITIES));
+ query.setRepositories(request.paramAsStrings(PARAM_REPOSITORIES));
+ Date availableSince = request.paramAsDate(PARAM_AVAILABLE_SINCE);
+ query.setAvailableSince(availableSince != null ? availableSince.getTime() : null);
+ query.setStatuses(toEnums(request.paramAsStrings(PARAM_STATUSES), RuleStatus.class));
+ query.setLanguages(request.paramAsStrings(PARAM_LANGUAGES));
+ query.setActivation(request.paramAsBoolean(PARAM_ACTIVATION));
+ query.setQProfileKey(request.param(PARAM_QPROFILE));
+ query.setTags(request.paramAsStrings(PARAM_TAGS));
+ query.setInheritance(request.paramAsStrings(PARAM_INHERITANCE));
+ query.setActiveSeverities(request.paramAsStrings(PARAM_ACTIVE_SEVERITIES));
+ query.setIsTemplate(request.paramAsBoolean(PARAM_IS_TEMPLATE));
+ query.setTemplateKey(request.param(PARAM_TEMPLATE_KEY));
+ query.setTypes(toEnums(request.paramAsStrings(PARAM_TYPES), RuleType.class));
+ query.setKey(request.param(PARAM_RULE_KEY));
+
+ String sortParam = request.param(WebService.Param.SORT);
+ if (sortParam != null) {
+ query.setSortField(sortParam);
+ query.setAscendingSort(request.mandatoryParamAsBoolean(WebService.Param.ASCENDING));
+ }
+ return query;
+ }
+
+ @CheckForNull
+ private QualityProfileDto getProfileByKey(String key) {
+ DbSession dbSession = dbClient.openSession(false);
+ try {
+ return dbClient.qualityProfileDao().selectByKey(dbSession, key);
+ } finally {
+ dbSession.close();
+ }
+ }
+
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/rule/ws/SearchAction.java b/server/sonar-server/src/main/java/org/sonar/server/rule/ws/SearchAction.java
index f59dd90752c..ac49acb76e6 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/rule/ws/SearchAction.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/rule/ws/SearchAction.java
@@ -22,7 +22,6 @@ package org.sonar.server.rule.ws;
import com.google.common.base.Function;
import com.google.common.base.Predicates;
import com.google.common.collect.ArrayListMultimap;
-import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ListMultimap;
import com.google.common.collect.Lists;
@@ -50,7 +49,6 @@ import org.sonar.api.server.ws.WebService;
import org.sonar.api.server.ws.WebService.Param;
import org.sonar.db.DbClient;
import org.sonar.db.DbSession;
-import org.sonar.db.qualityprofile.QualityProfileDto;
import org.sonar.db.rule.RuleDto;
import org.sonar.db.rule.RuleParamDto;
import org.sonar.server.es.Facets;
@@ -65,7 +63,6 @@ import org.sonarqube.ws.Rules.SearchResponse;
import org.sonarqube.ws.client.rule.SearchWsRequest;
import static com.google.common.collect.FluentIterable.from;
-import static org.sonar.api.utils.DateUtils.parseDate;
import static org.sonar.server.rule.index.RuleIndex.ALL_STATUSES_EXCEPT_REMOVED;
import static org.sonar.server.rule.index.RuleIndex.FACET_ACTIVE_SEVERITIES;
import static org.sonar.server.rule.index.RuleIndex.FACET_LANGUAGES;
@@ -75,7 +72,6 @@ import static org.sonar.server.rule.index.RuleIndex.FACET_SEVERITIES;
import static org.sonar.server.rule.index.RuleIndex.FACET_STATUSES;
import static org.sonar.server.rule.index.RuleIndex.FACET_TAGS;
import static org.sonar.server.rule.index.RuleIndex.FACET_TYPES;
-import static org.sonar.server.util.EnumUtils.toEnums;
import static org.sonar.server.ws.WsUtils.writeProtobuf;
import static org.sonarqube.ws.client.rule.RulesWsParameters.OPTIONAL_FIELDS;
import static org.sonarqube.ws.client.rule.RulesWsParameters.PARAM_ACTIVATION;
@@ -101,14 +97,16 @@ public class SearchAction implements RulesWsAction {
private static final Collection<String> DEFAULT_FACETS = ImmutableSet.of(PARAM_LANGUAGES, PARAM_REPOSITORIES, "tags");
+ private final RuleQueryFactory ruleQueryFactory;
private final DbClient dbClient;
private final RuleIndex ruleIndex;
private final ActiveRuleCompleter activeRuleCompleter;
private final RuleMapper mapper;
- public SearchAction(RuleIndex ruleIndex, ActiveRuleCompleter activeRuleCompleter, DbClient dbClient, RuleMapper mapper) {
+ public SearchAction(RuleIndex ruleIndex, ActiveRuleCompleter activeRuleCompleter, RuleQueryFactory ruleQueryFactory, DbClient dbClient, RuleMapper mapper) {
this.ruleIndex = ruleIndex;
this.activeRuleCompleter = activeRuleCompleter;
+ this.ruleQueryFactory = ruleQueryFactory;
this.dbClient = dbClient;
this.mapper = mapper;
}
@@ -150,19 +148,19 @@ public class SearchAction implements RulesWsAction {
try {
SearchWsRequest searchWsRequest = toSearchWsRequest(request);
org.sonar.server.es.SearchOptions context = getQueryContext(searchWsRequest);
- RuleQuery query = doQuery(searchWsRequest);
+ RuleQuery query = ruleQueryFactory.createRuleQuery(request);
SearchResult searchResult = doSearch(dbSession, query, context);
- SearchResponse responseBuilder = buildResponse(dbSession, searchWsRequest, context, searchResult);
+ SearchResponse responseBuilder = buildResponse(dbSession, searchWsRequest, context, searchResult, query);
writeProtobuf(responseBuilder, request, response);
} finally {
dbClient.closeSession(dbSession);
}
}
- private SearchResponse buildResponse(DbSession dbSession, SearchWsRequest request, SearchOptions context, SearchResult result) {
+ private SearchResponse buildResponse(DbSession dbSession, SearchWsRequest request, SearchOptions context, SearchResult result, RuleQuery query) {
SearchResponse.Builder responseBuilder = SearchResponse.newBuilder();
writeStatistics(responseBuilder, result, context);
- doContextResponse(dbSession, request, result, responseBuilder);
+ doContextResponse(dbSession, request, result, responseBuilder, query);
if (!context.getFacets().isEmpty()) {
writeFacets(responseBuilder, request, context, result);
}
@@ -311,31 +309,6 @@ public class SearchAction implements RulesWsAction {
.setDefaultValue(true);
}
- private static RuleQuery createRuleQuery(RuleQuery query, SearchWsRequest request) {
- query.setQueryText(request.getQuery());
- query.setSeverities(request.getSeverities());
- query.setRepositories(request.getRepositories());
- query.setAvailableSince(request.getAvailableSince() != null ? parseDate(request.getAvailableSince()).getTime() : null);
- query.setStatuses(toEnums(request.getStatuses(), RuleStatus.class));
- query.setLanguages(request.getLanguages());
- query.setActivation(request.getActivation());
- query.setQProfileKey(request.getQProfile());
- query.setTags(request.getTags());
- query.setInheritance(request.getInheritance());
- query.setActiveSeverities(request.getActiveSeverities());
- query.setIsTemplate(request.getIsTemplate());
- query.setTemplateKey(request.getTemplateKey());
- query.setTypes(toEnums(request.getTypes(), RuleType.class));
- query.setKey(request.getRuleKey());
-
- String sortParam = request.getSort();
- if (sortParam != null) {
- query.setSortField(sortParam);
- query.setAscendingSort(request.getAsc());
- }
- return query;
- }
-
private void writeRules(SearchResponse.Builder response, SearchResult result, org.sonar.server.es.SearchOptions context) {
for (RuleDto rule : result.rules) {
response.addRules(mapper.toWsRule(rule, result, context.getFields()));
@@ -343,7 +316,6 @@ public class SearchAction implements RulesWsAction {
}
protected org.sonar.server.es.SearchOptions getQueryContext(SearchWsRequest request) {
- // TODO Get rid of this horrible hack: fields on request are not the same as fields for ES search ! 1/2
org.sonar.server.es.SearchOptions context = loadCommonContext(request);
org.sonar.server.es.SearchOptions searchQueryContext = new org.sonar.server.es.SearchOptions()
.setLimit(context.getLimit())
@@ -404,26 +376,11 @@ public class SearchAction implements RulesWsAction {
.setTotal(result.getTotal());
}
- protected RuleQuery doQuery(SearchWsRequest request) {
- RuleQuery plainQuery = createRuleQuery(new RuleQuery(), request);
-
- String qProfileKey = request.getQProfile();
- if (qProfileKey != null) {
- QualityProfileDto qProfile = activeRuleCompleter.loadProfile(qProfileKey);
- if (qProfile != null) {
- plainQuery.setLanguages(ImmutableList.of(qProfile.getLanguage()));
- }
- }
-
- return plainQuery;
- }
-
- protected void doContextResponse(DbSession dbSession, SearchWsRequest request, SearchResult result, SearchResponse.Builder response) {
- // TODO Get rid of this horrible hack: fields on request are not the same as fields for ES search ! 2/2
+ protected void doContextResponse(DbSession dbSession, SearchWsRequest request, SearchResult result, SearchResponse.Builder response, RuleQuery query) {
org.sonar.server.es.SearchOptions contextForResponse = loadCommonContext(request);
writeRules(response, result, contextForResponse);
if (contextForResponse.getFields().contains("actives")) {
- activeRuleCompleter.completeSearch(dbSession, doQuery(request), result.rules, response);
+ activeRuleCompleter.completeSearch(dbSession, query, result.rules, response);
}
}
@@ -600,13 +557,4 @@ public class SearchAction implements RulesWsAction {
}
}
- private enum TypeToString implements Function<RuleType, String> {
- INSTANCE;
-
- @Override
- public String apply(@Nonnull RuleType input) {
- return input.name();
- }
-
- }
}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/QProfilesWsMediumTest.java b/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/QProfilesWsMediumTest.java
index c7bb601ad53..975d3fc9f80 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/QProfilesWsMediumTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/QProfilesWsMediumTest.java
@@ -56,6 +56,7 @@ import org.sonar.server.ws.WsTester;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.Assert.fail;
import static org.sonarqube.ws.client.rule.RulesWsParameters.PARAM_LANGUAGES;
+import static org.sonarqube.ws.client.rule.RulesWsParameters.PARAM_QPROFILE;
public class QProfilesWsMediumTest {
@@ -269,10 +270,10 @@ public class QProfilesWsMediumTest {
@Test
public void bulk_activate_rule() throws Exception {
QualityProfileDto profile = createProfile("java");
- RuleDto rule0 = createRule(profile.getLanguage(), "toto");
- RuleDto rule1 = createRule(profile.getLanguage(), "tata");
- RuleDto rule2 = createRule(profile.getLanguage(), "hello");
- RuleDto rule3 = createRule(profile.getLanguage(), "world");
+ createRule(profile.getLanguage(), "toto");
+ createRule(profile.getLanguage(), "tata");
+ createRule(profile.getLanguage(), "hello");
+ createRule(profile.getLanguage(), "world");
session.commit();
ruIndexer.index();
@@ -283,7 +284,7 @@ public class QProfilesWsMediumTest {
WsTester.TestRequest request = wsTester.newPostRequest(QProfilesWs.API_ENDPOINT, BulkRuleActivationActions.BULK_ACTIVATE_ACTION);
request.setParam(RuleActivationActions.PROFILE_KEY, profile.getKey());
request.setParam(PARAM_LANGUAGES, "java");
- WsTester.Result result = request.execute();
+ request.execute().assertJson(getClass(), "bulk_activate_rule.json");
session.clearCache();
// 2. Assert ActiveRule in DAO
@@ -294,10 +295,10 @@ public class QProfilesWsMediumTest {
public void bulk_activate_rule_not_all() throws Exception {
QualityProfileDto java = createProfile("java");
QualityProfileDto php = createProfile("php");
- RuleDto rule0 = createRule(java.getLanguage(), "toto");
- RuleDto rule1 = createRule(java.getLanguage(), "tata");
- RuleDto rule2 = createRule(php.getLanguage(), "hello");
- RuleDto rule3 = createRule(php.getLanguage(), "world");
+ createRule(java.getLanguage(), "toto");
+ createRule(java.getLanguage(), "tata");
+ createRule(php.getLanguage(), "hello");
+ createRule(php.getLanguage(), "world");
session.commit();
ruIndexer.index();
@@ -308,7 +309,7 @@ public class QProfilesWsMediumTest {
WsTester.TestRequest request = wsTester.newPostRequest(QProfilesWs.API_ENDPOINT, BulkRuleActivationActions.BULK_ACTIVATE_ACTION);
request.setParam(RuleActivationActions.PROFILE_KEY, php.getKey());
request.setParam(PARAM_LANGUAGES, "php");
- WsTester.Result result = request.execute();
+ request.execute().assertJson(getClass(), "bulk_activate_rule_not_all.json");
session.clearCache();
// 2. Assert ActiveRule in DAO
@@ -318,10 +319,10 @@ public class QProfilesWsMediumTest {
@Test
public void bulk_activate_rule_by_query() throws Exception {
QualityProfileDto profile = createProfile("java");
- RuleDto rule0 = createRule(profile.getLanguage(), "toto");
- RuleDto rule1 = createRule(profile.getLanguage(), "tata");
- RuleDto rule2 = createRule(profile.getLanguage(), "hello");
- RuleDto rule3 = createRule(profile.getLanguage(), "world");
+ createRule(profile.getLanguage(), "toto");
+ createRule(profile.getLanguage(), "tata");
+ createRule(profile.getLanguage(), "hello");
+ createRule(profile.getLanguage(), "world");
session.commit();
ruIndexer.index();
@@ -332,7 +333,7 @@ public class QProfilesWsMediumTest {
WsTester.TestRequest request = wsTester.newPostRequest(QProfilesWs.API_ENDPOINT, BulkRuleActivationActions.BULK_ACTIVATE_ACTION);
request.setParam(RuleActivationActions.PROFILE_KEY, profile.getKey());
request.setParam(WebService.Param.TEXT_QUERY, "php");
- WsTester.Result result = request.execute();
+ request.execute();
session.clearCache();
// 2. Assert ActiveRule in DAO
@@ -342,7 +343,7 @@ public class QProfilesWsMediumTest {
request = wsTester.newPostRequest(QProfilesWs.API_ENDPOINT, BulkRuleActivationActions.BULK_ACTIVATE_ACTION);
request.setParam(RuleActivationActions.PROFILE_KEY, profile.getKey());
request.setParam(WebService.Param.TEXT_QUERY, "world");
- result = request.execute();
+ request.execute();
session.commit();
// 2. Assert ActiveRule in DAO
@@ -375,7 +376,29 @@ public class QProfilesWsMediumTest {
// 2. Assert ActiveRule with MINOR severity
assertThat(tester.get(ActiveRuleIndex.class).findByRule(rule0.getKey()).get(0).severity()).isEqualTo("MINOR");
+ }
+ @Test
+ public void does_not_return_warnings_when_bulk_activate_on_profile_and_rules_exist_on_another_language_than_profile() throws Exception {
+ QualityProfileDto javaProfile = createProfile("java");
+ createRule(javaProfile.getLanguage(), "toto");
+ createRule(javaProfile.getLanguage(), "tata");
+ QualityProfileDto phpProfile = createProfile("php");
+ createRule(phpProfile.getLanguage(), "hello");
+ createRule(phpProfile.getLanguage(), "world");
+ session.commit();
+ ruIndexer.index();
+
+ // 1. Activate Rule
+ WsTester.TestRequest request = wsTester.newPostRequest(QProfilesWs.API_ENDPOINT, BulkRuleActivationActions.BULK_ACTIVATE_ACTION);
+ request.setParam(RuleActivationActions.PROFILE_KEY, javaProfile.getKey());
+ request.setParam(PARAM_QPROFILE, javaProfile.getKey());
+ request.setParam("activation", "false");
+ request.execute().assertJson(getClass(), "does_not_return_warnings_when_bulk_activate_on_profile_and_rules_exist_on_another_language_than_profile.json");
+ session.clearCache();
+
+ // 2. Assert ActiveRule in DAO
+ assertThat(db.activeRuleDao().selectByProfileKey(session, javaProfile.getKey())).hasSize(2);
}
@Test
diff --git a/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/QProfilesWsTest.java b/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/QProfilesWsTest.java
index 2e7597413a0..3ae6c310731 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/QProfilesWsTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/QProfilesWsTest.java
@@ -33,7 +33,6 @@ import org.sonar.api.utils.ValidationMessages;
import org.sonar.server.language.LanguageTesting;
import org.sonar.server.qualityprofile.QProfileExporters;
import org.sonar.server.qualityprofile.QProfileService;
-import org.sonar.server.rule.RuleService;
import org.sonar.server.tester.UserSessionRule;
import org.sonar.server.ws.WsTester;
@@ -52,7 +51,6 @@ public class QProfilesWsTest {
@Before
public void setUp() {
QProfileService profileService = mock(QProfileService.class);
- RuleService ruleService = mock(RuleService.class);
I18n i18n = mock(I18n.class);
Languages languages = LanguageTesting.newLanguages(xoo1Key, xoo2Key);
@@ -61,7 +59,7 @@ public class QProfilesWsTest {
controller = new WsTester(new QProfilesWs(
new RuleActivationActions(profileService),
- new BulkRuleActivationActions(null, profileService, ruleService, i18n, userSessionRule),
+ new BulkRuleActivationActions(profileService, null, i18n, userSessionRule),
new ProjectAssociationActions(null, null, null, languages, userSessionRule),
new CreateAction(null, null, null, languages, importers, userSessionRule),
new ImportersAction(importers),
@@ -79,8 +77,7 @@ public class QProfilesWsTest {
new ExportAction(null, null, null, mock(QProfileExporters.class), languages),
new ExportersAction(),
new InheritanceAction(null, null, null, null, languages),
- new RenameAction(null, userSessionRule)
- )).controller(QProfilesWs.API_ENDPOINT);
+ new RenameAction(null, userSessionRule))).controller(QProfilesWs.API_ENDPOINT);
}
private ProfileImporter[] createImporters(Languages languages) {
@@ -236,8 +233,7 @@ public class QProfilesWsTest {
assertThat(changelog).isNotNull();
assertThat(changelog.isPost()).isFalse();
assertThat(changelog.params()).hasSize(7).extracting("key").containsOnly(
- "profileKey", "profileName", "language", "since", "to", "p", "ps"
- );
+ "profileKey", "profileName", "language", "since", "to", "p", "ps");
assertThat(changelog.responseExampleAsString()).isNotEmpty();
}
@@ -247,8 +243,7 @@ public class QProfilesWsTest {
assertThat(changeParent).isNotNull();
assertThat(changeParent.isPost()).isTrue();
assertThat(changeParent.params()).hasSize(5).extracting("key").containsOnly(
- "profileKey", "profileName", "language", "parentKey", "parentName"
- );
+ "profileKey", "profileName", "language", "parentKey", "parentName");
}
@Test
@@ -258,8 +253,7 @@ public class QProfilesWsTest {
assertThat(compare.isPost()).isFalse();
assertThat(compare.isInternal()).isTrue();
assertThat(compare.params()).hasSize(2).extracting("key").containsOnly(
- "leftKey", "rightKey"
- );
+ "leftKey", "rightKey");
assertThat(compare.responseExampleAsString()).isNotEmpty();
}
@@ -269,8 +263,7 @@ public class QProfilesWsTest {
assertThat(copy).isNotNull();
assertThat(copy.isPost()).isTrue();
assertThat(copy.params()).hasSize(2).extracting("key").containsOnly(
- "fromKey", "toName"
- );
+ "fromKey", "toName");
}
@Test
@@ -279,8 +272,7 @@ public class QProfilesWsTest {
assertThat(delete).isNotNull();
assertThat(delete.isPost()).isTrue();
assertThat(delete.params()).hasSize(3).extracting("key").containsOnly(
- "profileKey", "language", "profileName"
- );
+ "profileKey", "language", "profileName");
}
@Test
@@ -289,8 +281,7 @@ public class QProfilesWsTest {
assertThat(export).isNotNull();
assertThat(export.isPost()).isFalse();
assertThat(export.params()).hasSize(2).extracting("key").containsOnly(
- "language", "name"
- );
+ "language", "name");
}
@Test
@@ -308,8 +299,7 @@ public class QProfilesWsTest {
assertThat(inheritance).isNotNull();
assertThat(inheritance.isPost()).isFalse();
assertThat(inheritance.params()).hasSize(3).extracting("key").containsOnly(
- "profileKey", "language", "profileName"
- );
+ "profileKey", "language", "profileName");
assertThat(inheritance.responseExampleAsString()).isNotEmpty();
}
@@ -319,7 +309,6 @@ public class QProfilesWsTest {
assertThat(rename).isNotNull();
assertThat(rename.isPost()).isTrue();
assertThat(rename.params()).hasSize(2).extracting("key").containsOnly(
- "key", "name"
- );
+ "key", "name");
}
}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/rule/index/RuleIndexTest.java b/server/sonar-server/src/test/java/org/sonar/server/rule/index/RuleIndexTest.java
index 6ac245f2339..2f0fb5e6f5b 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/rule/index/RuleIndexTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/rule/index/RuleIndexTest.java
@@ -253,8 +253,7 @@ public class RuleIndexTest {
newDoc(RULE_KEY_1).setType(CODE_SMELL),
newDoc(RULE_KEY_2).setType(VULNERABILITY),
newDoc(RULE_KEY_3).setType(BUG),
- newDoc(RULE_KEY_4).setType(BUG)
- );
+ newDoc(RULE_KEY_4).setType(BUG));
// find all
RuleQuery query = new RuleQuery();
@@ -265,7 +264,7 @@ public class RuleIndexTest {
assertThat(index.search(query, new SearchOptions()).getIds()).containsOnly(RULE_KEY_2);
query = new RuleQuery().setTypes(ImmutableSet.of(BUG));
- assertThat(index.search(query, new SearchOptions()).getIds()).containsOnly(RULE_KEY_3,RULE_KEY_4);
+ assertThat(index.search(query, new SearchOptions()).getIds()).containsOnly(RULE_KEY_3, RULE_KEY_4);
// types in query => nothing
query = new RuleQuery().setQueryText("code smell bug vulnerability");
@@ -458,54 +457,54 @@ public class RuleIndexTest {
// 1. get all active rules
assertThat(index.search(new RuleQuery()
.setActivation(true), new SearchOptions()).getIds())
- .hasSize(3);
+ .hasSize(3);
// 2. get all inactive rules.
assertThat(index.search(new RuleQuery()
.setActivation(false), new SearchOptions()).getIds())
- .containsOnly(RULE_KEY_4);
+ .containsOnly(RULE_KEY_4);
// 3. get Inherited Rules on profile1
assertThat(index.search(new RuleQuery().setActivation(true)
.setQProfileKey(QUALITY_PROFILE_KEY1)
.setInheritance(ImmutableSet.of(INHERITED.name())),
new SearchOptions()).getIds())
- .isEmpty();
+ .isEmpty();
// 4. get Inherited Rules on profile2
assertThat(index.search(new RuleQuery().setActivation(true)
.setQProfileKey(QUALITY_PROFILE_KEY2)
.setInheritance(ImmutableSet.of(INHERITED.name())),
new SearchOptions()).getIds())
- .hasSize(2);
+ .hasSize(2);
// 5. get Overridden Rules on profile1
assertThat(index.search(new RuleQuery().setActivation(true)
.setQProfileKey(QUALITY_PROFILE_KEY1)
.setInheritance(ImmutableSet.of(OVERRIDES.name())),
new SearchOptions()).getIds())
- .isEmpty();
+ .isEmpty();
// 6. get Overridden Rules on profile2
assertThat(index.search(new RuleQuery().setActivation(true)
.setQProfileKey(QUALITY_PROFILE_KEY2)
.setInheritance(ImmutableSet.of(OVERRIDES.name())),
new SearchOptions()).getIds())
- .hasSize(1);
+ .hasSize(1);
// 7. get Inherited AND Overridden Rules on profile1
assertThat(index.search(new RuleQuery().setActivation(true)
.setQProfileKey(QUALITY_PROFILE_KEY1)
.setInheritance(ImmutableSet.of(INHERITED.name(), OVERRIDES.name())),
new SearchOptions()).getIds())
- .isEmpty();
+ .isEmpty();
// 8. get Inherited AND Overridden Rules on profile2
assertThat(index.search(new RuleQuery().setActivation(true)
.setQProfileKey(QUALITY_PROFILE_KEY2)
.setInheritance(ImmutableSet.of(INHERITED.name(), OVERRIDES.name())),
new SearchOptions()).getIds())
- .hasSize(3);
+ .hasSize(3);
}
@Test
@@ -623,8 +622,7 @@ public class RuleIndexTest {
// 2 Facet with a language filter
// -- lang facet should still have all language
- result = index.search(new RuleQuery().setLanguages(ImmutableList.of("cpp"))
- , new SearchOptions().addFacets(asList(FACET_LANGUAGES, FACET_REPOSITORIES, FACET_TAGS)));
+ result = index.search(new RuleQuery().setLanguages(ImmutableList.of("cpp")), new SearchOptions().addFacets(asList(FACET_LANGUAGES, FACET_REPOSITORIES, FACET_TAGS)));
assertThat(result.getIds()).hasSize(3);
assertThat(result.getFacets().getAll()).hasSize(3);
assertThat(result.getFacets().get(FACET_LANGUAGES).keySet()).containsOnly("cpp", "java", "cobol");
@@ -635,8 +633,7 @@ public class RuleIndexTest {
// -- repository for cpp & T2
result = index.search(new RuleQuery()
.setLanguages(ImmutableList.of("cpp"))
- .setTags(ImmutableList.of("T2"))
- , new SearchOptions().addFacets(asList(FACET_LANGUAGES, FACET_REPOSITORIES, FACET_TAGS)));
+ .setTags(ImmutableList.of("T2")), new SearchOptions().addFacets(asList(FACET_LANGUAGES, FACET_REPOSITORIES, FACET_TAGS)));
assertThat(result.getIds()).hasSize(1);
assertThat(result.getFacets().getAll()).hasSize(3);
assertThat(result.getFacets().get(FACET_LANGUAGES).keySet()).containsOnly("cpp", "java");
@@ -651,8 +648,7 @@ public class RuleIndexTest {
result = index.search(new RuleQuery()
.setLanguages(ImmutableList.of("cpp", "java"))
.setTags(ImmutableList.of("T2"))
- .setTypes(asList(BUG, CODE_SMELL))
- , new SearchOptions().addFacets(asList(FACET_LANGUAGES, FACET_REPOSITORIES, FACET_TAGS, FACET_TYPES)));
+ .setTypes(asList(BUG, CODE_SMELL)), new SearchOptions().addFacets(asList(FACET_LANGUAGES, FACET_REPOSITORIES, FACET_TAGS, FACET_TYPES)));
assertThat(result.getIds()).hasSize(2);
assertThat(result.getFacets().getAll()).hasSize(4);
assertThat(result.getFacets().get(FACET_LANGUAGES).keySet()).containsOnly("cpp", "java");
@@ -751,6 +747,33 @@ public class RuleIndexTest {
assertThat(index.searchAll(new RuleQuery().setQueryText("javascript:X001"))).hasSize(1);
}
+ @Test
+ public void search_all_keys_by_profile() {
+ indexRules(
+ newDoc(RULE_KEY_1),
+ newDoc(RULE_KEY_2),
+ newDoc(RULE_KEY_3));
+
+ indexActiveRules(
+ ActiveRuleDocTesting.newDoc(ActiveRuleKey.of(QUALITY_PROFILE_KEY1, RULE_KEY_1)),
+ ActiveRuleDocTesting.newDoc(ActiveRuleKey.of(QUALITY_PROFILE_KEY2, RULE_KEY_1)),
+ ActiveRuleDocTesting.newDoc(ActiveRuleKey.of(QUALITY_PROFILE_KEY1, RULE_KEY_2)));
+
+ assertThat(tester.countDocuments(INDEX, TYPE_ACTIVE_RULE)).isEqualTo(3);
+
+ // 1. get all active rules.
+ assertThat(index.searchAll(new RuleQuery().setActivation(true))).containsOnly(RULE_KEY_1, RULE_KEY_2);
+
+ // 2. get all inactive rules.
+ assertThat(index.searchAll(new RuleQuery().setActivation(false))).containsOnly(RULE_KEY_3);
+
+ // 3. get all rules not active on profile
+ assertThat(index.searchAll(new RuleQuery().setActivation(false).setQProfileKey(QUALITY_PROFILE_KEY2))).containsOnly(RULE_KEY_2, RULE_KEY_3);
+
+ // 4. get all active rules on profile
+ assertThat(index.searchAll(new RuleQuery().setActivation(true).setQProfileKey(QUALITY_PROFILE_KEY2))).containsOnly(RULE_KEY_1);
+ }
+
private void indexRules(RuleDoc... rules) {
ruleIndexer.index(asList(rules).iterator());
}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/rule/ws/RuleQueryFactoryTest.java b/server/sonar-server/src/test/java/org/sonar/server/rule/ws/RuleQueryFactoryTest.java
new file mode 100644
index 00000000000..524ba146f29
--- /dev/null
+++ b/server/sonar-server/src/test/java/org/sonar/server/rule/ws/RuleQueryFactoryTest.java
@@ -0,0 +1,200 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program 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.
+ *
+ * This program 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.
+ */
+
+package org.sonar.server.rule.ws;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.sonar.api.server.ws.Request;
+import org.sonar.api.server.ws.Response;
+import org.sonar.api.server.ws.WebService;
+import org.sonar.api.utils.System2;
+import org.sonar.db.DbClient;
+import org.sonar.db.DbSession;
+import org.sonar.db.DbTester;
+import org.sonar.db.qualityprofile.QualityProfileDto;
+import org.sonar.server.rule.index.RuleQuery;
+import org.sonar.server.ws.TestRequest;
+import org.sonar.server.ws.WsAction;
+import org.sonar.server.ws.WsActionTester;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.sonar.api.rule.RuleStatus.DEPRECATED;
+import static org.sonar.api.rule.RuleStatus.READY;
+import static org.sonar.api.rule.Severity.CRITICAL;
+import static org.sonar.api.rule.Severity.MAJOR;
+import static org.sonar.api.rule.Severity.MINOR;
+import static org.sonar.api.rules.RuleType.BUG;
+import static org.sonar.api.rules.RuleType.CODE_SMELL;
+import static org.sonar.api.server.ws.WebService.Param.ASCENDING;
+import static org.sonar.api.server.ws.WebService.Param.SORT;
+import static org.sonar.api.server.ws.WebService.Param.TEXT_QUERY;
+import static org.sonar.db.qualityprofile.ActiveRuleDto.INHERITED;
+import static org.sonar.db.qualityprofile.ActiveRuleDto.OVERRIDES;
+import static org.sonar.server.rule.ws.SearchAction.defineRuleSearchParameters;
+import static org.sonarqube.ws.client.rule.RulesWsParameters.PARAM_ACTIVATION;
+import static org.sonarqube.ws.client.rule.RulesWsParameters.PARAM_ACTIVE_SEVERITIES;
+import static org.sonarqube.ws.client.rule.RulesWsParameters.PARAM_AVAILABLE_SINCE;
+import static org.sonarqube.ws.client.rule.RulesWsParameters.PARAM_INHERITANCE;
+import static org.sonarqube.ws.client.rule.RulesWsParameters.PARAM_IS_TEMPLATE;
+import static org.sonarqube.ws.client.rule.RulesWsParameters.PARAM_LANGUAGES;
+import static org.sonarqube.ws.client.rule.RulesWsParameters.PARAM_QPROFILE;
+import static org.sonarqube.ws.client.rule.RulesWsParameters.PARAM_REPOSITORIES;
+import static org.sonarqube.ws.client.rule.RulesWsParameters.PARAM_RULE_KEY;
+import static org.sonarqube.ws.client.rule.RulesWsParameters.PARAM_SEVERITIES;
+import static org.sonarqube.ws.client.rule.RulesWsParameters.PARAM_STATUSES;
+import static org.sonarqube.ws.client.rule.RulesWsParameters.PARAM_TAGS;
+import static org.sonarqube.ws.client.rule.RulesWsParameters.PARAM_TEMPLATE_KEY;
+import static org.sonarqube.ws.client.rule.RulesWsParameters.PARAM_TYPES;
+
+public class RuleQueryFactoryTest {
+
+ @Rule
+ public DbTester dbTester = DbTester.create(System2.INSTANCE);
+
+ DbClient dbClient = dbTester.getDbClient();
+
+ DbSession dbSession = dbTester.getSession();
+
+ RuleQueryFactory underTest = new RuleQueryFactory(dbClient);
+
+ FakeAction fakeAction = new FakeAction(underTest);
+
+ @Test
+ public void create_empty_query() throws Exception {
+ RuleQuery result = execute();
+
+ assertThat(result.getKey()).isNull();
+
+ assertThat(result.getActivation()).isNull();
+ assertThat(result.getActiveSeverities()).isNull();
+ assertThat(result.isAscendingSort()).isTrue();
+ assertThat(result.getAvailableSinceLong()).isNull();
+ assertThat(result.getInheritance()).isNull();
+ assertThat(result.isTemplate()).isNull();
+ assertThat(result.getLanguages()).isNull();
+ assertThat(result.getQueryText()).isNull();
+ assertThat(result.getQProfileKey()).isNull();
+ assertThat(result.getRepositories()).isNull();
+ assertThat(result.getRuleKey()).isNull();
+ assertThat(result.getSeverities()).isNull();
+ assertThat(result.getStatuses()).isEmpty();
+ assertThat(result.getTags()).isNull();
+ assertThat(result.templateKey()).isNull();
+ assertThat(result.getTypes()).isEmpty();
+
+ assertThat(result.getSortField()).isNull();
+ }
+
+ @Test
+ public void create_query() throws Exception {
+ RuleQuery result = execute(
+ PARAM_RULE_KEY, "ruleKey",
+
+ PARAM_ACTIVATION, "true",
+ PARAM_ACTIVE_SEVERITIES, "MINOR,MAJOR",
+ PARAM_AVAILABLE_SINCE, "2016-01-01",
+ PARAM_INHERITANCE, "INHERITED,OVERRIDES",
+ PARAM_IS_TEMPLATE, "true",
+ PARAM_LANGUAGES, "java,js",
+ TEXT_QUERY, "S001",
+ PARAM_QPROFILE, "sonar-way",
+ PARAM_REPOSITORIES, "pmd,checkstyle",
+ PARAM_SEVERITIES, "MINOR,CRITICAL",
+ PARAM_STATUSES, "DEPRECATED,READY",
+ PARAM_TAGS, "tag1,tag2",
+ PARAM_TEMPLATE_KEY, "architectural",
+ PARAM_TYPES, "CODE_SMELL,BUG",
+
+ SORT, "updatedAt",
+ ASCENDING, "false");
+
+ assertThat(result.getKey()).isEqualTo("ruleKey");
+
+ assertThat(result.getActivation()).isTrue();
+ assertThat(result.getActiveSeverities()).containsOnly(MINOR, MAJOR);
+ assertThat(result.isAscendingSort()).isFalse();
+ assertThat(result.getAvailableSinceLong()).isNotNull();
+ assertThat(result.getInheritance()).containsOnly(INHERITED, OVERRIDES);
+ assertThat(result.isTemplate()).isTrue();
+ assertThat(result.getLanguages()).containsOnly("java", "js");
+ assertThat(result.getQueryText()).isEqualTo("S001");
+ assertThat(result.getQProfileKey()).isEqualTo("sonar-way");
+ assertThat(result.getRepositories()).containsOnly("pmd", "checkstyle");
+ assertThat(result.getRuleKey()).isNull();
+ assertThat(result.getSeverities()).containsOnly(MINOR, CRITICAL);
+ assertThat(result.getStatuses()).containsOnly(DEPRECATED, READY);
+ assertThat(result.getTags()).containsOnly("tag1", "tag2");
+ assertThat(result.templateKey()).isEqualTo("architectural");
+ assertThat(result.getTypes()).containsOnly(BUG, CODE_SMELL);
+
+ assertThat(result.getSortField()).isEqualTo("updatedAt");
+ }
+
+ @Test
+ public void create_query_add_language_from_profile() throws Exception {
+ String profileKey = "sonar-way";
+ dbClient.qualityProfileDao().insert(dbSession, QualityProfileDto.createFor(profileKey).setName("Sonar Way").setLanguage("xoo"));
+ dbSession.commit();
+
+ RuleQuery result = execute(
+ PARAM_QPROFILE, profileKey,
+ PARAM_LANGUAGES, "java,js");
+
+ assertThat(result.getQProfileKey()).isEqualTo(profileKey);
+ assertThat(result.getLanguages()).containsOnly("xoo");
+ }
+
+ private RuleQuery execute(String... paramsKeyAndValue) {
+ WsActionTester ws = new WsActionTester(fakeAction);
+ TestRequest request = ws.newRequest();
+ for (int i = 0; i < paramsKeyAndValue.length; i += 2) {
+ request.setParam(paramsKeyAndValue[i], paramsKeyAndValue[i + 1]);
+ }
+ request.execute();
+ return fakeAction.getRuleQuery();
+ }
+
+ private static class FakeAction implements WsAction {
+
+ private final RuleQueryFactory ruleQueryFactory;
+ private RuleQuery ruleQuery;
+
+ private FakeAction(RuleQueryFactory ruleQueryFactory) {
+ this.ruleQueryFactory = ruleQueryFactory;
+ }
+
+ @Override
+ public void define(WebService.NewController controller) {
+ WebService.NewAction action = controller.createAction("fake")
+ .setHandler(this);
+ defineRuleSearchParameters(action);
+ }
+
+ @Override
+ public void handle(Request request, Response response) throws Exception {
+ ruleQuery = ruleQueryFactory.createRuleQuery(request);
+ }
+
+ RuleQuery getRuleQuery() {
+ return ruleQuery;
+ }
+ }
+}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/QProfilesWsMediumTest/bulk_activate_rule.json b/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/QProfilesWsMediumTest/bulk_activate_rule.json
new file mode 100644
index 00000000000..fc904cd1ca9
--- /dev/null
+++ b/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/QProfilesWsMediumTest/bulk_activate_rule.json
@@ -0,0 +1,4 @@
+{
+ "succeeded": 4,
+ "failed": 0
+}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/QProfilesWsMediumTest/bulk_activate_rule_not_all.json b/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/QProfilesWsMediumTest/bulk_activate_rule_not_all.json
new file mode 100644
index 00000000000..5c9511a9ea8
--- /dev/null
+++ b/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/QProfilesWsMediumTest/bulk_activate_rule_not_all.json
@@ -0,0 +1,4 @@
+{
+ "succeeded": 2,
+ "failed": 0
+}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/QProfilesWsMediumTest/does_not_return_warnings_when_bulk_activate_on_profile_and_rules_exist_on_another_language_than_profile.json b/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/QProfilesWsMediumTest/does_not_return_warnings_when_bulk_activate_on_profile_and_rules_exist_on_another_language_than_profile.json
new file mode 100644
index 00000000000..5c9511a9ea8
--- /dev/null
+++ b/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/QProfilesWsMediumTest/does_not_return_warnings_when_bulk_activate_on_profile_and_rules_exist_on_another_language_than_profile.json
@@ -0,0 +1,4 @@
+{
+ "succeeded": 2,
+ "failed": 0
+}
diff --git a/sonar-ws/src/main/java/org/sonarqube/ws/client/rule/RulesService.java b/sonar-ws/src/main/java/org/sonarqube/ws/client/rule/RulesService.java
index 3fa569bfcca..e624b5c00ea 100644
--- a/sonar-ws/src/main/java/org/sonarqube/ws/client/rule/RulesService.java
+++ b/sonar-ws/src/main/java/org/sonarqube/ws/client/rule/RulesService.java
@@ -30,10 +30,10 @@ import static org.sonarqube.ws.client.rule.RulesWsParameters.PARAM_ACTIVE_SEVERI
import static org.sonarqube.ws.client.rule.RulesWsParameters.PARAM_AVAILABLE_SINCE;
import static org.sonarqube.ws.client.rule.RulesWsParameters.PARAM_INHERITANCE;
import static org.sonarqube.ws.client.rule.RulesWsParameters.PARAM_IS_TEMPLATE;
-import static org.sonarqube.ws.client.rule.RulesWsParameters.PARAM_RULE_KEY;
import static org.sonarqube.ws.client.rule.RulesWsParameters.PARAM_LANGUAGES;
import static org.sonarqube.ws.client.rule.RulesWsParameters.PARAM_QPROFILE;
import static org.sonarqube.ws.client.rule.RulesWsParameters.PARAM_REPOSITORIES;
+import static org.sonarqube.ws.client.rule.RulesWsParameters.PARAM_RULE_KEY;
import static org.sonarqube.ws.client.rule.RulesWsParameters.PARAM_SEVERITIES;
import static org.sonarqube.ws.client.rule.RulesWsParameters.PARAM_STATUSES;
import static org.sonarqube.ws.client.rule.RulesWsParameters.PARAM_TAGS;
diff --git a/sonar-ws/src/test/java/org/sonarqube/ws/client/rule/RulesServiceTest.java b/sonar-ws/src/test/java/org/sonarqube/ws/client/rule/RulesServiceTest.java
index 211de126eb0..8be893f9259 100644
--- a/sonar-ws/src/test/java/org/sonarqube/ws/client/rule/RulesServiceTest.java
+++ b/sonar-ws/src/test/java/org/sonarqube/ws/client/rule/RulesServiceTest.java
@@ -37,10 +37,10 @@ import static org.sonarqube.ws.client.rule.RulesWsParameters.PARAM_ACTIVE_SEVERI
import static org.sonarqube.ws.client.rule.RulesWsParameters.PARAM_AVAILABLE_SINCE;
import static org.sonarqube.ws.client.rule.RulesWsParameters.PARAM_INHERITANCE;
import static org.sonarqube.ws.client.rule.RulesWsParameters.PARAM_IS_TEMPLATE;
-import static org.sonarqube.ws.client.rule.RulesWsParameters.PARAM_RULE_KEY;
import static org.sonarqube.ws.client.rule.RulesWsParameters.PARAM_LANGUAGES;
import static org.sonarqube.ws.client.rule.RulesWsParameters.PARAM_QPROFILE;
import static org.sonarqube.ws.client.rule.RulesWsParameters.PARAM_REPOSITORIES;
+import static org.sonarqube.ws.client.rule.RulesWsParameters.PARAM_RULE_KEY;
import static org.sonarqube.ws.client.rule.RulesWsParameters.PARAM_SEVERITIES;
import static org.sonarqube.ws.client.rule.RulesWsParameters.PARAM_STATUSES;
import static org.sonarqube.ws.client.rule.RulesWsParameters.PARAM_TAGS;