aboutsummaryrefslogtreecommitdiffstats
path: root/server/sonar-server-common
diff options
context:
space:
mode:
authorPierre Guillot <pierre.guillot@sonarsource.com>2024-12-10 15:29:09 +0100
committerSteve Marion <steve.marion@sonarsource.com>2024-12-18 11:13:21 +0100
commitd639a965bce7acafb004906cd07a8f0b5f7af993 (patch)
tree647cd646abddb12dfeeef7e637aa33b4658f1049 /server/sonar-server-common
parent451c1c2e4856ec3df87f86189fcdb25b31794027 (diff)
downloadsonarqube-d639a965bce7acafb004906cd07a8f0b5f7af993.tar.gz
sonarqube-d639a965bce7acafb004906cd07a8f0b5f7af993.zip
SONAR-22998 fetch active rules with a dedicated endpoint
Co-authored-by: Julien HENRY <julien.henry@sonarsource.com>
Diffstat (limited to 'server/sonar-server-common')
-rw-r--r--server/sonar-server-common/src/it/java/org/sonar/server/rule/ActiveRuleServiceIT.java206
-rw-r--r--server/sonar-server-common/src/main/java/org/sonar/server/rule/ActiveRuleRestReponse.java123
-rw-r--r--server/sonar-server-common/src/main/java/org/sonar/server/rule/ActiveRuleService.java177
3 files changed, 506 insertions, 0 deletions
diff --git a/server/sonar-server-common/src/it/java/org/sonar/server/rule/ActiveRuleServiceIT.java b/server/sonar-server-common/src/it/java/org/sonar/server/rule/ActiveRuleServiceIT.java
new file mode 100644
index 00000000000..2d36a185236
--- /dev/null
+++ b/server/sonar-server-common/src/it/java/org/sonar/server/rule/ActiveRuleServiceIT.java
@@ -0,0 +1,206 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2024 SonarSource SA
+ * mailto:info 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;
+
+import java.util.List;
+import org.assertj.core.groups.Tuple;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.RegisterExtension;
+import org.sonar.api.resources.Language;
+import org.sonar.api.resources.Languages;
+import org.sonar.api.utils.System2;
+import org.sonar.db.DbTester;
+import org.sonar.db.component.ProjectData;
+import org.sonar.db.qualityprofile.ActiveRuleDto;
+import org.sonar.db.qualityprofile.ActiveRuleKey;
+import org.sonar.db.qualityprofile.ActiveRuleParamDto;
+import org.sonar.db.qualityprofile.QProfileDto;
+import org.sonar.db.rule.RuleDto;
+import org.sonar.db.rule.RuleParamDto;
+import org.sonar.server.rule.ActiveRuleRestReponse.ActiveRule;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.tuple;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+import static org.sonar.api.utils.DateUtils.formatDateTime;
+
+class ActiveRuleServiceIT {
+
+ public static final Language XOO_LANGUAGE = mock(Language.class);
+ public static final Language XOO2_LANGUAGE = mock(Language.class);
+
+ public static final String XOO_LANGUAGE_KEY = "xoo";
+ public static final String XOO2_LANGUAGE_KEY = "xoo2";
+
+ static {
+ when(XOO_LANGUAGE.getKey()).thenReturn(XOO_LANGUAGE_KEY);
+ when(XOO2_LANGUAGE.getKey()).thenReturn(XOO2_LANGUAGE_KEY);
+ }
+
+ @RegisterExtension
+ DbTester db = DbTester.create(System2.INSTANCE);
+
+ private final ActiveRuleService activeRuleService = new ActiveRuleService(db.getDbClient(), new Languages(XOO_LANGUAGE, XOO2_LANGUAGE));
+
+ @Test
+ void buildDefaultActiveRules() {
+ QProfileDto qProfileDto1 = db.qualityProfiles().insert(qp -> qp.setLanguage(XOO_LANGUAGE_KEY));
+ db.qualityProfiles().setAsDefault(qProfileDto1);
+ RuleDto rule1 = db.rules().insert(r -> r.setLanguage(XOO_LANGUAGE_KEY), r -> r.setName("rule1"));
+ ActiveRuleDto activatedRule1 = db.qualityProfiles().activateRule(qProfileDto1, rule1);
+ RuleDto rule2 = db.rules().insert(r -> r.setLanguage(XOO_LANGUAGE_KEY), r -> r.setName("rule2"));
+ ActiveRuleDto activatedRule2 = db.qualityProfiles().activateRule(qProfileDto1, rule2);
+
+ QProfileDto qProfileDto2 = db.qualityProfiles().insert(qp -> qp.setLanguage(XOO2_LANGUAGE_KEY));
+ db.qualityProfiles().setAsDefault(qProfileDto2);
+ RuleDto rule3 = db.rules().insert(r -> r.setLanguage(XOO2_LANGUAGE_KEY), r -> r.setName("rule3"));
+ ActiveRuleDto activatedRule3 = db.qualityProfiles().activateRule(qProfileDto2, rule3);
+
+ List<ActiveRule> activeRules = activeRuleService.buildDefaultActiveRules();
+ assertThat(activeRules).isNotNull().hasSize(3)
+ .extracting(ActiveRule::ruleKey, ActiveRule::name, ActiveRule::severity,
+ ActiveRule::createdAt, ActiveRule::updatedAt, ActiveRule::internalKey,
+ ActiveRule::language, ActiveRule::templateRuleKey, ActiveRule::qProfileKey,
+ ActiveRule::deprecatedKeys, ActiveRule::params)
+ .containsExactlyInAnyOrder(
+ toTuple(activatedRule1, XOO_LANGUAGE_KEY, qProfileDto1, List.of()),
+ toTuple(activatedRule2, XOO_LANGUAGE_KEY, qProfileDto1, List.of()),
+ toTuple(activatedRule3, XOO2_LANGUAGE_KEY, qProfileDto2, List.of()));
+ }
+
+ @Test
+ void buildActiveRule_with_default_profile() {
+ QProfileDto qProfileDto1 = db.qualityProfiles().insert(qp -> qp.setLanguage(XOO_LANGUAGE_KEY));
+ db.qualityProfiles().setAsDefault(qProfileDto1);
+ RuleDto rule1 = db.rules().insert(r -> r.setLanguage(XOO_LANGUAGE_KEY), r -> r.setName("rule1"));
+ ActiveRuleDto activatedRule1 = db.qualityProfiles().activateRule(qProfileDto1, rule1);
+ RuleDto rule2 = db.rules().insert(r -> r.setLanguage(XOO_LANGUAGE_KEY), r -> r.setName("rule2"));
+ ActiveRuleDto activatedRule2 = db.qualityProfiles().activateRule(qProfileDto1, rule2);
+
+ QProfileDto qProfileDto2 = db.qualityProfiles().insert(qp -> qp.setLanguage(XOO2_LANGUAGE_KEY));
+ db.qualityProfiles().setAsDefault(qProfileDto2);
+ RuleDto rule3 = db.rules().insert(r -> r.setLanguage(XOO2_LANGUAGE_KEY), r -> r.setName("rule3"));
+ ActiveRuleDto activatedRule3 = db.qualityProfiles().activateRule(qProfileDto2, rule3);
+
+ var removedLanguageKey = "removed";
+ QProfileDto qProfileDtoRemovedLanguage = db.qualityProfiles().insert(qp -> qp.setLanguage(removedLanguageKey));
+ db.qualityProfiles().setAsDefault(qProfileDtoRemovedLanguage);
+ RuleDto ruleRemovedLanguage = db.rules().insert(r -> r.setLanguage(removedLanguageKey), r -> r.setName("ruleRemovedLanguage"));
+ db.qualityProfiles().activateRule(qProfileDtoRemovedLanguage, ruleRemovedLanguage);
+
+ List<ActiveRule> activeRules = activeRuleService.buildActiveRules("myProjectUuid");
+ assertThat(activeRules).isNotNull().hasSize(3)
+ .extracting(ActiveRule::ruleKey, ActiveRule::name, ActiveRule::severity,
+ ActiveRule::createdAt, ActiveRule::updatedAt, ActiveRule::internalKey,
+ ActiveRule::language, ActiveRule::templateRuleKey, ActiveRule::qProfileKey,
+ ActiveRule::deprecatedKeys, ActiveRule::params)
+ .containsExactlyInAnyOrder(
+ toTuple(activatedRule1, XOO_LANGUAGE_KEY, qProfileDto1, List.of()),
+ toTuple(activatedRule2, XOO_LANGUAGE_KEY, qProfileDto1, List.of()),
+ toTuple(activatedRule3, XOO2_LANGUAGE_KEY, qProfileDto2, List.of()));
+ }
+
+ @Test
+ void projectProfile_overrides_defaultProfile() {
+ QProfileDto qProfileDto1 = db.qualityProfiles().insert(qp -> qp.setLanguage(XOO_LANGUAGE_KEY));
+ db.qualityProfiles().setAsDefault(qProfileDto1);
+ RuleDto rule1 = db.rules().insert(r -> r.setLanguage(XOO_LANGUAGE_KEY), r -> r.setName("rule1"));
+ db.qualityProfiles().activateRule(qProfileDto1, rule1);
+
+ QProfileDto qProfileDto2 = db.qualityProfiles().insert(qp -> qp.setLanguage(XOO_LANGUAGE_KEY));
+ ProjectData project = db.components().insertPrivateProject();
+ db.qualityProfiles().associateWithProject(project.getProjectDto(), qProfileDto2);
+ ActiveRuleDto activatedRule2 = db.qualityProfiles().activateRule(qProfileDto2, rule1);
+
+ List<ActiveRule> activeRules = activeRuleService.buildActiveRules(project.projectUuid());
+ assertThat(activeRules).hasSize(1)
+ .extracting(ActiveRule::ruleKey, ActiveRule::name, ActiveRule::severity,
+ ActiveRule::createdAt, ActiveRule::updatedAt, ActiveRule::internalKey,
+ ActiveRule::language, ActiveRule::templateRuleKey, ActiveRule::qProfileKey,
+ ActiveRule::deprecatedKeys, ActiveRule::params)
+ .containsExactlyInAnyOrder(
+ toTuple(activatedRule2, XOO_LANGUAGE_KEY, qProfileDto2, List.of()));
+ }
+
+ @Test
+ void customRuleParam_overrides_defaultRuleParamValue() {
+ RuleDto rule = db.rules().insert(r -> r.setLanguage(XOO_LANGUAGE_KEY), r -> r.setName("rule"));
+ RuleParamDto ruleParam = db.rules().insertRuleParam(rule, p -> p.setDefaultValue("defaultValue"));
+ QProfileDto defaultQualityProfile = db.qualityProfiles().insert(qp -> qp.setLanguage(XOO_LANGUAGE_KEY));
+ db.qualityProfiles().setAsDefault(defaultQualityProfile);
+ db.qualityProfiles().activateRule(defaultQualityProfile, rule);
+
+ QProfileDto qProfileDto2 = db.qualityProfiles().insert(qp -> qp.setLanguage(XOO_LANGUAGE_KEY));
+ ProjectData project = db.components().insertPrivateProject();
+ db.qualityProfiles().associateWithProject(project.getProjectDto(), qProfileDto2);
+ ActiveRuleDto activatedRule2 = db.qualityProfiles().activateRule(qProfileDto2, rule);
+ db.getDbClient().activeRuleDao().insertParam(db.getSession(), activatedRule2, new ActiveRuleParamDto()
+ .setRulesParameterUuid(ruleParam.getUuid())
+ .setKey(ruleParam.getName())
+ .setValue("overriddenValue"));
+
+ db.commit();
+
+ List<ActiveRule> activeRules = activeRuleService.buildActiveRules(project.projectUuid());
+ assertThat(activeRules).hasSize(1)
+ .extracting(ActiveRule::ruleKey, ActiveRule::name, ActiveRule::severity,
+ ActiveRule::createdAt, ActiveRule::updatedAt, ActiveRule::internalKey,
+ ActiveRule::language, ActiveRule::templateRuleKey, ActiveRule::qProfileKey,
+ ActiveRule::deprecatedKeys, ActiveRule::params)
+ .containsExactlyInAnyOrder(
+ toTuple(activatedRule2, XOO_LANGUAGE_KEY, qProfileDto2, List.of(new ActiveRuleRestReponse.Param(ruleParam.getName(), "overriddenValue"))));
+ }
+
+ @Test
+ void returnsRuleTemplate() {
+ RuleDto templateRule = db.rules().insert(r -> r.setLanguage(XOO_LANGUAGE_KEY)
+ .setIsTemplate(true));
+ RuleDto rule = db.rules().insert(r -> r.setLanguage(XOO_LANGUAGE_KEY)
+ .setTemplateUuid(templateRule.getUuid()));
+ RuleParamDto ruleParam = db.rules().insertRuleParam(rule);
+ QProfileDto defaultQualityProfile = db.qualityProfiles().insert(qp -> qp.setLanguage(XOO_LANGUAGE_KEY));
+ db.qualityProfiles().setAsDefault(defaultQualityProfile);
+ ActiveRuleDto activeRule = db.qualityProfiles().activateRule(defaultQualityProfile, rule);
+ ProjectData project = db.components().insertPrivateProject();
+
+ List<ActiveRule> activeRules = activeRuleService.buildActiveRules(project.projectUuid());
+ assertThat(activeRules).hasSize(1)
+ .extracting(ActiveRule::ruleKey, ActiveRule::name, ActiveRule::severity,
+ ActiveRule::createdAt, ActiveRule::updatedAt, ActiveRule::internalKey,
+ ActiveRule::language, ActiveRule::templateRuleKey, ActiveRule::qProfileKey,
+ ActiveRule::deprecatedKeys, ActiveRule::params)
+ .containsExactlyInAnyOrder(
+ tuple(toRuleKey(activeRule.getKey()), activeRule.getName(), activeRule.getSeverityString(), formatDateTime(activeRule.getCreatedAt()),
+ formatDateTime(activeRule.getUpdatedAt()), activeRule.getConfigKey(), XOO_LANGUAGE_KEY, templateRule.getKey().toString(), defaultQualityProfile.getKee(), List.of(),
+ List.of(new ActiveRuleRestReponse.Param(ruleParam.getName(), ruleParam.getDefaultValue()))));
+
+ }
+
+ private Tuple toTuple(ActiveRuleDto activatedRule, String language, QProfileDto qProfileDto, List<ActiveRuleRestReponse.Param> expectedParams) {
+ return tuple(toRuleKey(activatedRule.getKey()), activatedRule.getName(), activatedRule.getSeverityString(), formatDateTime(activatedRule.getCreatedAt()),
+ formatDateTime(activatedRule.getUpdatedAt()), activatedRule.getConfigKey(), language, null, qProfileDto.getKee(), List.of(), expectedParams);
+ }
+
+ private ActiveRuleRestReponse.RuleKey toRuleKey(ActiveRuleKey key) {
+ return new ActiveRuleRestReponse.RuleKey(key.getRuleKey().repository(), key.getRuleKey().rule());
+ }
+
+}
diff --git a/server/sonar-server-common/src/main/java/org/sonar/server/rule/ActiveRuleRestReponse.java b/server/sonar-server-common/src/main/java/org/sonar/server/rule/ActiveRuleRestReponse.java
new file mode 100644
index 00000000000..f802e7f004d
--- /dev/null
+++ b/server/sonar-server-common/src/main/java/org/sonar/server/rule/ActiveRuleRestReponse.java
@@ -0,0 +1,123 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2024 SonarSource SA
+ * mailto:info 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;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import java.util.ArrayList;
+import java.util.EnumMap;
+import java.util.List;
+import java.util.Map;
+import javax.annotation.Nullable;
+import org.sonar.api.issue.impact.Severity;
+import org.sonar.api.issue.impact.SoftwareQuality;
+
+public class ActiveRuleRestReponse {
+
+ public record ActiveRule(
+ RuleKey ruleKey,
+ String name,
+ String severity,
+ String createdAt,
+ String updatedAt,
+ @JsonInclude(JsonInclude.Include.NON_NULL) @Nullable String internalKey,
+ String language,
+ @JsonInclude(JsonInclude.Include.NON_NULL) @Nullable String templateRuleKey,
+ String qProfileKey,
+ @JsonInclude(JsonInclude.Include.NON_EMPTY) List<RuleKey> deprecatedKeys,
+ @JsonInclude(JsonInclude.Include.NON_EMPTY) List<Param> params,
+ @JsonInclude(JsonInclude.Include.NON_EMPTY) Map<SoftwareQuality, Severity> impacts) {
+ }
+
+ public record RuleKey(String repository, String rule) {
+ }
+
+ public record Param(String key, String value) {
+ }
+
+ public static class Builder {
+ private RuleKey ruleKey;
+ private String name;
+ private String severity;
+ private String createdAt;
+ private String updatedAt;
+ private String internalKey;
+ private String language;
+ private String templateRuleKey;
+ private String qProfilKey;
+ private final List<RuleKey> deprecatedKeys = new ArrayList<>();
+ private final List<Param> params = new ArrayList<>();
+ private final Map<SoftwareQuality, Severity> impacts = new EnumMap<>(SoftwareQuality.class);
+
+ public void setRuleKey(RuleKey ruleKey) {
+ this.ruleKey = ruleKey;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public void setSeverity(String severity) {
+ this.severity = severity;
+ }
+
+ public void setCreatedAt(String createdAt) {
+ this.createdAt = createdAt;
+ }
+
+ public void setUpdatedAt(String updatedAt) {
+ this.updatedAt = updatedAt;
+ }
+
+ public void setInternalKey(String internalKey) {
+ this.internalKey = internalKey;
+ }
+
+ public void setLanguage(String language) {
+ this.language = language;
+ }
+
+ public void setTemplateRuleKey(String templateRuleKey) {
+ this.templateRuleKey = templateRuleKey;
+ }
+
+ public void setQProfilKey(String qProfilKey) {
+ this.qProfilKey = qProfilKey;
+ }
+
+ public void setParams(List<Param> params) {
+ this.params.clear();
+ this.params.addAll(params);
+ }
+
+ public void addAllDeprecatedKeys(List<RuleKey> deprecatedKeys) {
+ this.deprecatedKeys.addAll(deprecatedKeys);
+ }
+
+ public void setImpacts(Map<SoftwareQuality, Severity> impacts) {
+ this.impacts.clear();
+ this.impacts.putAll(impacts);
+ }
+
+ public ActiveRule build() {
+ return new ActiveRule(ruleKey, name, severity, createdAt, updatedAt, internalKey, language, templateRuleKey, qProfilKey, deprecatedKeys, params, impacts);
+ }
+ }
+
+}
diff --git a/server/sonar-server-common/src/main/java/org/sonar/server/rule/ActiveRuleService.java b/server/sonar-server-common/src/main/java/org/sonar/server/rule/ActiveRuleService.java
new file mode 100644
index 00000000000..5a7960a6010
--- /dev/null
+++ b/server/sonar-server-common/src/main/java/org/sonar/server/rule/ActiveRuleService.java
@@ -0,0 +1,177 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2024 SonarSource SA
+ * mailto:info 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;
+
+import com.google.common.base.Strings;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.Set;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+import javax.annotation.Nullable;
+import org.sonar.api.resources.Language;
+import org.sonar.api.resources.Languages;
+import org.sonar.api.rule.RuleKey;
+import org.sonar.api.utils.DateUtils;
+import org.sonar.db.DbClient;
+import org.sonar.db.DbSession;
+import org.sonar.db.qualityprofile.ActiveRuleParamDto;
+import org.sonar.db.qualityprofile.OrgActiveRuleDto;
+import org.sonar.db.qualityprofile.QProfileDto;
+import org.sonar.db.rule.DeprecatedRuleKeyDto;
+import org.sonar.db.rule.RuleDto;
+import org.sonar.db.rule.RuleParamDto;
+
+import static java.util.Optional.ofNullable;
+
+public class ActiveRuleService {
+
+ private final DbClient dbClient;
+ private final Languages languages;
+
+ public ActiveRuleService(DbClient dbClient, Languages languages) {
+ this.dbClient = dbClient;
+ this.languages = languages;
+ }
+
+ public List<ActiveRuleRestReponse.ActiveRule> buildDefaultActiveRules() {
+ try (DbSession dbSession = dbClient.openSession(false)) {
+ List<QProfileDto> qualityProfiles = dbClient.qualityProfileDao().selectDefaultProfiles(dbSession, getLanguageKeys());
+ return loadActiveRules(qualityProfiles, dbSession);
+ }
+ }
+
+ public List<ActiveRuleRestReponse.ActiveRule> buildActiveRules(String projectUuid) {
+ try (DbSession dbSession = dbClient.openSession(false)) {
+ List<QProfileDto> qualityProfiles = getQualityProfiles(dbSession, projectUuid);
+ return loadActiveRules(qualityProfiles, dbSession);
+ }
+ }
+
+ private Set<String> getLanguageKeys() {
+ return Arrays.stream(languages.all()).map(Language::getKey).collect(Collectors.toSet());
+ }
+
+ private List<ActiveRuleRestReponse.ActiveRule> loadActiveRules(List<QProfileDto> qualityProfiles, DbSession dbSession) {
+
+ Map<String, QProfileDto> profilesByUuids = qualityProfiles.stream().collect(Collectors.toMap(QProfileDto::getKee, Function.identity()));
+
+ Map<String, List<RuleParamDto>> ruleParamsByRuleUuid = dbClient.ruleDao().selectAllRuleParams(dbSession).stream()
+ .collect(Collectors.groupingBy(RuleParamDto::getRuleUuid));
+
+ Map<String, List<ActiveRuleParamDto>> activeRuleParamsByActiveRuleUuid = dbClient.activeRuleDao().selectAllParamsByProfileUuids(dbSession, profilesByUuids.keySet()).stream()
+ .collect(Collectors.groupingBy(ActiveRuleParamDto::getActiveRuleUuid));
+
+ List<OrgActiveRuleDto> activeRuleDtos = dbClient.activeRuleDao().selectByProfileUuids(dbSession, profilesByUuids.keySet());
+ Map<String, RuleDto> templateRulesByUuid = getTemplateRulesByUuid(dbSession, activeRuleDtos);
+ Map<String, List<DeprecatedRuleKeyDto>> deprecatedRuleKeysByRuleUuid = getDeprecatedRuleKeysByRuleUuid(dbSession);
+
+ return activeRuleDtos.stream()
+ .map(
+ activeRuleDto -> buildActiveRule(activeRuleDto, profilesByUuids, templateRulesByUuid, deprecatedRuleKeysByRuleUuid, ruleParamsByRuleUuid, activeRuleParamsByActiveRuleUuid))
+ .toList();
+ }
+
+ private static ActiveRuleRestReponse.ActiveRule buildActiveRule(OrgActiveRuleDto activeRuleDto,
+ Map<String, QProfileDto> profilesByUuids,
+ Map<String, RuleDto> templateRulesByUuid,
+ Map<String, List<DeprecatedRuleKeyDto>> deprecatedRuleKeysByRuleUuid,
+ Map<String, List<RuleParamDto>> ruleParamsByRuleUuid,
+ Map<String, List<ActiveRuleParamDto>> activeRuleParamsByActiveRuleUuid) {
+ ActiveRuleRestReponse.Builder activeRuleBuilder = new ActiveRuleRestReponse.Builder();
+ activeRuleBuilder.setRuleKey(toRuleKey(activeRuleDto.getRuleKey()));
+ activeRuleBuilder.setName(activeRuleDto.getName());
+ activeRuleBuilder.setSeverity(activeRuleDto.getSeverityString());
+ activeRuleBuilder.setCreatedAt(DateUtils.formatDateTime(activeRuleDto.getCreatedAt()));
+ activeRuleBuilder.setUpdatedAt(DateUtils.formatDateTime(activeRuleDto.getUpdatedAt()));
+ // same as RuleForIndexingDto mapping
+ activeRuleBuilder.setInternalKey(activeRuleDto.getConfigKey());
+ activeRuleBuilder.setQProfilKey(profilesByUuids.get(activeRuleDto.getOrgProfileUuid()).getKee());
+ activeRuleBuilder.setLanguage(activeRuleDto.getLanguage());
+ Optional<RuleDto> templateRule = ofNullable(templateRulesByUuid.get(activeRuleDto.getTemplateUuid()));
+ templateRule.ifPresent(template -> activeRuleBuilder.setTemplateRuleKey(template.getKey().toString()));
+
+ List<ActiveRuleRestReponse.RuleKey> deprecatedKeys = buildDeprecatedKeys(activeRuleDto, deprecatedRuleKeysByRuleUuid);
+ activeRuleBuilder.addAllDeprecatedKeys(deprecatedKeys);
+
+ List<RuleParamDto> ruleParams = ruleParamsByRuleUuid.get(activeRuleDto.getRuleUuid());
+ List<ActiveRuleParamDto> activeRuleParams = ofNullable(activeRuleParamsByActiveRuleUuid.get(activeRuleDto.getUuid())).orElse(List.of());
+ List<ActiveRuleRestReponse.Param> params = buildParams(ruleParams, activeRuleParams);
+ activeRuleBuilder.setParams(params);
+
+ activeRuleBuilder.setImpacts(activeRuleDto.getImpacts());
+
+ return activeRuleBuilder.build();
+ }
+
+ private static List<ActiveRuleRestReponse.Param> buildParams(@Nullable List<RuleParamDto> ruleParams, List<ActiveRuleParamDto> activeRuleParams) {
+ if (ruleParams == null) {
+ return List.of();
+ }
+ return ruleParams.stream()
+ .map(parameter -> {
+ Optional<ActiveRuleParamDto> activeRuleParamDto = activeRuleParams.stream()
+ .filter(arp -> arp.getRulesParameterUuid().equals(parameter.getUuid()))
+ .findAny();
+ String paramValue = activeRuleParamDto.map(ActiveRuleParamDto::getValue).orElse(parameter.getDefaultValue());
+ return new ActiveRuleRestReponse.Param(parameter.getName(), Strings.nullToEmpty(paramValue));
+ })
+ .toList();
+ }
+
+ private static List<ActiveRuleRestReponse.RuleKey> buildDeprecatedKeys(OrgActiveRuleDto activeRuleDto, Map<String, List<DeprecatedRuleKeyDto>> deprecatedRuleKeysByRuleUuid) {
+ List<DeprecatedRuleKeyDto> deprecatedRuleKeyDtos = deprecatedRuleKeysByRuleUuid.getOrDefault(activeRuleDto.getUuid(), List.of());
+ return deprecatedRuleKeyDtos.stream()
+ .map(ActiveRuleService::toRuleKey)
+ .toList();
+ }
+
+ private List<QProfileDto> getQualityProfiles(DbSession dbSession, String projectUuid) {
+ List<QProfileDto> defaultProfiles = dbClient.qualityProfileDao().selectDefaultProfiles(dbSession, getLanguageKeys());
+ Map<String, QProfileDto> projectProfiles = dbClient.qualityProfileDao().selectAssociatedToProjectAndLanguages(dbSession, projectUuid, getLanguageKeys())
+ .stream().collect(Collectors.toMap(QProfileDto::getLanguage, Function.identity()));
+
+ return defaultProfiles.stream()
+ .map(defaultProfile -> projectProfiles.getOrDefault(defaultProfile.getLanguage(), defaultProfile))
+ .toList();
+ }
+
+ private Map<String, RuleDto> getTemplateRulesByUuid(DbSession dbSession, List<OrgActiveRuleDto> activeRuleDtos) {
+ Set<String> templateRuleUuids = activeRuleDtos.stream().map(OrgActiveRuleDto::getTemplateUuid).filter(Objects::nonNull).collect(Collectors.toSet());
+ return dbClient.ruleDao().selectByUuids(dbSession, templateRuleUuids).stream().collect(Collectors.toMap(RuleDto::getUuid, p -> p));
+ }
+
+ private static ActiveRuleRestReponse.RuleKey toRuleKey(RuleKey ruleKey) {
+ return new ActiveRuleRestReponse.RuleKey(ruleKey.repository(), ruleKey.rule());
+ }
+
+ private static ActiveRuleRestReponse.RuleKey toRuleKey(DeprecatedRuleKeyDto r) {
+ return new ActiveRuleRestReponse.RuleKey(r.getOldRepositoryKey(), r.getOldRuleKey());
+ }
+
+ private Map<String, List<DeprecatedRuleKeyDto>> getDeprecatedRuleKeysByRuleUuid(DbSession dbSession) {
+ return dbClient.ruleDao().selectAllDeprecatedRuleKeys(dbSession).stream()
+ .collect(Collectors.groupingBy(DeprecatedRuleKeyDto::getRuleUuid));
+ }
+
+}