/* * SonarQube * Copyright (C) 2009-2017 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 3 of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ package org.sonar.server.measure.ws; import com.google.common.collect.HashBasedTable; import com.google.common.collect.Table; import java.util.Map; import java.util.function.Predicate; import java.util.function.UnaryOperator; import java.util.stream.Stream; import org.sonar.core.util.stream.MoreCollectors; import org.sonar.db.component.SnapshotDto; import org.sonar.db.measure.MeasureDto; import org.sonar.db.metric.MetricDto; import org.sonarqube.ws.WsMeasures.SearchHistoryResponse; import org.sonarqube.ws.WsMeasures.SearchHistoryResponse.HistoryMeasure; import org.sonarqube.ws.WsMeasures.SearchHistoryResponse.HistoryValue; import static org.sonar.api.utils.DateUtils.formatDateTime; import static org.sonar.server.measure.ws.MeasureValueFormatter.formatMeasureValue; import static org.sonar.server.measure.ws.MeasureValueFormatter.formatNumericalValue; class SearchHistoryResponseFactory { private final SearchHistoryResult result; private final HistoryMeasure.Builder measure; private final HistoryValue.Builder value; SearchHistoryResponseFactory(SearchHistoryResult result) { this.result = result; this.measure = HistoryMeasure.newBuilder(); this.value = HistoryValue.newBuilder(); } public SearchHistoryResponse apply() { return Stream.of(SearchHistoryResponse.newBuilder()) .map(addPaging()) .map(addMeasures()) .map(SearchHistoryResponse.Builder::build) .collect(MoreCollectors.toOneElement()); } private UnaryOperator<SearchHistoryResponse.Builder> addPaging() { return response -> response.setPaging(result.getPaging()); } private UnaryOperator<SearchHistoryResponse.Builder> addMeasures() { Map<Integer, MetricDto> metricsById = result.getMetrics().stream().collect(MoreCollectors.uniqueIndex(MetricDto::getId)); Map<String, SnapshotDto> analysesByUuid = result.getAnalyses().stream().collect(MoreCollectors.uniqueIndex(SnapshotDto::getUuid)); Table<MetricDto, SnapshotDto, MeasureDto> measuresByMetricByAnalysis = HashBasedTable.create(result.getMetrics().size(), result.getAnalyses().size()); result.getMeasures().forEach(m -> measuresByMetricByAnalysis.put(metricsById.get(m.getMetricId()), analysesByUuid.get(m.getAnalysisUuid()), m)); return response -> { result.getMetrics().stream() .peek(metric -> measure.clear()) .map(addMetric()) .map(metric -> addValues(measuresByMetricByAnalysis.row(metric)).apply(metric)) .forEach(metric -> response.addMeasures(measure)); return response; }; } private UnaryOperator<MetricDto> addMetric() { return metric -> { measure.setMetric(metric.getKey()); return metric; }; } private UnaryOperator<MetricDto> addValues(Map<SnapshotDto, MeasureDto> measuresByAnalysis) { Predicate<SnapshotDto> hasMeasure = analysis -> measuresByAnalysis.get(analysis) != null; return metric -> { result.getAnalyses().stream() .filter(hasMeasure) .peek(analysis -> value.clear()) .map(addDate()) .map(analysis -> addValue(metric, measuresByAnalysis.get(analysis)).apply(analysis)) .forEach(analysis -> measure.addHistory(value)); return metric; }; } private UnaryOperator<SnapshotDto> addDate() { return analysis -> { value.setDate(formatDateTime(analysis.getCreatedAt())); return analysis; }; } private UnaryOperator<SnapshotDto> addValue(MetricDto dbMetric, MeasureDto dbMeasure) { return analysis -> { String measureValue = dbMetric.getKey().startsWith("new_") ? formatNumericalValue(dbMeasure.getVariation(), dbMetric) : formatMeasureValue(dbMeasure, dbMetric); value.setValue(measureValue); return analysis; }; } }