import static org.sonarqube.ws.client.measure.MeasuresWsParameters.PARAM_BASE_COMPONENT_ID;
import static org.sonarqube.ws.client.measure.MeasuresWsParameters.PARAM_BASE_COMPONENT_KEY;
import static org.sonarqube.ws.client.measure.MeasuresWsParameters.PARAM_METRIC_KEYS;
+import static org.sonarqube.ws.client.measure.MeasuresWsParameters.PARAM_METRIC_PERIOD_SORT;
import static org.sonarqube.ws.client.measure.MeasuresWsParameters.PARAM_METRIC_SORT;
import static org.sonarqube.ws.client.measure.MeasuresWsParameters.PARAM_QUALIFIERS;
import static org.sonarqube.ws.client.measure.MeasuresWsParameters.PARAM_STRATEGY;
static final String PATH_SORT = "path";
static final String QUALIFIER_SORT = "qualifier";
static final String METRIC_SORT = "metric";
- static final Set<String> SORTS = ImmutableSortedSet.of(NAME_SORT, PATH_SORT, QUALIFIER_SORT, METRIC_SORT);
+ static final String METRIC_PERIOD_SORT = "metricPeriod";
+ static final Set<String> SORTS = ImmutableSortedSet.of(NAME_SORT, PATH_SORT, QUALIFIER_SORT, METRIC_SORT, METRIC_PERIOD_SORT);
private final ComponentTreeDataLoader dataLoader;
private final UserSession userSession;
action.createSortParams(SORTS, NAME_SORT, true)
.setDescription("Comma-separated list of sort fields")
- .setExampleValue(NAME_SORT + ", " + PATH_SORT);
+ .setExampleValue(NAME_SORT + "," + PATH_SORT);
action.createParam(Param.TEXT_QUERY)
.setDescription(format("Limit search to: <ul>" +
format("Metric key to sort by. The '%s' parameter must contain the '%s' value. It must be part of the '%s' parameter", Param.SORT, METRIC_SORT, PARAM_METRIC_KEYS))
.setExampleValue("ncloc");
+ action.createParam(PARAM_METRIC_PERIOD_SORT)
+ .setDescription(format("Measure period to sort by. The '%s' parameter must contain the '%s' value.", Param.SORT, METRIC_PERIOD_SORT))
+ .setSince("5.5")
+ .setPossibleValues(1, 2, 3, 4, 5);
+
createMetricKeysParameter(action);
createAdditionalFieldsParameter(action);
createQualifiersParameter(action, newQualifierParameterContext(userSession, i18n, resourceTypes));
.setSort(request.paramAsStrings(Param.SORT))
.setAsc(request.paramAsBoolean(Param.ASCENDING))
.setMetricSort(request.param(PARAM_METRIC_SORT))
+ .setMetricPeriodSort(request.paramAsInt(PARAM_METRIC_PERIOD_SORT))
.setPage(request.mandatoryParamAsInt(Param.PAGE))
.setPageSize(request.mandatoryParamAsInt(Param.PAGE_SIZE))
.setQuery(request.param(Param.TEXT_QUERY));
"The '%s' parameter must have at least %d characters", Param.TEXT_QUERY, QUERY_MINIMUM_LENGTH);
String metricSortValue = componentTreeWsRequest.getMetricSort();
checkRequest(!componentTreeWsRequest.getMetricKeys().isEmpty(), "The '%s' parameter must contain at least one metric key", PARAM_METRIC_KEYS);
- checkRequest(metricSortValue == null ^ componentTreeWsRequest.getSort().contains(METRIC_SORT),
- "To sort by a metric, the '%s' parameter must contain '%s' and a metric key must be provided in the '%s' parameter",
- Param.SORT, METRIC_SORT, PARAM_METRIC_SORT);
+ checkRequest(metricSortValue == null ^ componentTreeWsRequest.getSort().contains(METRIC_SORT)
+ ^ componentTreeWsRequest.getSort().contains(METRIC_PERIOD_SORT),
+ "To sort by a metric, the '%s' parameter must contain '%s' or '%s', and a metric key must be provided in the '%s' parameter",
+ Param.SORT, METRIC_SORT, METRIC_PERIOD_SORT, PARAM_METRIC_SORT);
checkRequest(metricSortValue == null ^ componentTreeWsRequest.getMetricKeys().contains(metricSortValue),
"To sort by the '%s' metric, it must be in the list of metric keys in the '%s' parameter", metricSortValue, PARAM_METRIC_KEYS);
+ checkRequest(componentTreeWsRequest.getMetricPeriodSort() == null ^ componentTreeWsRequest.getSort().contains(METRIC_PERIOD_SORT),
+ "To sort by a metric period, the '%s' parameter must contain '%s' and the '%s' must be provided.", Param.SORT, METRIC_PERIOD_SORT, PARAM_METRIC_PERIOD_SORT);
return componentTreeWsRequest;
}
}
import static org.sonar.server.measure.ws.ComponentTreeAction.ALL_STRATEGY;
import static org.sonar.server.measure.ws.ComponentTreeAction.CHILDREN_STRATEGY;
import static org.sonar.server.measure.ws.ComponentTreeAction.LEAVES_STRATEGY;
+import static org.sonar.server.measure.ws.ComponentTreeAction.METRIC_PERIOD_SORT;
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.SnapshotDtoToWsPeriods.snapshotToWsPeriods;
private static List<ComponentDtoWithSnapshotId> sortComponents(List<ComponentDtoWithSnapshotId> components, ComponentTreeWsRequest wsRequest, List<MetricDto> metrics,
Table<String, MetricDto, MeasureDto> measuresByComponentUuidAndMetric) {
- if (!wsRequest.getSort().contains(METRIC_SORT)) {
+ if (!isSortByMetric(wsRequest)) {
return components;
}
}
private static List<ComponentDtoWithSnapshotId> paginateComponents(List<ComponentDtoWithSnapshotId> components, int componentCount, ComponentTreeWsRequest wsRequest) {
- if (!wsRequest.getSort().contains(METRIC_SORT)) {
+ if (!isSortByMetric(wsRequest)) {
return components;
}
.toList();
}
+ private static boolean isSortByMetric(ComponentTreeWsRequest wsRequest) {
+ return wsRequest.getSort().contains(METRIC_SORT) || wsRequest.getSort().contains(METRIC_PERIOD_SORT);
+ }
+
@CheckForNull
private List<String> childrenQualifiers(ComponentTreeWsRequest request, String baseQualifier) {
List<String> requestQualifiers = request.getQualifiers();
dbQuery.setQualifiers(childrenQualifiers);
}
// load all components if we must sort by metric value
- if (wsRequest.getSort().contains(METRIC_SORT)) {
+ if (isSortByMetric(wsRequest)) {
dbQuery.setPage(1);
dbQuery.setPageSize(Integer.MAX_VALUE);
}
@Override
public boolean apply(@Nonnull String input) {
- return !input.equals(METRIC_SORT);
+ return !input.equals(METRIC_SORT) && !input.equals(METRIC_PERIOD_SORT);
}
}
import com.google.common.base.Function;
import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Maps;
import com.google.common.collect.Ordering;
import com.google.common.collect.Table;
import java.util.List;
import java.util.Map;
+import java.util.Set;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import org.sonar.api.measures.Metric.ValueType;
import org.sonar.db.measure.MeasureDto;
import org.sonar.db.metric.MetricDto;
import org.sonar.db.metric.MetricDtoFunctions;
+import org.sonar.server.exceptions.BadRequestException;
import org.sonarqube.ws.client.measure.ComponentTreeWsRequest;
import static java.lang.String.CASE_INSENSITIVE_ORDER;
+import static java.lang.String.format;
+import static org.sonar.api.measures.Metric.ValueType.BOOL;
+import static org.sonar.api.measures.Metric.ValueType.DATA;
+import static org.sonar.api.measures.Metric.ValueType.DISTRIB;
+import static org.sonar.api.measures.Metric.ValueType.FLOAT;
+import static org.sonar.api.measures.Metric.ValueType.INT;
+import static org.sonar.api.measures.Metric.ValueType.LEVEL;
+import static org.sonar.api.measures.Metric.ValueType.MILLISEC;
+import static org.sonar.api.measures.Metric.ValueType.PERCENT;
+import static org.sonar.api.measures.Metric.ValueType.RATING;
+import static org.sonar.api.measures.Metric.ValueType.STRING;
+import static org.sonar.api.measures.Metric.ValueType.WORK_DUR;
+import static org.sonar.server.measure.ws.ComponentTreeAction.METRIC_PERIOD_SORT;
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;
class ComponentTreeSort {
+ private static final Set<ValueType> NUMERIC_VALUE_TYPES = ImmutableSet.of(BOOL, FLOAT, INT, MILLISEC, WORK_DUR, PERCENT, RATING);
+ private static final Set<ValueType> TEXTUAL_VALUE_TYPES = ImmutableSet.of(DATA, DISTRIB, LEVEL, STRING);
+
private ComponentTreeSort() {
// static method only
}
.put(NAME_SORT, componentNameOrdering(isAscending))
.put(QUALIFIER_SORT, componentQualifierOrdering(isAscending))
.put(PATH_SORT, componentPathOrdering(isAscending))
- .put(METRIC_SORT, metricOrdering(wsRequest, metrics, measuresByComponentUuidAndMetric))
+ .put(METRIC_SORT, metricValueOrdering(wsRequest, metrics, measuresByComponentUuidAndMetric))
+ .put(METRIC_PERIOD_SORT, metricPeriodOrdering(wsRequest, metrics, measuresByComponentUuidAndMetric))
.build();
String firstSortParameter = sortParameters.get(0);
return ordering.nullsLast().onResultOf(function);
}
- /**
- * Order by measure value, taking the metric direction into account
- */
- private static Ordering<ComponentDtoWithSnapshotId> metricOrdering(ComponentTreeWsRequest wsRequest, List<MetricDto> metrics,
+ private static Ordering<ComponentDtoWithSnapshotId> metricValueOrdering(ComponentTreeWsRequest wsRequest, List<MetricDto> metrics,
Table<String, MetricDto, MeasureDto> measuresByComponentUuidAndMetric) {
if (wsRequest.getMetricSort() == null) {
return componentNameOrdering(wsRequest.getAsc());
MetricDto metric = metricsByKey.get(wsRequest.getMetricSort());
boolean isAscending = wsRequest.getAsc();
- switch (ValueType.valueOf(metric.getValueType())) {
- case BOOL:
- case INT:
- case MILLISEC:
- case WORK_DUR:
- case FLOAT:
- case PERCENT:
- case RATING:
- return numericalMetricOrdering(isAscending, metric, measuresByComponentUuidAndMetric);
- case DATA:
- case DISTRIB:
- case LEVEL:
- case STRING:
- return stringOrdering(isAscending, new ComponentDtoWithSnapshotIdToTextualMeasureValue(metric, measuresByComponentUuidAndMetric));
- default:
- throw new IllegalStateException("Unrecognized metric value type: " + metric.getValueType());
+ ValueType metricValueType = ValueType.valueOf(metric.getValueType());
+ if (NUMERIC_VALUE_TYPES.contains(metricValueType)) {
+ return numericalMetricOrdering(isAscending, metric, measuresByComponentUuidAndMetric);
+ } else if (TEXTUAL_VALUE_TYPES.contains(metricValueType)) {
+ return stringOrdering(isAscending, new ComponentDtoWithSnapshotIdToTextualMeasureValue(metric, measuresByComponentUuidAndMetric));
+ }
+
+ throw new IllegalStateException("Unrecognized metric value type: " + metric.getValueType());
+ }
+
+ private static Ordering<ComponentDtoWithSnapshotId> metricPeriodOrdering(ComponentTreeWsRequest wsRequest, List<MetricDto> metrics,
+ Table<String, MetricDto, MeasureDto> measuresByComponentUuidAndMetric) {
+ if (wsRequest.getMetricSort() == null || wsRequest.getMetricPeriodSort() == null) {
+ return componentNameOrdering(wsRequest.getAsc());
+ }
+ Map<String, MetricDto> metricsByKey = Maps.uniqueIndex(metrics, MetricDtoFunctions.toKey());
+ MetricDto metric = metricsByKey.get(wsRequest.getMetricSort());
+
+ ValueType metricValueType = ValueType.valueOf(metric.getValueType());
+ if (NUMERIC_VALUE_TYPES.contains(metricValueType)) {
+ return numericalMetricPeriodOrdering(wsRequest, metric, measuresByComponentUuidAndMetric);
}
+
+ throw new BadRequestException(format("Impossible to sort metric '%s' by measure period.", metric.getKey()));
}
private static Ordering<ComponentDtoWithSnapshotId> numericalMetricOrdering(boolean isAscending, @Nullable MetricDto metric,
return ordering.nullsLast().onResultOf(new ComponentDtoWithSnapshotIdToNumericalMeasureValue(metric, measuresByComponentUuidAndMetric));
}
+ private static Ordering<ComponentDtoWithSnapshotId> numericalMetricPeriodOrdering(ComponentTreeWsRequest request, @Nullable MetricDto metric,
+ Table<String, MetricDto, MeasureDto> measuresByComponentUuidAndMetric) {
+ Ordering<Double> ordering = Ordering.natural();
+
+ if (!request.getAsc()) {
+ ordering = ordering.reverse();
+ }
+
+ return ordering.nullsLast().onResultOf(new ComponentDtoWithSnapshotIdToMeasureVariationValue(metric, measuresByComponentUuidAndMetric, request.getMetricPeriodSort()));
+ }
+
private static class ComponentDtoWithSnapshotIdToNumericalMeasureValue implements Function<ComponentDtoWithSnapshotId, Double> {
private final MetricDto metric;
private final Table<String, MetricDto, MeasureDto> measuresByComponentUuidAndMetric;
}
}
+ private static class ComponentDtoWithSnapshotIdToMeasureVariationValue implements Function<ComponentDtoWithSnapshotId, Double> {
+ private final MetricDto metric;
+ private final Table<String, MetricDto, MeasureDto> measuresByComponentUuidAndMetric;
+ private final int variationIndex;
+
+ private ComponentDtoWithSnapshotIdToMeasureVariationValue(@Nullable MetricDto metric,
+ Table<String, MetricDto, MeasureDto> measuresByComponentUuidAndMetric, int variationIndex) {
+ this.metric = metric;
+ this.measuresByComponentUuidAndMetric = measuresByComponentUuidAndMetric;
+ this.variationIndex = variationIndex;
+ }
+
+ @Override
+ public Double apply(@Nonnull ComponentDtoWithSnapshotId input) {
+ MeasureDto measure = measuresByComponentUuidAndMetric.get(input.uuid(), metric);
+ if (measure == null || measure.getVariation(variationIndex) == null) {
+ return null;
+ }
+
+ return measure.getVariation(variationIndex);
+ }
+ }
+
private static class ComponentDtoWithSnapshotIdToTextualMeasureValue implements Function<ComponentDtoWithSnapshotId, String> {
private final MetricDto metric;
private final Table<String, MetricDto, MeasureDto> measuresByComponentUuidAndMetric;
import static org.sonar.db.component.SnapshotTesting.newSnapshotForProject;
import static org.sonar.db.measure.MeasureTesting.newMeasureDto;
import static org.sonar.db.metric.MetricTesting.newMetricDto;
+import static org.sonar.server.measure.ws.ComponentTreeAction.METRIC_PERIOD_SORT;
import static org.sonar.server.measure.ws.ComponentTreeAction.METRIC_SORT;
import static org.sonar.server.measure.ws.ComponentTreeAction.NAME_SORT;
import static org.sonar.test.JsonAssert.assertJson;
import static org.sonarqube.ws.client.measure.MeasuresWsParameters.PARAM_ADDITIONAL_FIELDS;
import static org.sonarqube.ws.client.measure.MeasuresWsParameters.PARAM_BASE_COMPONENT_ID;
import static org.sonarqube.ws.client.measure.MeasuresWsParameters.PARAM_METRIC_KEYS;
+import static org.sonarqube.ws.client.measure.MeasuresWsParameters.PARAM_METRIC_PERIOD_SORT;
import static org.sonarqube.ws.client.measure.MeasuresWsParameters.PARAM_METRIC_SORT;
import static org.sonarqube.ws.client.measure.MeasuresWsParameters.PARAM_QUALIFIERS;
import static org.sonarqube.ws.client.measure.MeasuresWsParameters.PARAM_STRATEGY;
-
public class ComponentTreeActionTest {
@Rule
public UserSessionRule userSession = UserSessionRule.standalone();
}
@Test
- public void sort_by_metric_key() {
+ public void sort_by_metric_value() {
ComponentDto projectDto = newProjectDto("project-uuid");
SnapshotDto projectSnapshot = componentDb.insertProjectAndSnapshot(projectDto);
SnapshotDto fileSnapshot3 = componentDb.insertComponentAndSnapshot(newFileDto(projectDto, "file-uuid-3"), projectSnapshot);
assertThat(response.getComponentsList()).extracting("id").containsExactly("file-uuid-1", "file-uuid-2", "file-uuid-3");
}
+ @Test
+ public void sort_by_metric_period() {
+ ComponentDto projectDto = newProjectDto("project-uuid");
+ SnapshotDto projectSnapshot = componentDb.insertProjectAndSnapshot(projectDto);
+ SnapshotDto fileSnapshot3 = componentDb.insertComponentAndSnapshot(newFileDto(projectDto, "file-uuid-3"), projectSnapshot);
+ SnapshotDto fileSnapshot1 = componentDb.insertComponentAndSnapshot(newFileDto(projectDto, "file-uuid-1"), projectSnapshot);
+ SnapshotDto fileSnapshot2 = componentDb.insertComponentAndSnapshot(newFileDto(projectDto, "file-uuid-2"), projectSnapshot);
+ MetricDto ncloc = newMetricDtoWithoutOptimization().setKey("ncloc").setValueType(ValueType.INT.name()).setDirection(1);
+ dbClient.metricDao().insert(dbSession, ncloc);
+ dbClient.measureDao().insert(dbSession,
+ newMeasureDto(ncloc, fileSnapshot1.getId()).setVariation(1, 1.0d),
+ newMeasureDto(ncloc, fileSnapshot2.getId()).setVariation(1, 2.0d),
+ newMeasureDto(ncloc, fileSnapshot3.getId()).setVariation(1, 3.0d));
+ db.commit();
+
+ ComponentTreeWsResponse response = call(ws.newRequest()
+ .setParam(PARAM_BASE_COMPONENT_ID, "project-uuid")
+ .setParam(Param.SORT, METRIC_PERIOD_SORT)
+ .setParam(PARAM_METRIC_SORT, "ncloc")
+ .setParam(PARAM_METRIC_KEYS, "ncloc")
+ .setParam(PARAM_METRIC_PERIOD_SORT, "1"));
+
+ assertThat(response.getComponentsList()).extracting("id").containsExactly("file-uuid-1", "file-uuid-2", "file-uuid-3");
+ }
+
@Test
public void load_developer_descendants() {
ComponentDto developer = newDeveloper("developer").setUuid("developer-uuid");
public void fail_when_sort_by_metric_and_no_metric_sort_provided() {
componentDb.insertProjectAndSnapshot(newProjectDto("project-uuid"));
expectedException.expect(BadRequestException.class);
- expectedException.expectMessage("To sort by a metric, the 's' parameter must contain 'metric' and a metric key must be provided in the 'metricSort' parameter");
+ expectedException
+ .expectMessage("To sort by a metric, the 's' parameter must contain 'metric' or 'metricPeriod', and a metric key must be provided in the 'metricSort' parameter");
call(ws.newRequest()
.setParam(PARAM_BASE_COMPONENT_ID, "project-uuid")
.setParam(Param.SORT, METRIC_SORT));
}
+ @Test
+ public void fail_when_sort_by_metric_period_and_no_metric_period_sort_provided() {
+ componentDb.insertProjectAndSnapshot(newProjectDto("project-uuid"));
+ expectedException.expect(BadRequestException.class);
+ expectedException.expectMessage("To sort by a metric period, the 's' parameter must contain 'metricPeriod' and the 'metricPeriodSort' must be provided.");
+
+ call(ws.newRequest()
+ .setParam(PARAM_BASE_COMPONENT_ID, "project-uuid")
+ .setParam(PARAM_METRIC_KEYS, "ncloc")
+ .setParam(PARAM_METRIC_SORT, "ncloc")
+ // PARAM_METRIC_PERIOD_SORT_IS_NOT_SET
+ .setParam(Param.SORT, METRIC_PERIOD_SORT));
+ }
+
@Test
public void fail_when_paging_parameter_is_too_big() {
componentDb.insertProjectAndSnapshot(newProjectDto("project-uuid"));
import static java.util.Collections.singletonList;
import static org.assertj.core.api.Assertions.assertThat;
import static org.sonar.db.metric.MetricTesting.newMetricDto;
+import static org.sonar.server.measure.ws.ComponentTreeAction.METRIC_PERIOD_SORT;
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;
// same number than path field
double currentValue = 9;
for (ComponentDtoWithSnapshotId component : components) {
- measuresByComponentUuidAndMetric.put(component.uuid(), violationsMetric, new MeasureDto().setValue(currentValue));
+ measuresByComponentUuidAndMetric.put(component.uuid(), violationsMetric, new MeasureDto().setValue(currentValue)
+ .setVariation(1, -currentValue)
+ .setVariation(5, currentValue));
measuresByComponentUuidAndMetric.put(component.uuid(), sqaleIndexMetric, new MeasureDto().setData(String.valueOf(currentValue)));
currentValue--;
}
.containsExactly("path-9", "path-8", "path-7", "path-6", "path-5", "path-4", "path-3", "path-2", "path-1", "path-without-measure");
}
+ @Test
+ public void sort_by_numerical_metric_period_1_key_ascending() {
+ components.add(newComponentWithoutSnapshotId("name-without-measure", "qualifier-without-measure", "path-without-measure"));
+ ComponentTreeWsRequest wsRequest = newRequest(singletonList(METRIC_PERIOD_SORT), true, NUM_METRIC_KEY).setMetricPeriodSort(1);
+
+ List<ComponentDtoWithSnapshotId> result = sortComponents(wsRequest);
+
+ assertThat(result).extracting("path")
+ .containsExactly("path-9", "path-8", "path-7", "path-6", "path-5", "path-4", "path-3", "path-2", "path-1", "path-without-measure");
+ }
+
+ @Test
+ public void sort_by_numerical_metric_period_1_key_descending() {
+ components.add(newComponentWithoutSnapshotId("name-without-measure", "qualifier-without-measure", "path-without-measure"));
+ ComponentTreeWsRequest wsRequest = newRequest(singletonList(METRIC_PERIOD_SORT), false, NUM_METRIC_KEY).setMetricPeriodSort(1);
+
+ List<ComponentDtoWithSnapshotId> result = sortComponents(wsRequest);
+
+ assertThat(result).extracting("path")
+ .containsExactly("path-1", "path-2", "path-3", "path-4", "path-5", "path-6", "path-7", "path-8", "path-9", "path-without-measure");
+ }
+
+ @Test
+ public void sort_by_numerical_metric_period_5_key() {
+ components.add(newComponentWithoutSnapshotId("name-without-measure", "qualifier-without-measure", "path-without-measure"));
+ ComponentTreeWsRequest wsRequest = newRequest(singletonList(METRIC_SORT), false, NUM_METRIC_KEY).setMetricPeriodSort(5);
+
+ List<ComponentDtoWithSnapshotId> result = sortComponents(wsRequest);
+
+ assertThat(result).extracting("path")
+ .containsExactly("path-9", "path-8", "path-7", "path-6", "path-5", "path-4", "path-3", "path-2", "path-1", "path-without-measure");
+ }
+
@Test
public void sort_by_textual_metric_key_ascending() {
components.add(newComponentWithoutSnapshotId("name-without-measure", "qualifier-without-measure", "path-without-measure"));
private List<String> sort;
private Boolean asc;
private String metricSort;
+ private Integer metricPeriodSort;
private List<String> metricKeys;
private Integer page;
private Integer pageSize;
this.pageSize = pageSize;
return this;
}
+
+ @CheckForNull
+ public Integer getMetricPeriodSort() {
+ return metricPeriodSort;
+ }
+
+ public ComponentTreeWsRequest setMetricPeriodSort(@Nullable Integer metricPeriodSort) {
+ this.metricPeriodSort = metricPeriodSort;
+ return this;
+ }
}
public static final String PARAM_QUALIFIERS = "qualifiers";
public static final String PARAM_METRIC_KEYS = "metricKeys";
public static final String PARAM_METRIC_SORT = "metricSort";
+ public static final String PARAM_METRIC_PERIOD_SORT = "metricPeriodSort";
public static final String PARAM_ADDITIONAL_FIELDS = "additionalFields";
public static final String PARAM_COMPONENT_ID = "componentId";
public static final String PARAM_COMPONENT_KEY = "componentKey";