]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-3231 Allow to associate measure with committer
authorEvgeny Mandrikov <mandrikov@gmail.com>
Wed, 1 Feb 2012 14:19:33 +0000 (18:19 +0400)
committerEvgeny Mandrikov <mandrikov@gmail.com>
Wed, 1 Feb 2012 16:11:21 +0000 (20:11 +0400)
plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/VariationDecorator.java
plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/timemachine/VariationDecoratorTest.java
sonar-batch/src/main/java/org/sonar/batch/DefaultTimeMachine.java
sonar-batch/src/main/java/org/sonar/batch/components/PastMeasuresLoader.java
sonar-batch/src/main/java/org/sonar/batch/index/MeasurePersister.java
sonar-batch/src/test/java/org/sonar/batch/components/PastMeasuresLoaderTest.java
sonar-plugin-api/src/main/java/org/sonar/api/database/model/MeasureModel.java
sonar-plugin-api/src/main/java/org/sonar/api/measures/Measure.java
sonar-plugin-api/src/main/java/org/sonar/api/measures/MeasuresFilters.java
sonar-server/src/main/java/org/sonar/server/filters/FilterExecutor.java

index b3a5d2581218dea7fbe358b428f83bff6d2ddef9..dab6531f55719ad7b8a3a0777dd9e37ca2fa0add 100644 (file)
@@ -98,9 +98,10 @@ public class VariationDecorator implements Decorator {
       // 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);
+      String committer = measure.getCommitter();
       Integer ruleId =  (measure instanceof RuleMeasure ? ((RuleMeasure)measure).getRule().getId() : null);
 
-      Object[] pastMeasure = pastMeasuresByKey.get(new MeasureKey(metricId, characteristicId, ruleId));
+      Object[] pastMeasure = pastMeasuresByKey.get(new MeasureKey(metricId, characteristicId, committer, ruleId));
       if (updateVariation(measure, pastMeasure, index)) {
         context.saveMeasure(measure);
       }
@@ -124,17 +125,20 @@ public class VariationDecorator implements Decorator {
   static final class MeasureKey {
     int metricId;
     Integer characteristicId;
+    String committer;
     Integer ruleId;
 
     MeasureKey(Object[] pastFields) {
       metricId = PastMeasuresLoader.getMetricId(pastFields);
       characteristicId = PastMeasuresLoader.getCharacteristicId(pastFields);
+      committer = PastMeasuresLoader.getCommitter(pastFields);
       ruleId = PastMeasuresLoader.getRuleId(pastFields);
     }
 
-    MeasureKey(int metricId, Integer characteristicId, Integer ruleId) {
+    MeasureKey(int metricId, Integer characteristicId, String committer, Integer ruleId) {
       this.metricId = metricId;
       this.characteristicId = characteristicId;
+      this.committer = committer;
       this.ruleId = ruleId;
     }
 
@@ -153,6 +157,9 @@ public class VariationDecorator implements Decorator {
       if (characteristicId != null ? !characteristicId.equals(that.characteristicId) : that.characteristicId != null) {
         return false;
       }
+      if (committer != null ? !committer.equals(that.committer) : that.committer != null) {
+        return false;
+      }
       if (ruleId != null ? !ruleId.equals(that.ruleId) : that.ruleId != null) {
         return false;
       }
@@ -163,8 +170,9 @@ public class VariationDecorator implements Decorator {
     public int hashCode() {
       int result = metricId;
       result = 31 * result + (characteristicId != null ? characteristicId.hashCode() : 0);
+      result = 31 * result + (committer != null ? committer.hashCode() : 0);
       result = 31 * result + (ruleId != null ? ruleId.hashCode() : 0);
       return result;
     }
   }
-}
\ No newline at end of file
+}
index 35d5e524d3c7f99f8170397768e4a643b4559919..9ac297f1d2813f2faaedcabaf2cc8a5a145b5665 100644 (file)
@@ -23,11 +23,9 @@ import org.junit.Test;
 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.*;
 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;
@@ -100,12 +98,12 @@ public class VariationDecoratorTest extends AbstractDbUnitTestCase {
 
     // first past analysis
     when(pastMeasuresLoader.getPastMeasures(javaPackage, pastSnapshot1)).thenReturn(Arrays.asList(
-        new Object[]{NCLOC_ID, null, null, 180.0},
-        new Object[]{COVERAGE_ID, null, 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, null, 240.0}));
+        new Object[] {NCLOC_ID, null, null, null, 240.0}));
 
     // current analysis
     DecoratorContext context = mock(DecoratorContext.class);
@@ -142,9 +140,9 @@ public class VariationDecoratorTest extends AbstractDbUnitTestCase {
 
     // first past analysis
     when(pastMeasuresLoader.getPastMeasures(javaPackage, pastSnapshot1)).thenReturn(Arrays.asList(
-        new Object[]{VIOLATIONS_ID, null, null, 180.0},//total
-        new Object[]{VIOLATIONS_ID, null, rule1.getId(), 100.0},// rule 1
-        new Object[]{VIOLATIONS_ID, null, rule2.getId(), 80.0})); // rule 2
+        new Object[] {VIOLATIONS_ID, null, null, null, 180.0},// total
+        new Object[] {VIOLATIONS_ID, null, null, rule1.getId(), 100.0},// rule 1
+        new Object[] {VIOLATIONS_ID, null, null, rule2.getId(), 80.0})); // rule 2
 
     // current analysis
     DecoratorContext context = mock(DecoratorContext.class);
index fce98a19737b612be714d5ddd6d291592e28b803..326dfbb9b2dbf2ec02184f2746e95add062726b8 100644 (file)
@@ -34,6 +34,7 @@ import org.sonar.api.resources.Resource;
 import org.sonar.batch.index.DefaultIndex;
 
 import javax.persistence.Query;
+
 import java.util.*;
 
 public class DefaultTimeMachine implements TimeMachine {
@@ -93,12 +94,14 @@ public class DefaultTimeMachine implements TimeMachine {
         .append(MeasureModel.class.getSimpleName())
         .append(" m, ")
         .append(Snapshot.class.getSimpleName())
-        .append(" s WHERE m.snapshotId=s.id AND s.resourceId=:resourceId AND s.status=:status AND m.characteristic IS NULL AND s.qualifier<>:lib");
+        .append(" s WHERE m.snapshotId=s.id AND s.resourceId=:resourceId AND s.status=:status AND s.qualifier<>:lib");
     params.put("resourceId", resource.getId());
     params.put("status", Snapshot.STATUS_PROCESSED);
     params.put("lib", Qualifiers.LIBRARY);
 
-    sb.append(" AND m.ruleId IS NULL AND m.rulePriority IS NULL ");
+    sb.append(" AND m.characteristic IS NULL");
+    sb.append(" AND m.committer IS NULL");
+    sb.append(" AND m.ruleId IS NULL AND m.rulePriority IS NULL");
     if (!metricIds.isEmpty()) {
       sb.append(" AND m.metricId IN (:metricIds) ");
       params.put("metricIds", metricIds);
@@ -159,6 +162,7 @@ public class DefaultTimeMachine implements TimeMachine {
     measure.setVariation5(model.getVariationValue5());
     measure.setUrl(model.getUrl());
     measure.setCharacteristic(model.getCharacteristic());
+    measure.setCommitter(model.getCommitter());
     return measure;
   }
-}
\ No newline at end of file
+}
index a04a0311f0b35e9ddfd55a72d3fed5cd44fd4aad..7b2560a3e28f9e81bda29e86fc39b177e6edc332 100644 (file)
@@ -65,7 +65,7 @@ public class PastMeasuresLoader implements BatchExtension {
   }
 
   public List<Object[]> getPastMeasures(String resourceKey, Snapshot projectPastSnapshot) {
-    String sql = "select m.metric_id, m.characteristic_id, m.rule_id, m.value from project_measures m, snapshots s" +
+    String sql = "select m.metric_id, m.characteristic_id, m.committer, m.rule_id, 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)";
@@ -89,17 +89,22 @@ public class PastMeasuresLoader implements BatchExtension {
     return number != null ? number.intValue() : null;
   }
 
+  public static String getCommitter(Object[] row) {
+    return (String) row[2];
+  }
+
   public static Integer getRuleId(Object[] row) {
     // can be BigDecimal on Oracle
-    Number number = (Number) row[2];
+    Number number = (Number) row[3];
     return number != null ? number.intValue() : null;
   }
 
   public static boolean hasValue(Object[] row) {
-    return row[3] != null;
+    return row[4] != null;
   }
 
   public static double getValue(Object[] row) {
-    return ((Number) row[3]).doubleValue();
+    return ((Number) row[4]).doubleValue();
   }
+
 }
index 1f0326c55a1ba81665f061e2c9493cf3400a9c4d..620519345f00d11c14450ece94d3d463c66eefc1 100644 (file)
@@ -150,6 +150,7 @@ public final class MeasurePersister {
     merge.setVariationValue5(measure.getVariation5());
     merge.setUrl(measure.getUrl());
     merge.setCharacteristic(measure.getCharacteristic());
+    merge.setCommitter(measure.getCommitter());
     if (measure.getValue() != null) {
       merge.setValue(measure.getValue().doubleValue());
     } else {
index 5d56fde9600645e06ed490dafeb33ddf64348776..5c4e963850780868bda3410a59c5fca6f57ca901 100644 (file)
@@ -27,7 +27,6 @@ import org.sonar.jpa.test.AbstractDbUnitTestCase;
 import java.util.Arrays;
 import java.util.List;
 
-import static org.hamcrest.CoreMatchers.anyOf;
 import static org.hamcrest.CoreMatchers.is;
 import static org.hamcrest.MatcherAssert.assertThat;
 import static org.hamcrest.Matchers.nullValue;
@@ -53,11 +52,13 @@ public class PastMeasuresLoaderTest extends AbstractDbUnitTestCase {
     Object[] pastMeasure = measures.get(0);
     assertThat(PastMeasuresLoader.getMetricId(pastMeasure), is(1));
     assertThat(PastMeasuresLoader.getCharacteristicId(pastMeasure), nullValue());
+    assertThat(PastMeasuresLoader.getCommitter(pastMeasure), nullValue());
     assertThat(PastMeasuresLoader.getValue(pastMeasure), is(5.0));
 
     pastMeasure = measures.get(1);
     assertThat(PastMeasuresLoader.getMetricId(pastMeasure), is(2));
     assertThat(PastMeasuresLoader.getCharacteristicId(pastMeasure), nullValue());
+    assertThat(PastMeasuresLoader.getCommitter(pastMeasure), nullValue());
     assertThat(PastMeasuresLoader.getValue(pastMeasure), is(60.0));
   }
 
@@ -75,11 +76,13 @@ public class PastMeasuresLoaderTest extends AbstractDbUnitTestCase {
     Object[] pastMeasure = measures.get(0);
     assertThat(PastMeasuresLoader.getMetricId(pastMeasure), is(1));
     assertThat(PastMeasuresLoader.getCharacteristicId(pastMeasure), nullValue());
+    assertThat(PastMeasuresLoader.getCommitter(pastMeasure), nullValue());
     assertThat(PastMeasuresLoader.getValue(pastMeasure), is(60.0));
 
     pastMeasure = measures.get(1);
     assertThat(PastMeasuresLoader.getMetricId(pastMeasure), is(2));
     assertThat(PastMeasuresLoader.getCharacteristicId(pastMeasure), nullValue());
+    assertThat(PastMeasuresLoader.getCommitter(pastMeasure), nullValue());
     assertThat(PastMeasuresLoader.getValue(pastMeasure), is(80.0));
   }
 
@@ -94,7 +97,7 @@ public class PastMeasuresLoaderTest extends AbstractDbUnitTestCase {
     List<Metric> metrics = Arrays.asList(ncloc, complexity, data);
 
     PastMeasuresLoader loader = new PastMeasuresLoader(getSession(), metrics);
-    
+
     assertThat(loader.getMetrics().size(), is(2));
     assertThat(loader.getMetrics(), hasItems(ncloc, complexity));
   }
index 739c6dfc4232c9f6b52b1b2d9599d92cceb90e05..f63e730af7665002459c8355ec2e3d87b6d2faec 100644 (file)
@@ -27,6 +27,7 @@ import org.sonar.api.qualitymodel.Characteristic;
 import org.sonar.api.rules.RulePriority;
 
 import javax.persistence.*;
+
 import java.util.ArrayList;
 import java.util.Date;
 import java.util.List;
@@ -115,6 +116,9 @@ public class MeasureModel implements Cloneable {
   @JoinColumn(name = "characteristic_id")
   private Characteristic characteristic;
 
+  @Column(name = "committer", updatable = true, nullable = true, length = 100)
+  private String committer;
+
   public Long getId() {
     return id;
   }
@@ -122,7 +126,7 @@ public class MeasureModel implements Cloneable {
   public void setId(Long id) {
     this.id = id;
   }
-  
+
   /**
    * Creates a measure based on a metric and a double value
    */
@@ -518,6 +522,15 @@ public class MeasureModel implements Cloneable {
     return this;
   }
 
+  public String getCommitter() {
+    return committer;
+  }
+
+  public MeasureModel setCommitter(String committer) {
+    this.committer = committer;
+    return this;
+  }
+
   @Override
   public Object clone() {
     MeasureModel clone = new MeasureModel();
@@ -539,6 +552,8 @@ public class MeasureModel implements Cloneable {
     clone.setMeasureDate(getMeasureDate());
     clone.setUrl(getUrl());
     clone.setCharacteristic(getCharacteristic());
+    clone.setCommitter(getCommitter());
     return clone;
   }
+
 }
index 1b1c4134ecd6f71382b64c8f72cee72604c4d36c..61497f07af397aa29dc4f7f8c1857f348b138a3c 100644 (file)
@@ -19,6 +19,7 @@
  */
 package org.sonar.api.measures;
 
+import com.google.common.annotations.Beta;
 import org.apache.commons.lang.builder.ReflectionToStringBuilder;
 import org.sonar.api.qualitymodel.Characteristic;
 
@@ -52,6 +53,7 @@ public class Measure {
   protected Double variation1, variation2, variation3, variation4, variation5;
   protected String url;
   protected Characteristic characteristic;
+  protected String committer;
   protected PersistenceMode persistenceMode = PersistenceMode.FULL;
 
   public Measure(String metricKey) {
@@ -329,7 +331,7 @@ public class Measure {
     this.data=null;
     return this;
   }
-  
+
   /**
    * @return the description of the measure
    */
@@ -593,6 +595,23 @@ public class Measure {
     return this;
   }
 
+  /**
+   * @since 2.14
+   */
+  @Beta
+  public String getCommitter() {
+    return committer;
+  }
+
+  /**
+   * @since 2.14
+   */
+  @Beta
+  public Measure setCommitter(String committer) {
+    this.committer = committer;
+    return this;
+  }
+
   @Override
   public boolean equals(Object o) {
     if (this == o) {
@@ -609,6 +628,9 @@ public class Measure {
     if (characteristic != null ? !characteristic.equals(measure.characteristic) : measure.characteristic != null) {
       return false;
     }
+    if (committer != null ? !committer.equals(measure.committer) : measure.committer != null) {
+      return false;
+    }
     return true;
   }
 
@@ -616,6 +638,7 @@ public class Measure {
   public int hashCode() {
     int result = metricKey != null ? metricKey.hashCode() : 0;
     result = 31 * result + (characteristic != null ? characteristic.hashCode() : 0);
+    result = 31 * result + (committer != null ? committer.hashCode() : 0);
     return result;
   }
 
index 9a975e48cbeac549da85feb7bfcb592c88b2dad5..bf4e1964f15a05a9ea674a554a82467cde55bbd9 100644 (file)
@@ -57,7 +57,8 @@ public final class MeasuresFilters {
         for (Measure measure : measures) {
           if (measure.getClass().equals(Measure.class) &&
             measure.getMetricKey().equals(metricKey) &&
-            measure.getCharacteristic() == null) {
+            measure.getCharacteristic() == null &&
+            measure.getCommitter() == null) {
             return measure;
           }
         }
index fc820ed90ca32282905650ed6bc1f6172255084e..6dba0c4fa0170d08124e1a9fb2a2c026e8218051 100644 (file)
@@ -147,7 +147,10 @@ public class FilterExecutor implements ServerComponent {
 
         sql.append(" ) AND ");
       }
-      sql.append(" pm.rule_id is null AND pm.rule_priority is null AND pm.characteristic_id IS NULL AND ");
+      sql.append(" pm.rule_id IS NULL AND pm.rule_priority IS NULL");
+      sql.append(" AND pm.characteristic_id IS NULL");
+      sql.append(" AND pm.committer IS NULL");
+      sql.append(" AND ");
     }
     sql.append(" s.status=:status AND s.islast=:islast ");
     if (filter.getScopes() != null) {