]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-16598 Add new generic concepts to rules/show and rules/search endpoints
authorPierre <pierre.guillot@sonarsource.com>
Tue, 5 Jul 2022 15:53:50 +0000 (17:53 +0200)
committersonartech <sonartech@sonarsource.com>
Fri, 8 Jul 2022 20:02:47 +0000 (20:02 +0000)
server/sonar-db-dao/src/main/java/org/sonar/db/rule/RuleDto.java
server/sonar-db-dao/src/main/resources/org/sonar/db/rule/RuleMapper.xml
server/sonar-db-dao/src/test/java/org/sonar/db/rule/RuleDaoTest.java
server/sonar-db-dao/src/testFixtures/java/org/sonar/db/rule/RuleTesting.java
server/sonar-webserver-webapi/src/main/java/org/sonar/server/rule/ws/RuleMapper.java
server/sonar-webserver-webapi/src/main/java/org/sonar/server/rule/ws/RulesWsParameters.java
server/sonar-webserver-webapi/src/main/java/org/sonar/server/rule/ws/SearchAction.java
server/sonar-webserver-webapi/src/main/java/org/sonar/server/rule/ws/ShowAction.java
server/sonar-webserver-webapi/src/test/java/org/sonar/server/rule/ws/SearchActionTest.java
server/sonar-webserver-webapi/src/test/java/org/sonar/server/rule/ws/ShowActionTest.java
sonar-ws/src/main/protobuf/ws-rules.proto

index 2655b8e8f31c8b4aec054fecb8530f2a09891818..c3809c2ded6bbaa3cb1bdcf5cedf21dc5e1ea6d7 100644 (file)
@@ -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<RuleDescriptionSectionDto> 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<String> getGenericConcepts() {
+    return deserializeStringSet(genericConceptsField);
+  }
+
+  public RuleDto setGenericConcepts(Set<String> genericConcepts){
+    this.genericConceptsField = serializeStringSet(genericConcepts);
+    return this;
+  }
+
   @CheckForNull
   public Format getDescriptionFormat() {
     return descriptionFormat;
@@ -531,7 +541,7 @@ public class RuleDto {
   }
 
   public Set<String> 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() {
index 643343da0bd6c35c9ac5f9836f57150a9e5cfc6f..4ccbfe936519d4afbd43d716837229ea8d02e1fb 100644 (file)
@@ -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"
   </sql>
 
   <sql id="leftOuterJoinRulesDescriptionSections">
       ad_hoc_description,
       ad_hoc_severity,
       ad_hoc_type,
+      generic_concepts,
       created_at,
       updated_at
     )
       #{adHocDescription,jdbcType=CLOB},
       #{adHocSeverity,jdbcType=VARCHAR},
       #{adHocType,jdbcType=TINYINT},
+      #{genericConceptsField,jdbcType=VARCHAR},
       #{createdAt,jdbcType=BIGINT},
       #{updatedAt,jdbcType=BIGINT}
     )
       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}
index 0405c7eaa551c01bd95cb77029ae0f287d5294df..c26aea06e5708065bb39a2b8fbab7f084e9d2d19 100644 (file)
@@ -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
index c2a064c6a43016e1b2ecf97b19e7e761477dd4c9..87e7ed0dde571b933947fde0946ded984eb623e4 100644 (file)
@@ -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) {
index 682fc6a3efac3f2a705fa27c3eeca7da8857b248..78d505b97158ae132882fa6cec25cb19dbd89e56 100644 (file)
@@ -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<String> fieldsToReturn) {
+    if (shouldReturnField(fieldsToReturn, FIELD_GENERIC_CONCEPTS)) {
+      ruleResponse.getGenericConceptsBuilder().addAllGenericConcepts((ruleDto.getGenericConcepts()));
+    }
+  }
+
   private static void setDeprecatedKeys(Rules.Rule.Builder ruleResponse, RuleDto ruleDto, Set<String> fieldsToReturn,
     Map<String, List<DeprecatedRuleKeyDto>> deprecatedRuleKeysByRuleUuid) {
     if (shouldReturnField(fieldsToReturn, FIELD_DEPRECATED_KEYS)) {
index 15260041edfd6bcfd630fc923c1a6aea95920cd9..4f4af555c87752bc8c3ef348740e9ff1ffda2524 100644 (file)
@@ -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
index 1db0a7cada20b53a259119314ab311f0f7e5d374..31db2ae17a7ad2ff416a587733deae9e730a2133 100644 (file)
@@ -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)
index ec32f637346ada1fb5929720a6f8392fbc2eb01b..1e5afdb58f91b3c5040f597218968190506ff41a 100644 (file)
@@ -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
index de9ff93ddda2f2a6be542ba68bd4746c0e1b012d..c21b11165f3bc79bb4ff7c7cee566f6550070462 100644 (file)
@@ -308,7 +308,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);
 
@@ -319,6 +319,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();
index 2645ff9c9904ddf35f95900f85f175dfb18fbfd1..d9df48ca231679ce50c5a9ad1e1b818a4c7454b9 100644 (file)
@@ -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
index fb943a1d97ed70e7a73914aec48604e245641a6e..43338b2656341ff5b77ea65c501a24d7d193e61b 100644 (file)
@@ -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;
@@ -162,6 +163,10 @@ message Tags {
   repeated string tags = 1;
 }
 
+message GenericConcepts {
+  repeated string genericConcepts = 1;
+}
+
 message Actives {
   map<string, ActiveList> actives = 1;
 }