aboutsummaryrefslogtreecommitdiffstats
path: root/server/sonar-server-common
diff options
context:
space:
mode:
authorAurelien Poscia <aurelien.poscia@sonarsource.com>2022-07-13 14:48:11 +0200
committersonartech <sonartech@sonarsource.com>2022-07-14 20:03:48 +0000
commite840bd147581e8d73bd8f74c5488f1cde5844308 (patch)
treeaab348ff31aba260e6c836f7b26d1f3352c4fa77 /server/sonar-server-common
parent70d175ec3b14e379a6a52de4124a0dfd0ca26a3e (diff)
downloadsonarqube-e840bd147581e8d73bd8f74c5488f1cde5844308.tar.gz
sonarqube-e840bd147581e8d73bd8f74c5488f1cde5844308.zip
SONAR-16635 Use plugin-api htmlDesc to populate web api/rule/*** rule.htmlDesc and /api/hotspots/show fields
Diffstat (limited to 'server/sonar-server-common')
-rw-r--r--server/sonar-server-common/src/main/java/org/sonar/server/rule/RuleDescriptionFormatter.java67
-rw-r--r--server/sonar-server-common/src/test/java/org/sonar/server/rule/RuleDescriptionFormatterTest.java40
2 files changed, 13 insertions, 94 deletions
diff --git a/server/sonar-server-common/src/main/java/org/sonar/server/rule/RuleDescriptionFormatter.java b/server/sonar-server-common/src/main/java/org/sonar/server/rule/RuleDescriptionFormatter.java
index ad34b1f81d4..9492aaa3f1c 100644
--- a/server/sonar-server-common/src/main/java/org/sonar/server/rule/RuleDescriptionFormatter.java
+++ b/server/sonar-server-common/src/main/java/org/sonar/server/rule/RuleDescriptionFormatter.java
@@ -19,85 +19,34 @@
*/
package org.sonar.server.rule;
+import com.google.common.collect.MoreCollectors;
import java.util.Collection;
-import java.util.List;
-import java.util.Map;
import java.util.Objects;
-import java.util.Optional;
import javax.annotation.CheckForNull;
-import org.sonar.api.rules.RuleType;
-import org.sonar.db.rule.RuleDescriptionSectionContextDto;
import org.sonar.db.rule.RuleDescriptionSectionDto;
import org.sonar.db.rule.RuleDto;
import org.sonar.markdown.Markdown;
-import static java.util.Comparator.comparing;
-import static java.util.stream.Collectors.toMap;
-import static org.sonar.api.server.rule.RuleDescriptionSection.RuleDescriptionSectionKeys.ASSESS_THE_PROBLEM_SECTION_KEY;
-import static org.sonar.api.server.rule.RuleDescriptionSection.RuleDescriptionSectionKeys.HOW_TO_FIX_SECTION_KEY;
-import static org.sonar.api.server.rule.RuleDescriptionSection.RuleDescriptionSectionKeys.INTRODUCTION_SECTION_KEY;
-import static org.sonar.api.server.rule.RuleDescriptionSection.RuleDescriptionSectionKeys.RESOURCES_SECTION_KEY;
-import static org.sonar.api.server.rule.RuleDescriptionSection.RuleDescriptionSectionKeys.ROOT_CAUSE_SECTION_KEY;
-import static org.sonar.db.rule.RuleDescriptionSectionDto.DEFAULT_KEY;
import static org.sonar.db.rule.RuleDto.Format.MARKDOWN;
public class RuleDescriptionFormatter {
- public static final List<String> SECTION_KEYS = List.of(
- INTRODUCTION_SECTION_KEY,
- ROOT_CAUSE_SECTION_KEY,
- ASSESS_THE_PROBLEM_SECTION_KEY,
- HOW_TO_FIX_SECTION_KEY,
- RESOURCES_SECTION_KEY);
-
- public static final Map<String, String> HOTSPOT_SECTION_TITLES = Map.of(
- ROOT_CAUSE_SECTION_KEY, "What is the risk?",
- ASSESS_THE_PROBLEM_SECTION_KEY, "Assess the risk",
- HOW_TO_FIX_SECTION_KEY, "How can you fix it?"
- );
-
- public static final Map<String, String> RULE_SECTION_TITLES = Map.of(
- ROOT_CAUSE_SECTION_KEY, "Why is this an issue?",
- HOW_TO_FIX_SECTION_KEY, "How to fix it?",
- RESOURCES_SECTION_KEY, "Resources"
- );
-
@CheckForNull
public String getDescriptionAsHtml(RuleDto ruleDto) {
if (ruleDto.getDescriptionFormat() == null) {
return null;
}
Collection<RuleDescriptionSectionDto> ruleDescriptionSectionDtos = ruleDto.getRuleDescriptionSectionDtos();
- return retrieveDescription(ruleDescriptionSectionDtos, RuleType.valueOf(ruleDto.getType()), Objects.requireNonNull(ruleDto.getDescriptionFormat()));
+ return retrieveDescription(ruleDescriptionSectionDtos, Objects.requireNonNull(ruleDto.getDescriptionFormat()));
}
@CheckForNull
- private static String retrieveDescription(Collection<RuleDescriptionSectionDto> ruleDescriptionSectionDtos,
- RuleType ruleType, RuleDto.Format descriptionFormat) {
- if (ruleDescriptionSectionDtos.isEmpty()) {
- return null;
- }
- Map<String, String> sectionKeyToHtml = ruleDescriptionSectionDtos.stream()
- //TODO MMF-2765, merge operation on toMap should not be needed anymore
- .sorted(comparing(RuleDescriptionSectionDto::getKey).thenComparing(s -> Optional.ofNullable(s.getContext()).map(RuleDescriptionSectionContextDto::getKey).orElse(null)))
- .collect(toMap(RuleDescriptionSectionDto::getKey, section -> toHtml(descriptionFormat, section), (k1, k2) -> k1));
- if (sectionKeyToHtml.containsKey(DEFAULT_KEY)) {
- return sectionKeyToHtml.get(DEFAULT_KEY);
- } else {
- return concatHtmlSections(sectionKeyToHtml, ruleType);
- }
- }
-
- private static String concatHtmlSections(Map<String, String> sectionKeyToHtml, RuleType ruleType) {
- Map<String, String> titleMapping = ruleType.equals(RuleType.SECURITY_HOTSPOT) ? HOTSPOT_SECTION_TITLES : RULE_SECTION_TITLES;
- var builder = new StringBuilder();
- for (String sectionKey : SECTION_KEYS) {
- if (sectionKeyToHtml.containsKey(sectionKey)) {
- Optional.ofNullable(titleMapping.get(sectionKey)).ifPresent(title -> builder.append("<h2>").append(title).append("</h2>"));
- builder.append(sectionKeyToHtml.get(sectionKey)).append("<br/>");
- }
- }
- return builder.toString();
+ private static String retrieveDescription(Collection<RuleDescriptionSectionDto> ruleDescriptionSectionDtos, RuleDto.Format descriptionFormat) {
+ return ruleDescriptionSectionDtos.stream()
+ .filter(RuleDescriptionSectionDto::isDefault)
+ .collect(MoreCollectors.toOptional())
+ .map(section -> toHtml(descriptionFormat, section))
+ .orElse(null);
}
private static String toHtml(RuleDto.Format descriptionFormat, RuleDescriptionSectionDto ruleDescriptionSectionDto) {
diff --git a/server/sonar-server-common/src/test/java/org/sonar/server/rule/RuleDescriptionFormatterTest.java b/server/sonar-server-common/src/test/java/org/sonar/server/rule/RuleDescriptionFormatterTest.java
index 8466dfaaa4f..2268e2e408b 100644
--- a/server/sonar-server-common/src/test/java/org/sonar/server/rule/RuleDescriptionFormatterTest.java
+++ b/server/sonar-server-common/src/test/java/org/sonar/server/rule/RuleDescriptionFormatterTest.java
@@ -19,20 +19,13 @@
*/
package org.sonar.server.rule;
-import java.util.Optional;
-import org.apache.commons.lang.RandomStringUtils;
-import org.jetbrains.annotations.Nullable;
import org.junit.Test;
import org.sonar.api.rules.RuleType;
-import org.sonar.db.rule.RuleDescriptionSectionContextDto;
import org.sonar.db.rule.RuleDescriptionSectionDto;
import org.sonar.db.rule.RuleDto;
import static org.assertj.core.api.Assertions.assertThat;
import static org.sonar.api.server.rule.RuleDescriptionSection.RuleDescriptionSectionKeys.ASSESS_THE_PROBLEM_SECTION_KEY;
-import static org.sonar.api.server.rule.RuleDescriptionSection.RuleDescriptionSectionKeys.HOW_TO_FIX_SECTION_KEY;
-import static org.sonar.api.server.rule.RuleDescriptionSection.RuleDescriptionSectionKeys.INTRODUCTION_SECTION_KEY;
-import static org.sonar.api.server.rule.RuleDescriptionSection.RuleDescriptionSectionKeys.RESOURCES_SECTION_KEY;
import static org.sonar.api.server.rule.RuleDescriptionSection.RuleDescriptionSectionKeys.ROOT_CAUSE_SECTION_KEY;
import static org.sonar.db.rule.RuleDescriptionSectionDto.createDefaultRuleDescriptionSection;
@@ -57,33 +50,17 @@ public class RuleDescriptionFormatterTest {
}
@Test
- public void concatHtmlDescriptionSections() {
+ public void getDescriptionAsHtml_ignoresAdvancedSections() {
var section1 = createRuleDescriptionSection(ROOT_CAUSE_SECTION_KEY, "<div>Root is Root</div>");
var section2 = createRuleDescriptionSection(ASSESS_THE_PROBLEM_SECTION_KEY, "<div>This is not a problem</div>");
- var section3 = createRuleDescriptionSection(HOW_TO_FIX_SECTION_KEY, "<div>I don't want to fix</div>");
- var section4 = createRuleDescriptionSection(INTRODUCTION_SECTION_KEY, "<div>Introduction with no title</div>");
- var section5ctx1 = createRuleDescriptionSection(RESOURCES_SECTION_KEY, "<div>CTX_1</div>", "CTX_1");
- var section5ctx2 = createRuleDescriptionSection(RESOURCES_SECTION_KEY, "<div>CTX_2</div>", "CTX_2");
+ var defaultRuleDescriptionSection = createDefaultRuleDescriptionSection("uuid_432", "default description");
RuleDto rule = new RuleDto().setDescriptionFormat(RuleDto.Format.HTML)
.setType(RuleType.SECURITY_HOTSPOT)
.addRuleDescriptionSectionDto(section1)
.addRuleDescriptionSectionDto(section2)
- .addRuleDescriptionSectionDto(section3)
- .addRuleDescriptionSectionDto(section4)
- .addRuleDescriptionSectionDto(section5ctx2)
- .addRuleDescriptionSectionDto(section5ctx1);
+ .addRuleDescriptionSectionDto(defaultRuleDescriptionSection);
String html = ruleDescriptionFormatter.getDescriptionAsHtml(rule);
- assertThat(html)
- .isEqualTo(
- "<div>Introduction with no title</div><br/>"
- + "<h2>What is the risk?</h2>"
- + "<div>Root is Root</div><br/>"
- + "<h2>Assess the risk</h2>"
- + "<div>This is not a problem</div><br/>"
- + "<h2>How can you fix it?</h2>"
- + "<div>I don't want to fix</div><br/>"
- + "<div>CTX_1</div><br/>"
- );
+ assertThat(html).isEqualTo(defaultRuleDescriptionSection.getContent());
}
@Test
@@ -102,13 +79,6 @@ public class RuleDescriptionFormatterTest {
}
private static RuleDescriptionSectionDto createRuleDescriptionSection(String key, String content) {
- return createRuleDescriptionSection(key, content, null);
- }
-
- private static RuleDescriptionSectionDto createRuleDescriptionSection(String key, String content, @Nullable String contextKey) {
- RuleDescriptionSectionContextDto context = Optional.ofNullable(contextKey)
- .map(c -> RuleDescriptionSectionContextDto.of(contextKey, contextKey + RandomStringUtils.randomAlphanumeric(20)))
- .orElse(null);
- return RuleDescriptionSectionDto.builder().key(key).content(content).context(context).build();
+ return RuleDescriptionSectionDto.builder().key(key).content(content).build();
}
}