diff options
Diffstat (limited to 'server')
11 files changed, 165 insertions, 150 deletions
diff --git a/server/sonar-server/src/main/java/org/sonar/server/measure/ws/ComponentDtoToWsComponent.java b/server/sonar-server/src/main/java/org/sonar/server/measure/ws/ComponentDtoToWsComponent.java index 71bead5c102..301792a565d 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/measure/ws/ComponentDtoToWsComponent.java +++ b/server/sonar-server/src/main/java/org/sonar/server/measure/ws/ComponentDtoToWsComponent.java @@ -23,10 +23,9 @@ import java.util.Map; import org.sonar.db.component.ComponentDto; import org.sonar.db.measure.MeasureDto; import org.sonar.db.metric.MetricDto; +import org.sonarqube.ws.WsMeasures; import org.sonarqube.ws.WsMeasures.Component; -import static org.sonar.server.measure.ws.MeasureDtoToWsMeasure.measureDtoToWsMeasure; - class ComponentDtoToWsComponent { private ComponentDtoToWsComponent() { // static methods only @@ -42,8 +41,11 @@ class ComponentDtoToWsComponent { wsComponent.setRefKey(referenceComponent.key()); } + WsMeasures.Measure.Builder measureBuilder = WsMeasures.Measure.newBuilder(); for (Map.Entry<MetricDto, MeasureDto> entry : measuresByMetric.entrySet()) { - wsComponent.addMeasures(measureDtoToWsMeasure(entry.getKey(), entry.getValue())); + MeasureDtoToWsMeasure.updateMeasureBuilder(measureBuilder, entry.getKey(), entry.getValue()); + wsComponent.addMeasures(measureBuilder); + measureBuilder.clear(); } return wsComponent; diff --git a/server/sonar-server/src/main/java/org/sonar/server/measure/ws/ComponentTreeAction.java b/server/sonar-server/src/main/java/org/sonar/server/measure/ws/ComponentTreeAction.java index 4287fa36071..cbada12072d 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/measure/ws/ComponentTreeAction.java +++ b/server/sonar-server/src/main/java/org/sonar/server/measure/ws/ComponentTreeAction.java @@ -48,6 +48,7 @@ import static org.sonar.core.util.Uuids.UUID_EXAMPLE_02; import static org.sonar.db.component.ComponentTreeQuery.Strategy.CHILDREN; import static org.sonar.db.component.ComponentTreeQuery.Strategy.LEAVES; import static org.sonar.server.measure.ws.ComponentDtoToWsComponent.componentDtoToWsComponent; +import static org.sonar.server.measure.ws.MeasureDtoToWsMeasure.updateMeasureBuilder; import static org.sonar.server.measure.ws.MeasuresWsParametersBuilder.createAdditionalFieldsParameter; import static org.sonar.server.measure.ws.MeasuresWsParametersBuilder.createDeveloperParameters; import static org.sonar.server.measure.ws.MeasuresWsParametersBuilder.createMetricKeysParameter; @@ -223,13 +224,13 @@ public class ComponentTreeAction implements MeasuresWsAction { .build(); response.setBaseComponent( - componentDtoToWsComponent( + toWsComponent( data.getBaseComponent(), data.getMeasuresByComponentUuidAndMetric().row(data.getBaseComponent().uuid()), data.getReferenceComponentsByUuid())); for (ComponentDto componentDto : data.getComponents()) { - response.addComponents(componentDtoToWsComponent( + response.addComponents(toWsComponent( componentDto, data.getMeasuresByComponentUuidAndMetric().row(componentDto.uuid()), data.getReferenceComponentsByUuid())); @@ -306,4 +307,23 @@ public class ComponentTreeAction implements MeasuresWsAction { Param.SORT, METRIC_SORT, METRIC_PERIOD_SORT, PARAM_METRIC_SORT); return componentTreeWsRequest; } + + private static WsMeasures.Component.Builder toWsComponent(ComponentDto component, Map<MetricDto, ComponentTreeData.Measure> measures, + Map<String, ComponentDto> referenceComponentsByUuid) { + WsMeasures.Component.Builder wsComponent = componentDtoToWsComponent(component); + ComponentDto referenceComponent = referenceComponentsByUuid.get(component.getCopyResourceUuid()); + if (referenceComponent != null) { + wsComponent.setRefId(referenceComponent.uuid()); + wsComponent.setRefKey(referenceComponent.key()); + } + WsMeasures.Measure.Builder measureBuilder = WsMeasures.Measure.newBuilder(); + for (Map.Entry<MetricDto, ComponentTreeData.Measure> entry : measures.entrySet()) { + ComponentTreeData.Measure measure = entry.getValue(); + updateMeasureBuilder(measureBuilder, entry.getKey(), measure.getValue(), measure.getData(), measure.getVariation()); + wsComponent.addMeasures(measureBuilder); + measureBuilder.clear(); + } + return wsComponent; + } + } diff --git a/server/sonar-server/src/main/java/org/sonar/server/measure/ws/ComponentTreeData.java b/server/sonar-server/src/main/java/org/sonar/server/measure/ws/ComponentTreeData.java index ce311823d84..5aa59590dfa 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/measure/ws/ComponentTreeData.java +++ b/server/sonar-server/src/main/java/org/sonar/server/measure/ws/ComponentTreeData.java @@ -23,11 +23,14 @@ import com.google.common.collect.Table; import java.util.List; import java.util.Map; import javax.annotation.CheckForNull; +import javax.annotation.Nullable; import org.sonar.db.component.ComponentDto; import org.sonar.db.measure.MeasureDto; import org.sonar.db.metric.MetricDto; import org.sonarqube.ws.WsMeasures; +import static java.lang.Double.NaN; +import static java.lang.Double.isNaN; import static java.util.Objects.requireNonNull; class ComponentTreeData { @@ -37,7 +40,7 @@ class ComponentTreeData { private final Map<String, ComponentDto> referenceComponentsByUuid; private final List<MetricDto> metrics; private final List<WsMeasures.Period> periods; - private final Table<String, MetricDto, MeasureDto> measuresByComponentUuidAndMetric; + private final Table<String, MetricDto, Measure> measuresByComponentUuidAndMetric; private ComponentTreeData(Builder builder) { this.baseComponent = builder.baseComponent; @@ -79,7 +82,7 @@ class ComponentTreeData { } @CheckForNull - Table<String, MetricDto, MeasureDto> getMeasuresByComponentUuidAndMetric() { + Table<String, MetricDto, Measure> getMeasuresByComponentUuidAndMetric() { return measuresByComponentUuidAndMetric; } @@ -94,7 +97,7 @@ class ComponentTreeData { private int componentCount; private List<MetricDto> metrics; private List<WsMeasures.Period> periods; - private Table<String, MetricDto, MeasureDto> measuresByComponentUuidAndMetric; + private Table<String, MetricDto, Measure> measuresByComponentUuidAndMetric; private Builder() { // private constructor @@ -125,7 +128,7 @@ class ComponentTreeData { return this; } - public Builder setMeasuresByComponentUuidAndMetric(Table<String, MetricDto, MeasureDto> measuresByComponentUuidAndMetric) { + public Builder setMeasuresByComponentUuidAndMetric(Table<String, MetricDto, Measure> measuresByComponentUuidAndMetric) { this.measuresByComponentUuidAndMetric = measuresByComponentUuidAndMetric; return this; } @@ -140,4 +143,45 @@ class ComponentTreeData { return new ComponentTreeData(this); } } + + static class Measure { + private double value; + private String data; + private double variation; + + private Measure(MeasureDto measureDto) { + this.value = toPrimitive(measureDto.getValue()); + this.data = measureDto.getData(); + this.variation = toPrimitive(measureDto.getVariation()); + } + + public double getValue() { + return value; + } + + public boolean isValueSet() { + return !isNaN(value); + } + + @CheckForNull + public String getData() { + return data; + } + + public double getVariation() { + return variation; + } + + public boolean isVariationSet() { + return !isNaN(variation); + } + + static Measure createFromMeasureDto(MeasureDto measureDto) { + return new Measure(measureDto); + } + + private static double toPrimitive(@Nullable Double value) { + return value == null ? NaN : value; + } + } } diff --git a/server/sonar-server/src/main/java/org/sonar/server/measure/ws/ComponentTreeDataLoader.java b/server/sonar-server/src/main/java/org/sonar/server/measure/ws/ComponentTreeDataLoader.java index 7bd4d20f950..b8933979ffb 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/measure/ws/ComponentTreeDataLoader.java +++ b/server/sonar-server/src/main/java/org/sonar/server/measure/ws/ComponentTreeDataLoader.java @@ -58,6 +58,7 @@ import org.sonar.db.metric.MetricDto; import org.sonar.db.metric.MetricDtoFunctions; import org.sonar.server.component.ComponentFinder; import org.sonar.server.exceptions.NotFoundException; +import org.sonar.server.measure.ws.ComponentTreeData.Measure; import org.sonar.server.user.UserSession; import org.sonarqube.ws.client.measure.ComponentTreeWsRequest; @@ -106,7 +107,8 @@ public class ComponentTreeDataLoader { ComponentTreeQuery componentTreeQuery = toComponentTreeQuery(wsRequest, baseComponent); List<ComponentDto> components = searchComponents(dbSession, componentTreeQuery); List<MetricDto> metrics = searchMetrics(dbSession, wsRequest); - Table<String, MetricDto, MeasureDto> measuresByComponentUuidAndMetric = searchMeasuresByComponentUuidAndMetric(dbSession, baseComponent, componentTreeQuery, components, + Table<String, MetricDto, Measure> measuresByComponentUuidAndMetric = searchMeasuresByComponentUuidAndMetric(dbSession, baseComponent, componentTreeQuery, + components, metrics, developerId); components = filterComponents(components, measuresByComponentUuidAndMetric, metrics, wsRequest); @@ -179,7 +181,8 @@ public class ComponentTreeDataLoader { return metrics; } - private Table<String, MetricDto, MeasureDto> searchMeasuresByComponentUuidAndMetric(DbSession dbSession, ComponentDto baseComponent, ComponentTreeQuery componentTreeQuery, + private Table<String, MetricDto, Measure> searchMeasuresByComponentUuidAndMetric(DbSession dbSession, ComponentDto baseComponent, + ComponentTreeQuery componentTreeQuery, List<ComponentDto> components, List<MetricDto> metrics, @Nullable Long developerId) { Map<Integer, MetricDto> metricsById = Maps.uniqueIndex(metrics, MetricDto::getId); @@ -190,15 +193,15 @@ public class ComponentTreeDataLoader { .setPersonId(developerId) .setMetricIds(new ArrayList<>(metricsById.keySet())) .build(); - List<MeasureDto> measureDtos = dbClient.measureDao().selectTreeByQuery(dbSession, baseComponent, measureQuery); - Table<String, MetricDto, MeasureDto> measuresByComponentUuidAndMetric = HashBasedTable.create(components.size(), metrics.size()); - for (MeasureDto measureDto : measureDtos) { + Table<String, MetricDto, Measure> measuresByComponentUuidAndMetric = HashBasedTable.create(components.size(), metrics.size()); + dbClient.measureDao().selectTreeByQuery(dbSession, baseComponent, measureQuery, result -> { + MeasureDto measureDto = (MeasureDto) result.getResultObject(); measuresByComponentUuidAndMetric.put( measureDto.getComponentUuid(), metricsById.get(measureDto.getMetricId()), - measureDto); - } + Measure.createFromMeasureDto(measureDto)); + }); addBestValuesToMeasures(measuresByComponentUuidAndMetric, components, metrics); @@ -212,7 +215,7 @@ public class ComponentTreeDataLoader { * <li>metric is optimized for best value</li> * </ul> */ - private static void addBestValuesToMeasures(Table<String, MetricDto, MeasureDto> measuresByComponentUuidAndMetric, List<ComponentDto> components, + private static void addBestValuesToMeasures(Table<String, MetricDto, Measure> measuresByComponentUuidAndMetric, List<ComponentDto> components, List<MetricDto> metrics) { List<MetricDtoWithBestValue> metricDtosWithBestValueMeasure = metrics.stream() .filter(MetricDtoFunctions.isOptimizedForBestValue()) @@ -226,14 +229,15 @@ public class ComponentTreeDataLoader { componentsEligibleForBestValue.forEach(component -> { for (MetricDtoWithBestValue metricWithBestValue : metricDtosWithBestValueMeasure) { if (measuresByComponentUuidAndMetric.get(component.uuid(), metricWithBestValue.getMetric()) == null) { - measuresByComponentUuidAndMetric.put(component.uuid(), metricWithBestValue.getMetric(), metricWithBestValue.getBestValue()); + measuresByComponentUuidAndMetric.put(component.uuid(), metricWithBestValue.getMetric(), + Measure.createFromMeasureDto(metricWithBestValue.getBestValue())); } } }); } private static List<ComponentDto> filterComponents(List<ComponentDto> components, - Table<String, MetricDto, MeasureDto> measuresByComponentUuidAndMetric, List<MetricDto> metrics, ComponentTreeWsRequest wsRequest) { + Table<String, MetricDto, Measure> measuresByComponentUuidAndMetric, List<MetricDto> metrics, ComponentTreeWsRequest wsRequest) { if (!componentWithMeasuresOnly(wsRequest)) { return components; } @@ -253,7 +257,7 @@ public class ComponentTreeDataLoader { } private static List<ComponentDto> sortComponents(List<ComponentDto> components, ComponentTreeWsRequest wsRequest, List<MetricDto> metrics, - Table<String, MetricDto, MeasureDto> measuresByComponentUuidAndMetric) { + Table<String, MetricDto, Measure> measuresByComponentUuidAndMetric) { return ComponentTreeSort.sortComponents(components, wsRequest, metrics, measuresByComponentUuidAndMetric); } diff --git a/server/sonar-server/src/main/java/org/sonar/server/measure/ws/ComponentTreeSort.java b/server/sonar-server/src/main/java/org/sonar/server/measure/ws/ComponentTreeSort.java index fd354fa1603..cab59985488 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/measure/ws/ComponentTreeSort.java +++ b/server/sonar-server/src/main/java/org/sonar/server/measure/ws/ComponentTreeSort.java @@ -33,7 +33,6 @@ import javax.annotation.Nullable; import org.sonar.api.measures.Metric; import org.sonar.api.measures.Metric.ValueType; import org.sonar.db.component.ComponentDto; -import org.sonar.db.measure.MeasureDto; import org.sonar.db.metric.MetricDto; import org.sonar.server.exceptions.BadRequestException; import org.sonarqube.ws.client.measure.ComponentTreeWsRequest; @@ -64,7 +63,7 @@ public class ComponentTreeSort { } public static List<ComponentDto> sortComponents(List<ComponentDto> components, ComponentTreeWsRequest wsRequest, List<MetricDto> metrics, - Table<String, MetricDto, MeasureDto> measuresByComponentUuidAndMetric) { + Table<String, MetricDto, ComponentTreeData.Measure> measuresByComponentUuidAndMetric) { List<String> sortParameters = wsRequest.getSort(); if (sortParameters == null || sortParameters.isEmpty()) { return components; @@ -113,7 +112,7 @@ public class ComponentTreeSort { } private static Ordering<ComponentDto> metricValueOrdering(ComponentTreeWsRequest wsRequest, List<MetricDto> metrics, - Table<String, MetricDto, MeasureDto> measuresByComponentUuidAndMetric) { + Table<String, MetricDto, ComponentTreeData.Measure> measuresByComponentUuidAndMetric) { if (wsRequest.getMetricSort() == null) { return componentNameOrdering(wsRequest.getAsc()); } @@ -134,7 +133,7 @@ public class ComponentTreeSort { } private static Ordering<ComponentDto> metricPeriodOrdering(ComponentTreeWsRequest wsRequest, List<MetricDto> metrics, - Table<String, MetricDto, MeasureDto> measuresByComponentUuidAndMetric) { + Table<String, MetricDto, ComponentTreeData.Measure> measuresByComponentUuidAndMetric) { if (wsRequest.getMetricSort() == null || wsRequest.getMetricPeriodSort() == null) { return componentNameOrdering(wsRequest.getAsc()); } @@ -150,7 +149,7 @@ public class ComponentTreeSort { } private static Ordering<ComponentDto> numericalMetricOrdering(boolean isAscending, @Nullable MetricDto metric, - Table<String, MetricDto, MeasureDto> measuresByComponentUuidAndMetric) { + Table<String, MetricDto, ComponentTreeData.Measure> measuresByComponentUuidAndMetric) { Ordering<Double> ordering = Ordering.natural(); if (!isAscending) { @@ -161,7 +160,7 @@ public class ComponentTreeSort { } private static Ordering<ComponentDto> numericalMetricPeriodOrdering(ComponentTreeWsRequest request, @Nullable MetricDto metric, - Table<String, MetricDto, MeasureDto> measuresByComponentUuidAndMetric) { + Table<String, MetricDto, ComponentTreeData.Measure> measuresByComponentUuidAndMetric) { Ordering<Double> ordering = Ordering.natural(); if (!request.getAsc()) { @@ -172,7 +171,7 @@ public class ComponentTreeSort { } private static Ordering<ComponentDto> levelMetricOrdering(boolean isAscending, @Nullable MetricDto metric, - Table<String, MetricDto, MeasureDto> measuresByComponentUuidAndMetric) { + Table<String, MetricDto, ComponentTreeData.Measure> measuresByComponentUuidAndMetric) { Ordering<Integer> ordering = Ordering.natural(); // inverse the order of org.sonar.api.measures.Metric.Level @@ -185,18 +184,18 @@ public class ComponentTreeSort { private static class ComponentDtoToNumericalMeasureValue implements Function<ComponentDto, Double> { private final MetricDto metric; - private final Table<String, MetricDto, MeasureDto> measuresByComponentUuidAndMetric; + private final Table<String, MetricDto, ComponentTreeData.Measure> measuresByComponentUuidAndMetric; private ComponentDtoToNumericalMeasureValue(@Nullable MetricDto metric, - Table<String, MetricDto, MeasureDto> measuresByComponentUuidAndMetric) { + Table<String, MetricDto, ComponentTreeData.Measure> measuresByComponentUuidAndMetric) { this.metric = metric; this.measuresByComponentUuidAndMetric = measuresByComponentUuidAndMetric; } @Override public Double apply(@Nonnull ComponentDto input) { - MeasureDto measure = measuresByComponentUuidAndMetric.get(input.uuid(), metric); - if (measure == null || measure.getValue() == null) { + ComponentTreeData.Measure measure = measuresByComponentUuidAndMetric.get(input.uuid(), metric); + if (measure == null || !measure.isValueSet()) { return null; } @@ -206,17 +205,17 @@ public class ComponentTreeSort { private static class ComponentDtoToLevelIndex implements Function<ComponentDto, Integer> { private final MetricDto metric; - private final Table<String, MetricDto, MeasureDto> measuresByComponentUuidAndMetric; + private final Table<String, MetricDto, ComponentTreeData.Measure> measuresByComponentUuidAndMetric; private ComponentDtoToLevelIndex(@Nullable MetricDto metric, - Table<String, MetricDto, MeasureDto> measuresByComponentUuidAndMetric) { + Table<String, MetricDto, ComponentTreeData.Measure> measuresByComponentUuidAndMetric) { this.metric = metric; this.measuresByComponentUuidAndMetric = measuresByComponentUuidAndMetric; } @Override public Integer apply(@Nonnull ComponentDto input) { - MeasureDto measure = measuresByComponentUuidAndMetric.get(input.uuid(), metric); + ComponentTreeData.Measure measure = measuresByComponentUuidAndMetric.get(input.uuid(), metric); if (measure == null || measure.getData() == null) { return null; } @@ -227,18 +226,18 @@ public class ComponentTreeSort { private static class ComponentDtoToMeasureVariationValue implements Function<ComponentDto, Double> { private final MetricDto metric; - private final Table<String, MetricDto, MeasureDto> measuresByComponentUuidAndMetric; + private final Table<String, MetricDto, ComponentTreeData.Measure> measuresByComponentUuidAndMetric; private ComponentDtoToMeasureVariationValue(@Nullable MetricDto metric, - Table<String, MetricDto, MeasureDto> measuresByComponentUuidAndMetric) { + Table<String, MetricDto, ComponentTreeData.Measure> measuresByComponentUuidAndMetric) { this.metric = metric; this.measuresByComponentUuidAndMetric = measuresByComponentUuidAndMetric; } @Override public Double apply(@Nonnull ComponentDto input) { - MeasureDto measure = measuresByComponentUuidAndMetric.get(input.uuid(), metric); - if (measure == null) { + ComponentTreeData.Measure measure = measuresByComponentUuidAndMetric.get(input.uuid(), metric); + if (measure == null || !measure.isVariationSet()) { return null; } return measure.getVariation(); @@ -247,17 +246,17 @@ public class ComponentTreeSort { private static class ComponentDtoToTextualMeasureValue implements Function<ComponentDto, String> { private final MetricDto metric; - private final Table<String, MetricDto, MeasureDto> measuresByComponentUuidAndMetric; + private final Table<String, MetricDto, ComponentTreeData.Measure> measuresByComponentUuidAndMetric; private ComponentDtoToTextualMeasureValue(@Nullable MetricDto metric, - Table<String, MetricDto, MeasureDto> measuresByComponentUuidAndMetric) { + Table<String, MetricDto, ComponentTreeData.Measure> measuresByComponentUuidAndMetric) { this.metric = metric; this.measuresByComponentUuidAndMetric = measuresByComponentUuidAndMetric; } @Override public String apply(@Nonnull ComponentDto input) { - MeasureDto measure = measuresByComponentUuidAndMetric.get(input.uuid(), metric); + ComponentTreeData.Measure measure = measuresByComponentUuidAndMetric.get(input.uuid(), metric); if (measure == null || measure.getData() == null) { return null; } diff --git a/server/sonar-server/src/main/java/org/sonar/server/measure/ws/HasMeasure.java b/server/sonar-server/src/main/java/org/sonar/server/measure/ws/HasMeasure.java index 35055ade218..6893c6851bd 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/measure/ws/HasMeasure.java +++ b/server/sonar-server/src/main/java/org/sonar/server/measure/ws/HasMeasure.java @@ -23,14 +23,15 @@ import com.google.common.collect.Table; import java.util.function.Predicate; import javax.annotation.Nonnull; import org.sonar.db.component.ComponentDto; -import org.sonar.db.measure.MeasureDto; import org.sonar.db.metric.MetricDto; import org.sonarqube.ws.client.measure.ComponentTreeWsRequest; +import static org.sonar.server.measure.ws.ComponentTreeData.Measure; + class HasMeasure implements Predicate<ComponentDto> { private final Predicate<ComponentDto> predicate; - HasMeasure(Table<String, MetricDto, MeasureDto> table, MetricDto metric, ComponentTreeWsRequest request) { + HasMeasure(Table<String, MetricDto, ComponentTreeData.Measure> table, MetricDto metric, ComponentTreeWsRequest request) { Integer periodIndex = request.getMetricPeriodSort(); this.predicate = periodIndex == null ? new HasAbsoluteValue(table, metric) @@ -43,34 +44,34 @@ class HasMeasure implements Predicate<ComponentDto> { } private static class HasAbsoluteValue implements Predicate<ComponentDto> { - private final Table<String, MetricDto, MeasureDto> table; + private final Table<String, MetricDto, ComponentTreeData.Measure> table; private final MetricDto metric; - private HasAbsoluteValue(Table<String, MetricDto, MeasureDto> table, MetricDto metric) { + private HasAbsoluteValue(Table<String, MetricDto, ComponentTreeData.Measure> table, MetricDto metric) { this.table = table; this.metric = metric; } @Override public boolean test(@Nonnull ComponentDto input) { - MeasureDto measure = table.get(input.uuid(), metric); - return measure != null && (measure.getValue() != null || measure.getData() != null); + Measure measure = table.get(input.uuid(), metric); + return measure != null && (measure.isValueSet() || measure.getData() != null); } } private static class HasValueOnPeriod implements Predicate<ComponentDto> { - private final Table<String, MetricDto, MeasureDto> table; + private final Table<String, MetricDto, ComponentTreeData.Measure> table; private final MetricDto metric; - private HasValueOnPeriod(Table<String, MetricDto, MeasureDto> table, MetricDto metric) { + private HasValueOnPeriod(Table<String, MetricDto, ComponentTreeData.Measure> table, MetricDto metric) { this.table = table; this.metric = metric; } @Override public boolean test(@Nonnull ComponentDto input) { - MeasureDto measure = table.get(input.uuid(), metric); - return measure != null && measure.getVariation() != null; + Measure measure = table.get(input.uuid(), metric); + return measure != null && measure.isVariationSet(); } } diff --git a/server/sonar-server/src/main/java/org/sonar/server/measure/ws/MeasureDtoToWsMeasure.java b/server/sonar-server/src/main/java/org/sonar/server/measure/ws/MeasureDtoToWsMeasure.java index 13d43dfa28d..50cc2d5b980 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/measure/ws/MeasureDtoToWsMeasure.java +++ b/server/sonar-server/src/main/java/org/sonar/server/measure/ws/MeasureDtoToWsMeasure.java @@ -19,7 +19,7 @@ */ package org.sonar.server.measure.ws; -import org.sonar.db.component.ComponentDto; +import javax.annotation.Nullable; import org.sonar.db.measure.MeasureDto; import org.sonar.db.metric.MetricDto; import org.sonarqube.ws.WsMeasures; @@ -34,41 +34,26 @@ class MeasureDtoToWsMeasure { // static methods } - /** - * @see #measureDtoToWsMeasure(MetricDto, MeasureDto) - * add component uuid to the WS Measure object - * - */ - static Measure dbToWsMeasure(MeasureDto dbMeasure, MetricDto dbMetric, ComponentDto componentDto) { - return map(dbMetric, dbMeasure).setComponent(componentDto.getKey()).build(); + static void updateMeasureBuilder(Measure.Builder measureBuilder, MetricDto metricDto, MeasureDto measureDto) { + Double value = measureDto.getValue(); + Double variation = measureDto.getVariation(); + updateMeasureBuilder(measureBuilder, metricDto, value == null ? Double.NaN : value, measureDto.getData(), variation == null ? Double.NaN : variation); } - static Measure measureDtoToWsMeasure(MetricDto metricDto, MeasureDto measureDto) { - return map(metricDto, measureDto).build(); - } - - private static Measure.Builder map(MetricDto dbMetric, MeasureDto dbMeasure) { - try { - Measure.Builder measure = Measure.newBuilder(); - measure.setMetric(dbMetric.getKey()); - // a measure value can be null, new_violations metric for example - if (dbMeasure.getValue() != null - || dbMeasure.getData() != null) { - measure.setValue(formatMeasureValue(dbMeasure, dbMetric)); - } - - WsMeasures.PeriodValue.Builder periodBuilder = WsMeasures.PeriodValue.newBuilder(); - Double variation = dbMeasure.getVariation(); - if (variation != null) { - measure.getPeriodsBuilder().addPeriodsValue(periodBuilder - .clear() - .setIndex(1) - .setValue(formatNumericalValue(variation, dbMetric))); - } + static void updateMeasureBuilder(Measure.Builder measureBuilder, MetricDto metric, double doubleValue, @Nullable String stringValue, double variation) { + measureBuilder.setMetric(metric.getKey()); + // a measure value can be null, new_violations metric for example + if (!Double.isNaN(doubleValue) || stringValue != null) { + measureBuilder.setValue(formatMeasureValue(doubleValue, stringValue, metric)); + } - return measure; - } catch (Exception e) { - throw new IllegalStateException(String.format("Error while mapping a measure of metric key '%s' and parameters %s", dbMetric.getKey(), dbMeasure.toString()), e); + WsMeasures.PeriodValue.Builder periodBuilder = WsMeasures.PeriodValue.newBuilder(); + if (Double.isNaN(variation)) { + return; } + measureBuilder.getPeriodsBuilder().addPeriodsValue(periodBuilder + .clear() + .setIndex(1) + .setValue(formatNumericalValue(variation, metric))); } } diff --git a/server/sonar-server/src/main/java/org/sonar/server/measure/ws/MeasureValueFormatter.java b/server/sonar-server/src/main/java/org/sonar/server/measure/ws/MeasureValueFormatter.java index 7c609e10795..2dcc6aa930b 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/measure/ws/MeasureValueFormatter.java +++ b/server/sonar-server/src/main/java/org/sonar/server/measure/ws/MeasureValueFormatter.java @@ -19,6 +19,7 @@ */ package org.sonar.server.measure.ws; +import javax.annotation.Nullable; import org.sonar.api.measures.Metric; import org.sonar.db.measure.MeasureDto; import org.sonar.db.metric.MetricDto; @@ -31,10 +32,13 @@ class MeasureValueFormatter { } static String formatMeasureValue(MeasureDto measure, MetricDto metric) { - Metric.ValueType metricType = Metric.ValueType.valueOf(metric.getValueType()); Double doubleValue = measure.getValue(); String stringValue = measure.getData(); + return formatMeasureValue(doubleValue == null ? Double.NaN : doubleValue, stringValue, metric); + } + static String formatMeasureValue(double doubleValue, @Nullable String stringValue, MetricDto metric) { + Metric.ValueType metricType = Metric.ValueType.valueOf(metric.getValueType()); switch (metricType) { case BOOL: return formatBoolean(doubleValue); @@ -57,7 +61,7 @@ class MeasureValueFormatter { } } - static String formatNumericalValue(Double value, MetricDto metric) { + static String formatNumericalValue(double value, MetricDto metric) { Metric.ValueType metricType = Metric.ValueType.valueOf(metric.getValueType()); switch (metricType) { @@ -81,15 +85,15 @@ class MeasureValueFormatter { } } - private static String formatBoolean(Double value) { + private static String formatBoolean(double value) { return Math.abs(value - 1.0d) < DELTA ? "true" : "false"; } - private static String formatInteger(Double value) { - return String.valueOf(value.intValue()); + private static String formatInteger(double value) { + return String.valueOf((int) value); } - private static String formatLong(Double value) { - return String.valueOf(value.longValue()); + private static String formatLong(double value) { + return String.valueOf((long) value); } } diff --git a/server/sonar-server/src/main/java/org/sonar/server/measure/ws/SearchAction.java b/server/sonar-server/src/main/java/org/sonar/server/measure/ws/SearchAction.java index d6be0710a10..513d7d1f07f 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/measure/ws/SearchAction.java +++ b/server/sonar-server/src/main/java/org/sonar/server/measure/ws/SearchAction.java @@ -46,7 +46,7 @@ import static java.util.function.Function.identity; import static java.util.stream.Collectors.toMap; import static org.sonar.core.util.stream.Collectors.toList; import static org.sonar.core.util.stream.Collectors.uniqueIndex; -import static org.sonar.server.measure.ws.MeasureDtoToWsMeasure.dbToWsMeasure; +import static org.sonar.server.measure.ws.MeasureDtoToWsMeasure.updateMeasureBuilder; import static org.sonar.server.measure.ws.MeasuresWsParametersBuilder.createMetricKeysParameter; import static org.sonar.server.ws.KeyExamples.KEY_PROJECT_EXAMPLE_001; import static org.sonar.server.ws.KeyExamples.KEY_PROJECT_EXAMPLE_002; @@ -188,8 +188,15 @@ public class SearchAction implements MeasuresWsAction { Function<Measure, String> byMetricKey = Measure::getMetric; Function<Measure, String> byComponentName = wsMeasure -> componentNamesByKey.get(wsMeasure.getComponent()); + Measure.Builder measureBuilder = Measure.newBuilder(); return measures.stream() - .map(dbMeasure -> dbToWsMeasure(dbMeasure, dbMeasureToDbMetric.apply(dbMeasure), componentsByUuid.get(dbMeasure.getComponentUuid()))) + .map(dbMeasure -> { + updateMeasureBuilder(measureBuilder, dbMeasureToDbMetric.apply(dbMeasure), dbMeasure); + measureBuilder.setComponent(componentsByUuid.get(dbMeasure.getComponentUuid()).getKey()); + Measure measure = measureBuilder.build(); + measureBuilder.clear(); + return measure; + }) .sorted(comparing(byMetricKey).thenComparing(byComponentName)) .collect(toList()); } diff --git a/server/sonar-server/src/test/java/org/sonar/server/measure/ws/ComponentTreeSortTest.java b/server/sonar-server/src/test/java/org/sonar/server/measure/ws/ComponentTreeSortTest.java index 247d50280e1..43e47e025a1 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/measure/ws/ComponentTreeSortTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/measure/ws/ComponentTreeSortTest.java @@ -43,13 +43,14 @@ import static org.sonar.server.measure.ws.ComponentTreeAction.METRIC_SORT; import static org.sonar.server.measure.ws.ComponentTreeAction.NAME_SORT; import static org.sonar.server.measure.ws.ComponentTreeAction.PATH_SORT; import static org.sonar.server.measure.ws.ComponentTreeAction.QUALIFIER_SORT; +import static org.sonar.server.measure.ws.ComponentTreeData.Measure.createFromMeasureDto; public class ComponentTreeSortTest { private static final String NUM_METRIC_KEY = "violations"; private static final String TEXT_METRIC_KEY = "sqale_index"; private List<MetricDto> metrics; - private Table<String, MetricDto, MeasureDto> measuresByComponentUuidAndMetric; + private Table<String, MetricDto, ComponentTreeData.Measure> measuresByComponentUuidAndMetric; private List<ComponentDto> components; @Before @@ -78,9 +79,9 @@ public class ComponentTreeSortTest { // same number than path field double currentValue = 9; for (ComponentDto component : components) { - measuresByComponentUuidAndMetric.put(component.uuid(), violationsMetric, new MeasureDto().setValue(currentValue) - .setVariation(-currentValue)); - measuresByComponentUuidAndMetric.put(component.uuid(), sqaleIndexMetric, new MeasureDto().setData(String.valueOf(currentValue))); + measuresByComponentUuidAndMetric.put(component.uuid(), violationsMetric, createFromMeasureDto(new MeasureDto().setValue(currentValue) + .setVariation(-currentValue))); + measuresByComponentUuidAndMetric.put(component.uuid(), sqaleIndexMetric, createFromMeasureDto(new MeasureDto().setData(String.valueOf(currentValue)))); currentValue--; } } @@ -153,7 +154,7 @@ public class ComponentTreeSortTest { for (int i = 0; i < components.size(); i++) { ComponentDto component = components.get(i); String alertStatus = statuses.get(i % 3); - measuresByComponentUuidAndMetric.put(component.uuid(), metrics.get(0), new MeasureDto().setData(alertStatus)); + measuresByComponentUuidAndMetric.put(component.uuid(), metrics.get(0), createFromMeasureDto(new MeasureDto().setData(alertStatus))); } ComponentTreeWsRequest wsRequest = newRequest(newArrayList(METRIC_SORT, NAME_SORT), true, CoreMetrics.ALERT_STATUS_KEY); diff --git a/server/sonar-server/src/test/java/org/sonar/server/measure/ws/MeasureDtoToWsMeasureTest.java b/server/sonar-server/src/test/java/org/sonar/server/measure/ws/MeasureDtoToWsMeasureTest.java deleted file mode 100644 index 8c2b602dde8..00000000000 --- a/server/sonar-server/src/test/java/org/sonar/server/measure/ws/MeasureDtoToWsMeasureTest.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * 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 org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; -import org.sonar.db.metric.MetricDto; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Mockito.spy; -import static org.mockito.Mockito.when; -import static org.sonar.db.measure.MeasureTesting.newMeasure; -import static org.sonar.db.metric.MetricTesting.newMetricDto; -import static org.sonar.test.TestUtils.hasOnlyPrivateConstructors; - -public class MeasureDtoToWsMeasureTest { - @Rule - public ExpectedException expectedException = ExpectedException.none(); - - @Test - public void fail_when_mapping_fails() { - MetricDto metric = spy(newMetricDto().setKey("metric-key")); - when(metric.getValueType()).thenThrow(NullPointerException.class); - expectedException.expect(IllegalStateException.class); - expectedException.expectMessage("Error while mapping a measure of metric key 'metric-key' and parameters "); - - MeasureDtoToWsMeasure.measureDtoToWsMeasure(metric, newMeasure()); - } - - @Test - public void utility_class() { - assertThat(hasOnlyPrivateConstructors(MeasureDtoToWsMeasure.class)).isTrue(); - } -} |