import java.util.List;
import java.util.Map;
import java.util.Set;
+import javax.annotation.CheckForNull;
import javax.annotation.Nullable;
import org.sonar.api.resources.Qualifiers;
import org.sonar.api.server.ws.Request;
import static com.google.common.collect.FluentIterable.from;
import static java.lang.String.format;
import static java.util.Collections.emptyList;
-import static java.util.Collections.singletonList;
import static org.sonar.core.util.Uuids.UUID_EXAMPLE_01;
import static org.sonar.server.component.ComponentFinder.ParamNames.COMPONENT_ID_AND_KEY;
+import static org.sonar.server.component.ComponentFinder.ParamNames.DEVELOPER_ID_AND_KEY;
import static org.sonar.server.measure.ws.ComponentDtoToWsComponent.componentDtoToWsComponent;
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;
import static org.sonar.server.measure.ws.MetricDtoToWsMetric.metricDtoToWsMetric;
import static org.sonar.server.measure.ws.SnapshotDtoToWsPeriods.snapshotToWsPeriods;
import static org.sonarqube.ws.client.measure.MeasuresWsParameters.PARAM_ADDITIONAL_FIELDS;
import static org.sonarqube.ws.client.measure.MeasuresWsParameters.PARAM_COMPONENT_ID;
import static org.sonarqube.ws.client.measure.MeasuresWsParameters.PARAM_COMPONENT_KEY;
+import static org.sonarqube.ws.client.measure.MeasuresWsParameters.PARAM_DEVELOPER_ID;
+import static org.sonarqube.ws.client.measure.MeasuresWsParameters.PARAM_DEVELOPER_KEY;
import static org.sonarqube.ws.client.measure.MeasuresWsParameters.PARAM_METRIC_KEYS;
public class ComponentAction implements MeasuresWsAction {
createMetricKeysParameter(action);
createAdditionalFieldsParameter(action);
+ createDeveloperParameters(action);
}
@Override
DbSession dbSession = dbClient.openSession(false);
try {
ComponentDto component = componentFinder.getByUuidOrKey(dbSession, request.getComponentId(), request.getComponentKey(), COMPONENT_ID_AND_KEY);
+ Long developerId = searchDeveloperId(dbSession, request);
Optional<ComponentDto> refComponent = getReferenceComponent(dbSession, component);
checkPermissions(component);
SnapshotDto lastSnapshot = dbClient.snapshotDao().selectLastSnapshotByComponentId(dbSession, component.getId());
List<MetricDto> metrics = searchMetrics(dbSession, request);
List<WsMeasures.Period> periods = snapshotToWsPeriods(lastSnapshot);
- List<MeasureDto> measures = searchMeasures(dbSession, component, lastSnapshot, metrics, periods);
+ List<MeasureDto> measures = searchMeasures(dbSession, component, lastSnapshot, metrics, periods, developerId);
return buildResponse(request, component, refComponent, measures, metrics, periods);
} finally {
}
}
+ @CheckForNull
+ private Long searchDeveloperId(DbSession dbSession, ComponentWsRequest request) {
+ if ((request.getDeveloperId() == null && request.getDeveloperKey() == null)) {
+ return null;
+ }
+
+ return componentFinder.getByUuidOrKey(dbSession, request.getDeveloperId(), request.getDeveloperKey(), DEVELOPER_ID_AND_KEY).getId();
+ }
+
private Optional<ComponentDto> getReferenceComponent(DbSession dbSession, ComponentDto component) {
if (component.getCopyResourceId() == null) {
return Optional.absent();
return metrics;
}
- private List<MeasureDto> searchMeasures(DbSession dbSession, ComponentDto component, @Nullable SnapshotDto snapshot, List<MetricDto> metrics, List<WsMeasures.Period> periods) {
+ private List<MeasureDto> searchMeasures(DbSession dbSession, ComponentDto component, @Nullable SnapshotDto snapshot, List<MetricDto> metrics, List<WsMeasures.Period> periods,
+ @Nullable Long developerId) {
if (snapshot == null) {
return emptyList();
}
List<Integer> metricIds = Lists.transform(metrics, MetricDtoFunctions.toId());
- List<MeasureDto> measures = dbClient.measureDao().selectBySnapshotIdsAndMetricIds(dbSession, singletonList(snapshot.getId()), metricIds);
+ List<MeasureDto> measures = dbClient.measureDao().selectByDeveloperForSnapshotAndMetrics(dbSession, developerId, snapshot.getId(), metricIds);
addBestValuesToMeasures(measures, component, metrics, periods);
return measures;
.setComponentId(request.param(PARAM_COMPONENT_ID))
.setComponentKey(request.param(PARAM_COMPONENT_KEY))
.setAdditionalFields(request.paramAsStrings(PARAM_ADDITIONAL_FIELDS))
- .setMetricKeys(request.mandatoryParamAsStrings(PARAM_METRIC_KEYS));
+ .setMetricKeys(request.mandatoryParamAsStrings(PARAM_METRIC_KEYS))
+ .setDeveloperId(request.param(PARAM_DEVELOPER_ID))
+ .setDeveloperKey(request.param(PARAM_DEVELOPER_KEY));
checkRequest(!componentWsRequest.getMetricKeys().isEmpty(), "At least one metric key must be provided");
return componentWsRequest;
}
import org.sonar.server.exceptions.ForbiddenException;
import org.sonar.server.exceptions.NotFoundException;
import org.sonar.server.tester.UserSessionRule;
+import org.sonar.server.ws.TestRequest;
import org.sonar.server.ws.WsActionTester;
import org.sonarqube.ws.MediaTypes;
import org.sonarqube.ws.WsMeasures.ComponentWsResponse;
import static org.assertj.core.api.Assertions.assertThat;
import static org.sonar.api.utils.DateUtils.parseDateTime;
+import static org.sonar.db.component.ComponentTesting.newDeveloper;
import static org.sonar.db.component.ComponentTesting.newFileDto;
import static org.sonar.db.component.ComponentTesting.newProjectCopy;
import static org.sonar.db.component.ComponentTesting.newProjectDto;
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_COMPONENT_ID;
+import static org.sonarqube.ws.client.measure.MeasuresWsParameters.PARAM_DEVELOPER_ID;
+import static org.sonarqube.ws.client.measure.MeasuresWsParameters.PARAM_DEVELOPER_KEY;
import static org.sonarqube.ws.client.measure.MeasuresWsParameters.PARAM_METRIC_KEYS;
-
public class ComponentActionTest {
private static final String PROJECT_UUID = "project-uuid";
assertThat(response.getComponent().getRefKey()).isEqualTo("project-key");
}
+ @Test
+ public void developer_measure_by_developer_uuid() {
+ ComponentDto developer = newDeveloper("developer-name");
+ componentDb.insertDeveloperAndSnapshot(developer);
+ ComponentDto project = newProjectDto("project-uuid");
+ SnapshotDto projectSnapshot = componentDb.insertProjectAndSnapshot(project);
+ ComponentDto file = newFileDto(project, "file-uuid");
+ SnapshotDto fileSnapshot = componentDb.insertComponentAndSnapshot(file, projectSnapshot);
+ MetricDto ncloc = insertNclocMetric();
+ dbClient.measureDao().insert(dbSession,
+ newMeasureDto(ncloc, fileSnapshot.getId()).setValue(42.0d).setDeveloperId(null),
+ newMeasureDto(ncloc, fileSnapshot.getId()).setValue(1984.0d).setDeveloperId(developer.getId()));
+ db.commit();
+
+ ComponentWsResponse result = call(ws.newRequest()
+ .setParam(PARAM_COMPONENT_ID, "file-uuid")
+ .setParam(PARAM_DEVELOPER_ID, developer.uuid())
+ .setParam(PARAM_METRIC_KEYS, "ncloc"));
+
+ assertThat(result.getComponent().getMeasuresCount()).isEqualTo(1);
+ assertThat(result.getComponent().getMeasures(0).getValue()).isEqualTo("1984");
+ }
+
+ @Test
+ public void developer_measure_by_developer_key() {
+ ComponentDto developer = newDeveloper("developer-name");
+ componentDb.insertDeveloperAndSnapshot(developer);
+ ComponentDto project = newProjectDto(PROJECT_UUID);
+ SnapshotDto projectSnapshot = componentDb.insertProjectAndSnapshot(project);
+ ComponentDto file = newFileDto(project, "file-uuid");
+ SnapshotDto fileSnapshot = componentDb.insertComponentAndSnapshot(file, projectSnapshot);
+ MetricDto ncloc = insertNclocMetric();
+ dbClient.measureDao().insert(dbSession,
+ newMeasureDto(ncloc, fileSnapshot.getId()).setValue(42.0d).setDeveloperId(null),
+ newMeasureDto(ncloc, fileSnapshot.getId()).setValue(1984.0d).setDeveloperId(developer.getId()));
+ db.commit();
+
+ ComponentWsResponse result = call(ws.newRequest()
+ .setParam(PARAM_COMPONENT_ID, "file-uuid")
+ .setParam(PARAM_DEVELOPER_KEY, developer.key())
+ .setParam(PARAM_METRIC_KEYS, "ncloc"));
+
+ assertThat(result.getComponent().getMeasuresCount()).isEqualTo(1);
+ assertThat(result.getComponent().getMeasures(0).getValue()).isEqualTo("1984");
+ }
+
+ @Test
+ public void fail_when_developer_is_not_found() {
+ expectedException.expect(NotFoundException.class);
+ expectedException.expectMessage("Component id 'unknown-developer-id' not found");
+
+ componentDb.insertProjectAndSnapshot(newProjectDto(PROJECT_UUID));
+ insertNclocMetric();
+
+ call(ws.newRequest()
+ .setParam(PARAM_COMPONENT_ID, PROJECT_UUID)
+ .setParam(PARAM_METRIC_KEYS, "ncloc")
+ .setParam(PARAM_DEVELOPER_ID, "unknown-developer-id")
+ );
+ }
+
@Test
public void fail_when_a_metric_is_not_found() {
componentDb.insertProjectAndSnapshot(newProjectDto(PROJECT_UUID));
}
private ComponentWsResponse newRequest(String componentUuid, String metricKeys) {
- InputStream responseStream = ws.newRequest()
- .setMediaType(MediaTypes.PROTOBUF)
+ return call(ws.newRequest()
.setParam(PARAM_COMPONENT_ID, componentUuid)
.setParam(PARAM_METRIC_KEYS, metricKeys)
- .setParam(PARAM_ADDITIONAL_FIELDS, "metrics,periods")
- .execute()
- .getInputStream();
+ .setParam(PARAM_ADDITIONAL_FIELDS, "metrics,periods"));
+ }
+
+ private ComponentWsResponse call(TestRequest request) {
+ InputStream responseStream = request
+ .setMediaType(MediaTypes.PROTOBUF)
+ .execute().getInputStream();
try {
return ComponentWsResponse.parseFrom(responseStream);
List<MeasureDto> selectBySnapshotAndMetricKeys(@Param("snapshotId") long snapshotId, @Param("metricKeys") List<String> metricKeys);
- List<MeasureDto> selectByDeveloperForSnapshotAndMetrics(@Param("developerId") long developerId, @Param("snapshotId") long snapshotId,
+ List<MeasureDto> selectByDeveloperForSnapshotAndMetrics(@Nullable @Param("developerId") Long developerId, @Param("snapshotId") long snapshotId,
@Param("metricIds") List<Integer> metricIds);
List<MeasureDto> selectBySnapshotAndMetrics(@Param("snapshotId") long snapshotId, @Param("metricIds") List<Integer> input);
FROM project_measures pm
<where>
pm.snapshot_id = #{snapshotId}
- AND pm.person_id = #{developerId}
+ <if test="developerId!=null">
+ AND pm.person_id = #{developerId}
+ </if>
+ <if test="developerId==null">
+ AND pm.person_id is NULL
+ </if>
AND
<foreach item="metricId" index="index" collection="metricIds" open="(" separator=" or " close=")">
pm.metric_id=#{metricId}
private String componentKey;
private List<String> metricKeys;
private List<String> additionalFields;
+ private String developerId;
+ private String developerKey;
@CheckForNull
public String getComponentId() {
this.additionalFields = additionalFields;
return this;
}
+
+ @CheckForNull
+ public String getDeveloperId() {
+ return developerId;
+ }
+
+ public ComponentWsRequest setDeveloperId(@Nullable String developerId) {
+ this.developerId = developerId;
+ return this;
+ }
+
+ @CheckForNull
+ public String getDeveloperKey() {
+ return developerKey;
+ }
+
+ public ComponentWsRequest setDeveloperKey(@Nullable String developerKey) {
+ this.developerKey = developerKey;
+ return this;
+ }
}
.setParam(PARAM_COMPONENT_ID, request.getComponentId())
.setParam(PARAM_COMPONENT_KEY, request.getComponentKey())
.setParam(PARAM_ADDITIONAL_FIELDS, inlineMultipleParamValue(request.getAdditionalFields()))
- .setParam(PARAM_METRIC_KEYS, inlineMultipleParamValue(request.getMetricKeys()));
+ .setParam(PARAM_METRIC_KEYS, inlineMultipleParamValue(request.getMetricKeys()))
+ .setParam(PARAM_DEVELOPER_ID, request.getDeveloperId())
+ .setParam(PARAM_DEVELOPER_KEY, request.getDeveloperKey());
return call(getRequest, ComponentWsResponse.parser());
}