You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

EducationRulesDefinition.java 11KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  1. /*
  2. * SonarQube
  3. * Copyright (C) 2009-2023 SonarSource SA
  4. * mailto:info AT sonarsource DOT com
  5. *
  6. * This program is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU Lesser General Public
  8. * License as published by the Free Software Foundation; either
  9. * version 3 of the License, or (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * Lesser General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Lesser General Public License
  17. * along with this program; if not, write to the Free Software Foundation,
  18. * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  19. */
  20. package org.sonar.education;
  21. import java.nio.charset.StandardCharsets;
  22. import org.apache.commons.io.IOUtils;
  23. import org.sonar.api.server.rule.RuleDescriptionSection;
  24. import org.sonar.api.server.rule.RulesDefinition;
  25. import org.sonar.education.sensors.EducationPrinciplesSensor;
  26. import org.sonar.education.sensors.EducationWithContextsSensor;
  27. import org.sonar.education.sensors.EducationWithDetectedContextSensor;
  28. import static org.sonar.api.server.rule.RuleDescriptionSection.RuleDescriptionSectionKeys.ASSESS_THE_PROBLEM_SECTION_KEY;
  29. import static org.sonar.api.server.rule.RuleDescriptionSection.RuleDescriptionSectionKeys.HOW_TO_FIX_SECTION_KEY;
  30. import static org.sonar.api.server.rule.RuleDescriptionSection.RuleDescriptionSectionKeys.INTRODUCTION_SECTION_KEY;
  31. import static org.sonar.api.server.rule.RuleDescriptionSection.RuleDescriptionSectionKeys.RESOURCES_SECTION_KEY;
  32. import static org.sonar.api.server.rule.RuleDescriptionSection.RuleDescriptionSectionKeys.ROOT_CAUSE_SECTION_KEY;
  33. import static org.sonar.education.sensors.EducationWith2LinkedCodeSnippetsSensor.EDUCATION_WITH_2_LINKED_CODE_SNIPPETS_RULE_KEY;
  34. import static org.sonar.education.sensors.EducationWith4LinkedCodeSnippetsSensor.EDUCATION_WITH_4_LINKED_CODE_SNIPPETS_RULE_KEY;
  35. import static org.sonar.education.sensors.EducationWithSingleContextSensor.EDUCATION_WITH_SINGLE_CONTEXT_RULE_KEY;
  36. public class EducationRulesDefinition implements RulesDefinition {
  37. public static final String EDUCATION_RULE_REPOSITORY_KEY = "edu";
  38. public static final String EDUCATION_KEY = "education";
  39. private static final String[] ALL_SECTIONS = {INTRODUCTION_SECTION_KEY, ROOT_CAUSE_SECTION_KEY, ASSESS_THE_PROBLEM_SECTION_KEY,
  40. RESOURCES_SECTION_KEY, HOW_TO_FIX_SECTION_KEY};
  41. private static final String IGNORED_FAKE_SECTION = "fake_section_to_be_ignored";
  42. public static final String[] CONTEXTS = {"spring", "hibernate", "apache_commons", "vaadin", "mybatis"};
  43. private static final String HTML_LOREM_IPSUM = "<a href=\"https://google.com\">Lorem</a> ipsum dolor sit amet, consectetur adipiscing " +
  44. "elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco " +
  45. "laboris nisi ut aliquip ex ea commodo consequat.<br />Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu " +
  46. "fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.";
  47. @Override
  48. public void define(Context context) {
  49. NewRepository repo = context.createRepository(EDUCATION_RULE_REPOSITORY_KEY, EDUCATION_KEY);
  50. createRuleWithDescriptionSectionsAndEducationPrinciples(repo);
  51. createRuleWithDescriptionSectionsAndSingleContext(repo);
  52. createRuleWithDescriptionSectionsAndMultipleContexts(repo);
  53. createRuleWithDescriptionSectionsAndMultipleContextsIncludingOneDetected(repo);
  54. createRuleWith2LinkedCodeSnippetsInTwoSections(repo);
  55. createRuleWith4LinkedCodeSnippetsInOneSection(repo);
  56. repo.done();
  57. }
  58. private void createRuleWithDescriptionSectionsAndEducationPrinciples(NewRepository repo) {
  59. String[] educationPrinciples = {"defense_in_depth", "never_trust_user_input"};
  60. String ruleKey = EducationPrinciplesSensor.EDUCATION_WITH_GENERIC_CONCEPTS_RULE_KEY;
  61. NewRule ruleWithSingleContext = repo.createRule(ruleKey).setName("Rule with description sections and education principles")
  62. .addTags(EDUCATION_KEY);
  63. ruleWithSingleContext
  64. .setHtmlDescription(String.format("This rule contains description sections. To trigger an issue using this rule you need to " +
  65. "scan any text file with a line containing %s key word. This rule also contains 2 education principles - %s and %s",
  66. ruleKey, educationPrinciples[0], educationPrinciples[1]))
  67. .addEducationPrincipleKeys(educationPrinciples);
  68. addNonContextualizedDescriptionSections(ruleWithSingleContext);
  69. descriptionSection(HOW_TO_FIX_SECTION_KEY);
  70. }
  71. private void createRuleWithDescriptionSectionsAndSingleContext(NewRepository repo) {
  72. String ruleKey = EDUCATION_WITH_SINGLE_CONTEXT_RULE_KEY;
  73. NewRule ruleWithSingleContext = repo.createRule(ruleKey).setName("Rule with description sections and single " +
  74. "contexts for 'how to fix'")
  75. .addTags(EDUCATION_KEY);
  76. ruleWithSingleContext
  77. .setHtmlDescription(String.format("This rule contains description sections and single context for 'how to fix' section. To " +
  78. "trigger an issue using this rule you need to scan any text file with a line containing %s key word.", ruleKey));
  79. addNonContextualizedDescriptionSections(ruleWithSingleContext);
  80. ruleWithSingleContext.addDescriptionSection(descriptionHowToFixSectionWithContext(CONTEXTS[0]));
  81. }
  82. private void createRuleWithDescriptionSectionsAndMultipleContexts(NewRepository repo) {
  83. NewRule ruleWithMultipleContexts = repo.createRule(EducationWithContextsSensor.EDUCATION_WITH_CONTEXTS_RULE_KEY)
  84. .setName("Rule with description sections and multiple contexts for 'how to fix'")
  85. .addTags(EDUCATION_KEY);
  86. ruleWithMultipleContexts
  87. .setHtmlDescription(String.format("This rule contains description sections and multiple contexts for 'how to fix' section. To trigger " +
  88. "an issue using this rule you need to scan any text file with a line containing %s keyword.",
  89. EducationWithContextsSensor.EDUCATION_WITH_CONTEXTS_RULE_KEY));
  90. addNonContextualizedDescriptionSections(ruleWithMultipleContexts);
  91. for (String context : CONTEXTS) {
  92. ruleWithMultipleContexts.addDescriptionSection(descriptionHowToFixSectionWithContext(context));
  93. }
  94. }
  95. private void createRuleWithDescriptionSectionsAndMultipleContextsIncludingOneDetected(NewRepository repo) {
  96. NewRule ruleWithMultipleContexts = repo.createRule(EducationWithDetectedContextSensor.EDUCATION_WITH_DETECTED_CONTEXT_RULE_KEY)
  97. .setName("Rule with description sections and multiple contexts (including one detected) for 'how to fix'")
  98. .addTags(EDUCATION_KEY);
  99. ruleWithMultipleContexts
  100. .setHtmlDescription(String.format("This rule contains description sections and multiple contexts (including one detected) for " +
  101. "'how to fix' section. To trigger an issue using this rule you need to scan any text file with a line containing %s keyword.",
  102. EducationWithDetectedContextSensor.EDUCATION_WITH_DETECTED_CONTEXT_RULE_KEY));
  103. addNonContextualizedDescriptionSections(ruleWithMultipleContexts);
  104. for (String context : CONTEXTS) {
  105. ruleWithMultipleContexts.addDescriptionSection(descriptionHowToFixSectionWithContext(context));
  106. }
  107. }
  108. private void createRuleWith2LinkedCodeSnippetsInTwoSections(NewRepository repo) {
  109. String ruleKey = EDUCATION_WITH_2_LINKED_CODE_SNIPPETS_RULE_KEY;
  110. NewRule rule2CodeSnippetsIn2Sections = repo.createRule(ruleKey).setName("Rule with description sections and code snippets " +
  111. "linked to each other in 2 different sections in order to display diff between them.")
  112. .addTags(EDUCATION_KEY);
  113. rule2CodeSnippetsIn2Sections
  114. .setHtmlDescription(String.format("This rule contains description sections and 2 linked code snippets in 2 sections. To " +
  115. "trigger an issue using this rule you need to scan any text file with a line containing %s key word.", ruleKey));
  116. String completelyDifferentSnippetsHtml = readResource("2completelyDifferentSnippets.html");
  117. String codeSnippetsHtml = readResource("2codeSnippets.html");
  118. rule2CodeSnippetsIn2Sections.addDescriptionSection(descriptionSection(INTRODUCTION_SECTION_KEY))
  119. .addDescriptionSection(descriptionSection(ROOT_CAUSE_SECTION_KEY, completelyDifferentSnippetsHtml))
  120. .addDescriptionSection(descriptionSection(ASSESS_THE_PROBLEM_SECTION_KEY))
  121. .addDescriptionSection(descriptionSection(HOW_TO_FIX_SECTION_KEY, codeSnippetsHtml))
  122. .addDescriptionSection(descriptionSection(RESOURCES_SECTION_KEY));
  123. }
  124. private void createRuleWith4LinkedCodeSnippetsInOneSection(NewRepository repo) {
  125. String ruleKey = EDUCATION_WITH_4_LINKED_CODE_SNIPPETS_RULE_KEY;
  126. NewRule rule2CodeSnippetsInTheSameSection = repo.createRule(ruleKey).setName("Rule with description sections and code snippets " +
  127. "linked to each other in the same section in order to display diff between them.")
  128. .addTags(EDUCATION_KEY);
  129. rule2CodeSnippetsInTheSameSection
  130. .setHtmlDescription(String.format("This rule contains description sections and 4 linked code snippets in the same section. To " +
  131. "trigger an issue using this rule you need to scan any text file with a line containing %s key word.", ruleKey));
  132. String codeSnippetsHtml = readResource("4codeSnippets.html");
  133. rule2CodeSnippetsInTheSameSection.addDescriptionSection(descriptionSection(INTRODUCTION_SECTION_KEY))
  134. .addDescriptionSection(descriptionSection(ROOT_CAUSE_SECTION_KEY, codeSnippetsHtml))
  135. .addDescriptionSection(descriptionSection(ASSESS_THE_PROBLEM_SECTION_KEY))
  136. .addDescriptionSection(descriptionSection(HOW_TO_FIX_SECTION_KEY))
  137. .addDescriptionSection(descriptionSection(RESOURCES_SECTION_KEY));
  138. }
  139. private static void addNonContextualizedDescriptionSections(NewRule newRule) {
  140. newRule.addDescriptionSection(descriptionSection(INTRODUCTION_SECTION_KEY))
  141. .addDescriptionSection(descriptionSection(ROOT_CAUSE_SECTION_KEY))
  142. .addDescriptionSection(descriptionSection(ASSESS_THE_PROBLEM_SECTION_KEY))
  143. .addDescriptionSection(descriptionSection(RESOURCES_SECTION_KEY))
  144. .addDescriptionSection(descriptionSection(IGNORED_FAKE_SECTION));
  145. }
  146. private static RuleDescriptionSection descriptionHowToFixSectionWithContext(String context) {
  147. var ruleContext = new org.sonar.api.server.rule.Context(context, context);
  148. return RuleDescriptionSection.builder()
  149. .sectionKey(HOW_TO_FIX_SECTION_KEY)
  150. .context(ruleContext)
  151. .htmlContent(String.format("%s: %s", HOW_TO_FIX_SECTION_KEY, HTML_LOREM_IPSUM))
  152. .build();
  153. }
  154. private static RuleDescriptionSection descriptionSection(String sectionKey) {
  155. return descriptionSection(sectionKey, HTML_LOREM_IPSUM);
  156. }
  157. private static RuleDescriptionSection descriptionSection(String sectionKey, String htmlContent) {
  158. return RuleDescriptionSection.builder()
  159. .sectionKey(sectionKey)
  160. .htmlContent(htmlContent)
  161. .build();
  162. }
  163. private String readResource(String file) {
  164. try {
  165. return IOUtils.toString(getClass().getResource(file), StandardCharsets.UTF_8);
  166. } catch (Exception e) {
  167. throw new RuntimeException(e);
  168. }
  169. }
  170. }