aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/computation/measure/BatchReportMeasureUtils.java93
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/computation/step/PersistMeasuresStep.java34
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/computation/measure/BatchReportMeasureUtilsTest.java93
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/computation/step/PersistMeasuresStepTest.java140
-rw-r--r--sonar-batch-protocol/src/main/protobuf/batch_report.proto1
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/index/DuplicationPersister.java74
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/index/MeasurePersister.java134
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/phases/DatabaseModePhaseExecutor.java23
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/report/IssuesPublisher.java13
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/report/MeasuresPublisher.java203
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/scan/ModuleScanContainer.java2
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/scan/ProjectScanContainer.java2
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/index/DuplicationPersisterTest.java94
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/index/MeasurePersisterTest.java222
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/phases/DatabaseModePhaseExecutorTest.java53
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/report/MeasuresPublisherTest.java163
-rw-r--r--sonar-batch/src/test/resources/org/sonar/batch/index/DuplicationPersisterTest/empty.xml2
-rw-r--r--sonar-batch/src/test/resources/org/sonar/batch/index/DuplicationPersisterTest/shouldInsertDuplication-result.xml13
-rw-r--r--sonar-batch/src/test/resources/org/sonar/batch/index/MeasurePersisterTest/data.xml21
-rw-r--r--sonar-batch/src/test/resources/org/sonar/batch/index/MeasurePersisterTest/empty.xml2
-rw-r--r--sonar-batch/src/test/resources/org/sonar/batch/index/MeasurePersisterTest/shouldAddDelayedMeasureSeveralTimes-result.xml10
-rw-r--r--sonar-batch/src/test/resources/org/sonar/batch/index/MeasurePersisterTest/shouldAlwaysPersistNonFileMeasures-result.xml16
-rw-r--r--sonar-batch/src/test/resources/org/sonar/batch/index/MeasurePersisterTest/shouldDelaySaving-result.xml18
-rw-r--r--sonar-batch/src/test/resources/org/sonar/batch/index/MeasurePersisterTest/shouldInsertMeasure-result.xml10
-rw-r--r--sonar-batch/src/test/resources/org/sonar/batch/index/MeasurePersisterTest/shouldInsertMeasureWithLargeData-result.xml11
-rw-r--r--sonar-batch/src/test/resources/org/sonar/batch/index/MeasurePersisterTest/shouldInsertRuleMeasure-result.xml10
-rw-r--r--sonar-core/src/main/java/org/sonar/core/persistence/MyBatis.java2
-rw-r--r--sonar-core/src/main/resources/org/sonar/core/measure/db/MeasureMapper.xml2
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/database/model/MeasureMapper.java26
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/measures/CoreMetrics.java2
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/measures/Measure.java16
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/measures/Metric.java11
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/measures/RuleMeasure.java4
-rw-r--r--sonar-plugin-api/src/main/resources/org/sonar/api/database/model/MeasureMapper.xml43
34 files changed, 554 insertions, 1009 deletions
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/measure/BatchReportMeasureUtils.java b/server/sonar-server/src/main/java/org/sonar/server/computation/measure/BatchReportMeasureUtils.java
deleted file mode 100644
index 54b224a9651..00000000000
--- a/server/sonar-server/src/main/java/org/sonar/server/computation/measure/BatchReportMeasureUtils.java
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * 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.computation.measure;
-
-import org.sonar.batch.protocol.output.BatchReport;
-
-import javax.annotation.CheckForNull;
-
-public class BatchReportMeasureUtils {
- private BatchReportMeasureUtils() {
- // static methods only
- }
-
- /**
- * return the numerical value as a double. It's the type used in db.
- * Returns null if no numerical value found
- */
- @CheckForNull
- public static Double valueAsDouble(BatchReport.Measure measure) {
- switch (measure.getValueType()) {
- case BOOLEAN:
- return measure.getBooleanValue() ? 1.0d : 0.0d;
- case INT:
- return Double.valueOf(measure.getIntValue());
- case LONG:
- return Double.valueOf(measure.getLongValue());
- case DOUBLE:
- return measure.getDoubleValue();
- default:
- return null;
- }
- }
-
- /**
- * check that measure has a value (numerical or string) and a metric key
- */
- public static void checkMeasure(BatchReport.Measure measure) {
- if (!hasValueTypeAndMetricKey(measure)) {
- throw newIllegalStateException(measure);
- }
-
- boolean hasValueOrData;
- switch (measure.getValueType()) {
- case DOUBLE:
- hasValueOrData = measure.hasDoubleValue();
- break;
- case INT:
- hasValueOrData = measure.hasIntValue();
- break;
- case LONG:
- hasValueOrData = measure.hasLongValue();
- break;
- case STRING:
- hasValueOrData = measure.hasStringValue();
- break;
- case BOOLEAN:
- hasValueOrData = measure.hasBooleanValue();
- break;
- default:
- throw newIllegalStateException(measure);
- }
-
- if (!hasValueOrData) {
- throw newIllegalStateException(measure);
- }
- }
-
- private static boolean hasValueTypeAndMetricKey(BatchReport.Measure measure) {
- return measure.hasValueType() && measure.hasMetricKey();
- }
-
- private static IllegalStateException newIllegalStateException(BatchReport.Measure measure) {
- return new IllegalStateException(String.format("Measure %s does not have value", measure));
- }
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/step/PersistMeasuresStep.java b/server/sonar-server/src/main/java/org/sonar/server/computation/step/PersistMeasuresStep.java
index 4991bab9b7c..4c10a8be07d 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/computation/step/PersistMeasuresStep.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/computation/step/PersistMeasuresStep.java
@@ -34,10 +34,9 @@ import org.sonar.server.computation.issue.RuleCache;
import org.sonar.server.computation.measure.MetricCache;
import org.sonar.server.db.DbClient;
-import java.util.List;
+import javax.annotation.CheckForNull;
-import static org.sonar.server.computation.measure.BatchReportMeasureUtils.checkMeasure;
-import static org.sonar.server.computation.measure.BatchReportMeasureUtils.valueAsDouble;
+import java.util.List;
public class PersistMeasuresStep implements ComputationStep {
@@ -95,7 +94,12 @@ public class PersistMeasuresStep implements ComputationStep {
@VisibleForTesting
MeasureDto toMeasureDto(BatchReport.Measure in, BatchReport.Component component) {
- checkMeasure(in);
+ if (!in.hasValueType()) {
+ throw new IllegalStateException(String.format("Measure %s does not have value type", in));
+ }
+ if (!in.hasMetricKey()) {
+ throw new IllegalStateException(String.format("Measure %s does not have metric key", in));
+ }
MeasureDto out = new MeasureDto();
out.setTendency(in.hasTendency() ? in.getTendency() : null);
@@ -111,13 +115,33 @@ public class PersistMeasuresStep implements ComputationStep {
out.setComponentId(component.getId());
out.setSnapshotId(component.getSnapshotId());
out.setMetricId(metricCache.get(in.getMetricKey()).getId());
- out.setRuleId(ruleCache.get(RuleKey.parse(in.getRuleKey())).getId());
+ out.setRuleId(in.hasRuleKey() ? ruleCache.get(RuleKey.parse(in.getRuleKey())).getId() : null);
out.setCharacteristicId(in.hasCharactericId() ? in.getCharactericId() : null);
out.setValue(valueAsDouble(in));
setData(in, out);
return out;
}
+ /**
+ * return the numerical value as a double. It's the type used in db.
+ * Returns null if no numerical value found
+ */
+ @CheckForNull
+ private static Double valueAsDouble(BatchReport.Measure measure) {
+ switch (measure.getValueType()) {
+ case BOOLEAN:
+ return measure.hasBooleanValue() ? (measure.getBooleanValue() ? 1.0d : 0.0d) : null;
+ case INT:
+ return measure.hasIntValue() ? Double.valueOf(measure.getIntValue()) : null;
+ case LONG:
+ return measure.hasLongValue() ? Double.valueOf(measure.getLongValue()) : null;
+ case DOUBLE:
+ return measure.hasDoubleValue() ? measure.getDoubleValue() : null;
+ default:
+ return null;
+ }
+ }
+
private MeasureDto setData(BatchReport.Measure in, MeasureDto out) {
if (in.hasStringValue()) {
out.setData(in.getStringValue());
diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/measure/BatchReportMeasureUtilsTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/measure/BatchReportMeasureUtilsTest.java
deleted file mode 100644
index 6d743fa2757..00000000000
--- a/server/sonar-server/src/test/java/org/sonar/server/computation/measure/BatchReportMeasureUtilsTest.java
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * 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.computation.measure;
-
-import org.junit.Test;
-import org.sonar.batch.protocol.Constants;
-import org.sonar.batch.protocol.output.BatchReport;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.sonar.batch.protocol.Constants.MeasureValueType.*;
-import static org.sonar.server.computation.measure.BatchReportMeasureUtils.checkMeasure;
-import static org.sonar.server.computation.measure.BatchReportMeasureUtils.valueAsDouble;
-
-public class BatchReportMeasureUtilsTest {
-
- @Test(expected = IllegalStateException.class)
- public void fail_when_no_metric_key() throws Exception {
- BatchReport.Measure measure = BatchReport.Measure.newBuilder()
- .setValueType(STRING)
- .setStringValue("string-value")
- .build();
-
- checkMeasure(measure);
- }
-
- @Test(expected = IllegalStateException.class)
- public void fail_when_no_value() throws Exception {
- BatchReport.Measure measure = BatchReport.Measure.newBuilder()
- .setMetricKey("repo:metric-key")
- .build();
-
- checkMeasure(measure);
- }
-
- @Test(expected = IllegalStateException.class)
- public void fail_when_no_consistency_between_string_value_and_numerical_value_type() throws Exception {
- BatchReport.Measure measure = BatchReport.Measure.newBuilder()
- .setValueType(DOUBLE)
- .setStringValue("string-value")
- .build();
-
- checkMeasure(measure);
- }
-
- @Test(expected = IllegalStateException.class)
- public void fail_when_no_consistence_between_numerical_value_types() throws Exception {
- BatchReport.Measure measure = BatchReport.Measure.newBuilder()
- .setValueType(DOUBLE)
- .setIntValue(3)
- .build();
-
- checkMeasure(measure);
- }
-
- @Test
- public void validate_all_value_type_without_exception_thrown() throws Exception {
- checkMeasure(newBuilder().setValueType(STRING).setStringValue("string-value").build());
- checkMeasure(newBuilder().setValueType(DOUBLE).setDoubleValue(1.0d).build());
- checkMeasure(newBuilder().setValueType(Constants.MeasureValueType.INT).setIntValue(1).build());
- checkMeasure(newBuilder().setValueType(Constants.MeasureValueType.LONG).setLongValue(2L).build());
- checkMeasure(newBuilder().setValueType(BOOLEAN).setBooleanValue(true).build());
- }
-
- @Test
- public void value_type_as_double_correct_for_all_numerical_types() throws Exception {
- assertThat(valueAsDouble(newBuilder().setBooleanValue(true).setValueType(BOOLEAN).build())).isEqualTo(1.0d);
- assertThat(valueAsDouble(newBuilder().setIntValue(2).setValueType(INT).build())).isEqualTo(2.0d);
- assertThat(valueAsDouble(newBuilder().setLongValue(3L).setValueType(LONG).build())).isEqualTo(3.0d);
- assertThat(valueAsDouble(newBuilder().setDoubleValue(4.4d).setValueType(DOUBLE).build())).isEqualTo(4.4d);
- }
-
- private BatchReport.Measure.Builder newBuilder() {
- return BatchReport.Measure.newBuilder().setMetricKey("repo:metric-key");
- }
-} \ No newline at end of file
diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/step/PersistMeasuresStepTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/step/PersistMeasuresStepTest.java
index 0e5aea549c7..1925596643d 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/computation/step/PersistMeasuresStepTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/computation/step/PersistMeasuresStepTest.java
@@ -30,6 +30,7 @@ import org.mockito.Mockito;
import org.sonar.api.rule.RuleKey;
import org.sonar.api.rule.Severity;
import org.sonar.batch.protocol.Constants;
+import org.sonar.batch.protocol.Constants.MeasureValueType;
import org.sonar.batch.protocol.output.BatchReport;
import org.sonar.batch.protocol.output.BatchReportReader;
import org.sonar.batch.protocol.output.BatchReportWriter;
@@ -49,7 +50,10 @@ import java.util.Date;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Matchers.any;
-import static org.mockito.Mockito.*;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
public class PersistMeasuresStepTest extends BaseStepTest {
@@ -63,6 +67,8 @@ public class PersistMeasuresStepTest extends BaseStepTest {
PersistMeasuresStep sut;
+ private BatchReport.Component component;
+
@Before
public void setUp() throws Exception {
dbClient = mock(DbClient.class, Mockito.RETURNS_DEEP_STUBS);
@@ -73,6 +79,8 @@ public class PersistMeasuresStepTest extends BaseStepTest {
when(ruleCache.get(any(RuleKey.class)).getId()).thenReturn(987);
sut = new PersistMeasuresStep(dbClient, ruleCache, metricCache);
+
+ component = defaultComponent().build();
}
@Test
@@ -172,8 +180,6 @@ public class PersistMeasuresStepTest extends BaseStepTest {
.setCharactericId(123456)
.build();
- BatchReport.Component component = defaultComponent().build();
-
MeasureDto measure = sut.toMeasureDto(batchMeasure, component);
assertThat(measure).isEqualToComparingFieldByField(expectedFullMeasure());
@@ -183,18 +189,131 @@ public class PersistMeasuresStepTest extends BaseStepTest {
public void map_minimal_batch_measure() throws Exception {
BatchReport.Measure batchMeasure = BatchReport.Measure.newBuilder()
.setValueType(Constants.MeasureValueType.INT)
- .setIntValue(123)
- .setSeverity(Constants.Severity.INFO)
.setMetricKey("metric-key")
- .setRuleKey("repo:rule-key")
.build();
- BatchReport.Component component = defaultComponent()
+ MeasureDto measure = sut.toMeasureDto(batchMeasure, component);
+
+ assertThat(measure).isEqualToComparingFieldByField(expectedMinimalistMeasure());
+ }
+
+ @Test
+ public void map_boolean_batch_measure() throws Exception {
+ BatchReport.Measure batchMeasure = BatchReport.Measure.newBuilder()
+ .setValueType(Constants.MeasureValueType.BOOLEAN)
+ .setBooleanValue(true)
+ .setMetricKey("metric-key")
.build();
MeasureDto measure = sut.toMeasureDto(batchMeasure, component);
- assertThat(measure).isEqualToComparingFieldByField(expectedMinimalistMeasure());
+ assertThat(measure.getValue()).isEqualTo(1.0);
+
+ batchMeasure = BatchReport.Measure.newBuilder()
+ .setValueType(Constants.MeasureValueType.BOOLEAN)
+ .setBooleanValue(false)
+ .setMetricKey("metric-key")
+ .build();
+
+ measure = sut.toMeasureDto(batchMeasure, component);
+
+ assertThat(measure.getValue()).isEqualTo(0.0);
+
+ batchMeasure = BatchReport.Measure.newBuilder()
+ .setValueType(Constants.MeasureValueType.BOOLEAN)
+ .setMetricKey("metric-key")
+ .build();
+
+ measure = sut.toMeasureDto(batchMeasure, component);
+
+ assertThat(measure.getValue()).isNull();
+ }
+
+ @Test
+ public void map_double_batch_measure() throws Exception {
+ BatchReport.Measure batchMeasure = BatchReport.Measure.newBuilder()
+ .setValueType(Constants.MeasureValueType.DOUBLE)
+ .setDoubleValue(3.2)
+ .setMetricKey("metric-key")
+ .build();
+
+ MeasureDto measure = sut.toMeasureDto(batchMeasure, component);
+
+ assertThat(measure.getValue()).isEqualTo(3.2);
+
+ batchMeasure = BatchReport.Measure.newBuilder()
+ .setValueType(Constants.MeasureValueType.DOUBLE)
+ .setMetricKey("metric-key")
+ .build();
+
+ measure = sut.toMeasureDto(batchMeasure, component);
+
+ assertThat(measure.getValue()).isNull();
+ }
+
+ @Test
+ public void map_int_batch_measure() throws Exception {
+ BatchReport.Measure batchMeasure = BatchReport.Measure.newBuilder()
+ .setValueType(Constants.MeasureValueType.INT)
+ .setIntValue(3)
+ .setMetricKey("metric-key")
+ .build();
+
+ MeasureDto measure = sut.toMeasureDto(batchMeasure, component);
+
+ assertThat(measure.getValue()).isEqualTo(3.0);
+
+ batchMeasure = BatchReport.Measure.newBuilder()
+ .setValueType(Constants.MeasureValueType.INT)
+ .setMetricKey("metric-key")
+ .build();
+
+ measure = sut.toMeasureDto(batchMeasure, component);
+
+ assertThat(measure.getValue()).isNull();
+ }
+
+ @Test
+ public void map_long_batch_measure() throws Exception {
+ BatchReport.Measure batchMeasure = BatchReport.Measure.newBuilder()
+ .setValueType(Constants.MeasureValueType.LONG)
+ .setLongValue(3L)
+ .setMetricKey("metric-key")
+ .build();
+
+ MeasureDto measure = sut.toMeasureDto(batchMeasure, component);
+
+ assertThat(measure.getValue()).isEqualTo(3.0);
+
+ batchMeasure = BatchReport.Measure.newBuilder()
+ .setValueType(Constants.MeasureValueType.LONG)
+ .setMetricKey("metric-key")
+ .build();
+
+ measure = sut.toMeasureDto(batchMeasure, component);
+
+ assertThat(measure.getValue()).isNull();
+ }
+
+ @Test(expected = IllegalStateException.class)
+ public void fail_when_no_metric_key() throws Exception {
+ BatchReport.Measure measure = BatchReport.Measure.newBuilder()
+ .setValueType(MeasureValueType.STRING)
+ .setStringValue("string-value")
+ .build();
+ BatchReport.Component component = defaultComponent()
+ .build();
+ sut.toMeasureDto(measure, component);
+ }
+
+ @Test(expected = IllegalStateException.class)
+ public void fail_when_no_value() throws Exception {
+ BatchReport.Measure measure = BatchReport.Measure.newBuilder()
+ .setMetricKey("repo:metric-key")
+ .build();
+ BatchReport.Component component = defaultComponent()
+ .build();
+ sut.toMeasureDto(measure, component);
}
private MeasureDto expectedFullMeasure() {
@@ -221,10 +340,7 @@ public class PersistMeasuresStepTest extends BaseStepTest {
return new MeasureDto()
.setComponentId(2L)
.setSnapshotId(3L)
- .setValue(123d)
- .setSeverity(Severity.INFO)
- .setMetricId(654)
- .setRuleId(987);
+ .setMetricId(654);
}
@Override
diff --git a/sonar-batch-protocol/src/main/protobuf/batch_report.proto b/sonar-batch-protocol/src/main/protobuf/batch_report.proto
index 32ac04440f2..0d4a34998cb 100644
--- a/sonar-batch-protocol/src/main/protobuf/batch_report.proto
+++ b/sonar-batch-protocol/src/main/protobuf/batch_report.proto
@@ -84,6 +84,7 @@ message Component {
message Measure {
optional MeasureValueType value_type = 1;
+ # all values may be unset for "new_xxx" measures (only variations are populated)
optional bool boolean_value = 2;
optional int32 int_value = 3;
optional int64 long_value = 4;
diff --git a/sonar-batch/src/main/java/org/sonar/batch/index/DuplicationPersister.java b/sonar-batch/src/main/java/org/sonar/batch/index/DuplicationPersister.java
deleted file mode 100644
index cf5e56ea5a3..00000000000
--- a/sonar-batch/src/main/java/org/sonar/batch/index/DuplicationPersister.java
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * 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.batch.index;
-
-import org.sonar.api.batch.sensor.duplication.internal.DefaultDuplication;
-import org.sonar.api.database.model.MeasureMapper;
-import org.sonar.api.database.model.MeasureModel;
-import org.sonar.api.measures.CoreMetrics;
-import org.sonar.api.measures.Measure;
-import org.sonar.api.measures.Metric;
-import org.sonar.api.measures.MetricFinder;
-import org.sonar.api.measures.PersistenceMode;
-import org.sonar.api.rules.RuleFinder;
-import org.sonar.batch.duplication.DuplicationCache;
-import org.sonar.batch.duplication.DuplicationUtils;
-import org.sonar.core.persistence.DbSession;
-import org.sonar.core.persistence.MyBatis;
-
-public final class DuplicationPersister implements ScanPersister {
- private final MyBatis mybatis;
- private final RuleFinder ruleFinder;
- private final ResourceCache resourceCache;
- private final DuplicationCache duplicationCache;
- private final MetricFinder metricFinder;
-
- public DuplicationPersister(MyBatis mybatis, RuleFinder ruleFinder, ResourceCache resourceCache,
- DuplicationCache duplicationCache, MetricFinder metricFinder) {
- this.mybatis = mybatis;
- this.ruleFinder = ruleFinder;
- this.resourceCache = resourceCache;
- this.duplicationCache = duplicationCache;
- this.metricFinder = metricFinder;
- }
-
- @Override
- public void persist() {
- // Don't use batch insert for duplications since keeping all data in memory can produce OOM
- try (DbSession session = mybatis.openSession(false)) {
- MeasureMapper mapper = session.getMapper(MeasureMapper.class);
- Metric duplicationMetricWithId = metricFinder.findByKey(CoreMetrics.DUPLICATIONS_DATA_KEY);
- for (String effectiveKey : duplicationCache.componentKeys()) {
- Iterable<DefaultDuplication> dups = duplicationCache.byComponent(effectiveKey);
- Measure measure = new Measure(duplicationMetricWithId, DuplicationUtils.toXml(dups)).setPersistenceMode(PersistenceMode.DATABASE);
- BatchResource batchResource = resourceCache.get(effectiveKey);
-
- if (MeasurePersister.shouldPersistMeasure(batchResource.resource(), measure)) {
- MeasureModel measureModel = MeasurePersister.model(measure, ruleFinder).setSnapshotId(batchResource.snapshotId());
- mapper.insert(measureModel);
- session.commit();
- }
- }
- } catch (Exception e) {
- throw new IllegalStateException("Unable to save some measures", e);
- }
- }
-
-}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/index/MeasurePersister.java b/sonar-batch/src/main/java/org/sonar/batch/index/MeasurePersister.java
deleted file mode 100644
index 6559b0a7f7f..00000000000
--- a/sonar-batch/src/main/java/org/sonar/batch/index/MeasurePersister.java
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * 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.batch.index;
-
-import com.google.common.annotations.VisibleForTesting;
-import org.sonar.api.database.model.MeasureMapper;
-import org.sonar.api.database.model.MeasureModel;
-import org.sonar.api.measures.Measure;
-import org.sonar.api.measures.MetricFinder;
-import org.sonar.api.measures.RuleMeasure;
-import org.sonar.api.resources.Resource;
-import org.sonar.api.resources.ResourceUtils;
-import org.sonar.api.rule.RuleKey;
-import org.sonar.api.rules.Rule;
-import org.sonar.api.rules.RuleFinder;
-import org.sonar.api.technicaldebt.batch.Characteristic;
-import org.sonar.batch.index.Cache.Entry;
-import org.sonar.batch.scan.measure.MeasureCache;
-import org.sonar.core.persistence.DbSession;
-import org.sonar.core.persistence.MyBatis;
-
-import javax.annotation.Nullable;
-
-public class MeasurePersister implements ScanPersister {
- private final MyBatis mybatis;
- private final RuleFinder ruleFinder;
- private final MeasureCache measureCache;
- private final ResourceCache resourceCache;
- private final MetricFinder metricFinder;
-
- public MeasurePersister(MyBatis mybatis, RuleFinder ruleFinder, MetricFinder metricFinder,
- MeasureCache measureCache, ResourceCache resourceCache) {
- this.mybatis = mybatis;
- this.ruleFinder = ruleFinder;
- this.metricFinder = metricFinder;
- this.measureCache = measureCache;
- this.resourceCache = resourceCache;
- }
-
- @Override
- public void persist() {
- try (DbSession session = mybatis.openSession(true)) {
- MeasureMapper mapper = session.getMapper(MeasureMapper.class);
-
- for (Entry<Measure> entry : measureCache.entries()) {
- String effectiveKey = entry.key()[0].toString();
- Measure measure = entry.value();
- BatchResource batchResource = resourceCache.get(effectiveKey);
-
- // Reload Metric to have all Hibernate fields populated
- measure.setMetric(metricFinder.findByKey(measure.getMetricKey()));
-
- if (shouldPersistMeasure(batchResource.resource(), measure)) {
- MeasureModel measureModel = model(measure, ruleFinder).setSnapshotId(batchResource.snapshotId());
- mapper.insert(measureModel);
- }
- }
-
- session.commit();
- } catch (Exception e) {
- throw new IllegalStateException("Unable to save some measures", e);
- }
- }
-
- @VisibleForTesting
- static boolean shouldPersistMeasure(@Nullable Resource resource, @Nullable Measure measure) {
- if (resource == null || measure == null) {
- return false;
- }
- return measure.getPersistenceMode().useDatabase() &&
- !(ResourceUtils.isEntity(resource) && measure.isBestValue()) && isMeasureNotEmpty(measure);
- }
-
- private static boolean isMeasureNotEmpty(Measure measure) {
- boolean isNotEmpty = false;
- for (int i = 1; i <= 5; i++) {
- isNotEmpty = isNotEmpty || measure.getVariation(i) != null;
- }
- return measure.getValue() != null || measure.getData() != null
- || isNotEmpty;
- }
-
- static MeasureModel model(Measure measure, RuleFinder ruleFinder) {
- MeasureModel model = new MeasureModel();
- // Assume Metric was reloaded
- model.setMetricId(measure.getMetric().getId());
- model.setDescription(measure.getDescription());
- model.setData(measure.getData());
- model.setAlertStatus(measure.getAlertStatus());
- model.setAlertText(measure.getAlertText());
- model.setTendency(measure.getTendency());
- model.setVariationValue1(measure.getVariation1());
- model.setVariationValue2(measure.getVariation2());
- model.setVariationValue3(measure.getVariation3());
- model.setVariationValue4(measure.getVariation4());
- model.setVariationValue5(measure.getVariation5());
- Characteristic characteristic = measure.getCharacteristic();
- if (characteristic != null) {
- model.setCharacteristicId(characteristic.id());
- }
- model.setPersonId(measure.getPersonId());
- model.setValue(measure.getValue());
- if (measure instanceof RuleMeasure) {
- RuleMeasure ruleMeasure = (RuleMeasure) measure;
- model.setRulePriority(ruleMeasure.getSeverity());
- RuleKey ruleKey = ruleMeasure.ruleKey();
- if (ruleKey != null) {
- Rule ruleWithId = ruleFinder.findByKey(ruleKey);
- if (ruleWithId == null) {
- throw new IllegalStateException("Can not save a measure with unknown rule " + ruleMeasure);
- }
- model.setRuleId(ruleWithId.getId());
- }
- }
- return model;
- }
-}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/phases/DatabaseModePhaseExecutor.java b/sonar-batch/src/main/java/org/sonar/batch/phases/DatabaseModePhaseExecutor.java
index cf54bb43943..13ec298b8d4 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/phases/DatabaseModePhaseExecutor.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/phases/DatabaseModePhaseExecutor.java
@@ -37,11 +37,7 @@ import org.sonar.batch.scan.filesystem.DefaultModuleFileSystem;
import org.sonar.batch.scan.filesystem.FileSystemLogger;
import org.sonar.batch.scan.report.IssuesReports;
-import java.util.ArrayList;
import java.util.Arrays;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.List;
public final class DatabaseModePhaseExecutor implements PhaseExecutor {
@@ -157,31 +153,18 @@ public final class DatabaseModePhaseExecutor implements PhaseExecutor {
private void executePersisters() {
if (!analysisMode.isPreview()) {
LOGGER.info("Store results in database");
- List<ScanPersister> sortedPersisters = sortedPersisters();
- eventBus.fireEvent(new PersistersPhaseEvent(sortedPersisters, true));
- for (ScanPersister persister : sortedPersisters) {
+ eventBus.fireEvent(new PersistersPhaseEvent(Arrays.asList(persisters), true));
+ for (ScanPersister persister : persisters) {
LOGGER.debug("Execute {}", persister.getClass().getName());
eventBus.fireEvent(new PersisterExecutionEvent(persister, true));
persister.persist();
eventBus.fireEvent(new PersisterExecutionEvent(persister, false));
}
- eventBus.fireEvent(new PersistersPhaseEvent(sortedPersisters, false));
+ eventBus.fireEvent(new PersistersPhaseEvent(Arrays.asList(persisters), false));
}
}
- List<ScanPersister> sortedPersisters() {
- // Sort by reverse name so that ResourcePersister is executed before MeasurePersister
- List<ScanPersister> sortedPersisters = new ArrayList<>(Arrays.asList(persisters));
- Collections.sort(sortedPersisters, new Comparator<ScanPersister>() {
- @Override
- public int compare(ScanPersister o1, ScanPersister o2) {
- return o2.getClass().getName().compareTo(o1.getClass().getName());
- }
- });
- return sortedPersisters;
- }
-
private void publishReportJob() {
String stepName = "Publish report";
eventBus.fireEvent(new BatchStepEvent(stepName, true));
diff --git a/sonar-batch/src/main/java/org/sonar/batch/report/IssuesPublisher.java b/sonar-batch/src/main/java/org/sonar/batch/report/IssuesPublisher.java
index 540c3fb723f..640552eccfe 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/report/IssuesPublisher.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/report/IssuesPublisher.java
@@ -58,9 +58,11 @@ public class IssuesPublisher implements ReportPublisher {
String componentKey = resource.resource().getEffectiveKey();
Iterable<DefaultIssue> issues = issueCache.byComponent(componentKey);
writer.writeComponentIssues(resource.batchId(), Iterables.transform(issues, new Function<DefaultIssue, BatchReport.Issue>() {
+ private BatchReport.Issue.Builder builder = BatchReport.Issue.newBuilder();
+
@Override
public BatchReport.Issue apply(DefaultIssue input) {
- return toReportIssue(input);
+ return toReportIssue(builder, input);
}
}));
deletedComponentKeys.remove(componentKey);
@@ -94,9 +96,11 @@ public class IssuesPublisher implements ReportPublisher {
if (iterator.hasNext()) {
String componentUuid = iterator.next().componentUuid();
writer.writeDeletedComponentIssues(deletedComponentCount, componentUuid, Iterables.transform(issues, new Function<DefaultIssue, BatchReport.Issue>() {
+ private BatchReport.Issue.Builder builder = BatchReport.Issue.newBuilder();
+
@Override
public BatchReport.Issue apply(DefaultIssue input) {
- return toReportIssue(input);
+ return toReportIssue(builder, input);
}
}));
}
@@ -104,9 +108,8 @@ public class IssuesPublisher implements ReportPublisher {
return deletedComponentCount;
}
- private BatchReport.Issue toReportIssue(DefaultIssue issue) {
- BatchReport.Issue.Builder builder = BatchReport.Issue.newBuilder();
-
+ private BatchReport.Issue toReportIssue(BatchReport.Issue.Builder builder, DefaultIssue issue) {
+ builder.clear();
// non-null fields
builder.setUuid(issue.key());
builder.setIsNew(issue.isNew());
diff --git a/sonar-batch/src/main/java/org/sonar/batch/report/MeasuresPublisher.java b/sonar-batch/src/main/java/org/sonar/batch/report/MeasuresPublisher.java
new file mode 100644
index 00000000000..ed0b342dba0
--- /dev/null
+++ b/sonar-batch/src/main/java/org/sonar/batch/report/MeasuresPublisher.java
@@ -0,0 +1,203 @@
+/*
+ * 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.batch.report;
+
+import com.google.common.base.Function;
+import com.google.common.collect.Iterables;
+import org.sonar.api.batch.sensor.duplication.internal.DefaultDuplication;
+import org.sonar.api.measures.*;
+import org.sonar.api.measures.Metric.Level;
+import org.sonar.api.measures.Metric.ValueType;
+import org.sonar.api.rule.RuleKey;
+import org.sonar.api.rules.RulePriority;
+import org.sonar.api.technicaldebt.batch.Characteristic;
+import org.sonar.batch.duplication.DuplicationCache;
+import org.sonar.batch.duplication.DuplicationUtils;
+import org.sonar.batch.index.BatchResource;
+import org.sonar.batch.index.ResourceCache;
+import org.sonar.batch.protocol.Constants;
+import org.sonar.batch.protocol.Constants.MeasureValueType;
+import org.sonar.batch.protocol.output.BatchReport;
+import org.sonar.batch.protocol.output.BatchReportWriter;
+import org.sonar.batch.scan.measure.MeasureCache;
+
+import java.io.Serializable;
+import java.util.Arrays;
+
+public class MeasuresPublisher implements ReportPublisher {
+
+ private final ResourceCache resourceCache;
+ private final MeasureCache measureCache;
+ private final DuplicationCache duplicationCache;
+
+ public MeasuresPublisher(ResourceCache resourceCache, MeasureCache measureCache, DuplicationCache duplicationCache) {
+ this.resourceCache = resourceCache;
+ this.measureCache = measureCache;
+ this.duplicationCache = duplicationCache;
+ }
+
+ @Override
+ public void publish(BatchReportWriter writer) {
+ for (BatchResource resource : resourceCache.all()) {
+ Iterable<Measure> batchMeasures = measureCache.byResource(resource.resource());
+ Iterable<org.sonar.batch.protocol.output.BatchReport.Measure> reportMeasures = Iterables.transform(batchMeasures, new Function<Measure, BatchReport.Measure>() {
+ private BatchReport.Measure.Builder builder = BatchReport.Measure.newBuilder();
+
+ @Override
+ public BatchReport.Measure apply(Measure input) {
+ return toReportMeasure(builder, input);
+ }
+ });
+ Iterable<DefaultDuplication> dups = duplicationCache.byComponent(resource.resource().getEffectiveKey());
+ if (dups.iterator().hasNext()) {
+ org.sonar.batch.protocol.output.BatchReport.Measure dupMeasure = toReportMeasure(BatchReport.Measure.newBuilder(), dups);
+ writer.writeComponentMeasures(resource.batchId(), Iterables.concat(Arrays.asList(dupMeasure), reportMeasures));
+ } else {
+ writer.writeComponentMeasures(resource.batchId(), reportMeasures);
+ }
+ }
+ }
+
+ private BatchReport.Measure toReportMeasure(BatchReport.Measure.Builder builder, Iterable<DefaultDuplication> dups) {
+ builder.clear();
+
+ builder.setValueType(MeasureValueType.STRING);
+ builder.setStringValue(DuplicationUtils.toXml(dups));
+ builder.setMetricKey(CoreMetrics.DUPLICATIONS_DATA_KEY);
+ return builder.build();
+ }
+
+ private BatchReport.Measure toReportMeasure(BatchReport.Measure.Builder builder, Measure measure) {
+ builder.clear();
+
+ builder.setValueType(getMeasureValueType(measure.getMetric().getType()));
+ setValueAccordingToType(builder, measure);
+ // Because some numeric measures also have a data (like Sqale rating)
+ String data = measure.getData();
+ if (data != null) {
+ builder.setStringValue(data);
+ }
+ builder.setMetricKey(measure.getMetricKey());
+
+ // temporary fields during development of computation stack
+ String description = measure.getDescription();
+ if (description != null) {
+ builder.setDescription(description);
+ }
+ if (measure instanceof RuleMeasure) {
+ RuleMeasure ruleMeasure = (RuleMeasure) measure;
+ RuleKey ruleKey = ruleMeasure.ruleKey();
+ if (ruleKey != null) {
+ builder.setRuleKey(ruleKey.toString());
+ }
+ RulePriority severity = ruleMeasure.getSeverity();
+ if (severity != null) {
+ builder.setSeverity(Constants.Severity.valueOf(severity.toString()));
+ }
+ }
+ Level alertStatus = measure.getAlertStatus();
+ if (alertStatus != null) {
+ builder.setAlertStatus(alertStatus.toString());
+ }
+ String alertText = measure.getAlertText();
+ if (alertText != null) {
+ builder.setAlertText(alertText);
+ }
+ Double variation1 = measure.getVariation1();
+ if (variation1 != null) {
+ builder.setVariationValue1(variation1);
+ }
+ Double variation2 = measure.getVariation2();
+ if (variation2 != null) {
+ builder.setVariationValue1(variation2);
+ }
+ Double variation3 = measure.getVariation3();
+ if (variation3 != null) {
+ builder.setVariationValue1(variation3);
+ }
+ Double variation4 = measure.getVariation4();
+ if (variation4 != null) {
+ builder.setVariationValue1(variation4);
+ }
+ Double variation5 = measure.getVariation5();
+ if (variation5 != null) {
+ builder.setVariationValue1(variation5);
+ }
+ Integer tendency = measure.getTendency();
+ if (tendency != null) {
+ builder.setTendency(tendency);
+ }
+ Characteristic charac = measure.getCharacteristic();
+ if (charac != null) {
+ builder.setCharactericId(charac.id());
+ }
+ return builder.build();
+ }
+
+ private void setValueAccordingToType(BatchReport.Measure.Builder builder, Measure measure) {
+ Serializable value = measure.value();
+ // Value is null for new_xxx measures where only variations are populated
+ if (value != null) {
+ switch (builder.getValueType()) {
+ case BOOLEAN:
+ builder.setBooleanValue((Boolean) value);
+ break;
+ case DOUBLE:
+ builder.setDoubleValue((Double) value);
+ break;
+ case INT:
+ builder.setIntValue((Integer) value);
+ break;
+ case LONG:
+ builder.setLongValue((Long) value);
+ break;
+ case STRING:
+ builder.setStringValue((String) value);
+ break;
+ default:
+ throw new IllegalStateException("Unknown value type: " + builder.getValueType());
+ }
+ }
+ }
+
+ private MeasureValueType getMeasureValueType(ValueType type) {
+ switch (type) {
+ case INT:
+ case MILLISEC:
+ case RATING:
+ return MeasureValueType.INT;
+ case FLOAT:
+ case PERCENT:
+ return MeasureValueType.DOUBLE;
+ case BOOL:
+ return MeasureValueType.BOOLEAN;
+ case STRING:
+ case DATA:
+ case LEVEL:
+ case DISTRIB:
+ return MeasureValueType.STRING;
+ case WORK_DUR:
+ return MeasureValueType.LONG;
+ default:
+ throw new IllegalStateException("Unknown value type: " + type);
+ }
+ }
+
+}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/ModuleScanContainer.java b/sonar-batch/src/main/java/org/sonar/batch/scan/ModuleScanContainer.java
index a092c3a9f36..aa35effd389 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/scan/ModuleScanContainer.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/scan/ModuleScanContainer.java
@@ -57,6 +57,7 @@ import org.sonar.batch.qualitygate.GenerateQualityGateEvents;
import org.sonar.batch.qualitygate.QualityGateVerifier;
import org.sonar.batch.report.ComponentsPublisher;
import org.sonar.batch.report.IssuesPublisher;
+import org.sonar.batch.report.MeasuresPublisher;
import org.sonar.batch.report.PublishReportJob;
import org.sonar.batch.rule.*;
import org.sonar.batch.scan.filesystem.*;
@@ -116,6 +117,7 @@ public class ModuleScanContainer extends ComponentContainer {
PublishReportJob.class,
ComponentsPublisher.class,
IssuesPublisher.class,
+ MeasuresPublisher.class,
moduleDefinition.getContainerExtensions(),
// file system
diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/ProjectScanContainer.java b/sonar-batch/src/main/java/org/sonar/batch/scan/ProjectScanContainer.java
index 8c4f5e6272d..ffa93f69285 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/scan/ProjectScanContainer.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/scan/ProjectScanContainer.java
@@ -192,8 +192,6 @@ public class ProjectScanContainer extends ComponentContainer {
private void addDataBaseComponents() {
add(
- MeasurePersister.class,
- DuplicationPersister.class,
ResourcePersister.class,
SourcePersister.class,
ResourceKeyMigration.class,
diff --git a/sonar-batch/src/test/java/org/sonar/batch/index/DuplicationPersisterTest.java b/sonar-batch/src/test/java/org/sonar/batch/index/DuplicationPersisterTest.java
deleted file mode 100644
index c12eee78b4c..00000000000
--- a/sonar-batch/src/test/java/org/sonar/batch/index/DuplicationPersisterTest.java
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * 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.batch.index;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
-import org.sonar.api.batch.sensor.duplication.Duplication;
-import org.sonar.api.batch.sensor.duplication.internal.DefaultDuplication;
-import org.sonar.api.database.model.Snapshot;
-import org.sonar.api.measures.CoreMetrics;
-import org.sonar.api.measures.MetricFinder;
-import org.sonar.api.resources.File;
-import org.sonar.api.rules.RuleFinder;
-import org.sonar.batch.duplication.DuplicationCache;
-import org.sonar.core.persistence.AbstractDaoTestCase;
-
-import java.util.Arrays;
-
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-public class DuplicationPersisterTest extends AbstractDaoTestCase {
-
- @org.junit.Rule
- public ExpectedException thrown = ExpectedException.none();
-
- public static final int FILE_SNAPSHOT_ID = 3003;
-
- DuplicationPersister duplicationPersister;
- RuleFinder ruleFinder = mock(RuleFinder.class);
- File aFile = File.create("org/foo/Bar.java");
- Snapshot fileSnapshot = snapshot(FILE_SNAPSHOT_ID);
-
- private DuplicationCache duplicationCache;
-
- @Before
- public void mockResourcePersister() {
- duplicationCache = mock(DuplicationCache.class);
-
- ResourceCache resourceCache = mock(ResourceCache.class);
- BatchResource batchResource = mock(BatchResource.class);
- when(batchResource.resource()).thenReturn(aFile);
- when(batchResource.snapshotId()).thenReturn(FILE_SNAPSHOT_ID);
- when(resourceCache.get("foo:org/foo/Bar.java")).thenReturn(batchResource);
-
- MetricFinder metricFinder = mock(MetricFinder.class);
- when(metricFinder.findByKey(CoreMetrics.DUPLICATIONS_DATA_KEY)).thenReturn(CoreMetrics.DUPLICATIONS_DATA.setId(2));
-
- duplicationPersister = new DuplicationPersister(getMyBatis(), ruleFinder, resourceCache, duplicationCache, metricFinder);
- }
-
- @Test
- public void should_insert_duplications() {
- setupData("empty");
-
- Duplication.Block originBlock = new Duplication.Block("foo:org/foo/Bar.java", 1, 4);
-
- DefaultDuplication group = new DefaultDuplication().setOriginBlock(originBlock);
- group.duplicates().add(new Duplication.Block("foo:org/foo/Foo.java", 5, 9));
-
- when(duplicationCache.componentKeys()).thenReturn(Arrays.asList("foo:org/foo/Bar.java"));
-
- when(duplicationCache.byComponent("foo:org/foo/Bar.java")).thenReturn(Arrays.asList(group));
-
- duplicationPersister.persist();
-
- checkTables("shouldInsertDuplication", "project_measures");
- }
-
- private static Snapshot snapshot(int id) {
- Snapshot snapshot = mock(Snapshot.class);
- when(snapshot.getId()).thenReturn(id);
- return snapshot;
- }
-
-}
diff --git a/sonar-batch/src/test/java/org/sonar/batch/index/MeasurePersisterTest.java b/sonar-batch/src/test/java/org/sonar/batch/index/MeasurePersisterTest.java
deleted file mode 100644
index fb59aa4d0a5..00000000000
--- a/sonar-batch/src/test/java/org/sonar/batch/index/MeasurePersisterTest.java
+++ /dev/null
@@ -1,222 +0,0 @@
-/*
- * 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.batch.index;
-
-import org.apache.commons.lang.StringUtils;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
-import org.sonar.api.database.model.Snapshot;
-import org.sonar.api.measures.CoreMetrics;
-import org.sonar.api.measures.Measure;
-import org.sonar.api.measures.Metric;
-import org.sonar.api.measures.MetricFinder;
-import org.sonar.api.measures.PersistenceMode;
-import org.sonar.api.measures.RuleMeasure;
-import org.sonar.api.resources.Directory;
-import org.sonar.api.resources.File;
-import org.sonar.api.resources.Project;
-import org.sonar.api.resources.Resource;
-import org.sonar.api.rules.Rule;
-import org.sonar.api.rules.RuleFinder;
-import org.sonar.api.rules.RulePriority;
-import org.sonar.batch.scan.measure.MeasureCache;
-import org.sonar.core.persistence.AbstractDaoTestCase;
-
-import java.util.Arrays;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-public class MeasurePersisterTest extends AbstractDaoTestCase {
-
- @org.junit.Rule
- public ExpectedException thrown = ExpectedException.none();
-
- private static final String TOO_LONG_FOR_VARCHAR_4000 = StringUtils.repeat("0123456789", 401);
-
- public static final int PROJECT_SNAPSHOT_ID = 3001;
- public static final int PACKAGE_SNAPSHOT_ID = 3002;
- public static final int FILE_SNAPSHOT_ID = 3003;
- public static final int COVERAGE_METRIC_ID = 2;
-
- MeasurePersister measurePersister;
- RuleFinder ruleFinder = mock(RuleFinder.class);
- Project project = new Project("foo");
- Directory aDirectory = Directory.create("org/foo");
- File aFile = File.create("org/foo/Bar.java");
- BatchResource projectResource = batchResource(project, PROJECT_SNAPSHOT_ID);
- BatchResource dirResource = batchResource(aDirectory, PACKAGE_SNAPSHOT_ID);
- BatchResource fileResource = batchResource(aFile, FILE_SNAPSHOT_ID);
- MeasureCache measureCache;
-
- @Before
- public void mockResourcePersister() {
- measureCache = mock(MeasureCache.class);
- ResourceCache resourceCache = mock(ResourceCache.class);
- when(resourceCache.get("foo")).thenReturn(projectResource);
- when(resourceCache.get("foo:org/foo/Bar.java")).thenReturn(fileResource);
- when(resourceCache.get("foo:org/foo")).thenReturn(dirResource);
-
- MetricFinder metricFinder = mock(MetricFinder.class);
- Metric ncloc = ncloc();
- Metric coverage = coverage();
- when(metricFinder.findByKey(ncloc.getKey())).thenReturn(ncloc);
- when(metricFinder.findByKey(coverage.getKey())).thenReturn(coverage);
-
- measurePersister = new MeasurePersister(getMyBatis(), ruleFinder, metricFinder, measureCache, resourceCache);
- }
-
- @Test
- public void should_insert_measure() {
- setupData("empty");
-
- Measure measure = new Measure(ncloc()).setValue(1234.0);
- when(measureCache.entries()).thenReturn(Arrays.asList(new Cache.Entry<Measure>(new String[] {"foo", "ncloc"}, measure)));
- measurePersister.persist();
-
- checkTables("shouldInsertMeasure", "project_measures");
- }
-
- @Test
- public void should_display_message_when_error_during_insert_measure() {
- setupData("empty");
-
- Measure measure = new Measure(ncloc()).setValue(1234.0).setAlertText(TOO_LONG_FOR_VARCHAR_4000);
- when(measureCache.entries()).thenReturn(Arrays.asList(new Cache.Entry<Measure>(new String[] {"foo", "ncloc"}, measure)));
-
- thrown.expect(IllegalStateException.class);
- thrown.expectMessage("Unable to save some measures");
-
- measurePersister.persist();
- }
-
- @Test
- public void should_insert_rule_measure() {
- setupData("empty");
-
- Rule rule = Rule.create("pmd", "key");
- when(ruleFinder.findByKey(rule.ruleKey())).thenReturn(rule);
-
- Measure measure = new RuleMeasure(ncloc(), rule, RulePriority.MAJOR, 1).setValue(1234.0);
- when(measureCache.entries()).thenReturn(Arrays.asList(new Cache.Entry<Measure>(new String[] {"foo", "ncloc"}, measure)));
-
- measurePersister.persist();
-
- checkTables("shouldInsertRuleMeasure", "project_measures");
- }
-
- @Test
- public void should_insert_measure_with_text_data() {
- setupData("empty");
-
- Measure withLargeData = new Measure(ncloc()).setData(TOO_LONG_FOR_VARCHAR_4000);
- when(measureCache.entries()).thenReturn(Arrays.asList(new Cache.Entry<Measure>(new String[] {"foo", "ncloc"}, withLargeData)));
-
- measurePersister.persist();
-
- checkTables("shouldInsertMeasureWithLargeData", "project_measures");
- }
-
- @Test
- public void should_not_save_best_values() {
- setupData("empty");
-
- Measure measure = new Measure(coverage()).setValue(100.0);
- when(measureCache.entries()).thenReturn(Arrays.asList(new Cache.Entry<Measure>(new String[] {"foo:org/foo/Bar.java", "coverage"}, measure)));
-
- measurePersister.persist();
-
- assertEmptyTables("project_measures");
- }
-
- @Test
- public void should_not_save_memory_only_measures() {
- setupData("empty");
-
- Measure measure = new Measure("ncloc").setPersistenceMode(PersistenceMode.MEMORY);
- when(measureCache.entries()).thenReturn(Arrays.asList(new Cache.Entry<Measure>(new String[] {"foo:org/foo/Bar.java", "ncloc"}, measure)));
-
- measurePersister.persist();
-
- assertEmptyTables("project_measures");
- }
-
- @Test
- public void should_always_save_non_file_measures() {
- setupData("empty");
-
- Measure measure1 = new Measure(ncloc()).setValue(200.0);
- Measure measure2 = new Measure(ncloc()).setValue(300.0);
- when(measureCache.entries()).thenReturn(Arrays.asList(
- new Cache.Entry<Measure>(new String[] {"foo", "ncloc"}, measure1),
- new Cache.Entry<Measure>(new String[] {"foo:org/foo", "ncloc"}, measure2)));
-
- measurePersister.persist();
-
- checkTables("shouldAlwaysPersistNonFileMeasures", "project_measures");
- }
-
- @Test
- public void should_not_save_some_file_measures_with_best_value() {
- assertThat(MeasurePersister.shouldPersistMeasure(aFile, new Measure(CoreMetrics.LINES, 200.0))).isTrue();
- assertThat(MeasurePersister.shouldPersistMeasure(aFile, new Measure(CoreMetrics.DUPLICATED_LINES_DENSITY, 3.0))).isTrue();
-
- Measure duplicatedLines = new Measure(CoreMetrics.DUPLICATED_LINES_DENSITY, 0.0);
- assertThat(MeasurePersister.shouldPersistMeasure(aFile, duplicatedLines)).isFalse();
-
- duplicatedLines.setVariation1(0.0);
- assertThat(MeasurePersister.shouldPersistMeasure(aFile, duplicatedLines)).isFalse();
-
- duplicatedLines.setVariation1(-3.0);
- assertThat(MeasurePersister.shouldPersistMeasure(aFile, duplicatedLines)).isTrue();
- }
-
- @Test
- public void should_not_save_measures_without_data() {
- assertThat(MeasurePersister.shouldPersistMeasure(aFile, new Measure(CoreMetrics.LINES))).isFalse();
-
- Measure duplicatedLines = new Measure(CoreMetrics.DUPLICATED_LINES_DENSITY);
- assertThat(MeasurePersister.shouldPersistMeasure(aFile, duplicatedLines)).isFalse();
- }
-
- private static BatchResource batchResource(Resource resource, int id) {
- Snapshot snapshot = mock(Snapshot.class);
- when(snapshot.getId()).thenReturn(id);
- return new BatchResource(1, resource, null).setSnapshot(snapshot);
- }
-
- private static Metric ncloc() {
- Metric ncloc = mock(Metric.class);
- when(ncloc.getId()).thenReturn(1);
- when(ncloc.getKey()).thenReturn("ncloc");
- return ncloc;
- }
-
- private static Metric coverage() {
- Metric coverage = mock(Metric.class);
- when(coverage.getId()).thenReturn(COVERAGE_METRIC_ID);
- when(coverage.getKey()).thenReturn("coverage");
- when(coverage.isOptimizedBestValue()).thenReturn(true);
- when(coverage.getBestValue()).thenReturn(100.0);
- return coverage;
- }
-}
diff --git a/sonar-batch/src/test/java/org/sonar/batch/phases/DatabaseModePhaseExecutorTest.java b/sonar-batch/src/test/java/org/sonar/batch/phases/DatabaseModePhaseExecutorTest.java
deleted file mode 100644
index 57e72f0ed40..00000000000
--- a/sonar-batch/src/test/java/org/sonar/batch/phases/DatabaseModePhaseExecutorTest.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * 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.batch.phases;
-
-import org.junit.Test;
-import org.sonar.batch.index.MeasurePersister;
-import org.sonar.batch.index.ResourcePersister;
-import org.sonar.batch.index.ScanPersister;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Mockito.mock;
-
-public class DatabaseModePhaseExecutorTest {
-
- @Test
- public void shouldSortPersisters() {
- ScanPersister otherPersister = mock(ScanPersister.class);
- MeasurePersister measurePersister = new MeasurePersister(null, null, null, null, null);
- ResourcePersister resourcePersister = new ResourcePersister(null, null, null, null, null);
- ScanPersister[] persisters = new ScanPersister[] {otherPersister, measurePersister, resourcePersister};
- DatabaseModePhaseExecutor executor = new DatabaseModePhaseExecutor(null, null, null, null, null,
- null, null, null, null, null, persisters, null, null, null, null, null, null, null, null);
- assertThat(executor.sortedPersisters()).containsSubsequence(resourcePersister, measurePersister);
-
- persisters = new ScanPersister[] {measurePersister, resourcePersister, otherPersister};
- executor = new DatabaseModePhaseExecutor(null, null, null, null, null,
- null, null, null, null, null, persisters, null, null, null, null, null, null, null, null);
- assertThat(executor.sortedPersisters()).containsSubsequence(resourcePersister, measurePersister);
-
- persisters = new ScanPersister[] {measurePersister, otherPersister, resourcePersister};
- executor = new DatabaseModePhaseExecutor(null, null, null, null, null,
- null, null, null, null, null, persisters, null, null, null, null, null, null, null, null);
- assertThat(executor.sortedPersisters()).containsSubsequence(resourcePersister, measurePersister);
- }
-
-}
diff --git a/sonar-batch/src/test/java/org/sonar/batch/report/MeasuresPublisherTest.java b/sonar-batch/src/test/java/org/sonar/batch/report/MeasuresPublisherTest.java
new file mode 100644
index 00000000000..ea8e3462afe
--- /dev/null
+++ b/sonar-batch/src/test/java/org/sonar/batch/report/MeasuresPublisherTest.java
@@ -0,0 +1,163 @@
+/*
+ * 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.batch.report;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+import org.sonar.api.batch.sensor.duplication.Duplication;
+import org.sonar.api.batch.sensor.duplication.internal.DefaultDuplication;
+import org.sonar.api.database.model.Snapshot;
+import org.sonar.api.measures.*;
+import org.sonar.api.measures.Metric.Level;
+import org.sonar.api.measures.Metric.ValueType;
+import org.sonar.api.resources.Project;
+import org.sonar.api.resources.Resource;
+import org.sonar.api.rule.RuleKey;
+import org.sonar.api.rules.RulePriority;
+import org.sonar.api.technicaldebt.batch.Characteristic;
+import org.sonar.batch.duplication.DuplicationCache;
+import org.sonar.batch.index.ResourceCache;
+import org.sonar.batch.protocol.output.BatchReportReader;
+import org.sonar.batch.protocol.output.BatchReportWriter;
+import org.sonar.batch.scan.measure.MeasureCache;
+
+import java.io.File;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Date;
+import java.util.List;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+public class MeasuresPublisherTest {
+
+ @Rule
+ public TemporaryFolder temp = new TemporaryFolder();
+
+ private MeasureCache measureCache;
+ private DuplicationCache duplicationCache;
+ private MeasuresPublisher publisher;
+
+ private org.sonar.api.resources.Resource sampleFile;
+
+ @Before
+ public void prepare() {
+ Project p = new Project("foo").setAnalysisDate(new Date(1234567L));
+ ResourceCache resourceCache = new ResourceCache();
+ sampleFile = org.sonar.api.resources.File.create("src/Foo.php").setEffectiveKey("foo:src/Foo.php");
+ resourceCache.add(p, null).setSnapshot(new Snapshot().setId(2));
+ resourceCache.add(sampleFile, null);
+ measureCache = mock(MeasureCache.class);
+ duplicationCache = mock(DuplicationCache.class);
+ when(measureCache.byResource(any(Resource.class))).thenReturn(Collections.<Measure>emptyList());
+ when(duplicationCache.byComponent(anyString())).thenReturn(Collections.<DefaultDuplication>emptyList());
+ publisher = new MeasuresPublisher(resourceCache, measureCache, duplicationCache);
+ }
+
+ @Test
+ public void publishMeasures() throws Exception {
+
+ Measure measure1 = new Measure<>(CoreMetrics.COVERAGE)
+ .setValue(2.0)
+ .setAlertStatus(Level.ERROR)
+ .setAlertText("Foo")
+ .setTendency(-1)
+ .setCharacteristic(mock(Characteristic.class));
+ // No value on new_xxx
+ Measure measure2 = new Measure<>(CoreMetrics.NEW_BLOCKER_VIOLATIONS)
+ .setVariation1(1.0)
+ .setVariation2(2.0)
+ .setVariation3(3.0)
+ .setVariation4(4.0)
+ .setVariation5(5.0);
+ // Manual measure
+ Measure manual = new Measure<>(new Metric<>("manual_metric", ValueType.BOOL))
+ .setValue(1.0)
+ .setDescription("Manual");
+ // Rule measure
+ RuleMeasure ruleMeasureBySeverity = RuleMeasure.createForPriority(CoreMetrics.NCLOC, RulePriority.BLOCKER, 1.0);
+ RuleMeasure ruleMeasureByRule = RuleMeasure.createForRule(CoreMetrics.NCLOC, RuleKey.of("squid", "S12345"), 1.0);
+ // Sqale rating have both a value and a data
+ Measure rating = new Measure<>(CoreMetrics.SQALE_RATING)
+ .setValue(2.0)
+ .setData("A");
+ // Long measure
+ Measure longMeasure = new Measure<>(CoreMetrics.TECHNICAL_DEBT)
+ .setValue(1.0);
+ // String value
+ Measure stringMeasure = new Measure<>(CoreMetrics.NCLOC_LANGUAGE_DISTRIBUTION)
+ .setData("foo bar");
+
+ when(measureCache.byResource(sampleFile)).thenReturn(Arrays.asList(measure1, measure2, manual, ruleMeasureBySeverity, ruleMeasureByRule, rating, longMeasure, stringMeasure));
+
+ File outputDir = temp.newFolder();
+ BatchReportWriter writer = new BatchReportWriter(outputDir);
+
+ publisher.publish(writer);
+
+ BatchReportReader reader = new BatchReportReader(outputDir);
+
+ assertThat(reader.readComponentMeasures(1)).hasSize(0);
+ List<org.sonar.batch.protocol.output.BatchReport.Measure> componentMeasures = reader.readComponentMeasures(2);
+ assertThat(componentMeasures).hasSize(8);
+ assertThat(componentMeasures.get(0).getDoubleValue()).isEqualTo(2.0);
+ assertThat(componentMeasures.get(0).getAlertStatus()).isEqualTo("ERROR");
+ assertThat(componentMeasures.get(0).getAlertText()).isEqualTo("Foo");
+
+ }
+
+ @Test
+ public void publishMeasureAndDuplication() throws Exception {
+
+ Measure measure1 = new Measure<>(CoreMetrics.COVERAGE)
+ .setValue(2.0);
+
+ when(measureCache.byResource(sampleFile)).thenReturn(Arrays.asList(measure1));
+ DefaultDuplication dup1 = new DefaultDuplication()
+ .setOriginBlock(new Duplication.Block("foo:src/Foo.php", 1, 10))
+ .isDuplicatedBy("foo:src/Foo.php", 20, 50);
+ DefaultDuplication dup2 = new DefaultDuplication()
+ .setOriginBlock(new Duplication.Block("foo:src/Foo.php", 1, 10))
+ .isDuplicatedBy("another", 20, 50);
+ when(duplicationCache.byComponent("foo:src/Foo.php")).thenReturn(Arrays.asList(dup1, dup2));
+
+ File outputDir = temp.newFolder();
+ BatchReportWriter writer = new BatchReportWriter(outputDir);
+
+ publisher.publish(writer);
+
+ BatchReportReader reader = new BatchReportReader(outputDir);
+
+ assertThat(reader.readComponentMeasures(1)).hasSize(0);
+ List<org.sonar.batch.protocol.output.BatchReport.Measure> componentMeasures = reader.readComponentMeasures(2);
+ assertThat(componentMeasures).hasSize(2);
+ assertThat(componentMeasures.get(0).getStringValue())
+ .isEqualTo(
+ "<duplications><g><b s=\"1\" l=\"10\" r=\"foo:src/Foo.php\"/><b s=\"20\" l=\"31\" r=\"foo:src/Foo.php\"/></g><g><b s=\"1\" l=\"10\" r=\"foo:src/Foo.php\"/><b s=\"20\" l=\"31\" r=\"another\"/></g></duplications>");
+
+ }
+
+}
diff --git a/sonar-batch/src/test/resources/org/sonar/batch/index/DuplicationPersisterTest/empty.xml b/sonar-batch/src/test/resources/org/sonar/batch/index/DuplicationPersisterTest/empty.xml
deleted file mode 100644
index fb0854fccbe..00000000000
--- a/sonar-batch/src/test/resources/org/sonar/batch/index/DuplicationPersisterTest/empty.xml
+++ /dev/null
@@ -1,2 +0,0 @@
-<dataset>
-</dataset>
diff --git a/sonar-batch/src/test/resources/org/sonar/batch/index/DuplicationPersisterTest/shouldInsertDuplication-result.xml b/sonar-batch/src/test/resources/org/sonar/batch/index/DuplicationPersisterTest/shouldInsertDuplication-result.xml
deleted file mode 100644
index f6c6e26ce4e..00000000000
--- a/sonar-batch/src/test/resources/org/sonar/batch/index/DuplicationPersisterTest/shouldInsertDuplication-result.xml
+++ /dev/null
@@ -1,13 +0,0 @@
-<dataset>
-
- <project_measures id="1" VALUE="[null]" METRIC_ID="2" SNAPSHOT_ID="3003" alert_text="[null]" RULES_CATEGORY_ID="[null]"
- RULE_ID="[null]"
- text_value='&lt;duplications&gt;&lt;g&gt;&lt;b s="1" l="4" r="foo:org/foo/Bar.java"/&gt;&lt;b s="5" l="9" r="foo:org/foo/Foo.java"/&gt;&lt;/g&gt;&lt;/duplications&gt;'
- tendency="[null]" measure_date="[null]" project_id="[null]"
- alert_status="[null]" description="[null]" rule_priority="[null]" characteristic_id="[null]" url="[null]"
- person_id="[null]"
- variation_value_1="[null]" variation_value_2="[null]" variation_value_3="[null]" variation_value_4="[null]" variation_value_5="[null]"
- measure_data="[null]"/>
-
-</dataset>
-
diff --git a/sonar-batch/src/test/resources/org/sonar/batch/index/MeasurePersisterTest/data.xml b/sonar-batch/src/test/resources/org/sonar/batch/index/MeasurePersisterTest/data.xml
deleted file mode 100644
index b64b9b2d480..00000000000
--- a/sonar-batch/src/test/resources/org/sonar/batch/index/MeasurePersisterTest/data.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<dataset>
-
- <project_measures id="1" VALUE="60" METRIC_ID="2" SNAPSHOT_ID="3001" alert_text="[null]" RULES_CATEGORY_ID="[null]"
- RULE_ID="[null]" text_value="[null]" tendency="[null]" measure_date="[null]" project_id="[null]"
- alert_status="[null]" description="[null]" rule_priority="[null]" characteristic_id="[null]" url="[null]"
- person_id="[null]"
- variation_value_1="[null]" variation_value_2="[null]" variation_value_3="[null]" variation_value_4="[null]" variation_value_5="[null]"/>
-
- <project_measures id="2" VALUE="60" METRIC_ID="2" SNAPSHOT_ID="3001" alert_text="[null]" RULES_CATEGORY_ID="[null]"
- RULE_ID="[null]" text_value="[null]" tendency="[null]" measure_date="[null]" project_id="[null]"
- alert_status="[null]" description="[null]" rule_priority="[null]" characteristic_id="[null]" url="[null]"
- person_id="[null]"
- variation_value_1="[null]" variation_value_2="[null]" variation_value_3="[null]" variation_value_4="[null]" variation_value_5="[null]"/>
-
- <project_measures id="3" VALUE="60" METRIC_ID="2" SNAPSHOT_ID="3002" alert_text="[null]" RULES_CATEGORY_ID="[null]"
- RULE_ID="[null]" text_value="[null]" tendency="[null]" measure_date="[null]" project_id="[null]"
- alert_status="[null]" description="[null]" rule_priority="[null]" characteristic_id="[null]" url="[null]"
- person_id="[null]"
- variation_value_1="[null]" variation_value_2="[null]" variation_value_3="[null]" variation_value_4="[null]" variation_value_5="[null]"/>
-
-</dataset>
diff --git a/sonar-batch/src/test/resources/org/sonar/batch/index/MeasurePersisterTest/empty.xml b/sonar-batch/src/test/resources/org/sonar/batch/index/MeasurePersisterTest/empty.xml
deleted file mode 100644
index fb0854fccbe..00000000000
--- a/sonar-batch/src/test/resources/org/sonar/batch/index/MeasurePersisterTest/empty.xml
+++ /dev/null
@@ -1,2 +0,0 @@
-<dataset>
-</dataset>
diff --git a/sonar-batch/src/test/resources/org/sonar/batch/index/MeasurePersisterTest/shouldAddDelayedMeasureSeveralTimes-result.xml b/sonar-batch/src/test/resources/org/sonar/batch/index/MeasurePersisterTest/shouldAddDelayedMeasureSeveralTimes-result.xml
deleted file mode 100644
index 416ec0a604b..00000000000
--- a/sonar-batch/src/test/resources/org/sonar/batch/index/MeasurePersisterTest/shouldAddDelayedMeasureSeveralTimes-result.xml
+++ /dev/null
@@ -1,10 +0,0 @@
-<dataset>
-
- <project_measures id="1" VALUE="300.0" METRIC_ID="1" SNAPSHOT_ID="3001" alert_text="[null]" RULES_CATEGORY_ID="[null]"
- RULE_ID="[null]" text_value="[null]" tendency="[null]" measure_date="[null]" project_id="[null]"
- alert_status="[null]" description="[null]" rule_priority="[null]" characteristic_id="[null]" url="[null]"
- person_id="[null]"
- variation_value_1="[null]" variation_value_2="[null]" variation_value_3="[null]" variation_value_4="[null]" variation_value_5="[null]"
- measure_data="[null]"/>
-
-</dataset>
diff --git a/sonar-batch/src/test/resources/org/sonar/batch/index/MeasurePersisterTest/shouldAlwaysPersistNonFileMeasures-result.xml b/sonar-batch/src/test/resources/org/sonar/batch/index/MeasurePersisterTest/shouldAlwaysPersistNonFileMeasures-result.xml
deleted file mode 100644
index cd064d6d9f1..00000000000
--- a/sonar-batch/src/test/resources/org/sonar/batch/index/MeasurePersisterTest/shouldAlwaysPersistNonFileMeasures-result.xml
+++ /dev/null
@@ -1,16 +0,0 @@
-<dataset>
-
- <project_measures id="1" VALUE="200.0" METRIC_ID="1" SNAPSHOT_ID="3001" alert_text="[null]" RULES_CATEGORY_ID="[null]"
- RULE_ID="[null]" text_value="[null]" tendency="[null]" measure_date="[null]" project_id="[null]"
- alert_status="[null]" description="[null]" rule_priority="[null]" characteristic_id="[null]" url="[null]"
- person_id="[null]"
- variation_value_1="[null]" variation_value_2="[null]" variation_value_3="[null]" variation_value_4="[null]" variation_value_5="[null]"
- measure_data="[null]"/>
-
- <project_measures id="2" VALUE="300.0" METRIC_ID="1" SNAPSHOT_ID="3002" alert_text="[null]" RULES_CATEGORY_ID="[null]"
- RULE_ID="[null]" text_value="[null]" tendency="[null]" measure_date="[null]" project_id="[null]"
- alert_status="[null]" description="[null]" rule_priority="[null]" characteristic_id="[null]" url="[null]"
- person_id="[null]"
- variation_value_1="[null]" variation_value_2="[null]" variation_value_3="[null]" variation_value_4="[null]" variation_value_5="[null]"
- measure_data="[null]"/>
-</dataset>
diff --git a/sonar-batch/src/test/resources/org/sonar/batch/index/MeasurePersisterTest/shouldDelaySaving-result.xml b/sonar-batch/src/test/resources/org/sonar/batch/index/MeasurePersisterTest/shouldDelaySaving-result.xml
deleted file mode 100644
index 28f2942aec1..00000000000
--- a/sonar-batch/src/test/resources/org/sonar/batch/index/MeasurePersisterTest/shouldDelaySaving-result.xml
+++ /dev/null
@@ -1,18 +0,0 @@
-<dataset>
-
- <project_measures id="1" VALUE="1234.0" METRIC_ID="1" SNAPSHOT_ID="3001" alert_text="[null]"
- RULES_CATEGORY_ID="[null]"
- RULE_ID="[null]" text_value="SHORT" tendency="[null]" measure_date="[null]" project_id="[null]"
- alert_status="[null]" description="[null]" rule_priority="[null]" characteristic_id="[null]" url="[null]"
- person_id="[null]"
- variation_value_1="[null]" variation_value_2="[null]" variation_value_3="[null]" variation_value_4="[null]" variation_value_5="[null]"
- measure_data="[null]"/>
-
- <project_measures id="2" VALUE="50.0" METRIC_ID="1" SNAPSHOT_ID="3002" alert_text="[null]" RULES_CATEGORY_ID="[null]"
- RULE_ID="[null]" text_value="[null]" tendency="[null]" measure_date="[null]" project_id="[null]"
- alert_status="[null]" description="[null]" rule_priority="[null]" characteristic_id="[null]" url="[null]"
- person_id="[null]"
- variation_value_1="[null]" variation_value_2="[null]" variation_value_3="[null]" variation_value_4="[null]" variation_value_5="[null]"
- measure_data="MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OQ=="/>
-
-</dataset>
diff --git a/sonar-batch/src/test/resources/org/sonar/batch/index/MeasurePersisterTest/shouldInsertMeasure-result.xml b/sonar-batch/src/test/resources/org/sonar/batch/index/MeasurePersisterTest/shouldInsertMeasure-result.xml
deleted file mode 100644
index a19db3a8c05..00000000000
--- a/sonar-batch/src/test/resources/org/sonar/batch/index/MeasurePersisterTest/shouldInsertMeasure-result.xml
+++ /dev/null
@@ -1,10 +0,0 @@
-<dataset>
-
- <project_measures id="1" VALUE="1234.0" METRIC_ID="1" SNAPSHOT_ID="3001" alert_text="[null]" RULES_CATEGORY_ID="[null]"
- RULE_ID="[null]" text_value="[null]" tendency="[null]" measure_date="[null]" project_id="[null]"
- alert_status="[null]" description="[null]" rule_priority="[null]" characteristic_id="[null]" url="[null]"
- person_id="[null]"
- variation_value_1="[null]" variation_value_2="[null]" variation_value_3="[null]" variation_value_4="[null]" variation_value_5="[null]"
- measure_data="[null]"/>
-
-</dataset>
diff --git a/sonar-batch/src/test/resources/org/sonar/batch/index/MeasurePersisterTest/shouldInsertMeasureWithLargeData-result.xml b/sonar-batch/src/test/resources/org/sonar/batch/index/MeasurePersisterTest/shouldInsertMeasureWithLargeData-result.xml
deleted file mode 100644
index c578a5c4974..00000000000
--- a/sonar-batch/src/test/resources/org/sonar/batch/index/MeasurePersisterTest/shouldInsertMeasureWithLargeData-result.xml
+++ /dev/null
@@ -1,11 +0,0 @@
-<dataset>
-
- <project_measures id="1" VALUE="[null]" METRIC_ID="1" SNAPSHOT_ID="3001" alert_text="[null]" RULES_CATEGORY_ID="[null]"
- RULE_ID="[null]" text_value="[null]"
- tendency="[null]" measure_date="[null]" project_id="[null]"
- alert_status="[null]" description="[null]" rule_priority="[null]" characteristic_id="[null]" url="[null]"
- person_id="[null]"
- variation_value_1="[null]" variation_value_2="[null]" variation_value_3="[null]" variation_value_4="[null]" variation_value_5="[null]"
- measure_data="MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODk="/>
-
-</dataset>
diff --git a/sonar-batch/src/test/resources/org/sonar/batch/index/MeasurePersisterTest/shouldInsertRuleMeasure-result.xml b/sonar-batch/src/test/resources/org/sonar/batch/index/MeasurePersisterTest/shouldInsertRuleMeasure-result.xml
deleted file mode 100644
index 89acf2b2223..00000000000
--- a/sonar-batch/src/test/resources/org/sonar/batch/index/MeasurePersisterTest/shouldInsertRuleMeasure-result.xml
+++ /dev/null
@@ -1,10 +0,0 @@
-<dataset>
-
- <project_measures id="1" VALUE="1234.0" METRIC_ID="1" SNAPSHOT_ID="3001" alert_text="[null]" RULES_CATEGORY_ID="[null]"
- RULE_ID="[null]" text_value="[null]" tendency="[null]" measure_date="[null]" project_id="[null]"
- alert_status="[null]" description="[null]" rule_priority="2" characteristic_id="[null]" url="[null]"
- person_id="[null]"
- variation_value_1="[null]" variation_value_2="[null]" variation_value_3="[null]" variation_value_4="[null]" variation_value_5="[null]"
- measure_data="[null]"/>
-
-</dataset>
diff --git a/sonar-core/src/main/java/org/sonar/core/persistence/MyBatis.java b/sonar-core/src/main/java/org/sonar/core/persistence/MyBatis.java
index 85873f4fc45..764b81c800d 100644
--- a/sonar-core/src/main/java/org/sonar/core/persistence/MyBatis.java
+++ b/sonar-core/src/main/java/org/sonar/core/persistence/MyBatis.java
@@ -200,7 +200,7 @@ public class MyBatis implements BatchComponent, ServerComponent {
LoadedTemplateMapper.class, MeasureFilterMapper.class, Migration44Mapper.class, PermissionTemplateMapper.class, PropertiesMapper.class, PurgeMapper.class,
ResourceKeyUpdaterMapper.class, ResourceIndexerMapper.class, ResourceSnapshotMapper.class, RoleMapper.class, RuleMapper.class,
SchemaMigrationMapper.class, SemaphoreMapper.class, UserMapper.class, GroupMapper.class, UserGroupMapper.class, WidgetMapper.class, WidgetPropertyMapper.class,
- org.sonar.api.database.model.MeasureMapper.class, FileSourceMapper.class, ActionPlanMapper.class,
+ FileSourceMapper.class, ActionPlanMapper.class,
ActionPlanStatsMapper.class,
NotificationQueueMapper.class, CharacteristicMapper.class,
GroupMembershipMapper.class, QualityProfileMapper.class, ActiveRuleMapper.class,
diff --git a/sonar-core/src/main/resources/org/sonar/core/measure/db/MeasureMapper.xml b/sonar-core/src/main/resources/org/sonar/core/measure/db/MeasureMapper.xml
index 288eccb685d..57c42516632 100644
--- a/sonar-core/src/main/resources/org/sonar/core/measure/db/MeasureMapper.xml
+++ b/sonar-core/src/main/resources/org/sonar/core/measure/db/MeasureMapper.xml
@@ -68,7 +68,7 @@
</where>
</select>
- <insert id="insert" parameterType="Measure" useGeneratedKeys="true" keyColumn="id" keyProperty="id">
+ <insert id="insert" parameterType="Measure" useGeneratedKeys="false" keyColumn="id" keyProperty="id">
INSERT INTO project_measures (
value, metric_id, snapshot_id, rule_id, text_value, tendency, project_id, alert_status, alert_text, description,
rule_priority, characteristic_id, variation_value_1, variation_value_2, variation_value_3, variation_value_4,
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/database/model/MeasureMapper.java b/sonar-plugin-api/src/main/java/org/sonar/api/database/model/MeasureMapper.java
deleted file mode 100644
index 42b7afc9b70..00000000000
--- a/sonar-plugin-api/src/main/java/org/sonar/api/database/model/MeasureMapper.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * 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.api.database.model;
-
-public interface MeasureMapper {
- void insert(MeasureModel measure);
-
- void update(MeasureModel measure);
-}
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/measures/CoreMetrics.java b/sonar-plugin-api/src/main/java/org/sonar/api/measures/CoreMetrics.java
index 68615082e24..33dc4b35b71 100644
--- a/sonar-plugin-api/src/main/java/org/sonar/api/measures/CoreMetrics.java
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/measures/CoreMetrics.java
@@ -1998,7 +1998,7 @@ public final class CoreMetrics {
/**
* @since 4.5
*/
- public static final Metric<String> SQALE_RATING = new Metric.Builder(SQALE_RATING_KEY, "SQALE Rating", Metric.ValueType.RATING)
+ public static final Metric<Integer> SQALE_RATING = new Metric.Builder(SQALE_RATING_KEY, "SQALE Rating", Metric.ValueType.RATING)
.setDomain(DOMAIN_TECHNICAL_DEBT)
.setDirection(Metric.DIRECTION_WORST)
.setQualitative(true)
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/measures/Measure.java b/sonar-plugin-api/src/main/java/org/sonar/api/measures/Measure.java
index c3f56101a18..1901863576a 100644
--- a/sonar-plugin-api/src/main/java/org/sonar/api/measures/Measure.java
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/measures/Measure.java
@@ -248,26 +248,26 @@ public class Measure<G extends Serializable> implements Serializable {
public G value() {
switch (getMetric().getType()) {
case BOOL:
- return (G) Boolean.valueOf(Double.doubleToRawLongBits(value) != 0L);
+ return value == null ? null : (G) Boolean.valueOf(Double.doubleToRawLongBits(value) != 0L);
case INT:
case MILLISEC:
- return (G) Integer.valueOf(value.intValue());
+ case RATING:
+ return value == null ? null : (G) Integer.valueOf(value.intValue());
case FLOAT:
case PERCENT:
- case RATING:
- return (G) value;
+ return value == null ? null : (G) value;
case STRING:
case LEVEL:
case DATA:
case DISTRIB:
- return (G) getData();
+ return data == null ? null : (G) data;
case WORK_DUR:
- return (G) Long.valueOf(value.longValue());
+ return value == null ? null : (G) Long.valueOf(value.longValue());
default:
if (getMetric().isNumericType()) {
- return (G) getValue();
+ return value == null ? null : (G) value;
} else if (getMetric().isDataType()) {
- return (G) getData();
+ return data == null ? null : (G) data;
} else {
throw new UnsupportedOperationException("Unsupported type :" + getMetric().getType());
}
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/measures/Metric.java b/sonar-plugin-api/src/main/java/org/sonar/api/measures/Metric.java
index af8af470cd1..111581d2f75 100644
--- a/sonar-plugin-api/src/main/java/org/sonar/api/measures/Metric.java
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/measures/Metric.java
@@ -28,14 +28,7 @@ import org.sonar.api.batch.InstantiationStrategy;
import javax.annotation.CheckForNull;
import javax.annotation.Nullable;
-import javax.persistence.Column;
-import javax.persistence.Entity;
-import javax.persistence.EnumType;
-import javax.persistence.Enumerated;
-import javax.persistence.GeneratedValue;
-import javax.persistence.Id;
-import javax.persistence.Table;
-import javax.persistence.Transient;
+import javax.persistence.*;
import java.io.Serializable;
@@ -72,7 +65,7 @@ public class Metric<G extends Serializable> implements ServerExtension, BatchExt
DATA(String.class),
LEVEL(Metric.Level.class),
DISTRIB(String.class),
- RATING(String.class),
+ RATING(Integer.class),
WORK_DUR(Long.class);
private final Class valueClass;
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/measures/RuleMeasure.java b/sonar-plugin-api/src/main/java/org/sonar/api/measures/RuleMeasure.java
index 13f642867e3..6c507bcb34f 100644
--- a/sonar-plugin-api/src/main/java/org/sonar/api/measures/RuleMeasure.java
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/measures/RuleMeasure.java
@@ -26,6 +26,7 @@ import org.sonar.api.rule.RuleKey;
import org.sonar.api.rules.Rule;
import org.sonar.api.rules.RulePriority;
+import javax.annotation.CheckForNull;
import javax.annotation.Nullable;
/**
@@ -54,6 +55,7 @@ public class RuleMeasure extends Measure {
this.rulePriority = rulePriority;
}
+ @CheckForNull
public RuleKey ruleKey() {
return ruleKey;
}
@@ -84,6 +86,7 @@ public class RuleMeasure extends Measure {
* @deprecated since 2.14 use {@link #getSeverity()} instead. See SONAR-1829.
*/
@Deprecated
+ @CheckForNull
public RulePriority getRulePriority() {
return rulePriority;
}
@@ -91,6 +94,7 @@ public class RuleMeasure extends Measure {
/**
* @since 2.14
*/
+ @CheckForNull
public RulePriority getSeverity() {
return rulePriority;
}
diff --git a/sonar-plugin-api/src/main/resources/org/sonar/api/database/model/MeasureMapper.xml b/sonar-plugin-api/src/main/resources/org/sonar/api/database/model/MeasureMapper.xml
deleted file mode 100644
index 1bf6e453f64..00000000000
--- a/sonar-plugin-api/src/main/resources/org/sonar/api/database/model/MeasureMapper.xml
+++ /dev/null
@@ -1,43 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" ?>
-<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
-
-<mapper namespace="org.sonar.api.database.model.MeasureMapper">
-
- <insert id="insert" parameterType="MeasureModel" useGeneratedKeys="false">
- INSERT INTO project_measures (
- value, metric_id, snapshot_id, rule_id, text_value, tendency,
- project_id, alert_status, alert_text, url, description, rule_priority, characteristic_id, variation_value_1,
- variation_value_2, variation_value_3, variation_value_4, variation_value_5, person_id, measure_data)
- VALUES (
- #{value, jdbcType=DOUBLE}, #{metricId, jdbcType=INTEGER}, #{snapshotId, jdbcType=INTEGER}, #{ruleId, jdbcType=INTEGER}, #{textValue, jdbcType=VARCHAR}, #{tendency, jdbcType=INTEGER},
- #{projectId, jdbcType=INTEGER}, #{alertStatus, jdbcType=VARCHAR}, #{alertText, jdbcType=VARCHAR},
- #{url, jdbcType=VARCHAR}, #{description, jdbcType=VARCHAR}, #{rulePriority.ordinal, jdbcType=INTEGER}, #{characteristicId, jdbcType=INTEGER}, #{variationValue1, jdbcType=DOUBLE},
- #{variationValue2, jdbcType=DOUBLE}, #{variationValue3, jdbcType=DOUBLE}, #{variationValue4, jdbcType=DOUBLE}, #{variationValue5, jdbcType=DOUBLE}, #{personId, jdbcType=INTEGER}, #{data}
- )
- </insert>
-
- <update id="update" parameterType="MeasureModel">
- UPDATE project_measures
- SET
- value = #{value},
- metric_id = #{metricId},
- rule_id = #{ruleId},
- text_value = #{textValue},
- tendency = #{tendency},
- alert_status = #{alertStatus},
- alert_text = #{alertText},
- url = #{url},
- description = #{description},
- rule_priority = #{rulePriority.ordinal},
- characteristic_id = #{characteristicId},
- variation_value_1 = #{variationValue1},
- variation_value_2 = #{variationValue2},
- variation_value_3 = #{variationValue3},
- variation_value_4 = #{variationValue4},
- variation_value_5 = #{variationValue5},
- person_id = #{personId},
- measure_data = #{data}
- WHERE id = #{id}
- </update>
-
-</mapper>