3 * Copyright (C) 2009-2024 SonarSource SA
4 * mailto:info AT sonarsource DOT com
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.
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.
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.
20 package org.sonar.ce.task.projectanalysis.measure;
22 import java.util.HashSet;
24 import java.util.Optional;
26 import org.sonar.ce.task.projectanalysis.batch.BatchReportReader;
27 import org.sonar.ce.task.projectanalysis.component.Component;
28 import org.sonar.ce.task.projectanalysis.measure.MapBasedRawMeasureRepository.OverridePolicy;
29 import org.sonar.ce.task.projectanalysis.metric.Metric;
30 import org.sonar.ce.task.projectanalysis.metric.MetricRepository;
31 import org.sonar.ce.task.projectanalysis.metric.ReportMetricValidator;
32 import org.sonar.core.util.CloseableIterator;
33 import org.sonar.db.DbClient;
34 import org.sonar.db.DbSession;
35 import org.sonar.db.measure.MeasureDto;
36 import org.sonar.scanner.protocol.output.ScannerReport;
38 import static java.util.Objects.requireNonNull;
39 import static org.sonar.ce.task.projectanalysis.component.ComponentFunctions.toComponentUuid;
41 public class MeasureRepositoryImpl implements MeasureRepository {
42 private final MapBasedRawMeasureRepository<String> delegate = new MapBasedRawMeasureRepository<>(toComponentUuid());
43 private final DbClient dbClient;
44 private final BatchReportReader reportReader;
45 private final BatchMeasureToMeasure batchMeasureToMeasure;
46 private final MetricRepository metricRepository;
47 private final ReportMetricValidator reportMetricValidator;
49 private MeasureDtoToMeasure measureTransformer = new MeasureDtoToMeasure();
50 private final Set<Integer> loadedComponents = new HashSet<>();
52 public MeasureRepositoryImpl(DbClient dbClient, BatchReportReader reportReader, MetricRepository metricRepository,
53 ReportMetricValidator reportMetricValidator) {
54 this.dbClient = dbClient;
55 this.reportReader = reportReader;
56 this.reportMetricValidator = reportMetricValidator;
57 this.batchMeasureToMeasure = new BatchMeasureToMeasure();
58 this.metricRepository = metricRepository;
62 public Optional<Measure> getBaseMeasure(Component component, Metric metric) {
64 requireNonNull(component);
65 requireNonNull(metric);
67 try (DbSession dbSession = dbClient.openSession(false)) {
68 Optional<MeasureDto> measureDto = dbClient.measureDao().selectLastMeasure(dbSession, component.getUuid(), metric.getKey());
69 if (measureDto.isPresent()) {
70 return measureTransformer.toMeasure(measureDto.get(), metric);
72 return Optional.empty();
77 public Optional<Measure> getRawMeasure(Component component, Metric metric) {
78 Optional<Measure> local = delegate.getRawMeasure(component, metric);
79 if (local.isPresent()) {
83 // look up in batch after loading (if not yet loaded) measures from batch
84 loadBatchMeasuresForComponent(component);
85 return delegate.getRawMeasure(component, metric);
89 public void add(Component component, Metric metric, Measure measure) {
90 delegate.add(component, metric, measure);
94 public void update(Component component, Metric metric, Measure measure) {
95 delegate.update(component, metric, measure);
99 public Map<String, Measure> getRawMeasures(Component component) {
100 loadBatchMeasuresForComponent(component);
101 return delegate.getRawMeasures(component);
104 private void loadBatchMeasuresForComponent(Component component) {
105 Integer ref = component.getReportAttributes().getRef();
106 if (ref == null || !loadedComponents.add(ref)) {
110 try (CloseableIterator<ScannerReport.Measure> readIt = reportReader.readComponentMeasures(component.getReportAttributes().getRef())) {
111 while (readIt.hasNext()) {
112 ScannerReport.Measure batchMeasure = readIt.next();
113 String metricKey = batchMeasure.getMetricKey();
114 if (reportMetricValidator.validate(metricKey)) {
115 Metric metric = metricRepository.getByKey(metricKey);
116 batchMeasureToMeasure.toMeasure(batchMeasure, metric).ifPresent(measure -> delegate.add(component, metric, measure, OverridePolicy.DO_NOT_OVERRIDE));