}; | }; | ||||
} | } | ||||
public void setIssues(Component component, DefaultIssue... issues) { | |||||
checkNotNull(component, "component cannot be null"); | |||||
setIssues(component.getReportAttributes().getRef(), issues); | |||||
} | |||||
public void setIssues(int componentRef, DefaultIssue... issues) { | public void setIssues(int componentRef, DefaultIssue... issues) { | ||||
Component component = treeRootHolder.getComponentByRef(componentRef); | Component component = treeRootHolder.getComponentByRef(componentRef); | ||||
checkArgument(component != null, String.format("Component '%s' does not exists in the report ", componentRef)); | checkArgument(component != null, String.format("Component '%s' does not exists in the report ", componentRef)); |
import static org.sonar.server.measure.ws.MeasuresWsParametersBuilder.createDeveloperParameters; | import static org.sonar.server.measure.ws.MeasuresWsParametersBuilder.createDeveloperParameters; | ||||
import static org.sonar.server.measure.ws.MeasuresWsParametersBuilder.createMetricKeysParameter; | import static org.sonar.server.measure.ws.MeasuresWsParametersBuilder.createMetricKeysParameter; | ||||
import static org.sonar.server.measure.ws.MetricDtoToWsMetric.metricDtoToWsMetric; | import static org.sonar.server.measure.ws.MetricDtoToWsMetric.metricDtoToWsMetric; | ||||
import static org.sonar.server.measure.ws.SnapshotDtoToWsPeriods.snapshotToWsPeriods; | |||||
import static org.sonar.server.measure.ws.SnapshotDtoToWsPeriod.snapshotToWsPeriods; | |||||
import static org.sonar.server.ws.KeyExamples.KEY_BRANCH_EXAMPLE_001; | import static org.sonar.server.ws.KeyExamples.KEY_BRANCH_EXAMPLE_001; | ||||
import static org.sonar.server.ws.KeyExamples.KEY_PROJECT_EXAMPLE_001; | import static org.sonar.server.ws.KeyExamples.KEY_PROJECT_EXAMPLE_001; | ||||
import static org.sonar.server.ws.KeyExamples.KEY_PULL_REQUEST_EXAMPLE_001; | import static org.sonar.server.ws.KeyExamples.KEY_PULL_REQUEST_EXAMPLE_001; | ||||
checkPermissions(component); | checkPermissions(component); | ||||
SnapshotDto analysis = dbClient.snapshotDao().selectLastAnalysisByRootComponentUuid(dbSession, component.projectUuid()).orElse(null); | SnapshotDto analysis = dbClient.snapshotDao().selectLastAnalysisByRootComponentUuid(dbSession, component.projectUuid()).orElse(null); | ||||
List<MetricDto> metrics = searchMetrics(dbSession, request); | List<MetricDto> metrics = searchMetrics(dbSession, request); | ||||
List<Measures.Period> periods = snapshotToWsPeriods(analysis); | |||||
Optional<Measures.Period> period = snapshotToWsPeriods(analysis); | |||||
List<LiveMeasureDto> measures = searchMeasures(dbSession, component, metrics); | List<LiveMeasureDto> measures = searchMeasures(dbSession, component, metrics); | ||||
return buildResponse(request, component, refComponent, measures, metrics, periods); | |||||
return buildResponse(request, component, refComponent, measures, metrics, period); | |||||
} | } | ||||
} | } | ||||
return dbClient.componentDao().selectByUuid(dbSession, component.getCopyResourceUuid()); | return dbClient.componentDao().selectByUuid(dbSession, component.getCopyResourceUuid()); | ||||
} | } | ||||
private static ComponentWsResponse buildResponse(ComponentRequest request, ComponentDto component, Optional<ComponentDto> refComponent, List<LiveMeasureDto> measures, | |||||
List<MetricDto> metrics, List<Measures.Period> periods) { | |||||
private static ComponentWsResponse buildResponse(ComponentRequest request, ComponentDto component, Optional<ComponentDto> refComponent, | |||||
List<LiveMeasureDto> measures, List<MetricDto> metrics, Optional<Measures.Period> period) { | |||||
ComponentWsResponse.Builder response = ComponentWsResponse.newBuilder(); | ComponentWsResponse.Builder response = ComponentWsResponse.newBuilder(); | ||||
Map<Integer, MetricDto> metricsById = Maps.uniqueIndex(metrics, MetricDto::getId); | Map<Integer, MetricDto> metricsById = Maps.uniqueIndex(metrics, MetricDto::getId); | ||||
Map<MetricDto, LiveMeasureDto> measuresByMetric = new HashMap<>(); | Map<MetricDto, LiveMeasureDto> measuresByMetric = new HashMap<>(); | ||||
response.getMetricsBuilder().addMetrics(metricDtoToWsMetric(metric)); | response.getMetricsBuilder().addMetrics(metricDtoToWsMetric(metric)); | ||||
} | } | ||||
} | } | ||||
if (additionalFields.contains(ADDITIONAL_PERIODS)) { | |||||
response.getPeriodsBuilder().addAllPeriods(periods); | |||||
if (additionalFields.contains(ADDITIONAL_PERIODS) && period.isPresent()) { | |||||
response.getPeriodsBuilder().addPeriods(period.get()); | |||||
} | } | ||||
} | } | ||||
private String pullRequest; | private String pullRequest; | ||||
private List<String> metricKeys; | private List<String> metricKeys; | ||||
private List<String> additionalFields; | private List<String> additionalFields; | ||||
private String developerId; | |||||
private String developerKey; | |||||
/** | /** | ||||
* @deprecated since 6.6, please use {@link #getComponent()} instead | * @deprecated since 6.6, please use {@link #getComponent()} instead | ||||
this.additionalFields = additionalFields; | this.additionalFields = additionalFields; | ||||
return this; | return this; | ||||
} | } | ||||
@CheckForNull | |||||
private String getDeveloperId() { | |||||
return developerId; | |||||
} | |||||
private ComponentRequest setDeveloperId(@Nullable String developerId) { | |||||
this.developerId = developerId; | |||||
return this; | |||||
} | |||||
@CheckForNull | |||||
private String getDeveloperKey() { | |||||
return developerKey; | |||||
} | |||||
private ComponentRequest setDeveloperKey(@Nullable String developerKey) { | |||||
this.developerKey = developerKey; | |||||
return this; | |||||
} | |||||
} | } | ||||
} | } |
import static org.sonar.server.measure.ws.MeasuresWsParametersBuilder.createDeveloperParameters; | import static org.sonar.server.measure.ws.MeasuresWsParametersBuilder.createDeveloperParameters; | ||||
import static org.sonar.server.measure.ws.MeasuresWsParametersBuilder.createMetricKeysParameter; | import static org.sonar.server.measure.ws.MeasuresWsParametersBuilder.createMetricKeysParameter; | ||||
import static org.sonar.server.measure.ws.MetricDtoToWsMetric.metricDtoToWsMetric; | import static org.sonar.server.measure.ws.MetricDtoToWsMetric.metricDtoToWsMetric; | ||||
import static org.sonar.server.measure.ws.SnapshotDtoToWsPeriods.snapshotToWsPeriods; | |||||
import static org.sonar.server.measure.ws.SnapshotDtoToWsPeriod.snapshotToWsPeriods; | |||||
import static org.sonar.server.ws.KeyExamples.KEY_BRANCH_EXAMPLE_001; | import static org.sonar.server.ws.KeyExamples.KEY_BRANCH_EXAMPLE_001; | ||||
import static org.sonar.server.ws.KeyExamples.KEY_PROJECT_EXAMPLE_001; | import static org.sonar.server.ws.KeyExamples.KEY_PROJECT_EXAMPLE_001; | ||||
import static org.sonar.server.ws.KeyExamples.KEY_PULL_REQUEST_EXAMPLE_001; | import static org.sonar.server.ws.KeyExamples.KEY_PULL_REQUEST_EXAMPLE_001; | ||||
import static org.sonar.server.ws.WsParameterBuilder.createQualifiersParameter; | |||||
import static org.sonar.server.ws.WsParameterBuilder.QualifierParameterContext.newQualifierParameterContext; | import static org.sonar.server.ws.WsParameterBuilder.QualifierParameterContext.newQualifierParameterContext; | ||||
import static org.sonar.server.ws.WsParameterBuilder.createQualifiersParameter; | |||||
import static org.sonar.server.ws.WsUtils.checkRequest; | import static org.sonar.server.ws.WsUtils.checkRequest; | ||||
import static org.sonar.server.ws.WsUtils.writeProtobuf; | import static org.sonar.server.ws.WsUtils.writeProtobuf; | ||||
* To limit the number of rows in database, a best value algorithm exists in database.</p> | * To limit the number of rows in database, a best value algorithm exists in database.</p> | ||||
* A measure is not stored in database if: | * A measure is not stored in database if: | ||||
* <ul> | * <ul> | ||||
* <li>the component is a file (production or test)</li> | |||||
* <li>optimization algorithm is enabled on the metric</li> | |||||
* <li>the measure computed equals the metric best value</li> | |||||
* <li>the period values are all equal to 0</li> | |||||
* <li>the component is a file (production or test)</li> | |||||
* <li>optimization algorithm is enabled on the metric</li> | |||||
* <li>the measure computed equals the metric best value</li> | |||||
* <li>the period values are all equal to 0</li> | |||||
* </ul> | * </ul> | ||||
* To recreate a best value 2 different cases: | * To recreate a best value 2 different cases: | ||||
* <ul> | * <ul> | ||||
* <li>Metric starts with 'new_' (ex: new_violations): the best value measure doesn't have a value and period values are all equal to 0</li> | |||||
* <li>Other metrics: the best value measure has a value of 0 and no period value</li> | |||||
* <li>Metric starts with 'new_' (ex: new_violations): the best value measure doesn't have a value and period values are all equal to 0</li> | |||||
* <li>Other metrics: the best value measure has a value of 0 and no period value</li> | |||||
* </ul> | * </ul> | ||||
*/ | */ | ||||
public class ComponentTreeAction implements MeasuresWsAction { | public class ComponentTreeAction implements MeasuresWsAction { | ||||
public void define(WebService.NewController context) { | public void define(WebService.NewController context) { | ||||
WebService.NewAction action = context.createAction(ACTION_COMPONENT_TREE) | WebService.NewAction action = context.createAction(ACTION_COMPONENT_TREE) | ||||
.setDescription(format("Navigate through components based on the chosen strategy with specified measures. The %s or the %s parameter must be provided.<br>" + | .setDescription(format("Navigate through components based on the chosen strategy with specified measures. The %s or the %s parameter must be provided.<br>" + | ||||
"Requires the following permission: 'Browse' on the specified project.<br>" + | |||||
"When limiting search with the %s parameter, directories are not returned.", | |||||
"Requires the following permission: 'Browse' on the specified project.<br>" + | |||||
"When limiting search with the %s parameter, directories are not returned.", | |||||
DEPRECATED_PARAM_BASE_COMPONENT_ID, PARAM_COMPONENT, Param.TEXT_QUERY)) | DEPRECATED_PARAM_BASE_COMPONENT_ID, PARAM_COMPONENT, Param.TEXT_QUERY)) | ||||
.setResponseExample(getClass().getResource("component_tree-example.json")) | .setResponseExample(getClass().getResource("component_tree-example.json")) | ||||
.setSince("5.4") | .setSince("5.4") | ||||
} | } | ||||
} | } | ||||
if (arePeriodsInResponse(request)) { | |||||
response.getPeriodsBuilder().addAllPeriods(data.getPeriods()); | |||||
if (arePeriodsInResponse(request) && data.getPeriod() != null) { | |||||
response.getPeriodsBuilder().addPeriods(data.getPeriod()); | |||||
} | } | ||||
return response.build(); | return response.build(); | ||||
.setComponentCount(componentCount) | .setComponentCount(componentCount) | ||||
.setMeasuresByComponentUuidAndMetric(measuresByComponentUuidAndMetric) | .setMeasuresByComponentUuidAndMetric(measuresByComponentUuidAndMetric) | ||||
.setMetrics(metrics) | .setMetrics(metrics) | ||||
.setPeriods(snapshotToWsPeriods(baseSnapshot.get())) | |||||
.setPeriod(snapshotToWsPeriods(baseSnapshot.get()).orElse(null)) | |||||
.setReferenceComponentsByUuid(searchReferenceComponentsById(dbSession, components)) | .setReferenceComponentsByUuid(searchReferenceComponentsById(dbSession, components)) | ||||
.build(); | .build(); | ||||
} | } |
private final int componentCount; | private final int componentCount; | ||||
private final Map<String, ComponentDto> referenceComponentsByUuid; | private final Map<String, ComponentDto> referenceComponentsByUuid; | ||||
private final List<MetricDto> metrics; | private final List<MetricDto> metrics; | ||||
private final List<Measures.Period> periods; | |||||
private final Measures.Period period; | |||||
private final Table<String, MetricDto, Measure> measuresByComponentUuidAndMetric; | private final Table<String, MetricDto, Measure> measuresByComponentUuidAndMetric; | ||||
private ComponentTreeData(Builder builder) { | private ComponentTreeData(Builder builder) { | ||||
this.referenceComponentsByUuid = builder.referenceComponentsByUuid; | this.referenceComponentsByUuid = builder.referenceComponentsByUuid; | ||||
this.metrics = builder.metrics; | this.metrics = builder.metrics; | ||||
this.measuresByComponentUuidAndMetric = builder.measuresByComponentUuidAndMetric; | this.measuresByComponentUuidAndMetric = builder.measuresByComponentUuidAndMetric; | ||||
this.periods = builder.periods; | |||||
this.period = builder.period; | |||||
} | } | ||||
public ComponentDto getBaseComponent() { | public ComponentDto getBaseComponent() { | ||||
} | } | ||||
@CheckForNull | @CheckForNull | ||||
List<Measures.Period> getPeriods() { | |||||
return periods; | |||||
Measures.Period getPeriod() { | |||||
return period; | |||||
} | } | ||||
@CheckForNull | @CheckForNull | ||||
private Map<String, ComponentDto> referenceComponentsByUuid; | private Map<String, ComponentDto> referenceComponentsByUuid; | ||||
private int componentCount; | private int componentCount; | ||||
private List<MetricDto> metrics; | private List<MetricDto> metrics; | ||||
private List<Measures.Period> periods; | |||||
private Measures.Period period; | |||||
private Table<String, MetricDto, Measure> measuresByComponentUuidAndMetric; | private Table<String, MetricDto, Measure> measuresByComponentUuidAndMetric; | ||||
private Builder() { | private Builder() { | ||||
return this; | return this; | ||||
} | } | ||||
public Builder setPeriods(List<Measures.Period> periods) { | |||||
this.periods = periods; | |||||
public Builder setPeriod(@Nullable Measures.Period period) { | |||||
this.period = period; | |||||
return this; | return this; | ||||
} | } | ||||
*/ | */ | ||||
package org.sonar.server.measure.ws; | package org.sonar.server.measure.ws; | ||||
import java.util.ArrayList; | |||||
import java.util.List; | |||||
import java.util.Optional; | |||||
import javax.annotation.Nullable; | import javax.annotation.Nullable; | ||||
import org.sonar.db.component.SnapshotDto; | import org.sonar.db.component.SnapshotDto; | ||||
import org.sonarqube.ws.Measures; | import org.sonarqube.ws.Measures; | ||||
import static java.util.Collections.emptyList; | |||||
import static org.sonar.api.utils.DateUtils.formatDateTime; | import static org.sonar.api.utils.DateUtils.formatDateTime; | ||||
class SnapshotDtoToWsPeriods { | |||||
private SnapshotDtoToWsPeriods() { | |||||
class SnapshotDtoToWsPeriod { | |||||
private SnapshotDtoToWsPeriod() { | |||||
// prevent instantiation | // prevent instantiation | ||||
} | } | ||||
static List<Measures.Period> snapshotToWsPeriods(@Nullable SnapshotDto snapshot) { | |||||
static Optional<Measures.Period> snapshotToWsPeriods(@Nullable SnapshotDto snapshot) { | |||||
if (snapshot == null) { | if (snapshot == null) { | ||||
return emptyList(); | |||||
return Optional.empty(); | |||||
} | } | ||||
List<Measures.Period> periods = new ArrayList<>(); | |||||
if (snapshot.getPeriodDate() != null) { | if (snapshot.getPeriodDate() != null) { | ||||
periods.add(snapshotDtoToWsPeriod(snapshot)); | |||||
return Optional.of(snapshotDtoToWsPeriod(snapshot)); | |||||
} | } | ||||
return periods; | |||||
return Optional.empty(); | |||||
} | } | ||||
private static Measures.Period snapshotDtoToWsPeriod(SnapshotDto snapshot) { | private static Measures.Period snapshotDtoToWsPeriod(SnapshotDto snapshot) { |