aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/measure/custom/persistence/CustomMeasureDao.java10
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/measure/custom/ws/CreateAction.java2
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/measure/custom/ws/CustomMeasureJsonWriter.java71
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/measure/custom/ws/CustomMeasuresWsModule.java1
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/measure/custom/ws/SearchAction.java180
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/measure/custom/ws/UpdateAction.java3
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/metric/persistence/MetricDao.java12
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/metric/ws/MetricJsonWriter.java30
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/ws/JsonWriterUtils.java7
-rw-r--r--server/sonar-server/src/main/resources/org/sonar/server/measure/custom/ws/example-search.json55
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/measure/custom/ws/CustomMeasuresWsModuleTest.java2
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/measure/custom/ws/MetricsActionTest.java16
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/measure/custom/ws/SearchActionTest.java274
-rw-r--r--server/sonar-server/src/test/resources/org/sonar/server/measure/custom/ws/SearchActionTest/empty.json7
-rw-r--r--server/sonar-server/src/test/resources/org/sonar/server/measure/custom/ws/SearchActionTest/metrics.json55
-rw-r--r--sonar-core/src/main/java/org/sonar/core/measure/custom/db/CustomMeasureMapper.java5
-rw-r--r--sonar-core/src/main/java/org/sonar/core/metric/db/MetricMapper.java10
-rw-r--r--sonar-core/src/main/resources/org/sonar/core/measure/custom/db/CustomMeasureMapper.xml6
-rw-r--r--sonar-core/src/main/resources/org/sonar/core/metric/db/MetricMapper.xml12
19 files changed, 706 insertions, 52 deletions
diff --git a/server/sonar-server/src/main/java/org/sonar/server/measure/custom/persistence/CustomMeasureDao.java b/server/sonar-server/src/main/java/org/sonar/server/measure/custom/persistence/CustomMeasureDao.java
index 6a454ee2720..7f660ea5e5d 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/measure/custom/persistence/CustomMeasureDao.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/measure/custom/persistence/CustomMeasureDao.java
@@ -24,12 +24,14 @@ import com.google.common.base.Function;
import java.util.List;
import javax.annotation.CheckForNull;
import javax.annotation.Nonnull;
+import org.apache.ibatis.session.RowBounds;
import org.sonar.api.server.ServerSide;
import org.sonar.core.measure.custom.db.CustomMeasureDto;
import org.sonar.core.measure.custom.db.CustomMeasureMapper;
import org.sonar.core.persistence.DaoComponent;
import org.sonar.core.persistence.DaoUtils;
import org.sonar.core.persistence.DbSession;
+import org.sonar.server.es.SearchOptions;
import org.sonar.server.exceptions.NotFoundException;
@ServerSide
@@ -77,6 +79,10 @@ public class CustomMeasureDao implements DaoComponent {
return mapper(session).countByComponentIdAndMetricId(componentUuid, metricId);
}
+ public List<CustomMeasureDto> selectByComponentUuid(DbSession session, String componentUuid, SearchOptions searchOptions) {
+ return mapper(session).selectByComponentUuid(componentUuid, new RowBounds(searchOptions.getOffset(), searchOptions.getLimit()));
+ }
+
public List<CustomMeasureDto> selectByComponentUuid(DbSession session, String componentUuid) {
return mapper(session).selectByComponentUuid(componentUuid);
}
@@ -84,4 +90,8 @@ public class CustomMeasureDao implements DaoComponent {
private CustomMeasureMapper mapper(DbSession session) {
return session.getMapper(CustomMeasureMapper.class);
}
+
+ public int countByComponentUuid(DbSession dbSession, String uuid) {
+ return mapper(dbSession).countByComponentUuid(uuid);
+ }
}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/measure/custom/ws/CreateAction.java b/server/sonar-server/src/main/java/org/sonar/server/measure/custom/ws/CreateAction.java
index 7618cd5d41a..a809a623028 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/measure/custom/ws/CreateAction.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/measure/custom/ws/CreateAction.java
@@ -132,7 +132,7 @@ public class CreateAction implements CustomMeasuresWsAction {
dbSession.commit();
JsonWriter json = response.newJsonWriter();
- customMeasureJsonWriter.write(json, measure, metric, component, user);
+ customMeasureJsonWriter.write(json, measure, metric, component, user, CustomMeasureJsonWriter.OPTIONAL_FIELDS);
json.close();
} finally {
MyBatis.closeQuietly(dbSession);
diff --git a/server/sonar-server/src/main/java/org/sonar/server/measure/custom/ws/CustomMeasureJsonWriter.java b/server/sonar-server/src/main/java/org/sonar/server/measure/custom/ws/CustomMeasureJsonWriter.java
index f2b9f2618bc..026d0cb9fa0 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/measure/custom/ws/CustomMeasureJsonWriter.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/measure/custom/ws/CustomMeasureJsonWriter.java
@@ -20,55 +20,63 @@
package org.sonar.server.measure.custom.ws;
+import com.google.common.collect.ImmutableSet;
+import java.util.Collection;
import java.util.Date;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
import org.sonar.api.measures.Metric;
-import org.sonar.api.server.ServerSide;
import org.sonar.api.user.User;
import org.sonar.api.utils.text.JsonWriter;
import org.sonar.core.component.ComponentDto;
import org.sonar.core.measure.custom.db.CustomMeasureDto;
import org.sonar.core.metric.db.MetricDto;
+import org.sonar.server.metric.ws.MetricJsonWriter;
import org.sonar.server.user.ws.UserJsonWriter;
-import static org.sonar.server.measure.custom.ws.CreateAction.PARAM_DESCRIPTION;
-import static org.sonar.server.measure.custom.ws.CreateAction.PARAM_PROJECT_ID;
-import static org.sonar.server.measure.custom.ws.CreateAction.PARAM_PROJECT_KEY;
-import static org.sonar.server.measure.custom.ws.CreateAction.PARAM_VALUE;
+import static org.sonar.server.ws.JsonWriterUtils.isFieldNeeded;
+import static org.sonar.server.ws.JsonWriterUtils.writeIfNeeded;
-@ServerSide
public class CustomMeasureJsonWriter {
private static final String FIELD_ID = "id";
- private static final String FIELD_PROJECT_ID = PARAM_PROJECT_ID;
- private static final String FIELD_PROJECT_KEY = PARAM_PROJECT_KEY;
- private static final String FIELD_VALUE = PARAM_VALUE;
- private static final String FIELD_DESCRIPTION = PARAM_DESCRIPTION;
+ private static final String FIELD_PROJECT_ID = "projectId";
+ private static final String FIELD_PROJECT_KEY = "projectKey";
+ private static final String FIELD_VALUE = "value";
+ private static final String FIELD_DESCRIPTION = "description";
private static final String FIELD_METRIC = "metric";
- private static final String FIELD_METRIC_KEY = "key";
- private static final String FIELD_METRIC_ID = "id";
- private static final String FIELD_METRIC_TYPE = "type";
private static final String FIELD_CREATED_AT = "createdAt";
private static final String FIELD_UPDATED_AT = "updatedAt";
private static final String FIELD_USER = "user";
+ public static final Set<String> OPTIONAL_FIELDS = ImmutableSet.of(FIELD_PROJECT_ID, FIELD_PROJECT_KEY, FIELD_VALUE, FIELD_DESCRIPTION, FIELD_METRIC, FIELD_CREATED_AT,
+ FIELD_UPDATED_AT, FIELD_USER);
+
private final UserJsonWriter userJsonWriter;
public CustomMeasureJsonWriter(UserJsonWriter userJsonWriter) {
this.userJsonWriter = userJsonWriter;
}
- public void write(JsonWriter json, CustomMeasureDto measure, MetricDto metric, ComponentDto component, User user) {
+ public void write(JsonWriter json, CustomMeasureDto measure, MetricDto metric, ComponentDto component, User user, Collection<String> fieldsToReturn) {
json.beginObject();
json.prop(FIELD_ID, String.valueOf(measure.getId()));
- json.name(FIELD_METRIC);
- writeMetric(json, metric);
- json.prop(FIELD_PROJECT_ID, component.uuid());
- json.prop(FIELD_PROJECT_KEY, component.key());
- json.prop(FIELD_DESCRIPTION, measure.getDescription());
- json.prop(FIELD_VALUE, measureValue(measure, metric));
- json.propDateTime(FIELD_CREATED_AT, new Date(measure.getCreatedAt()));
- json.propDateTime(FIELD_UPDATED_AT, new Date(measure.getUpdatedAt()));
- json.name(FIELD_USER);
- userJsonWriter.write(json, user);
+ writeIfNeeded(json, measureValue(measure, metric), FIELD_VALUE, fieldsToReturn);
+ writeIfNeeded(json, measure.getDescription(), FIELD_DESCRIPTION, fieldsToReturn);
+ if (isFieldNeeded(FIELD_METRIC, fieldsToReturn)) {
+ json.name(FIELD_METRIC);
+ MetricJsonWriter.write(json, metric, MetricJsonWriter.MANDATORY_FIELDS);
+ }
+ writeIfNeeded(json, component.uuid(), FIELD_PROJECT_ID, fieldsToReturn);
+ writeIfNeeded(json, component.key(), FIELD_PROJECT_KEY, fieldsToReturn);
+ writeIfNeeded(json, new Date(measure.getCreatedAt()), FIELD_CREATED_AT, fieldsToReturn);
+ writeIfNeeded(json, new Date(measure.getUpdatedAt()), FIELD_UPDATED_AT, fieldsToReturn);
+
+ if (isFieldNeeded(FIELD_USER, fieldsToReturn)) {
+ json.name(FIELD_USER);
+ userJsonWriter.write(json, user);
+ }
+
json.endObject();
}
@@ -99,12 +107,13 @@ public class CustomMeasureJsonWriter {
}
}
- private static void writeMetric(JsonWriter json, MetricDto metric) {
- json.beginObject();
- json.prop(FIELD_METRIC_ID, String.valueOf(metric.getId()));
- json.prop(FIELD_METRIC_KEY, metric.getKey());
- json.prop(FIELD_METRIC_TYPE, metric.getValueType());
- json.endObject();
+ public void write(JsonWriter json, List<CustomMeasureDto> customMeasures, ComponentDto project, Map<Integer, MetricDto> metricsById, Map<String, User> usersByLogin,
+ Collection<String> fieldsToReturn) {
+ json.name("customMeasures");
+ json.beginArray();
+ for (CustomMeasureDto customMeasure : customMeasures) {
+ write(json, customMeasure, metricsById.get(customMeasure.getMetricId()), project, usersByLogin.get(customMeasure.getUserLogin()), fieldsToReturn);
+ }
+ json.endArray();
}
-
}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/measure/custom/ws/CustomMeasuresWsModule.java b/server/sonar-server/src/main/java/org/sonar/server/measure/custom/ws/CustomMeasuresWsModule.java
index 136f332dcfe..1b40340d5a5 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/measure/custom/ws/CustomMeasuresWsModule.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/measure/custom/ws/CustomMeasuresWsModule.java
@@ -30,6 +30,7 @@ public class CustomMeasuresWsModule extends Module {
CreateAction.class,
UpdateAction.class,
DeleteAction.class,
+ SearchAction.class,
MetricsAction.class,
CustomMeasureJsonWriter.class,
CustomMeasureValidator.class);
diff --git a/server/sonar-server/src/main/java/org/sonar/server/measure/custom/ws/SearchAction.java b/server/sonar-server/src/main/java/org/sonar/server/measure/custom/ws/SearchAction.java
new file mode 100644
index 00000000000..02f33429d72
--- /dev/null
+++ b/server/sonar-server/src/main/java/org/sonar/server/measure/custom/ws/SearchAction.java
@@ -0,0 +1,180 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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.custom.ws;
+
+import com.google.common.base.Function;
+import com.google.common.collect.FluentIterable;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import java.util.List;
+import java.util.Map;
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+import org.sonar.api.server.ws.Request;
+import org.sonar.api.server.ws.Response;
+import org.sonar.api.server.ws.WebService;
+import org.sonar.api.user.User;
+import org.sonar.api.utils.text.JsonWriter;
+import org.sonar.core.component.ComponentDto;
+import org.sonar.core.measure.custom.db.CustomMeasureDto;
+import org.sonar.core.metric.db.MetricDto;
+import org.sonar.core.persistence.DbSession;
+import org.sonar.core.persistence.MyBatis;
+import org.sonar.server.db.DbClient;
+import org.sonar.server.es.SearchOptions;
+import org.sonar.server.user.index.UserIndex;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.collect.Sets.newHashSet;
+
+public class SearchAction implements CustomMeasuresWsAction {
+
+ public static final String ACTION = "search";
+ public static final String PARAM_PROJECT_ID = "projectId";
+ public static final String PARAM_PROJECT_KEY = "projectKey";
+
+ private final DbClient dbClient;
+ private final UserIndex userIndex;
+ private final CustomMeasureJsonWriter customMeasureJsonWriter;
+
+ public SearchAction(DbClient dbClient, UserIndex userIndex, CustomMeasureJsonWriter customMeasureJsonWriter) {
+ this.dbClient = dbClient;
+ this.userIndex = userIndex;
+ this.customMeasureJsonWriter = customMeasureJsonWriter;
+ }
+
+ @Override
+ public void define(WebService.NewController context) {
+ WebService.NewAction action = context.createAction(ACTION)
+ .setDescription("List custom measures. The project id or project key must be provided.")
+ .setSince("5.2")
+ .addFieldsParam(CustomMeasureJsonWriter.OPTIONAL_FIELDS)
+ .addPagingParams(100)
+ .setResponseExample(getClass().getResource("example-search.json"))
+ .setHandler(this);
+
+ action.createParam(PARAM_PROJECT_ID)
+ .setDescription("Project id")
+ .setExampleValue("ce4c03d6-430f-40a9-b777-ad877c00aa4d");
+
+ action.createParam(PARAM_PROJECT_KEY)
+ .setDescription("Project key")
+ .setExampleValue("org.apache.hbas:hbase");
+ }
+
+ @Override
+ public void handle(Request request, Response response) throws Exception {
+ String projectUuid = request.param(PARAM_PROJECT_ID);
+ String projectKey = request.param(PARAM_PROJECT_KEY);
+ List<String> fieldsToReturn = request.paramAsStrings(WebService.Param.FIELDS);
+ SearchOptions searchOptions = new SearchOptions()
+ .setPage(request.mandatoryParamAsInt(WebService.Param.PAGE),
+ request.mandatoryParamAsInt(WebService.Param.PAGE_SIZE));
+
+ DbSession dbSession = dbClient.openSession(false);
+ try {
+ ComponentDto project = searchProject(dbSession, projectUuid, projectKey);
+ List<CustomMeasureDto> customMeasures = searchCustomMeasures(dbSession, project, searchOptions);
+ int nbCustomMeasures = countTotalOfCustomMeasures(dbSession, project);
+ Map<String, User> usersByLogin = usersByLogin(customMeasures);
+ Map<Integer, MetricDto> metricsById = metricsById(dbSession, customMeasures);
+
+ writeResponse(response, customMeasures, nbCustomMeasures, project, metricsById, usersByLogin, searchOptions, fieldsToReturn);
+ } finally {
+ MyBatis.closeQuietly(dbSession);
+ }
+ }
+
+ private int countTotalOfCustomMeasures(DbSession dbSession, ComponentDto project) {
+ return dbClient.customMeasureDao().countByComponentUuid(dbSession, project.uuid());
+ }
+
+ private List<CustomMeasureDto> searchCustomMeasures(DbSession dbSession, ComponentDto project, SearchOptions searchOptions) {
+ return dbClient.customMeasureDao().selectByComponentUuid(dbSession, project.uuid(), searchOptions);
+ }
+
+ private void writeResponse(Response response, List<CustomMeasureDto> customMeasures, int nbCustomMeasures, ComponentDto project, Map<Integer, MetricDto> metricsById,
+ Map<String, User> usersByLogin, SearchOptions searchOptions, List<String> fieldsToReturn) {
+ JsonWriter json = response.newJsonWriter();
+ json.beginObject();
+ customMeasureJsonWriter.write(json, customMeasures, project, metricsById, usersByLogin, fieldsToReturn);
+ searchOptions.writeJson(json, nbCustomMeasures);
+ json.endObject();
+ json.close();
+ }
+
+ private Map<Integer, MetricDto> metricsById(DbSession dbSession, List<CustomMeasureDto> customMeasures) {
+ List<MetricDto> metrics = dbClient.metricDao().selectByIds(dbSession, newHashSet(Lists.transform(customMeasures, CustomMeasureToMetricIdFunction.INSTANCE)));
+ return Maps.uniqueIndex(metrics, MetricToIdFunction.INSTANCE);
+ }
+
+ private Map<String, User> usersByLogin(List<CustomMeasureDto> customMeasures) {
+ return FluentIterable.from(customMeasures)
+ .transform(CustomMeasureToUserLoginFunction.INSTANCE)
+ .toMap(new UserLoginToUserFunction());
+ }
+
+ private ComponentDto searchProject(DbSession dbSession, @Nullable String projectUuid, @Nullable String projectKey) {
+ checkArgument(projectUuid != null ^ projectKey != null, "The project id or project key must be provided, not both.");
+ ComponentDto project;
+ if (projectUuid != null) {
+ project = dbClient.componentDao().selectByUuid(dbSession, projectUuid);
+ } else {
+ project = dbClient.componentDao().selectByKey(dbSession, projectKey);
+ }
+
+ return project;
+ }
+
+ private enum CustomMeasureToUserLoginFunction implements Function<CustomMeasureDto, String> {
+ INSTANCE;
+
+ @Override
+ public String apply(@Nonnull CustomMeasureDto customMeasure) {
+ return customMeasure.getUserLogin();
+ }
+ }
+
+ private final class UserLoginToUserFunction implements Function<String, User> {
+ @Override
+ public User apply(@Nonnull String userLogin) {
+ return userIndex.getByLogin(userLogin);
+ }
+ }
+
+ private enum CustomMeasureToMetricIdFunction implements Function<CustomMeasureDto, Integer> {
+ INSTANCE;
+
+ @Override
+ public Integer apply(@Nonnull CustomMeasureDto customMeasure) {
+ return customMeasure.getMetricId();
+ }
+ }
+
+ private enum MetricToIdFunction implements Function<MetricDto, Integer> {
+ INSTANCE;
+
+ @Override
+ public Integer apply(@Nonnull MetricDto metric) {
+ return metric.getId();
+ }
+ }
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/measure/custom/ws/UpdateAction.java b/server/sonar-server/src/main/java/org/sonar/server/measure/custom/ws/UpdateAction.java
index a5edb38b2f0..60ef4a642cd 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/measure/custom/ws/UpdateAction.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/measure/custom/ws/UpdateAction.java
@@ -100,7 +100,6 @@ public class UpdateAction implements CustomMeasuresWsAction {
checkPermissions(component);
User user = userIndex.getByLogin(userSession.getLogin());
-
setValue(customMeasure, value, metric);
setDescription(customMeasure, description);
customMeasure.setUserLogin(user.login());
@@ -109,7 +108,7 @@ public class UpdateAction implements CustomMeasuresWsAction {
dbSession.commit();
JsonWriter json = response.newJsonWriter();
- customMeasureJsonWriter.write(json, customMeasure, metric, component, user);
+ customMeasureJsonWriter.write(json, customMeasure, metric, component, user, CustomMeasureJsonWriter.OPTIONAL_FIELDS);
json.close();
} finally {
MyBatis.closeQuietly(dbSession);
diff --git a/server/sonar-server/src/main/java/org/sonar/server/metric/persistence/MetricDao.java b/server/sonar-server/src/main/java/org/sonar/server/metric/persistence/MetricDao.java
index 3a72aecf2e4..1b0b5a4a9e6 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/metric/persistence/MetricDao.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/metric/persistence/MetricDao.java
@@ -25,9 +25,11 @@ import com.google.common.base.Predicate;
import com.google.common.collect.Collections2;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
+import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
+import java.util.Set;
import javax.annotation.CheckForNull;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
@@ -111,6 +113,16 @@ public class MetricDao implements DaoComponent {
return mapper(session).selectAvailableCustomMetricsByComponentUuid(projectKey);
}
+ public List<MetricDto> selectByIds(final DbSession session, Set<Integer> idsSet) {
+ List<Integer> ids = new ArrayList<>(idsSet);
+ return DaoUtils.executeLargeInputs(ids, new Function<List<Integer>, List<MetricDto>>() {
+ @Override
+ public List<MetricDto> apply(@Nonnull List<Integer> ids) {
+ return mapper(session).selectByIds(ids);
+ }
+ });
+ }
+
private static class NotEmptyPredicate implements Predicate<String> {
@Override
diff --git a/server/sonar-server/src/main/java/org/sonar/server/metric/ws/MetricJsonWriter.java b/server/sonar-server/src/main/java/org/sonar/server/metric/ws/MetricJsonWriter.java
index 0e752b2276f..474a518c3b4 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/metric/ws/MetricJsonWriter.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/metric/ws/MetricJsonWriter.java
@@ -41,7 +41,7 @@ public class MetricJsonWriter {
public static final String FIELD_HIDDEN = "hidden";
public static final String FIELD_CUSTOM = "custom";
public static final Set<String> OPTIONAL_FIELDS = ImmutableSet.of(FIELD_NAME, FIELD_DESCRIPTION, FIELD_DOMAIN, FIELD_DIRECTION, FIELD_QUALITATIVE, FIELD_HIDDEN, FIELD_CUSTOM);
- private static final Set<String> MANDATORY_FIELDS = ImmutableSet.of(FIELD_ID, FIELD_KEY, FIELD_TYPE);
+ public static final Set<String> MANDATORY_FIELDS = ImmutableSet.of(FIELD_ID, FIELD_KEY, FIELD_TYPE);
public static final Set<String> ALL_FIELDS = Sets.union(MANDATORY_FIELDS, OPTIONAL_FIELDS);
private MetricJsonWriter() {
@@ -52,19 +52,23 @@ public class MetricJsonWriter {
json.name("metrics");
json.beginArray();
for (MetricDto metric : metrics) {
- json.beginObject();
- json.prop(FIELD_ID, String.valueOf(metric.getId()));
- json.prop(FIELD_KEY, metric.getKey());
- json.prop(FIELD_TYPE, metric.getValueType());
- writeIfNeeded(json, metric.getShortName(), FIELD_NAME, fieldsToReturn);
- writeIfNeeded(json, metric.getDescription(), FIELD_DESCRIPTION, fieldsToReturn);
- writeIfNeeded(json, metric.getDomain(), FIELD_DOMAIN, fieldsToReturn);
- writeIfNeeded(json, metric.getDirection(), FIELD_DIRECTION, fieldsToReturn);
- writeIfNeeded(json, metric.isQualitative(), FIELD_QUALITATIVE, fieldsToReturn);
- writeIfNeeded(json, metric.isHidden(), FIELD_HIDDEN, fieldsToReturn);
- writeIfNeeded(json, metric.isUserManaged(), FIELD_CUSTOM, fieldsToReturn);
- json.endObject();
+ write(json, metric, fieldsToReturn);
}
json.endArray();
}
+
+ public static void write(JsonWriter json, MetricDto metric, Set<String> fieldsToReturn) {
+ json.beginObject();
+ json.prop(FIELD_ID, String.valueOf(metric.getId()));
+ json.prop(FIELD_KEY, metric.getKey());
+ json.prop(FIELD_TYPE, metric.getValueType());
+ writeIfNeeded(json, metric.getShortName(), FIELD_NAME, fieldsToReturn);
+ writeIfNeeded(json, metric.getDescription(), FIELD_DESCRIPTION, fieldsToReturn);
+ writeIfNeeded(json, metric.getDomain(), FIELD_DOMAIN, fieldsToReturn);
+ writeIfNeeded(json, metric.getDirection(), FIELD_DIRECTION, fieldsToReturn);
+ writeIfNeeded(json, metric.isQualitative(), FIELD_QUALITATIVE, fieldsToReturn);
+ writeIfNeeded(json, metric.isHidden(), FIELD_HIDDEN, fieldsToReturn);
+ writeIfNeeded(json, metric.isUserManaged(), FIELD_CUSTOM, fieldsToReturn);
+ json.endObject();
+ }
}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/ws/JsonWriterUtils.java b/server/sonar-server/src/main/java/org/sonar/server/ws/JsonWriterUtils.java
index 16cc16e9906..bd6548d82ac 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/ws/JsonWriterUtils.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/ws/JsonWriterUtils.java
@@ -20,6 +20,7 @@
package org.sonar.server.ws;
import java.util.Collection;
+import java.util.Date;
import javax.annotation.Nullable;
import org.sonar.api.utils.text.JsonWriter;
@@ -53,6 +54,12 @@ public class JsonWriterUtils {
}
}
+ public static void writeIfNeeded(JsonWriter json, @Nullable Date value, String field, Collection<String> fields) {
+ if (isFieldNeeded(field, fields)) {
+ json.propDateTime(field, value);
+ }
+ }
+
public static boolean isFieldNeeded(String field, @Nullable Collection<String> fields) {
return fields == null || fields.isEmpty() || fields.contains(field);
}
diff --git a/server/sonar-server/src/main/resources/org/sonar/server/measure/custom/ws/example-search.json b/server/sonar-server/src/main/resources/org/sonar/server/measure/custom/ws/example-search.json
new file mode 100644
index 00000000000..bbdb201c18e
--- /dev/null
+++ b/server/sonar-server/src/main/resources/org/sonar/server/measure/custom/ws/example-search.json
@@ -0,0 +1,55 @@
+{
+ "customMeasures": [
+ {
+ "description": "New arrivals",
+ "metric": {
+ "key": "team_size",
+ "type": "INT"
+ },
+ "projectId": "project-uuid",
+ "projectKey": "project-key",
+ "user": {
+ "active": true,
+ "email": "login@login.com",
+ "login": "login",
+ "name": "Stan Smith"
+ },
+ "value": "42"
+ },
+ {
+ "description": "New funds",
+ "metric": {
+ "key": "burned_budget",
+ "type": "INT"
+ },
+ "projectId": "project-uuid",
+ "projectKey": "project-key",
+ "user": {
+ "active": true,
+ "email": "login@login.com",
+ "login": "login",
+ "name": "Stan Smith"
+ },
+ "value": "1000000"
+ },
+ {
+ "description": "Great coverage",
+ "metric": {
+ "key": "uncovered_lines",
+ "type": "INT"
+ },
+ "projectId": "project-uuid",
+ "projectKey": "project-key",
+ "user": {
+ "active": true,
+ "email": "login@login.com",
+ "login": "login",
+ "name": "Stan Smith"
+ },
+ "value": "1"
+ }
+ ],
+ "p": 1,
+ "ps": 100,
+ "total": 3
+}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/measure/custom/ws/CustomMeasuresWsModuleTest.java b/server/sonar-server/src/test/java/org/sonar/server/measure/custom/ws/CustomMeasuresWsModuleTest.java
index b8c4f3fd306..fdbed1017be 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/measure/custom/ws/CustomMeasuresWsModuleTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/measure/custom/ws/CustomMeasuresWsModuleTest.java
@@ -30,6 +30,6 @@ public class CustomMeasuresWsModuleTest {
public void verify_count_of_added_components() {
ComponentContainer container = new ComponentContainer();
new CustomMeasuresWsModule().configure(container);
- assertThat(container.size()).isEqualTo(9);
+ assertThat(container.size()).isEqualTo(10);
}
}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/measure/custom/ws/MetricsActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/measure/custom/ws/MetricsActionTest.java
index 0225dcb5708..5dfafb50df0 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/measure/custom/ws/MetricsActionTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/measure/custom/ws/MetricsActionTest.java
@@ -22,11 +22,13 @@ package org.sonar.server.measure.custom.ws;
import org.junit.After;
import org.junit.Before;
+import org.junit.BeforeClass;
import org.junit.ClassRule;
import org.junit.Rule;
import org.junit.Test;
import org.junit.experimental.categories.Category;
import org.junit.rules.ExpectedException;
+import org.sonar.api.config.Settings;
import org.sonar.api.measures.Metric;
import org.sonar.core.component.ComponentDto;
import org.sonar.core.measure.custom.db.CustomMeasureDto;
@@ -36,8 +38,11 @@ import org.sonar.core.persistence.DbTester;
import org.sonar.server.component.ComponentTesting;
import org.sonar.server.component.db.ComponentDao;
import org.sonar.server.db.DbClient;
+import org.sonar.server.es.EsTester;
import org.sonar.server.measure.custom.persistence.CustomMeasureDao;
import org.sonar.server.metric.persistence.MetricDao;
+import org.sonar.server.user.index.UserDoc;
+import org.sonar.server.user.index.UserIndexDefinition;
import org.sonar.server.ws.WsTester;
import org.sonar.test.DbTests;
@@ -55,11 +60,22 @@ public class MetricsActionTest {
@Rule
public ExpectedException expectedException = ExpectedException.none();
@ClassRule
+ public static EsTester es = new EsTester().addDefinitions(new UserIndexDefinition(new Settings()));
+ @ClassRule
public static DbTester db = new DbTester();
DbClient dbClient;
DbSession dbSession;
WsTester ws;
+ @BeforeClass
+ public static void setUpClass() throws Exception {
+ es.putDocuments(UserIndexDefinition.INDEX, UserIndexDefinition.TYPE_USER, new UserDoc()
+ .setLogin("login")
+ .setName("Login")
+ .setEmail("login@login.com")
+ .setActive(true));
+ }
+
@Before
public void setUp() {
dbClient = new DbClient(db.database(), db.myBatis(), new MetricDao(), new ComponentDao(), new CustomMeasureDao());
diff --git a/server/sonar-server/src/test/java/org/sonar/server/measure/custom/ws/SearchActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/measure/custom/ws/SearchActionTest.java
new file mode 100644
index 00000000000..be3a25e4c0b
--- /dev/null
+++ b/server/sonar-server/src/test/java/org/sonar/server/measure/custom/ws/SearchActionTest.java
@@ -0,0 +1,274 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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.custom.ws;
+
+import org.apache.commons.lang.StringUtils;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.ClassRule;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.sonar.api.config.Settings;
+import org.sonar.api.measures.Metric.ValueType;
+import org.sonar.api.server.ws.WebService;
+import org.sonar.core.component.ComponentDto;
+import org.sonar.core.measure.custom.db.CustomMeasureDto;
+import org.sonar.core.metric.db.MetricDto;
+import org.sonar.core.persistence.DbSession;
+import org.sonar.core.persistence.DbTester;
+import org.sonar.server.component.ComponentTesting;
+import org.sonar.server.component.db.ComponentDao;
+import org.sonar.server.db.DbClient;
+import org.sonar.server.es.EsTester;
+import org.sonar.server.exceptions.NotFoundException;
+import org.sonar.server.measure.custom.persistence.CustomMeasureDao;
+import org.sonar.server.metric.persistence.MetricDao;
+import org.sonar.server.tester.UserSessionRule;
+import org.sonar.server.user.index.UserDoc;
+import org.sonar.server.user.index.UserIndex;
+import org.sonar.server.user.index.UserIndexDefinition;
+import org.sonar.server.user.ws.UserJsonWriter;
+import org.sonar.server.ws.WsTester;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.sonar.server.measure.custom.persistence.CustomMeasureTesting.newCustomMeasureDto;
+import static org.sonar.server.metric.ws.MetricTesting.newMetricDto;
+
+public class SearchActionTest {
+ private static final String DEFAULT_PROJECT_UUID = "project-uuid";
+ private static final String DEFAULT_PROJECT_KEY = "project-key";
+ private static final String METRIC_KEY_PREFIX = "metric-key-";
+
+ @Rule
+ public ExpectedException expectedException = ExpectedException.none();
+ @Rule
+ public UserSessionRule userSessionRule = UserSessionRule.standalone();
+ @ClassRule
+ public static DbTester db = new DbTester();
+ @ClassRule
+ public static EsTester es = new EsTester().addDefinitions(new UserIndexDefinition(new Settings()));
+ WsTester ws;
+ DbClient dbClient;
+ DbSession dbSession;
+ ComponentDto defaultProject;
+
+ @BeforeClass
+ public static void setUpClass() throws Exception {
+ es.putDocuments(UserIndexDefinition.INDEX, UserIndexDefinition.TYPE_USER, new UserDoc()
+ .setLogin("login")
+ .setName("Login")
+ .setEmail("login@login.com")
+ .setActive(true));
+ }
+
+ @Before
+ public void setUp() {
+ dbClient = new DbClient(db.database(), db.myBatis(), new CustomMeasureDao(), new ComponentDao(), new MetricDao());
+ dbSession = dbClient.openSession(false);
+ db.truncateTables();
+ CustomMeasureJsonWriter customMeasureJsonWriter = new CustomMeasureJsonWriter(new UserJsonWriter(userSessionRule));
+ UserIndex userIndex = new UserIndex(es.client());
+ ws = new WsTester(new CustomMeasuresWs(new SearchAction(dbClient, userIndex, customMeasureJsonWriter)));
+ defaultProject = insertDefaultProject();
+ }
+
+ @After
+ public void tearDown() {
+ dbSession.close();
+ }
+
+ @Test
+ public void json_well_formatted() throws Exception {
+ MetricDto metric1 = insertCustomMetric(1);
+ MetricDto metric2 = insertCustomMetric(2);
+ MetricDto metric3 = insertCustomMetric(3);
+ CustomMeasureDto customMeasure1 = insertCustomMeasure(1, metric1);
+ CustomMeasureDto customMeasure2 = insertCustomMeasure(2, metric2);
+ CustomMeasureDto customMeasure3 = insertCustomMeasure(3, metric3);
+
+ WsTester.Result response = newRequest()
+ .setParam(SearchAction.PARAM_PROJECT_ID, DEFAULT_PROJECT_UUID)
+ .execute();
+
+ response.assertJson(getClass(), "metrics.json");
+ String responseAsString = response.outputAsString();
+ assertThat(responseAsString).matches(nameValuePattern("id", metric1.getId().toString()));
+ assertThat(responseAsString).matches(nameValuePattern("id", metric2.getId().toString()));
+ assertThat(responseAsString).matches(nameValuePattern("id", metric3.getId().toString()));
+ assertThat(responseAsString).matches(nameValuePattern("id", String.valueOf(customMeasure1.getId())));
+ assertThat(responseAsString).matches(nameValuePattern("id", String.valueOf(customMeasure2.getId())));
+ assertThat(responseAsString).matches(nameValuePattern("id", String.valueOf(customMeasure3.getId())));
+ assertThat(responseAsString).contains("createdAt", "updatedAt");
+ }
+
+ @Test
+ public void search_by_project_uuid() throws Exception {
+ MetricDto metric1 = insertCustomMetric(1);
+ MetricDto metric2 = insertCustomMetric(2);
+ MetricDto metric3 = insertCustomMetric(3);
+ insertCustomMeasure(1, metric1);
+ insertCustomMeasure(2, metric2);
+ insertCustomMeasure(3, metric3);
+
+ String response = newRequest()
+ .setParam(SearchAction.PARAM_PROJECT_ID, DEFAULT_PROJECT_UUID)
+ .execute().outputAsString();
+
+ assertThat(response).contains("text-value-1", "text-value-2", "text-value-3");
+ }
+
+ @Test
+ public void search_by_project_key() throws Exception {
+ MetricDto metric1 = insertCustomMetric(1);
+ MetricDto metric2 = insertCustomMetric(2);
+ MetricDto metric3 = insertCustomMetric(3);
+ insertCustomMeasure(1, metric1);
+ insertCustomMeasure(2, metric2);
+ insertCustomMeasure(3, metric3);
+
+ String response = newRequest()
+ .setParam(SearchAction.PARAM_PROJECT_KEY, DEFAULT_PROJECT_KEY)
+ .execute().outputAsString();
+
+ assertThat(response).contains("text-value-1", "text-value-2", "text-value-3");
+ }
+
+ @Test
+ public void search_with_pagination() throws Exception {
+ for (int i = 0; i < 10; i++) {
+ MetricDto metric = insertCustomMetric(i);
+ insertCustomMeasure(i, metric);
+ }
+
+ String response = newRequest()
+ .setParam(SearchAction.PARAM_PROJECT_KEY, DEFAULT_PROJECT_KEY)
+ .setParam(WebService.Param.PAGE, "3")
+ .setParam(WebService.Param.PAGE_SIZE, "4")
+ .execute().outputAsString();
+
+ assertThat(StringUtils.countMatches(response, "text-value")).isEqualTo(2);
+ }
+
+ @Test
+ public void search_with_selectable_fields() throws Exception {
+ MetricDto metric = insertCustomMetric(1);
+ insertCustomMeasure(1, metric);
+
+ String response = newRequest()
+ .setParam(SearchAction.PARAM_PROJECT_KEY, DEFAULT_PROJECT_KEY)
+ .setParam(WebService.Param.FIELDS, "value, description")
+ .execute().outputAsString();
+
+ assertThat(response).contains("id", "value", "description")
+ .doesNotContain("createdAt")
+ .doesNotContain("updatedAt")
+ .doesNotContain("user")
+ .doesNotContain("metric");
+ }
+
+ @Test
+ public void empty_json_when_no_measure() throws Exception {
+ WsTester.Result response = newRequest()
+ .setParam(SearchAction.PARAM_PROJECT_KEY, DEFAULT_PROJECT_KEY)
+ .execute();
+
+ response.assertJson(getClass(), "empty.json");
+ }
+
+ @Test
+ public void fail_when_project_id_and_project_key_provided() throws Exception {
+ expectedException.expect(IllegalArgumentException.class);
+ expectedException.expectMessage("The project id or project key must be provided, not both.");
+
+ newRequest()
+ .setParam(SearchAction.PARAM_PROJECT_ID, DEFAULT_PROJECT_UUID)
+ .setParam(SearchAction.PARAM_PROJECT_KEY, DEFAULT_PROJECT_KEY)
+ .execute();
+ }
+
+ @Test
+ public void fail_when_project_id_nor_project_key_provided() throws Exception {
+ expectedException.expect(IllegalArgumentException.class);
+ expectedException.expectMessage("The project id or project key must be provided, not both.");
+ newRequest().execute();
+ }
+
+ @Test
+ public void fail_when_project_not_found_in_db() throws Exception {
+ expectedException.expect(NotFoundException.class);
+ expectedException.expectMessage("Component with uuid 'wrong-project-uuid' not found");
+
+ newRequest().setParam(SearchAction.PARAM_PROJECT_ID, "wrong-project-uuid").execute();
+ }
+
+ private ComponentDto insertDefaultProject() {
+ return insertProject(DEFAULT_PROJECT_UUID, DEFAULT_PROJECT_KEY);
+ }
+
+ private ComponentDto insertProject(String projectUuid, String projectKey) {
+ ComponentDto project = ComponentTesting.newProjectDto(projectUuid)
+ .setKey(projectKey);
+ dbClient.componentDao().insert(dbSession, project);
+ dbSession.commit();
+
+ return project;
+ }
+
+ private MetricDto insertCustomMetric(int id) {
+ MetricDto metric = newCustomMetric(METRIC_KEY_PREFIX + id);
+ dbClient.metricDao().insert(dbSession, metric);
+ dbSession.commit();
+
+ return metric;
+ }
+
+ private static MetricDto newCustomMetric(String metricKey) {
+ return newMetricDto().setEnabled(true).setUserManaged(true).setKey(metricKey).setValueType(ValueType.STRING.name());
+ }
+
+ private CustomMeasureDto insertCustomMeasure(int id, MetricDto metric) {
+ CustomMeasureDto customMeasure = newCustomMeasure(id, metric);
+ dbClient.customMeasureDao().insert(dbSession, customMeasure);
+ dbSession.commit();
+
+ return customMeasure;
+ }
+
+ private CustomMeasureDto newCustomMeasure(int id, MetricDto metric) {
+ return newCustomMeasureDto()
+ .setUserLogin("login")
+ .setValue(id)
+ .setTextValue("text-value-" + id)
+ .setDescription("description-" + id)
+ .setMetricId(metric.getId())
+ .setComponentUuid(defaultProject.uuid());
+ }
+
+ private WsTester.TestRequest newRequest() {
+ return ws.newGetRequest(CustomMeasuresWs.ENDPOINT, SearchAction.ACTION);
+ }
+
+ private static String nameValuePattern(String name, String value) {
+ return String.format(".*\"%s\"\\s*:\\s*\"%s\".*", name, value);
+ }
+}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/measure/custom/ws/SearchActionTest/empty.json b/server/sonar-server/src/test/resources/org/sonar/server/measure/custom/ws/SearchActionTest/empty.json
new file mode 100644
index 00000000000..07b3a2950c2
--- /dev/null
+++ b/server/sonar-server/src/test/resources/org/sonar/server/measure/custom/ws/SearchActionTest/empty.json
@@ -0,0 +1,7 @@
+{
+ "customMeasures": [
+ ],
+ "p": 1,
+ "ps": 100,
+ "total": 0
+}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/measure/custom/ws/SearchActionTest/metrics.json b/server/sonar-server/src/test/resources/org/sonar/server/measure/custom/ws/SearchActionTest/metrics.json
new file mode 100644
index 00000000000..bf3bd9f8083
--- /dev/null
+++ b/server/sonar-server/src/test/resources/org/sonar/server/measure/custom/ws/SearchActionTest/metrics.json
@@ -0,0 +1,55 @@
+{
+ "customMeasures": [
+ {
+ "description": "description-1",
+ "metric": {
+ "key": "metric-key-1",
+ "type": "STRING"
+ },
+ "projectId": "project-uuid",
+ "projectKey": "project-key",
+ "user": {
+ "active": true,
+ "email": "login@login.com",
+ "login": "login",
+ "name": "Login"
+ },
+ "value": "text-value-1"
+ },
+ {
+ "description": "description-2",
+ "metric": {
+ "key": "metric-key-2",
+ "type": "STRING"
+ },
+ "projectId": "project-uuid",
+ "projectKey": "project-key",
+ "user": {
+ "active": true,
+ "email": "login@login.com",
+ "login": "login",
+ "name": "Login"
+ },
+ "value": "text-value-2"
+ },
+ {
+ "description": "description-3",
+ "metric": {
+ "key": "metric-key-3",
+ "type": "STRING"
+ },
+ "projectId": "project-uuid",
+ "projectKey": "project-key",
+ "user": {
+ "active": true,
+ "email": "login@login.com",
+ "login": "login",
+ "name": "Login"
+ },
+ "value": "text-value-3"
+ }
+ ],
+ "p": 1,
+ "ps": 100,
+ "total": 3
+}
diff --git a/sonar-core/src/main/java/org/sonar/core/measure/custom/db/CustomMeasureMapper.java b/sonar-core/src/main/java/org/sonar/core/measure/custom/db/CustomMeasureMapper.java
index 444753996da..58bbb04b966 100644
--- a/sonar-core/src/main/java/org/sonar/core/measure/custom/db/CustomMeasureMapper.java
+++ b/sonar-core/src/main/java/org/sonar/core/measure/custom/db/CustomMeasureMapper.java
@@ -22,6 +22,7 @@ package org.sonar.core.measure.custom.db;
import java.util.List;
import org.apache.ibatis.annotations.Param;
+import org.apache.ibatis.session.RowBounds;
public interface CustomMeasureMapper {
void insert(CustomMeasureDto customMeasure);
@@ -38,5 +39,9 @@ public interface CustomMeasureMapper {
List<CustomMeasureDto> selectByComponentUuid(String s);
+ List<CustomMeasureDto> selectByComponentUuid(String s, RowBounds rowBounds);
+
+ int countByComponentUuid(String componentUuid);
+
int countByComponentIdAndMetricId(@Param("componentUuid") String componentUuid, @Param("metricId") int metricId);
}
diff --git a/sonar-core/src/main/java/org/sonar/core/metric/db/MetricMapper.java b/sonar-core/src/main/java/org/sonar/core/metric/db/MetricMapper.java
index 7644057f92e..aea1761b828 100644
--- a/sonar-core/src/main/java/org/sonar/core/metric/db/MetricMapper.java
+++ b/sonar-core/src/main/java/org/sonar/core/metric/db/MetricMapper.java
@@ -28,8 +28,14 @@ import org.apache.ibatis.session.RowBounds;
public interface MetricMapper {
+ MetricDto selectById(long id);
+
+ List<MetricDto> selectByIds(@Param("ids") List<Integer> ids);
+
MetricDto selectByKey(@Param("key") String key);
+ List<MetricDto> selectByKeys(@Param("keys") List<String> keys);
+
List<MetricDto> selectAllEnabled();
List<MetricDto> selectAllEnabled(Map<String, Object> properties, RowBounds rowBounds);
@@ -38,8 +44,6 @@ public interface MetricMapper {
List<String> selectDomains();
- List<MetricDto> selectByKeys(@Param("keys") List<String> keys);
-
void disableByIds(@Param("ids") List<Integer> ids);
void disableByKey(@Param("key") String key);
@@ -48,8 +52,6 @@ public interface MetricMapper {
void update(MetricDto metric);
- MetricDto selectById(long id);
-
List<MetricDto> selectAvailableCustomMetricsByComponentUuid(String projectUuid);
List<MetricDto> selectAvailableCustomMetricsByComponentKey(String projectKey);
diff --git a/sonar-core/src/main/resources/org/sonar/core/measure/custom/db/CustomMeasureMapper.xml b/sonar-core/src/main/resources/org/sonar/core/measure/custom/db/CustomMeasureMapper.xml
index e19060dbc1a..8d39aac0143 100644
--- a/sonar-core/src/main/resources/org/sonar/core/measure/custom/db/CustomMeasureMapper.xml
+++ b/sonar-core/src/main/resources/org/sonar/core/measure/custom/db/CustomMeasureMapper.xml
@@ -69,6 +69,12 @@
where id=#{id}
</delete>
+ <select id="countByComponentUuid" resultType="Integer">
+ select count(*)
+ from manual_measures m
+ where m.component_uuid=#{componentUuid}
+ </select>
+
<select id="countByComponentIdAndMetricId" resultType="Integer">
select count(*)
from manual_measures m
diff --git a/sonar-core/src/main/resources/org/sonar/core/metric/db/MetricMapper.xml b/sonar-core/src/main/resources/org/sonar/core/metric/db/MetricMapper.xml
index 3812362721b..f11d214d376 100644
--- a/sonar-core/src/main/resources/org/sonar/core/metric/db/MetricMapper.xml
+++ b/sonar-core/src/main/resources/org/sonar/core/metric/db/MetricMapper.xml
@@ -140,6 +140,18 @@
</where>
</select>
+ <select id="selectByIds" resultType="org.sonar.core.metric.db.MetricDto">
+ SELECT
+ <include refid="metricColumns"/>
+ FROM metrics m
+ <where>
+ AND m.id in
+ <foreach item="id" collection="ids" open="(" separator="," close=")">
+ #{id}
+ </foreach>
+ </where>
+ </select>
+
<select id="selectById" resultType="org.sonar.core.metric.db.MetricDto">
SELECT
<include refid="metricColumns"/>