From 18569e66e3e903aa63d2293def45a7c92b102de9 Mon Sep 17 00:00:00 2001 From: Pierre Date: Tue, 5 Jul 2022 17:53:50 +0200 Subject: [PATCH] SONAR-16598 Add new generic concepts to rules/show and rules/search endpoints (cherry picked from commit 31375405689110a07958f2c3be3f3b6d2a824e2b) --- .../src/main/java/org/sonar/db/rule/RuleDto.java | 14 ++++++++++++-- .../resources/org/sonar/db/rule/RuleMapper.xml | 6 +++++- .../test/java/org/sonar/db/rule/RuleDaoTest.java | 1 + .../java/org/sonar/db/rule/RuleTesting.java | 3 ++- .../java/org/sonar/server/rule/ws/RuleMapper.java | 8 ++++++++ .../sonar/server/rule/ws/RulesWsParameters.java | 3 ++- .../org/sonar/server/rule/ws/SearchAction.java | 3 ++- .../java/org/sonar/server/rule/ws/ShowAction.java | 3 ++- .../org/sonar/server/rule/ws/SearchActionTest.java | 3 ++- .../org/sonar/server/rule/ws/ShowActionTest.java | 1 + sonar-ws/src/main/protobuf/ws-rules.proto | 5 +++++ 11 files changed, 42 insertions(+), 8 deletions(-) diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/rule/RuleDto.java b/server/sonar-db-dao/src/main/java/org/sonar/db/rule/RuleDto.java index 2655b8e8f31..c3809c2ded6 100644 --- a/server/sonar-db-dao/src/main/java/org/sonar/db/rule/RuleDto.java +++ b/server/sonar-db-dao/src/main/java/org/sonar/db/rule/RuleDto.java @@ -21,7 +21,6 @@ package org.sonar.db.rule; import com.google.common.base.Splitter; import com.google.common.collect.ImmutableSet; -import java.util.Arrays; import java.util.Collection; import java.util.HashSet; import java.util.Objects; @@ -37,6 +36,7 @@ import org.sonar.api.rule.RuleStatus; import org.sonar.api.rules.RuleType; import static com.google.common.base.Preconditions.checkArgument; +import static java.util.Arrays.asList; import static java.util.Collections.emptySet; import static java.util.Optional.ofNullable; import static org.sonar.db.rule.RuleDescriptionSectionDto.DEFAULT_KEY; @@ -60,6 +60,7 @@ public class RuleDto { private String ruleKey = null; private final Set ruleDescriptionSectionDtos = new HashSet<>(); + private String genericConceptsField = null; /** * Description format can be null on external rule, otherwise it should never be null @@ -236,6 +237,15 @@ public class RuleDto { return Objects.equals(contextKey, otherContextKey); } + public Set getGenericConcepts() { + return deserializeStringSet(genericConceptsField); + } + + public RuleDto setGenericConcepts(Set genericConcepts){ + this.genericConceptsField = serializeStringSet(genericConcepts); + return this; + } + @CheckForNull public Format getDescriptionFormat() { return descriptionFormat; @@ -531,7 +541,7 @@ public class RuleDto { } public Set getTags() { - return tags == null ? new HashSet<>() : new TreeSet<>(Arrays.asList(StringUtils.split(tags, ','))); + return tags == null ? new HashSet<>() : new TreeSet<>(asList(StringUtils.split(tags, ','))); } String getTagsAsString() { diff --git a/server/sonar-db-dao/src/main/resources/org/sonar/db/rule/RuleMapper.xml b/server/sonar-db-dao/src/main/resources/org/sonar/db/rule/RuleMapper.xml index 643343da0bd..4ccbfe93651 100644 --- a/server/sonar-db-dao/src/main/resources/org/sonar/db/rule/RuleMapper.xml +++ b/server/sonar-db-dao/src/main/resources/org/sonar/db/rule/RuleMapper.xml @@ -38,7 +38,8 @@ r.ad_hoc_name as "adHocName", r.ad_hoc_description as "adHocDescription", r.ad_hoc_severity as "adHocSeverity", - r.ad_hoc_type as "adHocType" + r.ad_hoc_type as "adHocType", + r.generic_concepts as "genericConceptsField" @@ -272,6 +273,7 @@ ad_hoc_description, ad_hoc_severity, ad_hoc_type, + generic_concepts, created_at, updated_at ) @@ -310,6 +312,7 @@ #{adHocDescription,jdbcType=CLOB}, #{adHocSeverity,jdbcType=VARCHAR}, #{adHocType,jdbcType=TINYINT}, + #{genericConceptsField,jdbcType=VARCHAR}, #{createdAt,jdbcType=BIGINT}, #{updatedAt,jdbcType=BIGINT} ) @@ -350,6 +353,7 @@ ad_hoc_description=#{adHocDescription,jdbcType=CLOB}, ad_hoc_severity=#{adHocSeverity,jdbcType=VARCHAR}, ad_hoc_type=#{adHocType,jdbcType=TINYINT}, + generic_concepts=#{genericConceptsField,jdbcType=VARCHAR}, updated_at=#{updatedAt,jdbcType=BIGINT} where uuid=#{uuid,jdbcType=VARCHAR} diff --git a/server/sonar-db-dao/src/test/java/org/sonar/db/rule/RuleDaoTest.java b/server/sonar-db-dao/src/test/java/org/sonar/db/rule/RuleDaoTest.java index 0405c7eaa55..c26aea06e57 100644 --- a/server/sonar-db-dao/src/test/java/org/sonar/db/rule/RuleDaoTest.java +++ b/server/sonar-db-dao/src/test/java/org/sonar/db/rule/RuleDaoTest.java @@ -237,6 +237,7 @@ public class RuleDaoTest { assertThat(actual.getAdHocType()).isEqualTo(expected.getAdHocType()); assertThat(actual.getRuleDescriptionSectionDtos()).usingRecursiveFieldByFieldElementComparator() .containsExactlyInAnyOrderElementsOf(expected.getRuleDescriptionSectionDtos()); + assertThat(actual.getGenericConcepts()).isEqualTo(expected.getGenericConcepts()); } @Test diff --git a/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/rule/RuleTesting.java b/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/rule/RuleTesting.java index c2a064c6a43..87e7ed0dde5 100644 --- a/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/rule/RuleTesting.java +++ b/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/rule/RuleTesting.java @@ -118,7 +118,8 @@ public class RuleTesting { .setAdHocType(RuleType.values()[nextInt(RuleType.values().length - 1)]) .setCreatedAt(currentTimeMillis) .setUpdatedAt(currentTimeMillis + 5) - .setScope(Scope.MAIN); + .setScope(Scope.MAIN) + .setGenericConcepts(Set.of(randomAlphanumeric(5), randomAlphanumeric(5))); } public static RuleParamDto newRuleParam(RuleDto rule) { diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/rule/ws/RuleMapper.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/rule/ws/RuleMapper.java index 196cf330a26..856833ccf52 100644 --- a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/rule/ws/RuleMapper.java +++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/rule/ws/RuleMapper.java @@ -61,6 +61,7 @@ import static org.sonar.server.rule.ws.RulesWsParameters.FIELD_DEPRECATED_KEYS; import static org.sonar.server.rule.ws.RulesWsParameters.FIELD_DESCRIPTION_SECTIONS; import static org.sonar.server.rule.ws.RulesWsParameters.FIELD_EFFORT_TO_FIX_DESCRIPTION; import static org.sonar.server.rule.ws.RulesWsParameters.FIELD_GAP_DESCRIPTION; +import static org.sonar.server.rule.ws.RulesWsParameters.FIELD_GENERIC_CONCEPTS; import static org.sonar.server.rule.ws.RulesWsParameters.FIELD_HTML_DESCRIPTION; import static org.sonar.server.rule.ws.RulesWsParameters.FIELD_INTERNAL_KEY; import static org.sonar.server.rule.ws.RulesWsParameters.FIELD_IS_EXTERNAL; @@ -147,6 +148,7 @@ public class RuleMapper { setAdHocSeverity(ruleResponse, ruleDto, fieldsToReturn); setAdHocType(ruleResponse, ruleDto); } + setGenericConcepts(ruleResponse, ruleDto, fieldsToReturn); return ruleResponse; } @@ -197,6 +199,12 @@ public class RuleMapper { } } + private static void setGenericConcepts(Rules.Rule.Builder ruleResponse, RuleDto ruleDto, Set fieldsToReturn) { + if (shouldReturnField(fieldsToReturn, FIELD_GENERIC_CONCEPTS)) { + ruleResponse.getGenericConceptsBuilder().addAllGenericConcepts((ruleDto.getGenericConcepts())); + } + } + private static void setDeprecatedKeys(Rules.Rule.Builder ruleResponse, RuleDto ruleDto, Set fieldsToReturn, Map> deprecatedRuleKeysByRuleUuid) { if (shouldReturnField(fieldsToReturn, FIELD_DEPRECATED_KEYS)) { diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/rule/ws/RulesWsParameters.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/rule/ws/RulesWsParameters.java index 15260041edf..4f4af555c87 100644 --- a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/rule/ws/RulesWsParameters.java +++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/rule/ws/RulesWsParameters.java @@ -62,6 +62,7 @@ public class RulesWsParameters { public static final String FIELD_MARKDOWN_DESCRIPTION = "mdDesc"; public static final String FIELD_DESCRIPTION_SECTIONS = "descriptionSections"; + public static final String FIELD_GENERIC_CONCEPTS = "genericConcepts"; public static final String FIELD_NOTE_LOGIN = "noteLogin"; public static final String FIELD_MARKDOWN_NOTE = "mdNote"; public static final String FIELD_HTML_NOTE = "htmlNote"; @@ -109,7 +110,7 @@ public class RulesWsParameters { FIELD_MARKDOWN_DESCRIPTION, FIELD_DESCRIPTION_SECTIONS, FIELD_NOTE_LOGIN, FIELD_MARKDOWN_NOTE, FIELD_HTML_NOTE, FIELD_DEFAULT_DEBT_REM_FUNCTION, FIELD_EFFORT_TO_FIX_DESCRIPTION, FIELD_DEBT_OVERLOADED, FIELD_DEBT_REM_FUNCTION, FIELD_DEFAULT_REM_FUNCTION, FIELD_GAP_DESCRIPTION, FIELD_REM_FUNCTION_OVERLOADED, FIELD_REM_FUNCTION, - FIELD_PARAMS, FIELD_ACTIVES, FIELD_SCOPE, FIELD_DEPRECATED_KEYS); + FIELD_PARAMS, FIELD_ACTIVES, FIELD_SCOPE, FIELD_DEPRECATED_KEYS, FIELD_GENERIC_CONCEPTS); private RulesWsParameters() { // prevent instantiation diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/rule/ws/SearchAction.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/rule/ws/SearchAction.java index 1db0a7cada2..31db2ae17a7 100644 --- a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/rule/ws/SearchAction.java +++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/rule/ws/SearchAction.java @@ -151,7 +151,8 @@ public class SearchAction implements RulesWsAction { new Change("9.5", "The field 'htmlDesc' has been deprecated use 'descriptionSections' instead"), new Change("9.5", "The field 'descriptionSections' has been added to the payload"), new Change("9.5", "The field 'descriptionSections' has been added to the 'f' parameter"), - new Change("9.6", "'descriptionSections' can optionally embed a context field") + new Change("9.6", "'descriptionSections' can optionally embed a context field"), + new Change("9.6", "The field 'genericConcepts' has been added to the 'f' parameter") ); action.createParam(FACETS) diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/rule/ws/ShowAction.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/rule/ws/ShowAction.java index ec32f637346..1e5afdb58f9 100644 --- a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/rule/ws/ShowAction.java +++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/rule/ws/ShowAction.java @@ -79,7 +79,8 @@ public class ShowAction implements RulesWsAction { new Change("9.5", "The field 'htmlDesc' has been deprecated use 'descriptionSections' instead"), new Change("9.5", "The field 'descriptionSections' has been added to the payload"), new Change("9.5", "The field 'descriptionSections' has been added to the 'f' parameter"), - new Change("9.6", "'descriptionSections' can optionally embed a context field") + new Change("9.6", "'descriptionSections' can optionally embed a context field"), + new Change("9.6", "'genericConcepts' has been added") ); action diff --git a/server/sonar-webserver-webapi/src/test/java/org/sonar/server/rule/ws/SearchActionTest.java b/server/sonar-webserver-webapi/src/test/java/org/sonar/server/rule/ws/SearchActionTest.java index a4b683a5040..bdc2bf3c09a 100644 --- a/server/sonar-webserver-webapi/src/test/java/org/sonar/server/rule/ws/SearchActionTest.java +++ b/server/sonar-webserver-webapi/src/test/java/org/sonar/server/rule/ws/SearchActionTest.java @@ -309,7 +309,7 @@ public class SearchActionTest { indexRules(); Rules.SearchResponse response = ws.newRequest() - .setParam(WebService.Param.FIELDS, "createdAt,langName") + .setParam(WebService.Param.FIELDS, "createdAt,langName,genericConcepts") .executeProtobuf(Rules.SearchResponse.class); Rules.Rule result = response.getRules(0); @@ -320,6 +320,7 @@ public class SearchActionTest { // selected fields assertThat(result.getCreatedAt()).isNotEmpty(); assertThat(result.getLangName()).isNotEmpty(); + assertThat(result.getGenericConcepts().getGenericConceptsList()).containsExactlyElementsOf(rule.getGenericConcepts()); // not returned fields assertThat(result.hasEffortToFixDescription()).isFalse(); diff --git a/server/sonar-webserver-webapi/src/test/java/org/sonar/server/rule/ws/ShowActionTest.java b/server/sonar-webserver-webapi/src/test/java/org/sonar/server/rule/ws/ShowActionTest.java index 54b5775528a..8e6590dee74 100644 --- a/server/sonar-webserver-webapi/src/test/java/org/sonar/server/rule/ws/ShowActionTest.java +++ b/server/sonar-webserver-webapi/src/test/java/org/sonar/server/rule/ws/ShowActionTest.java @@ -130,6 +130,7 @@ public class ShowActionTest { assertThat(resultRule.getParams().getParamsList()) .extracting(Rule.Param::getKey, Rule.Param::getHtmlDesc, Rule.Param::getDefaultValue) .containsExactlyInAnyOrder(tuple(ruleParam.getName(), ruleParam.getDescription(), ruleParam.getDefaultValue())); + assertThat(resultRule.getGenericConcepts().getGenericConceptsList()).containsExactlyElementsOf(rule.getGenericConcepts()); } @Test diff --git a/sonar-ws/src/main/protobuf/ws-rules.proto b/sonar-ws/src/main/protobuf/ws-rules.proto index e1772529d3c..ec2ee250624 100644 --- a/sonar-ws/src/main/protobuf/ws-rules.proto +++ b/sonar-ws/src/main/protobuf/ws-rules.proto @@ -123,6 +123,7 @@ message Rule { optional bool isExternal = 47; optional DeprecatedKeys deprecatedKeys = 48; optional DescriptionSections descriptionSections = 49; + optional GenericConcepts genericConcepts = 50; message DescriptionSections { repeated DescriptionSection descriptionSections = 1; @@ -163,6 +164,10 @@ message Tags { repeated string tags = 1; } +message GenericConcepts { + repeated string genericConcepts = 1; +} + message Actives { map actives = 1; } -- 2.39.5