Du kannst nicht mehr als 25 Themen auswählen Themen müssen mit entweder einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.

MapBasedRawMeasureRepository.java 6.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. /*
  2. * SonarQube
  3. * Copyright (C) 2009-2019 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.ce.task.projectanalysis.measure;
  21. import com.google.common.collect.ImmutableSetMultimap;
  22. import com.google.common.collect.SetMultimap;
  23. import java.util.Collections;
  24. import java.util.HashMap;
  25. import java.util.Map;
  26. import java.util.Optional;
  27. import java.util.Set;
  28. import java.util.function.Function;
  29. import java.util.function.Predicate;
  30. import java.util.stream.Collectors;
  31. import javax.annotation.Nonnull;
  32. import javax.annotation.Nullable;
  33. import org.sonar.ce.task.projectanalysis.component.Component;
  34. import org.sonar.ce.task.projectanalysis.metric.Metric;
  35. import static com.google.common.base.Preconditions.checkArgument;
  36. import static java.lang.String.format;
  37. import static java.util.Objects.requireNonNull;
  38. /**
  39. * Map based implementation of MeasureRepository which supports only raw measures.
  40. * Intended to be used as a delegate of other MeasureRepository implementations (hence the final keyword).
  41. */
  42. public final class MapBasedRawMeasureRepository<T> implements MeasureRepository {
  43. private final Function<Component, T> componentToKey;
  44. private final Map<T, Map<MeasureKey, Measure>> measures = new HashMap<>();
  45. public MapBasedRawMeasureRepository(Function<Component, T> componentToKey) {
  46. this.componentToKey = requireNonNull(componentToKey);
  47. }
  48. /**
  49. * @throws UnsupportedOperationException all the time, not supported
  50. */
  51. @Override
  52. public Optional<Measure> getBaseMeasure(Component component, Metric metric) {
  53. throw new UnsupportedOperationException("This implementation of MeasureRepository supports only raw measures");
  54. }
  55. @Override
  56. public Optional<Measure> getRawMeasure(final Component component, final Metric metric) {
  57. // fail fast
  58. requireNonNull(component);
  59. requireNonNull(metric);
  60. return find(component, metric);
  61. }
  62. @Override
  63. public void add(Component component, Metric metric, Measure measure) {
  64. requireNonNull(component);
  65. checkValueTypeConsistency(metric, measure);
  66. Optional<Measure> existingMeasure = find(component, metric);
  67. if (existingMeasure.isPresent()) {
  68. throw new UnsupportedOperationException(
  69. format(
  70. "a measure can be set only once for a specific Component (key=%s), Metric (key=%s). Use update method",
  71. component.getDbKey(),
  72. metric.getKey()));
  73. }
  74. add(component, metric, measure, OverridePolicy.OVERRIDE);
  75. }
  76. @Override
  77. public void update(Component component, Metric metric, Measure measure) {
  78. requireNonNull(component);
  79. checkValueTypeConsistency(metric, measure);
  80. Optional<Measure> existingMeasure = find(component, metric);
  81. if (!existingMeasure.isPresent()) {
  82. throw new UnsupportedOperationException(
  83. format(
  84. "a measure can be updated only if one already exists for a specific Component (key=%s), Metric (key=%s). Use add method",
  85. component.getDbKey(),
  86. metric.getKey()));
  87. }
  88. add(component, metric, measure, OverridePolicy.OVERRIDE);
  89. }
  90. private static void checkValueTypeConsistency(Metric metric, Measure measure) {
  91. checkArgument(
  92. measure.getValueType() == Measure.ValueType.NO_VALUE || measure.getValueType() == metric.getType().getValueType(),
  93. "Measure's ValueType (%s) is not consistent with the Metric's ValueType (%s)",
  94. measure.getValueType(), metric.getType().getValueType());
  95. }
  96. @Override
  97. public Set<Measure> getRawMeasures(Component component, Metric metric) {
  98. requireNonNull(metric);
  99. requireNonNull(component);
  100. T componentKey = componentToKey.apply(component);
  101. Map<MeasureKey, Measure> rawMeasures = measures.get(componentKey);
  102. if (rawMeasures == null) {
  103. return Collections.emptySet();
  104. }
  105. return rawMeasures.entrySet().stream()
  106. .filter(new MatchMetric(metric))
  107. .map(ToMeasure.INSTANCE)
  108. .collect(Collectors.toSet());
  109. }
  110. @Override
  111. public SetMultimap<String, Measure> getRawMeasures(Component component) {
  112. T componentKey = componentToKey.apply(component);
  113. Map<MeasureKey, Measure> rawMeasures = measures.get(componentKey);
  114. if (rawMeasures == null) {
  115. return ImmutableSetMultimap.of();
  116. }
  117. ImmutableSetMultimap.Builder<String, Measure> builder = ImmutableSetMultimap.builder();
  118. for (Map.Entry<MeasureKey, Measure> entry : rawMeasures.entrySet()) {
  119. builder.put(entry.getKey().getMetricKey(), entry.getValue());
  120. }
  121. return builder.build();
  122. }
  123. private Optional<Measure> find(Component component, Metric metric) {
  124. T componentKey = componentToKey.apply(component);
  125. Map<MeasureKey, Measure> measuresPerMetric = measures.get(componentKey);
  126. if (measuresPerMetric == null) {
  127. return Optional.empty();
  128. }
  129. return Optional.ofNullable(measuresPerMetric.get(new MeasureKey(metric.getKey())));
  130. }
  131. public void add(Component component, Metric metric, Measure measure, OverridePolicy overridePolicy) {
  132. requireNonNull(component);
  133. requireNonNull(measure);
  134. requireNonNull(measure);
  135. requireNonNull(overridePolicy);
  136. T componentKey = componentToKey.apply(component);
  137. Map<MeasureKey, Measure> measuresPerMetric = measures.computeIfAbsent(componentKey, key -> new HashMap<>());
  138. MeasureKey key = new MeasureKey(metric.getKey());
  139. if (!measuresPerMetric.containsKey(key) || overridePolicy == OverridePolicy.OVERRIDE) {
  140. measuresPerMetric.put(key, measure);
  141. }
  142. }
  143. public enum OverridePolicy {
  144. OVERRIDE, DO_NOT_OVERRIDE
  145. }
  146. private static class MatchMetric implements Predicate<Map.Entry<MeasureKey, Measure>> {
  147. private final Metric metric;
  148. public MatchMetric(Metric metric) {
  149. this.metric = metric;
  150. }
  151. @Override
  152. public boolean test(@Nonnull Map.Entry<MeasureKey, Measure> input) {
  153. return input.getKey().getMetricKey().equals(metric.getKey());
  154. }
  155. }
  156. private enum ToMeasure implements Function<Map.Entry<MeasureKey, Measure>, Measure> {
  157. INSTANCE;
  158. @Nullable
  159. @Override
  160. public Measure apply(@Nonnull Map.Entry<MeasureKey, Measure> input) {
  161. return input.getValue();
  162. }
  163. }
  164. }