aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimon Brandhof <simon.brandhof@gmail.com>2011-06-29 12:54:22 +0200
committerSimon Brandhof <simon.brandhof@gmail.com>2011-06-29 12:54:22 +0200
commit4415d64999d90301ad128afa5949c73a65bfd43d (patch)
tree05498dfcea07ae2589378af9c59d616060328a2d
parent18b21f2ce809939ebfe25a31a4663526a1ad8b61 (diff)
downloadsonarqube-4415d64999d90301ad128afa5949c73a65bfd43d.tar.gz
sonarqube-4415d64999d90301ad128afa5949c73a65bfd43d.zip
SONAR-2553 API: compute the variations on all measures
-rw-r--r--plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/VariationDecorator.java34
-rw-r--r--plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/timemachine/VariationDecoratorTest.java54
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/components/PastMeasuresLoader.java20
3 files changed, 78 insertions, 30 deletions
diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/VariationDecorator.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/VariationDecorator.java
index c475fbfbe09..a1c9d5236b1 100644
--- a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/VariationDecorator.java
+++ b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/VariationDecorator.java
@@ -95,12 +95,14 @@ public class VariationDecorator implements Decorator {
}
// for each measure, search equivalent past measure
- for (Measure measure : context.getMeasures(new CustomMeasureFilter())) {
+ for (Measure measure : context.getMeasures(MeasuresFilters.all())) {
// compare with past measure
Integer metricId = (measure.getMetric().getId() != null ? measure.getMetric().getId() : metricFinder.findByKey(measure.getMetric().getKey()).getId());
Integer characteristicId = (measure.getCharacteristic() != null ? measure.getCharacteristic().getId() : null);
+ Integer ruleId = (measure instanceof RuleMeasure ? ((RuleMeasure)measure).getRule().getId() : null);
+ Integer severityId = (measure instanceof RuleMeasure ? ((RuleMeasure)measure).getRulePriority().ordinal() : null);
- Object[] pastMeasure = pastMeasuresByKey.get(new MeasureKey(metricId, characteristicId));
+ Object[] pastMeasure = pastMeasuresByKey.get(new MeasureKey(metricId, characteristicId, ruleId, severityId));
if (updateVariation(measure, pastMeasure, index)) {
context.saveMeasure(measure);
}
@@ -121,30 +123,24 @@ public class VariationDecorator implements Decorator {
return getClass().getSimpleName();
}
- static class CustomMeasureFilter implements MeasuresFilter<Collection<Measure>> {
- public Collection<Measure> filter(Collection<Measure> measures) {
- List<Measure> result = Lists.newArrayList();
- for (Measure measure : measures) {
- if (!(measure instanceof RuleMeasure)) {
- result.add(measure);
- }
- }
- return result;
- }
- }
-
static final class MeasureKey {
int metricId;
Integer characteristicId;
+ Integer ruleId;
+ Integer severityId;
MeasureKey(Object[] pastFields) {
metricId = PastMeasuresLoader.getMetricId(pastFields);
characteristicId = PastMeasuresLoader.getCharacteristicId(pastFields);
+ ruleId = PastMeasuresLoader.getRuleId(pastFields);
+ severityId = PastMeasuresLoader.getSeverityId(pastFields);
}
- MeasureKey(int metricId, Integer characteristicId) {
+ MeasureKey(int metricId, Integer characteristicId, Integer ruleId, Integer severityId) {
this.metricId = metricId;
this.characteristicId = characteristicId;
+ this.ruleId = ruleId;
+ this.severityId = severityId;
}
@Override
@@ -162,6 +158,12 @@ public class VariationDecorator implements Decorator {
if (characteristicId != null ? !characteristicId.equals(that.characteristicId) : that.characteristicId != null) {
return false;
}
+ if (ruleId != null ? !ruleId.equals(that.ruleId) : that.ruleId != null) {
+ return false;
+ }
+ if (severityId != null ? !severityId.equals(that.severityId) : that.severityId != null) {
+ return false;
+ }
return true;
}
@@ -169,6 +171,8 @@ public class VariationDecorator implements Decorator {
public int hashCode() {
int result = metricId;
result = 31 * result + (characteristicId != null ? characteristicId.hashCode() : 0);
+ result = 31 * result + (ruleId != null ? ruleId.hashCode() : 0);
+ result = 31 * result + (severityId != null ? severityId.hashCode() : 0);
return result;
}
}
diff --git a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/timemachine/VariationDecoratorTest.java b/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/timemachine/VariationDecoratorTest.java
index 9e4ac766aaf..ba963a10f0a 100644
--- a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/timemachine/VariationDecoratorTest.java
+++ b/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/timemachine/VariationDecoratorTest.java
@@ -24,11 +24,10 @@ import org.mockito.Matchers;
import org.sonar.api.CoreProperties;
import org.sonar.api.batch.DecoratorContext;
import org.sonar.api.database.model.MeasureModel;
-import org.sonar.api.measures.Measure;
-import org.sonar.api.measures.MeasuresFilter;
-import org.sonar.api.measures.Metric;
-import org.sonar.api.measures.MetricFinder;
+import org.sonar.api.measures.*;
import org.sonar.api.resources.*;
+import org.sonar.api.rules.Rule;
+import org.sonar.api.rules.RulePriority;
import org.sonar.batch.components.PastMeasuresLoader;
import org.sonar.batch.components.PastSnapshot;
import org.sonar.batch.components.TimeMachineConfiguration;
@@ -50,6 +49,9 @@ public class VariationDecoratorTest extends AbstractDbUnitTestCase {
public static final int COVERAGE_ID = 16;
public static final Metric COVERAGE = new Metric("coverage").setId(COVERAGE_ID);
+ public static final int VIOLATIONS_ID = 17;
+ public static final Metric VIOLATIONS = new Metric("violations").setId(VIOLATIONS_ID);
+
@Test
public void shouldComputeVariations() {
TimeMachineConfiguration conf = mock(TimeMachineConfiguration.class);
@@ -98,12 +100,12 @@ public class VariationDecoratorTest extends AbstractDbUnitTestCase {
// first past analysis
when(pastMeasuresLoader.getPastMeasures(javaPackage, pastSnapshot1)).thenReturn(Arrays.asList(
- new Object[]{NCLOC_ID, null, 180.0},
- new Object[]{COVERAGE_ID, null, 75.0}));
+ new Object[]{NCLOC_ID, null, null, null, 180.0},
+ new Object[]{COVERAGE_ID, null, null, null, 75.0}));
// second past analysis
when(pastMeasuresLoader.getPastMeasures(javaPackage, pastSnapshot3)).thenReturn(Arrays.<Object[]>asList(
- new Object[]{NCLOC_ID, null, 240.0}));
+ new Object[]{NCLOC_ID, null, null, null, 240.0}));
// current analysis
DecoratorContext context = mock(DecoratorContext.class);
@@ -126,11 +128,41 @@ public class VariationDecoratorTest extends AbstractDbUnitTestCase {
assertThat(currentCoverage.getVariation3(), nullValue());
}
- private Measure newMeasure(Metric metric, double value) {
- return new Measure(metric, value);
+ @Test
+ public void shouldComputeVariationOfRuleMeasures() {
+ Rule rule1 = Rule.create();
+ rule1.setId(1);
+ Rule rule2 = Rule.create();
+ rule2.setId(2);
+
+ Resource javaPackage = new JavaPackage("org.foo");
+
+ PastMeasuresLoader pastMeasuresLoader = mock(PastMeasuresLoader.class);
+ PastSnapshot pastSnapshot1 = new PastSnapshot("days", new Date()).setIndex(1);
+
+ // first past analysis
+ when(pastMeasuresLoader.getPastMeasures(javaPackage, pastSnapshot1)).thenReturn(Arrays.asList(
+ new Object[]{VIOLATIONS_ID, null, null, null, 180.0},//total
+ new Object[]{VIOLATIONS_ID, null, rule1.getId(), RulePriority.BLOCKER.ordinal(), 100.0},// rule 1
+ new Object[]{VIOLATIONS_ID, null, rule2.getId(), RulePriority.MAJOR.ordinal(), 80.0})); // rule 2
+
+ // current analysis
+ DecoratorContext context = mock(DecoratorContext.class);
+ Measure violations = newMeasure(VIOLATIONS, 200.0);
+ Measure violationsRule1 = new RuleMeasure(VIOLATIONS, rule1, RulePriority.BLOCKER, null).setValue(130.0);
+ Measure violationsRule2 = new RuleMeasure(VIOLATIONS, rule2, RulePriority.MAJOR, null).setValue(70.0);
+ when(context.getMeasures(Matchers.<MeasuresFilter>anyObject())).thenReturn(Arrays.asList(violations, violationsRule1, violationsRule2));
+
+ VariationDecorator decorator = new VariationDecorator(pastMeasuresLoader, mock(MetricFinder.class), Arrays.asList(pastSnapshot1), false);
+ decorator.decorate(javaPackage, context);
+
+ // context updated for each variation
+ verify(context, times(3)).saveMeasure(Matchers.<Measure>anyObject());
+
+ assertThat(violations.getVariation1(), is(20.0));
}
- private MeasureModel newMeasureModel(Metric metric, double value) {
- return new MeasureModel(metric.getId(), value);
+ private Measure newMeasure(Metric metric, double value) {
+ return new Measure(metric, value);
}
}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/components/PastMeasuresLoader.java b/sonar-batch/src/main/java/org/sonar/batch/components/PastMeasuresLoader.java
index c4dd2a56dc0..994625b1281 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/components/PastMeasuresLoader.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/components/PastMeasuresLoader.java
@@ -66,8 +66,8 @@ public class PastMeasuresLoader implements BatchExtension {
}
public List<Object[]> getPastMeasures(String resourceKey, Snapshot projectPastSnapshot) {
- String sql = "select m.metric_id, m.characteristic_id, m.value from project_measures m, snapshots s" +
- " where m.snapshot_id=s.id and m.metric_id in (:metricIds) and m.rule_id is null and m.rule_priority is null " +
+ String sql = "select m.metric_id, m.characteristic_id, m.rule_id, m.rule_priority, m.value from project_measures m, snapshots s" +
+ " where m.snapshot_id=s.id and m.metric_id in (:metricIds) " +
" and (s.root_snapshot_id=:rootSnapshotId or s.id=:rootSnapshotId) and s.status=:status and s.project_id=(select p.id from projects p where p.kee=:resourceKey and p.qualifier<>:lib)";
return session.createNativeQuery(sql)
.setParameter("metricIds", metricByIds.keySet())
@@ -89,11 +89,23 @@ public class PastMeasuresLoader implements BatchExtension {
return number!=null ? number.intValue() : null;
}
+ public static Integer getRuleId(Object[] row) {
+ // can be BigDecimal on Oracle
+ Number number = (Number) row[2];
+ return number!=null ? number.intValue() : null;
+ }
+
+ public static Integer getSeverityId(Object[] row) {
+ // can be BigDecimal on Oracle
+ Number number = (Number) row[3];
+ return number!=null ? number.intValue() : null;
+ }
+
public static boolean hasValue(Object[] row) {
- return row[2] != null;
+ return row[4] != null;
}
public static double getValue(Object[] row) {
- return ((Number) row[2]).doubleValue();
+ return ((Number) row[4]).doubleValue();
}
}