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.

IssueCounter.java 5.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. /*
  2. * SonarQube
  3. * Copyright (C) 2009-2021 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.server.measure.live;
  21. import java.util.Collection;
  22. import java.util.EnumMap;
  23. import java.util.HashMap;
  24. import java.util.Map;
  25. import java.util.Optional;
  26. import javax.annotation.Nullable;
  27. import org.sonar.api.rule.Severity;
  28. import org.sonar.api.rules.RuleType;
  29. import org.sonar.db.issue.IssueGroupDto;
  30. import org.sonar.db.rule.SeverityUtil;
  31. import static org.sonar.api.rules.RuleType.SECURITY_HOTSPOT;
  32. class IssueCounter {
  33. private final Map<RuleType, HighestSeverity> highestSeverityOfUnresolved = new EnumMap<>(RuleType.class);
  34. private final Map<RuleType, Effort> effortOfUnresolved = new EnumMap<>(RuleType.class);
  35. private final Map<String, Count> unresolvedBySeverity = new HashMap<>();
  36. private final Map<RuleType, Count> unresolvedByType = new EnumMap<>(RuleType.class);
  37. private final Map<String, Count> byResolution = new HashMap<>();
  38. private final Map<String, Count> byStatus = new HashMap<>();
  39. private final Map<String, Count> hotspotsByStatus = new HashMap<>();
  40. private final Count unresolved = new Count();
  41. IssueCounter(Collection<IssueGroupDto> groups) {
  42. for (IssueGroupDto group : groups) {
  43. RuleType ruleType = RuleType.valueOf(group.getRuleType());
  44. if (ruleType.equals(SECURITY_HOTSPOT)) {
  45. if (group.getResolution() == null) {
  46. unresolvedByType
  47. .computeIfAbsent(SECURITY_HOTSPOT, k -> new Count())
  48. .add(group);
  49. }
  50. if (group.getStatus() != null) {
  51. hotspotsByStatus
  52. .computeIfAbsent(group.getStatus(), k -> new Count())
  53. .add(group);
  54. }
  55. continue;
  56. }
  57. if (group.getResolution() == null) {
  58. highestSeverityOfUnresolved
  59. .computeIfAbsent(ruleType, k -> new HighestSeverity())
  60. .add(group);
  61. effortOfUnresolved
  62. .computeIfAbsent(ruleType, k -> new Effort())
  63. .add(group);
  64. unresolvedBySeverity
  65. .computeIfAbsent(group.getSeverity(), k -> new Count())
  66. .add(group);
  67. unresolvedByType
  68. .computeIfAbsent(ruleType, k -> new Count())
  69. .add(group);
  70. unresolved.add(group);
  71. } else {
  72. byResolution
  73. .computeIfAbsent(group.getResolution(), k -> new Count())
  74. .add(group);
  75. }
  76. if (group.getStatus() != null) {
  77. byStatus
  78. .computeIfAbsent(group.getStatus(), k -> new Count())
  79. .add(group);
  80. }
  81. }
  82. }
  83. public Optional<String> getHighestSeverityOfUnresolved(RuleType ruleType, boolean onlyInLeak) {
  84. return Optional.ofNullable(highestSeverityOfUnresolved.get(ruleType))
  85. .map(hs -> hs.severity(onlyInLeak));
  86. }
  87. public double sumEffortOfUnresolved(RuleType type, boolean onlyInLeak) {
  88. Effort effort = effortOfUnresolved.get(type);
  89. if (effort == null) {
  90. return 0.0;
  91. }
  92. return onlyInLeak ? effort.leak : effort.absolute;
  93. }
  94. public long countUnresolvedBySeverity(String severity, boolean onlyInLeak) {
  95. return value(unresolvedBySeverity.get(severity), onlyInLeak);
  96. }
  97. public long countByResolution(String resolution, boolean onlyInLeak) {
  98. return value(byResolution.get(resolution), onlyInLeak);
  99. }
  100. public long countUnresolvedByType(RuleType type, boolean onlyInLeak) {
  101. return value(unresolvedByType.get(type), onlyInLeak);
  102. }
  103. public long countByStatus(String status, boolean onlyInLeak) {
  104. return value(byStatus.get(status), onlyInLeak);
  105. }
  106. public long countUnresolved(boolean onlyInLeak) {
  107. return value(unresolved, onlyInLeak);
  108. }
  109. public long countHotspotsByStatus(String status, boolean onlyInLeak) {
  110. return value(hotspotsByStatus.get(status), onlyInLeak);
  111. }
  112. private static long value(@Nullable Count count, boolean onlyInLeak) {
  113. if (count == null) {
  114. return 0;
  115. }
  116. return onlyInLeak ? count.leak : count.absolute;
  117. }
  118. private static class Count {
  119. private long absolute = 0L;
  120. private long leak = 0L;
  121. void add(IssueGroupDto group) {
  122. absolute += group.getCount();
  123. if (group.isInLeak()) {
  124. leak += group.getCount();
  125. }
  126. }
  127. }
  128. private static class Effort {
  129. private double absolute = 0.0;
  130. private double leak = 0.0;
  131. void add(IssueGroupDto group) {
  132. absolute += group.getEffort();
  133. if (group.isInLeak()) {
  134. leak += group.getEffort();
  135. }
  136. }
  137. }
  138. private static class HighestSeverity {
  139. private int absolute = SeverityUtil.getOrdinalFromSeverity(Severity.INFO);
  140. private int leak = SeverityUtil.getOrdinalFromSeverity(Severity.INFO);
  141. void add(IssueGroupDto group) {
  142. int severity = SeverityUtil.getOrdinalFromSeverity(group.getSeverity());
  143. absolute = Math.max(severity, absolute);
  144. if (group.isInLeak()) {
  145. leak = Math.max(severity, leak);
  146. }
  147. }
  148. String severity(boolean inLeak) {
  149. return SeverityUtil.getSeverityFromOrdinal(inLeak ? leak : absolute);
  150. }
  151. }
  152. }