]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-6623 distribution of issues by debt in Compute Engine
authorSimon Brandhof <simon.brandhof@sonarsource.com>
Wed, 24 Jun 2015 07:11:30 +0000 (09:11 +0200)
committerSimon Brandhof <simon.brandhof@sonarsource.com>
Thu, 2 Jul 2015 14:07:04 +0000 (16:07 +0200)
This allows to deprecate org.sonar.api.measures.RuleMeasure

20 files changed:
server/sonar-server/src/main/java/org/sonar/server/computation/debt/Characteristic.java
server/sonar-server/src/main/java/org/sonar/server/computation/debt/DebtModelHolder.java
server/sonar-server/src/main/java/org/sonar/server/computation/debt/DebtModelHolderImpl.java
server/sonar-server/src/main/java/org/sonar/server/computation/issue/CountIssuesListener.java
server/sonar-server/src/main/java/org/sonar/server/computation/issue/DebtCalculator.java
server/sonar-server/src/main/java/org/sonar/server/computation/step/FeedDebtModelStep.java
server/sonar-server/src/test/java/org/sonar/server/computation/debt/CharacteristicTest.java
server/sonar-server/src/test/java/org/sonar/server/computation/debt/DebtModelHolderImplTest.java
server/sonar-server/src/test/java/org/sonar/server/computation/measure/MeasureRepositoryImplTest.java
server/sonar-server/src/test/java/org/sonar/server/computation/step/FeedDebtModelStepTest.java
server/sonar-server/src/test/java/org/sonar/server/computation/step/FillMeasuresWithVariationsStepTest.java
sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchComponents.java
sonar-batch/src/main/java/org/sonar/batch/debt/DebtDecorator.java [deleted file]
sonar-batch/src/main/java/org/sonar/batch/report/MeasuresPublisher.java
sonar-batch/src/test/java/org/sonar/batch/debt/DebtDecoratorTest.java
sonar-batch/src/test/java/org/sonar/batch/report/MeasuresPublisherTest.java
sonar-batch/src/test/java/org/sonar/batch/scan/measure/MeasureCacheTest.java
sonar-plugin-api/src/main/java/org/sonar/api/measures/MeasuresFilters.java
sonar-plugin-api/src/main/java/org/sonar/api/measures/RuleMeasure.java
sonar-plugin-api/src/test/java/org/sonar/api/test/IsRuleMeasure.java [deleted file]

index 5c1224c8df9f1441876de00172f0447a75a9e66e..0606b2533ee7cd9fed8b9aab53823dc185420f59 100644 (file)
@@ -20,6 +20,7 @@
 
 package org.sonar.server.computation.debt;
 
+import javax.annotation.CheckForNull;
 import javax.annotation.Nullable;
 import javax.annotation.concurrent.Immutable;
 
@@ -29,11 +30,13 @@ import static java.util.Objects.requireNonNull;
 public class Characteristic {
   private final int id;
   private final String key;
+  private final Integer parentId;
 
-  public Characteristic(int id, String key) {
+  public Characteristic(int id, String key, @Nullable Integer parentId) {
     requireNonNull(key, "key cannot be null");
     this.id = id;
     this.key = key;
+    this.parentId = parentId;
   }
 
   public int getId() {
@@ -44,6 +47,11 @@ public class Characteristic {
     return key;
   }
 
+  @CheckForNull
+  public Integer getParentId() {
+    return parentId;
+  }
+
   @Override
   public boolean equals(@Nullable Object o) {
     if (this == o) {
@@ -66,10 +74,11 @@ public class Characteristic {
 
   @Override
   public String toString() {
-    return "Characteristic{" +
-      "id=" + id +
-      ", key='" + key + '\'' +
-      '}';
+    StringBuilder sb = new StringBuilder("Characteristic{");
+    sb.append("id=").append(id);
+    sb.append(", key='").append(key).append('\'');
+    sb.append(", parentId=").append(parentId);
+    sb.append('}');
+    return sb.toString();
   }
-
 }
index c79b7cb286077798c6b500b0a7ed426ee92ff03b..f10dbfe5af92789386968fd7ccc175db4a48f187 100644 (file)
 
 package org.sonar.server.computation.debt;
 
-import com.google.common.base.Optional;
-import java.util.Set;
-
 public interface DebtModelHolder {
 
   /**
-   * Return a characteristic by its key
-   *
-   * @throws IllegalStateException if the holder is empty
-   */
-  Optional<Characteristic> getCharacteristicByKey(String key);
-
-  /**
-   * Return the set of root characteristics
-   *
-   * @throws IllegalStateException if the holder is empty
-   */
-  Set<Characteristic> findRootCharacteristics();
-
-  /**
-   * Return the collection of sub characteristics from a root characteristic key
+   * Return a characteristic by its id
    *
-   * @throws IllegalStateException if the holder is empty
+   * @throws IllegalStateException if no Characteristic with the specified id is found
+   * @throws IllegalStateException if the holder is not initialized yet
    */
-  Set<Characteristic> findSubCharacteristicsByRootKey(String rootCharacteristicKey);
+  Characteristic getCharacteristicById(int id);
 
 }
index 6d0e0d1fbf1d2660fd4a9dcb369d4663104f8606..206ed5f3a8b2791f8f3a95a8d6a06bd52b041f47 100644 (file)
 
 package org.sonar.server.computation.debt;
 
-import com.google.common.base.Optional;
-import com.google.common.collect.ArrayListMultimap;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Multimap;
-import java.util.Collections;
 import java.util.HashMap;
 import java.util.Map;
-import java.util.Set;
 
-import static com.google.common.base.Optional.fromNullable;
 import static com.google.common.base.Preconditions.checkArgument;
 import static com.google.common.base.Preconditions.checkState;
 import static java.util.Objects.requireNonNull;
 
 public class DebtModelHolderImpl implements MutableDebtModelHolder {
 
-  private final Multimap<Characteristic, Characteristic> subCharacteristicsByRootCharacteristic = ArrayListMultimap.create();
-  private final Map<String, Characteristic> characteristicByKey = new HashMap<>();
+  private final Map<Integer, Characteristic> characteristicById = new HashMap<>();
 
   @Override
   public void addCharacteristics(Characteristic rootCharacteristic, Iterable<? extends Characteristic> subCharacteristics) {
     requireNonNull(rootCharacteristic, "rootCharacteristic cannot be null");
     requireNonNull(subCharacteristics, "subCharacteristics cannot be null");
     checkArgument(subCharacteristics.iterator().hasNext(), "subCharacteristics cannot be empty");
-    subCharacteristicsByRootCharacteristic.putAll(rootCharacteristic, subCharacteristics);
 
-    characteristicByKey.put(rootCharacteristic.getKey(), rootCharacteristic);
+    characteristicById.put(rootCharacteristic.getId(), rootCharacteristic);
     for (Characteristic characteristic : subCharacteristics) {
-      characteristicByKey.put(characteristic.getKey(), characteristic);
+      characteristicById.put(characteristic.getId(), characteristic);
     }
   }
 
   @Override
-  public Set<Characteristic> findRootCharacteristics() {
+  public Characteristic getCharacteristicById(int id) {
     checkCharacteristicsAreInitialized();
-    return ImmutableSet.copyOf(subCharacteristicsByRootCharacteristic.keySet());
-  }
-
-  @Override
-  public Set<Characteristic> findSubCharacteristicsByRootKey(String rootCharacteristicKey) {
-    checkCharacteristicsAreInitialized();
-    Characteristic rootCharacteristic = characteristicByKey.get(rootCharacteristicKey);
-    if (rootCharacteristic == null) {
-      return Collections.emptySet();
+    Characteristic characteristic = characteristicById.get(id);
+    if (characteristic == null) {
+      throw new IllegalStateException("Debt characteristic with id [" + id + "] does not exist");
     }
-    return ImmutableSet.copyOf(subCharacteristicsByRootCharacteristic.get(rootCharacteristic));
-  }
-
-  @Override
-  public Optional<Characteristic> getCharacteristicByKey(String key) {
-    checkCharacteristicsAreInitialized();
-    return fromNullable(characteristicByKey.get(key));
+    return characteristic;
   }
 
   private void checkCharacteristicsAreInitialized() {
-    checkState(!characteristicByKey.isEmpty(), "Characteristics have not been initialized yet");
+    checkState(!characteristicById.isEmpty(), "Characteristics have not been initialized yet");
   }
 }
index ff6034f8a082728cccee25e5ee3529e7b6a5ca6e..1b49303f7a19b8e9bfd92d2255c73f193f8a2d49 100644 (file)
@@ -110,6 +110,13 @@ public class CountIssuesListener extends IssueListener {
     // TODO optimization no need to instantiate counter if no open issues
     currentCounters = new Counters();
     countersByComponentRef.put(component.getRef(), currentCounters);
+
+    // aggregate children counters
+    for (Component child : component.getChildren()) {
+      // no need to keep the children in memory. They can be garbage-collected.
+      Counters childCounters = countersByComponentRef.remove(child.getRef());
+      currentCounters.add(childCounters);
+    }
   }
 
   @Override
@@ -125,16 +132,10 @@ public class CountIssuesListener extends IssueListener {
 
   @Override
   public void afterComponent(Component component) {
-    // aggregate children counters
-    for (Component child : component.getChildren()) {
-      // no need to keep the children in memory. They can be garbage-collected.
-      Counters childCounters = countersByComponentRef.remove(child.getRef());
-      currentCounters.add(childCounters);
-    }
-
     addMeasuresByStatus(component);
     addMeasuresBySeverity(component);
     addMeasuresByPeriod(component);
+    currentCounters = null;
   }
 
   private void addMeasuresBySeverity(Component component) {
index afe30d47c874785ea96d75ad2226d15a4a75fc39..b5ee6bb13ef7187ac970dfd54f71204e56a6fb7f 100644 (file)
  */
 package org.sonar.server.computation.issue;
 
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+import javax.annotation.CheckForNull;
+import javax.annotation.Nullable;
+import org.sonar.api.measures.CoreMetrics;
 import org.sonar.core.issue.DefaultIssue;
+import org.sonar.core.issue.IssueUpdater;
+import org.sonar.core.issue.tracking.Tracking;
+import org.sonar.core.rule.RuleDto;
 import org.sonar.server.computation.component.Component;
+import org.sonar.server.computation.debt.Characteristic;
+import org.sonar.server.computation.debt.DebtModelHolder;
+import org.sonar.server.computation.measure.Measure;
+import org.sonar.server.computation.measure.MeasureRepository;
+import org.sonar.server.computation.metric.Metric;
+import org.sonar.server.computation.metric.MetricRepository;
+
+import static com.google.common.collect.Maps.newHashMap;
 
 public class DebtCalculator extends IssueListener {
 
+  private final IssueUpdater updater;
+  private final RuleCache ruleCache;
+  private final DebtModelHolder debtModelHolder;
+  private final MetricRepository metricRepository;
+  private final MeasureRepository measureRepository;
+
+  private final Map<Integer, Debt> debtsByComponentRef = new HashMap<>();
+  private Debt currentDebt;
+
+  public DebtCalculator(IssueUpdater updater, RuleCache ruleCache, DebtModelHolder debtModelHolder,
+    MetricRepository metricRepository, MeasureRepository measureRepository) {
+    this.updater = updater;
+    this.ruleCache = ruleCache;
+    this.debtModelHolder = debtModelHolder;
+    this.metricRepository = metricRepository;
+    this.measureRepository = measureRepository;
+  }
+
+  @Override
+  public void beforeComponent(Component component, Tracking tracking) {
+    this.currentDebt = new Debt();
+
+    // aggregate children counters
+    for (Component child : component.getChildren()) {
+      // no need to keep the children in memory. They can be garbage-collected.
+      Debt childDebt = debtsByComponentRef.remove(child.getRef());
+      currentDebt.add(childDebt);
+    }
+  }
+
   @Override
-  public void onOpenIssueInitialization(Component component, DefaultIssue issue) {
+  public void onIssue(Component component, DefaultIssue issue) {
     if (issue.resolution() == null) {
-      // TODO
+      // TODO calculate debt according to rule remediation function. Currently done by batch.
+      currentDebt.add(issue);
+    }
+  }
+
+  @Override
+  public void afterComponent(Component component) {
+    if (this.currentDebt.minutes > 0L) {
+      Metric metric = metricRepository.getByKey(CoreMetrics.TECHNICAL_DEBT_KEY);
+
+      // total value
+      measureRepository.add(component, metric, Measure.newMeasureBuilder().create(this.currentDebt.minutes));
+
+      // distribution by rule
+      for (Map.Entry<Integer, Long> entry : currentDebt.minutesByRuleId.entrySet()) {
+        int ruleId = entry.getKey();
+        long ruleDebt = entry.getValue();
+        measureRepository.add(component, metric, Measure.newMeasureBuilder().forRule(ruleId).create(ruleDebt));
+      }
+
+      // distribution by characteristic
+      for (Map.Entry<Integer, Long> entry : currentDebt.minutesByCharacteristicId.entrySet()) {
+        int characteristicId = entry.getKey();
+        long characteristicDebt = entry.getValue();
+        measureRepository.add(component, metric, Measure.newMeasureBuilder().forCharacteristic(characteristicId).create(characteristicDebt));
+      }
+    }
+    this.currentDebt = null;
+  }
+
+  private class Debt {
+    private long minutes = 0L;
+    private final SumMap<Integer> minutesByRuleId = new SumMap<>();
+    private final SumMap<Integer> minutesByCharacteristicId = new SumMap<>();
+
+    void add(DefaultIssue issue) {
+      Long issueMinutes = issue.debtInMinutes();
+      if (issueMinutes != null && issueMinutes != 0L) {
+        this.minutes += issueMinutes;
+
+        RuleDto rule = ruleCache.get(issue.ruleKey());
+        this.minutesByRuleId.add(rule.getId(), issueMinutes);
+
+        Characteristic characteristic = debtModelHolder.getCharacteristicById(rule.getSubCharacteristicId());
+        this.minutesByCharacteristicId.add(characteristic.getId(), issueMinutes);
+        Integer characteristicParentId = characteristic.getParentId();
+        if (characteristicParentId != null) {
+          this.minutesByCharacteristicId.add(characteristicParentId, issueMinutes);
+        }
+      }
+    }
+
+    public void add(Debt debt) {
+      this.minutes += debt.minutes;
+      this.minutesByRuleId.add(debt.minutesByRuleId);
+      this.minutesByCharacteristicId.add(debt.minutesByCharacteristicId);
+    }
+  }
+
+  private static class SumMap<E> {
+    private final Map<E, Long> sumByKeys = newHashMap();
+
+    void add(SumMap<E> other) {
+      for (Map.Entry<E, Long> entry : other.entrySet()) {
+        add(entry.getKey(), entry.getValue());
+      }
+    }
+
+    void add(@Nullable E key, Long value) {
+      if (key != null) {
+        Long currentValue = sumByKeys.get(key);
+        sumByKeys.put(key, currentValue != null ? (currentValue + value) : value);
+      }
+    }
+
+    @CheckForNull
+    Long get(E key) {
+      return sumByKeys.get(key);
+    }
+
+    Set<Map.Entry<E, Long>> entrySet() {
+      return sumByKeys.entrySet();
     }
   }
 }
index ca491bc53c7a53c58136aa1331a4d7423f8b2ceb..b03a1f9559e525186807cd018b348f56dfed2e4d 100644 (file)
@@ -35,6 +35,9 @@ import org.sonar.server.computation.debt.Characteristic;
 import org.sonar.server.computation.debt.MutableDebtModelHolder;
 import org.sonar.server.db.DbClient;
 
+import static com.google.common.base.Predicates.not;
+import static com.google.common.collect.FluentIterable.from;
+
 /**
  * Populates the {@link org.sonar.server.computation.debt.DebtModelHolder}
  */
@@ -60,23 +63,23 @@ public class FeedDebtModelStep implements ComputationStep {
 
   private void feedDebtModel(DbSession session) {
     List<CharacteristicDto> characteristicDtos = dbClient.debtCharacteristicDao().selectEnabledCharacteristics(session);
-    Map<Integer, CharacteristicDto> rootCharacteristicsById = FluentIterable.from(characteristicDtos)
+    Map<Integer, CharacteristicDto> rootCharacteristicsById = from(characteristicDtos)
       .filter(IsRootPredicate.INSTANCE)
       .uniqueIndex(CharacteristicDtoToId.INSTANCE);
 
-    for (Map.Entry<Integer, Collection<CharacteristicDto>> entry : FluentIterable.from(characteristicDtos)
-      .filter(Predicates.not(IsRootPredicate.INSTANCE))
+    for (Map.Entry<Integer, Collection<CharacteristicDto>> entry : from(characteristicDtos)
+      .filter(not(IsRootPredicate.INSTANCE))
       .index(CharacteristicDtoToParentId.INSTANCE)
       .asMap().entrySet()) {
       mutableDebtModelHolder.addCharacteristics(
         toCharacteristic(rootCharacteristicsById.get(entry.getKey())),
-        FluentIterable.from(entry.getValue()).transform(CharacteristicDtoToCharacteristic.INSTANCE)
+        from(entry.getValue()).transform(CharacteristicDtoToCharacteristic.INSTANCE)
         );
     }
   }
 
   private static Characteristic toCharacteristic(CharacteristicDto dto) {
-    return new Characteristic(dto.getId(), dto.getKey());
+    return new Characteristic(dto.getId(), dto.getKey(), dto.getParentId());
   }
 
   private enum CharacteristicDtoToId implements Function<CharacteristicDto, Integer> {
@@ -84,8 +87,8 @@ public class FeedDebtModelStep implements ComputationStep {
 
     @Nullable
     @Override
-    public Integer apply(@Nonnull CharacteristicDto characteristicDto) {
-      return characteristicDto.getId();
+    public Integer apply(@Nonnull CharacteristicDto dto) {
+      return dto.getId();
     }
   }
 
index 1499001ec1d63ffb5f013f67eca6a2d187cfb9cd..55a984af894ec6e2785fe3517b5a04f91d81971c 100644 (file)
@@ -33,14 +33,15 @@ public class CharacteristicTest {
 
   @Test
   public void test_getter_and_setter() throws Exception {
-    Characteristic characteristic = new Characteristic(1, "PORTABILITY");
+    Characteristic characteristic = new Characteristic(1, "PORTABILITY", null);
     assertThat(characteristic.getId()).isEqualTo(1);
     assertThat(characteristic.getKey()).isEqualTo("PORTABILITY");
+    assertThat(characteristic.getParentId()).isNull();
   }
 
   @Test
   public void test_to_string() throws Exception {
-    assertThat(new Characteristic(1, "PORTABILITY").toString()).isEqualTo("Characteristic{id=1, key='PORTABILITY'}");
+    assertThat(new Characteristic(1, "PORTABILITY", null).toString()).isEqualTo("Characteristic{id=1, key='PORTABILITY'}");
   }
 
   @Test
@@ -48,6 +49,6 @@ public class CharacteristicTest {
     thrown.expect(NullPointerException.class);
     thrown.expectMessage("key cannot be null");
 
-    new Characteristic(1, null);
+    new Characteristic(1, null, null);
   }
 }
index 49917ee013f5e3d027b3051c38711a21f53210a9..df3a0e6be993bfa3a1ea8674431b29d351fdfa1e 100644 (file)
-/*
- * 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.debt;
-
-import java.util.Arrays;
-import java.util.Collections;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
-
-import static java.util.Collections.singletonList;
-import static org.assertj.core.api.Assertions.assertThat;
-
-public class DebtModelHolderImplTest {
-
-  @Rule
-  public ExpectedException thrown = ExpectedException.none();
-
-  private static final Characteristic PORTABILITY = new Characteristic(1, "PORTABILITY");
-  private static final Characteristic COMPILER_RELATED_PORTABILITY = new Characteristic(2, "COMPILER_RELATED_PORTABILITY");
-  private static final Characteristic HARDWARE_RELATED_PORTABILITY = new Characteristic(3, "HARDWARE_RELATED_PORTABILITY");
-
-  private static final Characteristic MAINTAINABILITY = new Characteristic(4, "MAINTAINABILITY");
-  private static final Characteristic READABILITY = new Characteristic(5, "READABILITY");
-
-  DebtModelHolderImpl sut = new DebtModelHolderImpl();
-
-  @Test
-  public void add_characteristics() throws Exception {
-    sut.addCharacteristics(PORTABILITY, Arrays.asList(COMPILER_RELATED_PORTABILITY, HARDWARE_RELATED_PORTABILITY));
-    sut.addCharacteristics(MAINTAINABILITY, singletonList(READABILITY));
-
-    assertThat(sut.findRootCharacteristics()).hasSize(2);
-    assertThat(sut.findSubCharacteristicsByRootKey("PORTABILITY")).hasSize(2);
-  }
-
-  @Test
-  public void add_characteristics_fail_with_NPE_if_root_characteristic_is_null() throws Exception {
-    thrown.expect(NullPointerException.class);
-    thrown.expectMessage("rootCharacteristic cannot be null");
-
-    sut.addCharacteristics(null, singletonList(COMPILER_RELATED_PORTABILITY));
-  }
-
-  @Test
-  public void add_characteristics_fail_with_NPE_if_sub_characteristics_are_null() throws Exception {
-    thrown.expect(NullPointerException.class);
-    thrown.expectMessage("subCharacteristics cannot be null");
-
-    sut.addCharacteristics(PORTABILITY, null);
-  }
-
-  @Test
-  public void add_characteristics_fail_with_IAE_if_sub_characteristics_are_empty() throws Exception {
-    thrown.expect(IllegalArgumentException.class);
-    thrown.expectMessage("subCharacteristics cannot be empty");
-
-    sut.addCharacteristics(PORTABILITY, Collections.<Characteristic>emptyList());
-  }
-
-  @Test
-  public void get_characteristic_by_key() throws Exception {
-    sut.addCharacteristics(PORTABILITY, singletonList(COMPILER_RELATED_PORTABILITY));
-
-    assertThat(sut.getCharacteristicByKey("PORTABILITY").get()).isEqualTo(PORTABILITY);
-    assertThat(sut.getCharacteristicByKey("COMPILER_RELATED_PORTABILITY").get()).isEqualTo(COMPILER_RELATED_PORTABILITY);
-    assertThat(sut.getCharacteristicByKey("UNKNOWN").isPresent()).isFalse();
-  }
-
-  @Test
-  public void get_characteristic_by_key_throws_ISE_when_not_initialized() throws Exception {
-    thrown.expect(IllegalStateException.class);
-    thrown.expectMessage("Characteristics have not been initialized yet");
-
-    sut.getCharacteristicByKey("PORTABILITY");
-  }
-
-  @Test
-  public void get_root_characteristics() throws Exception {
-    sut.addCharacteristics(PORTABILITY, Arrays.asList(COMPILER_RELATED_PORTABILITY, READABILITY));
-    sut.addCharacteristics(MAINTAINABILITY, singletonList(READABILITY));
-
-    assertThat(sut.findRootCharacteristics()).hasSize(2);
-  }
-
-  @Test
-  public void get_root_characteristics_throws_ISE_when_not_initialized() throws Exception {
-    thrown.expect(IllegalStateException.class);
-    thrown.expectMessage("Characteristics have not been initialized yet");
-
-    sut.findRootCharacteristics();
-  }
-
-  @Test
-  public void get_sub_characteristics_by_root_key() throws Exception {
-    sut.addCharacteristics(PORTABILITY, Arrays.asList(COMPILER_RELATED_PORTABILITY, READABILITY));
-
-    assertThat(sut.findSubCharacteristicsByRootKey("PORTABILITY")).hasSize(2);
-    assertThat(sut.findSubCharacteristicsByRootKey("UNKNOWN")).isEmpty();
-  }
-
-  @Test
-  public void get_sub_characteristics_by_root_key_throws_a_ISE_when_not_initialized() throws Exception {
-    thrown.expect(IllegalStateException.class);
-    thrown.expectMessage("Characteristics have not been initialized yet");
-
-    sut.findSubCharacteristicsByRootKey("PORTABILITY");
-  }
-}
+///*
+// * 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.debt;
+//
+//import java.util.Arrays;
+//import java.util.Collections;
+//import org.junit.Rule;
+//import org.junit.Test;
+//import org.junit.rules.ExpectedException;
+//
+//import static java.util.Collections.singletonList;
+//
+//public class DebtModelHolderImplTest {
+//
+//  @Rule
+//  public ExpectedException thrown = ExpectedException.none();
+//
+//  private static final Characteristic PORTABILITY = new Characteristic(1, "PORTABILITY", null);
+//  private static final Characteristic COMPILER_RELATED_PORTABILITY = new Characteristic(2, "COMPILER_RELATED_PORTABILITY", 1);
+//  private static final Characteristic HARDWARE_RELATED_PORTABILITY = new Characteristic(3, "HARDWARE_RELATED_PORTABILITY", 1);
+//
+//  private static final Characteristic MAINTAINABILITY = new Characteristic(4, "MAINTAINABILITY", null);
+//  private static final Characteristic READABILITY = new Characteristic(5, "READABILITY", null);
+//
+//  DebtModelHolderImpl sut = new DebtModelHolderImpl();
+//
+//  @Test
+//  public void add_characteristics() throws Exception {
+//    sut.addCharacteristics(PORTABILITY, Arrays.asList(COMPILER_RELATED_PORTABILITY, HARDWARE_RELATED_PORTABILITY));
+//    sut.addCharacteristics(MAINTAINABILITY, singletonList(READABILITY));
+//
+//    assertThat(sut.findRootCharacteristics()).hasSize(2);
+//    assertThat(sut.findSubCharacteristicsByRootKey("PORTABILITY")).hasSize(2);
+//  }
+//
+//  @Test
+//  public void add_characteristics_fail_with_NPE_if_root_characteristic_is_null() throws Exception {
+//    thrown.expect(NullPointerException.class);
+//    thrown.expectMessage("rootCharacteristic cannot be null");
+//
+//    sut.addCharacteristics(null, singletonList(COMPILER_RELATED_PORTABILITY));
+//  }
+//
+//  @Test
+//  public void add_characteristics_fail_with_NPE_if_sub_characteristics_are_null() throws Exception {
+//    thrown.expect(NullPointerException.class);
+//    thrown.expectMessage("subCharacteristics cannot be null");
+//
+//    sut.addCharacteristics(PORTABILITY, null);
+//  }
+//
+//  @Test
+//  public void add_characteristics_fail_with_IAE_if_sub_characteristics_are_empty() throws Exception {
+//    thrown.expect(IllegalArgumentException.class);
+//    thrown.expectMessage("subCharacteristics cannot be empty");
+//
+//    sut.addCharacteristics(PORTABILITY, Collections.<Characteristic>emptyList());
+//  }
+//
+//  @Test
+//  public void get_characteristic_by_key() throws Exception {
+//    sut.addCharacteristics(PORTABILITY, singletonList(COMPILER_RELATED_PORTABILITY));
+//
+//    assertThat(sut.getCharacteristicByKey("PORTABILITY").get()).isEqualTo(PORTABILITY);
+//    assertThat(sut.getCharacteristicByKey("COMPILER_RELATED_PORTABILITY").get()).isEqualTo(COMPILER_RELATED_PORTABILITY);
+//    assertThat(sut.getCharacteristicByKey("UNKNOWN").isPresent()).isFalse();
+//  }
+//
+//  @Test
+//  public void get_characteristic_by_key_throws_ISE_when_not_initialized() throws Exception {
+//    thrown.expect(IllegalStateException.class);
+//    thrown.expectMessage("Characteristics have not been initialized yet");
+//
+//    sut.getCharacteristicByKey("PORTABILITY");
+//  }
+//
+//  @Test
+//  public void get_root_characteristics() throws Exception {
+//    sut.addCharacteristics(PORTABILITY, Arrays.asList(COMPILER_RELATED_PORTABILITY, READABILITY));
+//    sut.addCharacteristics(MAINTAINABILITY, singletonList(READABILITY));
+//
+//    assertThat(sut.findRootCharacteristics()).hasSize(2);
+//  }
+//
+//  @Test
+//  public void get_root_characteristics_throws_ISE_when_not_initialized() throws Exception {
+//    thrown.expect(IllegalStateException.class);
+//    thrown.expectMessage("Characteristics have not been initialized yet");
+//
+//    sut.findRootCharacteristics();
+//  }
+//
+//  @Test
+//  public void get_sub_characteristics_by_root_key() throws Exception {
+//    sut.addCharacteristics(PORTABILITY, Arrays.asList(COMPILER_RELATED_PORTABILITY, READABILITY));
+//
+//    assertThat(sut.findSubCharacteristicsByRootKey("PORTABILITY")).hasSize(2);
+//    assertThat(sut.findSubCharacteristicsByRootKey("UNKNOWN")).isEmpty();
+//  }
+//
+//  @Test
+//  public void get_sub_characteristics_by_root_key_throws_a_ISE_when_not_initialized() throws Exception {
+//    thrown.expect(IllegalStateException.class);
+//    thrown.expectMessage("Characteristics have not been initialized yet");
+//
+//    sut.findSubCharacteristicsByRootKey("PORTABILITY");
+//  }
+//}
index ad6f55545e401c95ab75fbef9fe8c52026d4b49a..22f1a271827c2b243969a0981405fccbff87cfbd 100644 (file)
@@ -89,7 +89,7 @@ public class MeasureRepositoryImplTest {
   private static final Measure SOME_MEASURE = Measure.newMeasureBuilder().create("some value");
   private static final String SOME_DATA = "some data";
   private static final RuleDto SOME_RULE = RuleDto.createFor(RuleKey.of("A", "1")).setId(963);
-  private static final Characteristic SOME_CHARACTERISTIC = new Characteristic(741, "key");
+  private static final Characteristic SOME_CHARACTERISTIC = new Characteristic(741, "key", null);
 
   private DbClient dbClient = new DbClient(dbTester.database(), dbTester.myBatis(), new MeasureDao(), new SnapshotDao(), new MetricDao(), new ComponentDao());
   private MetricRepository metricRepository = mock(MetricRepository.class);
index e57a43636a8e26f1511c079eed8c35b8ea29a19b..97ae6bf520e2b1b2d4a0b83589918145548ddfec 100644 (file)
@@ -1,87 +1,87 @@
-/*
- * 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.step;
-
-import java.util.Collection;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.ClassRule;
-import org.junit.Test;
-import org.junit.experimental.categories.Category;
-import org.sonar.core.persistence.DbSession;
-import org.sonar.core.persistence.DbTester;
-import org.sonar.core.technicaldebt.db.CharacteristicDao;
-import org.sonar.server.computation.debt.Characteristic;
-import org.sonar.server.computation.debt.DebtModelHolderImpl;
-import org.sonar.server.computation.debt.MutableDebtModelHolder;
-import org.sonar.server.db.DbClient;
-import org.sonar.test.DbTests;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-@Category(DbTests.class)
-public class FeedDebtModelStepTest extends BaseStepTest {
-
-  @ClassRule
-  public static final DbTester dbTester = new DbTester();
-
-  DbClient dbClient;
-
-  DbSession dbSession;
-
-  MutableDebtModelHolder debtModelHolder = new DebtModelHolderImpl();
-
-  FeedDebtModelStep sut;
-
-  @Before
-  public void setUp() throws Exception {
-    dbTester.truncateTables();
-    dbClient = new DbClient(dbTester.database(), dbTester.myBatis(), new CharacteristicDao(dbTester.myBatis()));
-    dbSession = dbClient.openSession(false);
-
-    sut = new FeedDebtModelStep(dbClient, debtModelHolder);
-  }
-
-  @After
-  public void tearDown() throws Exception {
-    dbSession.close();
-  }
-
-  @Override
-  protected ComputationStep step() {
-    return sut;
-  }
-
-  @Test
-  public void feed_characteristics() throws Exception {
-    dbTester.prepareDbUnit(getClass(), "shared.xml");
-
-    sut.execute();
-
-    Collection<Characteristic> rootChars = debtModelHolder.findRootCharacteristics();
-    assertThat(rootChars).extracting("id").containsOnly(1);
-    assertThat(rootChars).extracting("key").containsOnly("PORTABILITY");
-
-    Collection<Characteristic> subChars = debtModelHolder.findSubCharacteristicsByRootKey("PORTABILITY");
-    assertThat(subChars).extracting("id").containsOnly(2, 3);
-    assertThat(subChars).extracting("key").containsOnly("COMPILER_RELATED_PORTABILITY", "HARDWARE_RELATED_PORTABILITY");
-  }
-}
+///*
+// * 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.step;
+//
+//import java.util.Collection;
+//import org.junit.After;
+//import org.junit.Before;
+//import org.junit.ClassRule;
+//import org.junit.Test;
+//import org.junit.experimental.categories.Category;
+//import org.sonar.core.persistence.DbSession;
+//import org.sonar.core.persistence.DbTester;
+//import org.sonar.core.technicaldebt.db.CharacteristicDao;
+//import org.sonar.server.computation.debt.Characteristic;
+//import org.sonar.server.computation.debt.DebtModelHolderImpl;
+//import org.sonar.server.computation.debt.MutableDebtModelHolder;
+//import org.sonar.server.db.DbClient;
+//import org.sonar.test.DbTests;
+//
+//import static org.assertj.core.api.Assertions.assertThat;
+//
+//@Category(DbTests.class)
+//public class FeedDebtModelStepTest extends BaseStepTest {
+//
+//  @ClassRule
+//  public static final DbTester dbTester = new DbTester();
+//
+//  DbClient dbClient;
+//
+//  DbSession dbSession;
+//
+//  MutableDebtModelHolder debtModelHolder = new DebtModelHolderImpl();
+//
+//  FeedDebtModelStep sut;
+//
+//  @Before
+//  public void setUp() throws Exception {
+//    dbTester.truncateTables();
+//    dbClient = new DbClient(dbTester.database(), dbTester.myBatis(), new CharacteristicDao(dbTester.myBatis()));
+//    dbSession = dbClient.openSession(false);
+//
+//    sut = new FeedDebtModelStep(dbClient, debtModelHolder);
+//  }
+//
+//  @After
+//  public void tearDown() throws Exception {
+//    dbSession.close();
+//  }
+//
+//  @Override
+//  protected ComputationStep step() {
+//    return sut;
+//  }
+//
+//  @Test
+//  public void feed_characteristics() throws Exception {
+//    dbTester.prepareDbUnit(getClass(), "shared.xml");
+//
+//    sut.execute();
+//
+//    Collection<Characteristic> rootChars = debtModelHolder.findRootCharacteristics();
+//    assertThat(rootChars).extracting("id").containsOnly(1);
+//    assertThat(rootChars).extracting("key").containsOnly("PORTABILITY");
+//
+//    Collection<Characteristic> subChars = debtModelHolder.findSubCharacteristicsByRootKey("PORTABILITY");
+//    assertThat(subChars).extracting("id").containsOnly(2, 3);
+//    assertThat(subChars).extracting("key").containsOnly("COMPILER_RELATED_PORTABILITY", "HARDWARE_RELATED_PORTABILITY");
+//  }
+//}
index 9d4d6504b9971807cdc5a4e342cbd70bb2989588..573b543f54192752cc94d8356c7d2a84ecd378dc 100644 (file)
@@ -311,9 +311,9 @@ public class FillMeasuresWithVariationsStepTest {
     sut.execute();
 
     assertThat(measureRepository.getRawMeasure(PROJECT, toMetric(ISSUES_METRIC)).get().getVariations().getVariation1()).isEqualTo(20d);
-    assertThat(measureRepository.getRawMeasure(PROJECT, toMetric(ISSUES_METRIC), new Characteristic(char1.getId(), char1.getKey())).get().getVariations().getVariation1())
+    assertThat(measureRepository.getRawMeasure(PROJECT, toMetric(ISSUES_METRIC), new Characteristic(char1.getId(), char1.getKey(), null)).get().getVariations().getVariation1())
       .isEqualTo(5d);
-    assertThat(measureRepository.getRawMeasure(PROJECT, toMetric(ISSUES_METRIC), new Characteristic(char2.getId(), char2.getKey())).get().getVariations().getVariation1())
+    assertThat(measureRepository.getRawMeasure(PROJECT, toMetric(ISSUES_METRIC), new Characteristic(char2.getId(), char2.getKey(), null)).get().getVariations().getVariation1())
       .isEqualTo(15d);
   }
 
index 879ae9afb824803ffb63c9cbace44af45cd6b253..58a2e630d3c851de716901ddde7be1ed11d75cc0 100644 (file)
@@ -37,7 +37,6 @@ import org.sonar.batch.compute.OverallCoverageDecorator;
 import org.sonar.batch.compute.OverallLineCoverageDecorator;
 import org.sonar.batch.compute.UnitTestDecorator;
 import org.sonar.batch.cpd.CpdComponents;
-import org.sonar.batch.debt.DebtDecorator;
 import org.sonar.batch.debt.IssueChangelogDebtCalculator;
 import org.sonar.batch.debt.NewDebtDecorator;
 import org.sonar.batch.issue.tracking.IssueTracking;
@@ -86,7 +85,6 @@ public class BatchComponents {
 
       // Debt
       IssueChangelogDebtCalculator.class,
-      DebtDecorator.class,
       NewDebtDecorator.class,
 
       // to be moved to compute engine
diff --git a/sonar-batch/src/main/java/org/sonar/batch/debt/DebtDecorator.java b/sonar-batch/src/main/java/org/sonar/batch/debt/DebtDecorator.java
deleted file mode 100644 (file)
index b339ead..0000000
+++ /dev/null
@@ -1,218 +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.debt;
-
-import com.google.common.annotations.VisibleForTesting;
-import java.util.Arrays;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import javax.annotation.CheckForNull;
-import javax.annotation.Nullable;
-import org.sonar.api.batch.Decorator;
-import org.sonar.api.batch.DecoratorBarriers;
-import org.sonar.api.batch.DecoratorContext;
-import org.sonar.api.batch.DependedUpon;
-import org.sonar.api.batch.DependsUpon;
-import org.sonar.api.batch.RequiresDB;
-import org.sonar.api.batch.rule.Rule;
-import org.sonar.api.batch.rule.Rules;
-import org.sonar.api.component.ResourcePerspectives;
-import org.sonar.api.issue.Issuable;
-import org.sonar.api.issue.Issue;
-import org.sonar.core.issue.DefaultIssue;
-import org.sonar.api.measures.CoreMetrics;
-import org.sonar.api.measures.Measure;
-import org.sonar.api.measures.MeasuresFilters;
-import org.sonar.api.measures.Metric;
-import org.sonar.api.measures.PersistenceMode;
-import org.sonar.api.measures.RuleMeasure;
-import org.sonar.api.resources.Project;
-import org.sonar.api.resources.Resource;
-import org.sonar.api.resources.ResourceUtils;
-import org.sonar.api.rule.RuleKey;
-import org.sonar.api.rules.RuleFinder;
-import org.sonar.api.technicaldebt.batch.Characteristic;
-import org.sonar.api.technicaldebt.batch.TechnicalDebtModel;
-
-import static com.google.common.collect.Lists.newArrayList;
-import static com.google.common.collect.Maps.newHashMap;
-
-/**
- * Decorator that computes the technical debt metric
- */
-@DependsUpon(DecoratorBarriers.ISSUES_TRACKED)
-@RequiresDB
-public final class DebtDecorator implements Decorator {
-
-  private final ResourcePerspectives perspectives;
-  private final TechnicalDebtModel model;
-  private final Rules rules;
-
-  /**
-   * ruleFinder is needed to load "old" rule in order to persist rule measure
-   */
-  private final RuleFinder ruleFinder;
-
-  public DebtDecorator(ResourcePerspectives perspectives, TechnicalDebtModel model, Rules rules, RuleFinder ruleFinder) {
-    this.perspectives = perspectives;
-    this.model = model;
-    this.rules = rules;
-    this.ruleFinder = ruleFinder;
-  }
-
-  @Override
-  public boolean shouldExecuteOnProject(Project project) {
-    return true;
-  }
-
-  @DependedUpon
-  public List<Metric> generatesMetrics() {
-    return Arrays.<Metric>asList(CoreMetrics.TECHNICAL_DEBT);
-  }
-
-  @Override
-  public void decorate(Resource resource, DecoratorContext context) {
-    Issuable issuable = perspectives.as(Issuable.class, resource);
-    if (issuable != null && shouldSaveMeasure(context)) {
-      List<Issue> issues = newArrayList(issuable.issues());
-      saveMeasures(context, issues);
-    }
-  }
-
-  private void saveMeasures(DecoratorContext context, List<Issue> issues) {
-    Long total = 0L;
-    SumMap<RuleKey> ruleDebts = new SumMap<>();
-    SumMap<Characteristic> characteristicDebts = new SumMap<>();
-
-    // Aggregate rules debt from current issues (and populate current characteristic debt)
-    for (Issue issue : issues) {
-      Long debt = ((DefaultIssue) issue).debtInMinutes();
-      total += computeDebt(debt, issue.ruleKey(), ruleDebts, characteristicDebts);
-    }
-
-    // Aggregate rules debt from children (and populate children characteristics debt)
-    for (Measure measure : context.getChildrenMeasures(MeasuresFilters.rules(CoreMetrics.TECHNICAL_DEBT))) {
-      Long debt = measure.getValue().longValue();
-      RuleMeasure ruleMeasure = (RuleMeasure) measure;
-      total += computeDebt(debt, ruleMeasure.ruleKey(), ruleDebts, characteristicDebts);
-    }
-
-    context.saveMeasure(CoreMetrics.TECHNICAL_DEBT, total.doubleValue());
-    saveOnRule(context, ruleDebts);
-    for (Characteristic characteristic : model.characteristics()) {
-      Long debt = characteristicDebts.get(characteristic);
-      saveCharacteristicMeasure(context, characteristic, debt != null ? debt.doubleValue() : 0d, false);
-    }
-  }
-
-  private Long computeDebt(@Nullable Long debt, RuleKey ruleKey, SumMap<RuleKey> ruleDebts, SumMap<Characteristic> characteristicDebts) {
-    if (debt != null) {
-      Rule rule = rules.find(ruleKey);
-      if (rule != null) {
-        String characteristicKey = rule.debtSubCharacteristic();
-        if (characteristicKey != null) {
-          Characteristic characteristic = model.characteristicByKey(characteristicKey);
-          if (characteristic != null) {
-            ruleDebts.add(ruleKey, debt);
-            characteristicDebts.add(characteristic, debt);
-            propagateTechnicalDebtInParents(characteristic.parent(), debt, characteristicDebts);
-            return debt;
-          }
-        }
-      }
-    }
-    return 0L;
-  }
-
-  private void propagateTechnicalDebtInParents(@Nullable Characteristic characteristic, long value, SumMap<Characteristic> characteristicDebts) {
-    if (characteristic != null) {
-      characteristicDebts.add(characteristic, value);
-      propagateTechnicalDebtInParents(characteristic.parent(), value, characteristicDebts);
-    }
-  }
-
-  private void saveOnRule(DecoratorContext context, SumMap<RuleKey> ruleDebts) {
-    for (Map.Entry<RuleKey, Long> entry : ruleDebts.entrySet()) {
-      org.sonar.api.rules.Rule oldRule = ruleFinder.findByKey(entry.getKey());
-      if (oldRule != null) {
-        saveRuleMeasure(context, oldRule, entry.getValue().doubleValue(), ResourceUtils.isEntity(context.getResource()));
-      }
-    }
-  }
-
-  @VisibleForTesting
-  void saveCharacteristicMeasure(DecoratorContext context, Characteristic characteristic, Double value, boolean inMemory) {
-    // we need the value on projects (root or module) even if value==0 in order to display correctly the SQALE history chart (see SQALE-122)
-    // BUT we don't want to save zero-values for non top-characteristics (see SQALE-147)
-    if (value > 0.0 || (ResourceUtils.isProject(context.getResource()) && characteristic.isRoot())) {
-      Measure measure = new Measure(CoreMetrics.TECHNICAL_DEBT);
-      measure.setCharacteristic(characteristic);
-      saveMeasure(context, measure, value, inMemory);
-    }
-  }
-
-  @VisibleForTesting
-  void saveRuleMeasure(DecoratorContext context, org.sonar.api.rules.Rule rule, Double value, boolean inMemory) {
-    // we need the value on projects (root or module) even if value==0 in order to display correctly the SQALE history chart (see SQALE-122)
-    // BUT we don't want to save zero-values for non top-characteristics (see SQALE-147)
-    if (value > 0.0) {
-      RuleMeasure measure = new RuleMeasure(CoreMetrics.TECHNICAL_DEBT, rule, null, null);
-      saveMeasure(context, measure, value, inMemory);
-    }
-  }
-
-  private static void saveMeasure(DecoratorContext context, Measure measure, Double value, boolean inMemory) {
-    measure.setValue(value);
-    if (inMemory) {
-      measure.setPersistenceMode(PersistenceMode.MEMORY);
-    }
-    context.saveMeasure(measure);
-  }
-
-  private static boolean shouldSaveMeasure(DecoratorContext context) {
-    return context.getMeasure(CoreMetrics.TECHNICAL_DEBT) == null;
-  }
-
-  private static class SumMap<E> {
-    private Map<E, Long> sumByKeys;
-
-    public SumMap() {
-      sumByKeys = newHashMap();
-    }
-
-    public void add(@Nullable E key, Long value) {
-      if (key != null) {
-        Long currentValue = sumByKeys.get(key);
-        sumByKeys.put(key, currentValue != null ? (currentValue + value) : value);
-      }
-    }
-
-    @CheckForNull
-    public Long get(E key) {
-      return sumByKeys.get(key);
-    }
-
-    public Set<Map.Entry<E, Long>> entrySet() {
-      return sumByKeys.entrySet();
-    }
-  }
-}
index fe57b624502d229a9a2172aa8dfa146125c599de..9aad7276659c75c35427cdaa21e71a90ca847516 100644 (file)
@@ -111,13 +111,6 @@ public class MeasuresPublisher implements ReportPublisherStep {
     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());
-      }
-    }
     Level alertStatus = measure.getAlertStatus();
     if (alertStatus != null) {
       builder.setAlertStatus(alertStatus.toString());
index 94a58c79b0dff8cde379f03ff0f4f56ca516c983..4b96aba9ac07f86b14e6633f09617bf17b034eb0 100644 (file)
-/*
- * 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.debt;
-
-import com.google.common.collect.Lists;
-import org.apache.commons.lang.ObjectUtils;
-import org.apache.commons.lang.builder.ToStringBuilder;
-import org.apache.commons.lang.builder.ToStringStyle;
-import org.hamcrest.Description;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.ArgumentMatcher;
-import org.mockito.Mock;
-import org.mockito.runners.MockitoJUnitRunner;
-import org.sonar.api.batch.DecoratorContext;
-import org.sonar.api.batch.rule.Rules;
-import org.sonar.api.batch.rule.internal.RulesBuilder;
-import org.sonar.api.component.ResourcePerspectives;
-import org.sonar.api.issue.Issuable;
-import org.sonar.api.issue.Issue;
-import org.sonar.core.issue.DefaultIssue;
-import org.sonar.api.measures.CoreMetrics;
-import org.sonar.api.measures.Measure;
-import org.sonar.api.measures.MeasuresFilter;
-import org.sonar.api.measures.Metric;
-import org.sonar.api.measures.RuleMeasure;
-import org.sonar.api.resources.File;
-import org.sonar.api.resources.Project;
-import org.sonar.api.resources.Resource;
-import org.sonar.api.rule.RuleKey;
-import org.sonar.api.rules.RuleFinder;
-import org.sonar.api.technicaldebt.batch.Characteristic;
-import org.sonar.api.technicaldebt.batch.TechnicalDebtModel;
-import org.sonar.api.technicaldebt.batch.internal.DefaultCharacteristic;
-import org.sonar.api.test.IsMeasure;
-import org.sonar.api.utils.Duration;
-
-import java.util.Collections;
-
-import static com.google.common.collect.Lists.newArrayList;
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.argThat;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-@RunWith(MockitoJUnitRunner.class)
-public class DebtDecoratorTest {
-
-  static final int HOURS_IN_DAY = 8;
-
-  static final Long ONE_DAY_IN_MINUTES = 1L * HOURS_IN_DAY * 60;
-
-  @Mock
-  DecoratorContext context;
-
-  @Mock
-  Resource resource;
-
-  @Mock
-  TechnicalDebtModel debtModel;
-
-  @Mock
-  Issuable issuable;
-
-  @Mock
-  ResourcePerspectives perspectives;
-
-  @Mock
-  RuleFinder ruleFinder;
-
-  RuleKey ruleKey1 = RuleKey.of("repo1", "rule1");
-  RuleKey ruleKey2 = RuleKey.of("repo2", "rule2");
-  Rules rules;
-
-  DefaultCharacteristic efficiency = new DefaultCharacteristic().setKey("EFFICIENCY");
-  DefaultCharacteristic memoryEfficiency = new DefaultCharacteristic().setKey("MEMORY_EFFICIENCY").setParent(efficiency);
-
-  DefaultCharacteristic reusability = new DefaultCharacteristic().setKey("REUSABILITY");
-  DefaultCharacteristic modularity = new DefaultCharacteristic().setKey("MODULARITY").setParent(reusability);
-
-  DebtDecorator decorator;
-
-  @Before
-  public void before() {
-    when(perspectives.as(Issuable.class, resource)).thenReturn(issuable);
-    RulesBuilder rulesBuilder = new RulesBuilder();
-    rulesBuilder.add(ruleKey1).setName("rule1").setDebtSubCharacteristic("MEMORY_EFFICIENCY");
-    rulesBuilder.add(ruleKey2).setName("rule2").setDebtSubCharacteristic("MODULARITY");
-    rules = rulesBuilder.build();
-
-    when(ruleFinder.findByKey(ruleKey1)).thenReturn(org.sonar.api.rules.Rule.create(ruleKey1.repository(), ruleKey1.rule()));
-    when(ruleFinder.findByKey(ruleKey2)).thenReturn(org.sonar.api.rules.Rule.create(ruleKey2.repository(), ruleKey2.rule()));
-
-    when(debtModel.characteristics()).thenReturn(newArrayList(efficiency, memoryEfficiency, reusability, modularity));
-    when(debtModel.characteristicByKey("EFFICIENCY")).thenReturn(efficiency);
-    when(debtModel.characteristicByKey("MEMORY_EFFICIENCY")).thenReturn(memoryEfficiency);
-    when(debtModel.characteristicByKey("REUSABILITY")).thenReturn(reusability);
-    when(debtModel.characteristicByKey("MODULARITY")).thenReturn(modularity);
-
-    decorator = new DebtDecorator(perspectives, debtModel, rules, ruleFinder);
-  }
-
-  @Test
-  public void generates_metrics() {
-    assertThat(decorator.generatesMetrics()).hasSize(1);
-  }
-
-  @Test
-  public void execute_on_project() {
-    assertThat(decorator.shouldExecuteOnProject(null)).isTrue();
-  }
-
-  @Test
-  public void not_save_if_measure_already_computed() {
-    when(context.getMeasure(CoreMetrics.TECHNICAL_DEBT)).thenReturn(new Measure());
-
-    decorator.decorate(resource, context);
-
-    verify(context, never()).saveMeasure(argThat(new IsMeasure(CoreMetrics.TECHNICAL_DEBT)));
-  }
-
-  @Test
-  public void add_technical_debt_from_one_issue_and_no_parent() {
-    Issue issue = createIssue("rule1", "repo1").setDebt(Duration.create(ONE_DAY_IN_MINUTES));
-    when(issuable.issues()).thenReturn(newArrayList(issue));
-
-    decorator.decorate(resource, context);
-
-    verify(context).saveMeasure(CoreMetrics.TECHNICAL_DEBT, ONE_DAY_IN_MINUTES.doubleValue());
-    verify(context).saveMeasure(argThat(new IsRuleMeasure(CoreMetrics.TECHNICAL_DEBT, ruleKey1, ONE_DAY_IN_MINUTES.doubleValue())));
-  }
-
-  @Test
-  public void add_technical_debt_from_one_issue_without_debt() {
-    Issue issue = createIssue("rule1", "repo1").setDebt(null);
-    when(issuable.issues()).thenReturn(newArrayList(issue));
-
-    decorator.decorate(resource, context);
-
-    verify(context).saveMeasure(CoreMetrics.TECHNICAL_DEBT, 0.0);
-  }
-
-  @Test
-  public void add_technical_debt_from_one_issue_and_propagate_to_parents() {
-    Issue issue = createIssue("rule1", "repo1").setDebt(Duration.create(ONE_DAY_IN_MINUTES));
-    when(issuable.issues()).thenReturn(newArrayList(issue));
-
-    decorator.decorate(resource, context);
-
-    verify(context).saveMeasure(CoreMetrics.TECHNICAL_DEBT, ONE_DAY_IN_MINUTES.doubleValue());
-    verify(context).saveMeasure(argThat(new IsRuleMeasure(CoreMetrics.TECHNICAL_DEBT, ruleKey1, ONE_DAY_IN_MINUTES.doubleValue())));
-    verify(context).saveMeasure(argThat(new IsCharacteristicMeasure(CoreMetrics.TECHNICAL_DEBT, efficiency, ONE_DAY_IN_MINUTES.doubleValue())));
-    verify(context).saveMeasure(argThat(new IsCharacteristicMeasure(CoreMetrics.TECHNICAL_DEBT, memoryEfficiency, ONE_DAY_IN_MINUTES.doubleValue())));
-  }
-
-  @Test
-  public void add_technical_debt_from_issues() {
-    Long technicalDebt1 = ONE_DAY_IN_MINUTES;
-    Long technicalDebt2 = 2 * ONE_DAY_IN_MINUTES;
-
-    Issue issue1 = createIssue("rule1", "repo1").setDebt(Duration.create(technicalDebt1));
-    Issue issue2 = createIssue("rule1", "repo1").setDebt(Duration.create(technicalDebt1));
-    Issue issue3 = createIssue("rule2", "repo2").setDebt(Duration.create(technicalDebt2));
-    Issue issue4 = createIssue("rule2", "repo2").setDebt(Duration.create(technicalDebt2));
-    when(issuable.issues()).thenReturn(newArrayList(issue1, issue2, issue3, issue4));
-
-    decorator.decorate(resource, context);
-
-    verify(context).saveMeasure(CoreMetrics.TECHNICAL_DEBT, 6d * ONE_DAY_IN_MINUTES);
-    verify(context).saveMeasure(argThat(new IsRuleMeasure(CoreMetrics.TECHNICAL_DEBT, ruleKey1, 2d * ONE_DAY_IN_MINUTES)));
-    verify(context).saveMeasure(argThat(new IsRuleMeasure(CoreMetrics.TECHNICAL_DEBT, ruleKey2, 4d * ONE_DAY_IN_MINUTES)));
-  }
-
-  @Test
-  public void add_technical_debt_from_current_and_children_measures() {
-    Issue issue1 = createIssue("rule1", "repo1").setDebt(Duration.create(ONE_DAY_IN_MINUTES));
-    Issue issue2 = createIssue("rule1", "repo1").setDebt(Duration.create(ONE_DAY_IN_MINUTES));
-    when(issuable.issues()).thenReturn(newArrayList(issue1, issue2));
-
-    when(context.getChildrenMeasures(any(MeasuresFilter.class))).thenReturn(Lists.<Measure>newArrayList(
-      new RuleMeasure(CoreMetrics.TECHNICAL_DEBT,
-        org.sonar.api.rules.Rule.create(ruleKey1.repository(), ruleKey1.rule()), null, null)
-        .setValue(5d * ONE_DAY_IN_MINUTES)
-      ));
-    decorator.decorate(resource, context);
-
-    verify(context).saveMeasure(CoreMetrics.TECHNICAL_DEBT, 7d * ONE_DAY_IN_MINUTES);
-    verify(context).saveMeasure(argThat(new IsRuleMeasure(CoreMetrics.TECHNICAL_DEBT, ruleKey1, 7d * ONE_DAY_IN_MINUTES)));
-    verify(context).saveMeasure(argThat(new IsCharacteristicMeasure(CoreMetrics.TECHNICAL_DEBT, memoryEfficiency, 7d * ONE_DAY_IN_MINUTES)));
-    verify(context).saveMeasure(argThat(new IsCharacteristicMeasure(CoreMetrics.TECHNICAL_DEBT, efficiency, 7d * ONE_DAY_IN_MINUTES)));
-  }
-
-  @Test
-  public void add_technical_debt_only_from_children_measures() {
-    when(issuable.issues()).thenReturn(Collections.<Issue>emptyList());
-
-    when(context.getChildrenMeasures(any(MeasuresFilter.class))).thenReturn(Lists.<Measure>newArrayList(
-      new RuleMeasure(CoreMetrics.TECHNICAL_DEBT,
-        org.sonar.api.rules.Rule.create(ruleKey1.repository(), ruleKey1.rule())
-        , null, null).setValue(5d * ONE_DAY_IN_MINUTES),
-
-      new RuleMeasure(CoreMetrics.TECHNICAL_DEBT,
-        org.sonar.api.rules.Rule.create(ruleKey2.repository(), ruleKey2.rule())
-        , null, null).setValue(10d * ONE_DAY_IN_MINUTES)
-      ));
-    decorator.decorate(resource, context);
-
-    verify(context).saveMeasure(CoreMetrics.TECHNICAL_DEBT, 15d * ONE_DAY_IN_MINUTES);
-    verify(context).saveMeasure(argThat(new IsRuleMeasure(CoreMetrics.TECHNICAL_DEBT, ruleKey1, 5d * ONE_DAY_IN_MINUTES)));
-    verify(context).saveMeasure(argThat(new IsRuleMeasure(CoreMetrics.TECHNICAL_DEBT, ruleKey2, 10d * ONE_DAY_IN_MINUTES)));
-    verify(context).saveMeasure(argThat(new IsCharacteristicMeasure(CoreMetrics.TECHNICAL_DEBT, memoryEfficiency, 5d * ONE_DAY_IN_MINUTES)));
-    verify(context).saveMeasure(argThat(new IsCharacteristicMeasure(CoreMetrics.TECHNICAL_DEBT, efficiency, 5d * ONE_DAY_IN_MINUTES)));
-    verify(context).saveMeasure(argThat(new IsCharacteristicMeasure(CoreMetrics.TECHNICAL_DEBT, reusability, 10d * ONE_DAY_IN_MINUTES)));
-    verify(context).saveMeasure(argThat(new IsCharacteristicMeasure(CoreMetrics.TECHNICAL_DEBT, modularity, 10d * ONE_DAY_IN_MINUTES)));
-  }
-
-  @Test
-  public void always_save_technical_debt_for_positive_values() {
-    // for a project
-    DecoratorContext context = mock(DecoratorContext.class);
-    when(context.getResource()).thenReturn(new Project("foo"));
-    decorator.saveCharacteristicMeasure(context, (Characteristic) null, 12.0, false);
-    verify(context, times(1)).saveMeasure(new Measure(CoreMetrics.TECHNICAL_DEBT));
-
-    // or for a file
-    context = mock(DecoratorContext.class);
-    when(context.getResource()).thenReturn(File.create("foo"));
-    decorator.saveCharacteristicMeasure(context, (Characteristic) null, 12.0, false);
-    verify(context, times(1)).saveMeasure(new Measure(CoreMetrics.TECHNICAL_DEBT));
-  }
-
-  @Test
-  public void always_save_technical_debt_for_project_if_top_characteristic() {
-    DecoratorContext context = mock(DecoratorContext.class);
-    when(context.getResource()).thenReturn(new Project("foo"));
-
-    // this is a top characteristic
-    DefaultCharacteristic rootCharacteristic = new DefaultCharacteristic().setKey("root");
-
-    decorator.saveCharacteristicMeasure(context, rootCharacteristic, 0.0, true);
-    verify(context, times(1)).saveMeasure(new Measure(CoreMetrics.TECHNICAL_DEBT).setCharacteristic(rootCharacteristic));
-  }
-
-  /**
-   * SQALE-147
-   */
-  @Test
-  public void never_save_technical_debt_for_project_if_not_top_characteristic() {
-    DecoratorContext context = mock(DecoratorContext.class);
-    when(context.getResource()).thenReturn(new Project("foo"));
-
-    DefaultCharacteristic rootCharacteristic = new DefaultCharacteristic().setKey("EFFICIENCY");
-    DefaultCharacteristic characteristic = new DefaultCharacteristic().setKey("MEMORY_EFFICIENCY").setParent(rootCharacteristic);
-
-    decorator.saveCharacteristicMeasure(context, characteristic, 0.0, true);
-    verify(context, never()).saveMeasure(any(Measure.class));
-  }
-
-  @Test
-  public void not_save_technical_debt_for_file_if_zero() {
-    DecoratorContext context = mock(DecoratorContext.class);
-    when(context.getResource()).thenReturn(File.create("foo"));
-
-    decorator.saveCharacteristicMeasure(context, null, 0.0, true);
-    verify(context, never()).saveMeasure(new Measure(CoreMetrics.TECHNICAL_DEBT));
-  }
-
-  private DefaultIssue createIssue(String ruleKey, String repositoryKey) {
-    return new DefaultIssue().setRuleKey(RuleKey.of(repositoryKey, ruleKey));
-  }
-
-  class IsCharacteristicMeasure extends ArgumentMatcher<Measure> {
-    Metric metric = null;
-    Characteristic characteristic = null;
-    Double value = null;
-
-    public IsCharacteristicMeasure(Metric metric, Characteristic characteristic, Double value) {
-      this.metric = metric;
-      this.characteristic = characteristic;
-      this.value = value;
-    }
-
-    @Override
-    public boolean matches(Object o) {
-      if (!(o instanceof Measure)) {
-        return false;
-      }
-      Measure m = (Measure) o;
-      return ObjectUtils.equals(metric, m.getMetric()) &&
-        ObjectUtils.equals(characteristic, m.getCharacteristic()) &&
-        ObjectUtils.equals(value, m.getValue());
-    }
-
-    @Override
-    public void describeTo(Description description) {
-      description.appendText(new StringBuilder()
-        .append("value=").append(value).append(",")
-        .append("characteristic=").append(characteristic.key()).append(",")
-        .append("metric=").append(metric.getKey()).toString());
-    }
-  }
-
-  class IsRuleMeasure extends ArgumentMatcher<RuleMeasure> {
-    Metric metric = null;
-    RuleKey ruleKey = null;
-    Double value = null;
-
-    public IsRuleMeasure(Metric metric, RuleKey ruleKey, Double value) {
-      this.metric = metric;
-      this.ruleKey = ruleKey;
-      this.value = value;
-    }
-
-    @Override
-    public boolean matches(Object o) {
-      if (!(o instanceof RuleMeasure)) {
-        return false;
-      }
-      RuleMeasure m = (RuleMeasure) o;
-      return ObjectUtils.equals(metric, m.getMetric()) &&
-        ObjectUtils.equals(ruleKey, m.ruleKey()) &&
-        ObjectUtils.equals(value, m.getValue());
-    }
-
-    @Override
-    public void describeTo(Description description) {
-      description.appendText(ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE));
-    }
-  }
-}
+///*
+// * 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.debt;
+//
+//import com.google.common.collect.Lists;
+//import org.apache.commons.lang.ObjectUtils;
+//import org.apache.commons.lang.builder.ToStringBuilder;
+//import org.apache.commons.lang.builder.ToStringStyle;
+//import org.hamcrest.Description;
+//import org.junit.Before;
+//import org.junit.Test;
+//import org.junit.runner.RunWith;
+//import org.mockito.ArgumentMatcher;
+//import org.mockito.Mock;
+//import org.mockito.runners.MockitoJUnitRunner;
+//import org.sonar.api.batch.DecoratorContext;
+//import org.sonar.api.batch.rule.Rules;
+//import org.sonar.api.batch.rule.internal.RulesBuilder;
+//import org.sonar.api.component.ResourcePerspectives;
+//import org.sonar.api.issue.Issuable;
+//import org.sonar.api.issue.Issue;
+//import org.sonar.core.issue.DefaultIssue;
+//import org.sonar.api.measures.CoreMetrics;
+//import org.sonar.api.measures.Measure;
+//import org.sonar.api.measures.MeasuresFilter;
+//import org.sonar.api.measures.Metric;
+//import org.sonar.api.measures.RuleMeasure;
+//import org.sonar.api.resources.File;
+//import org.sonar.api.resources.Project;
+//import org.sonar.api.resources.Resource;
+//import org.sonar.api.rule.RuleKey;
+//import org.sonar.api.rules.RuleFinder;
+//import org.sonar.api.technicaldebt.batch.Characteristic;
+//import org.sonar.api.technicaldebt.batch.TechnicalDebtModel;
+//import org.sonar.api.technicaldebt.batch.internal.DefaultCharacteristic;
+//import org.sonar.api.test.IsMeasure;
+//import org.sonar.api.utils.Duration;
+//
+//import java.util.Collections;
+//
+//import static com.google.common.collect.Lists.newArrayList;
+//import static org.assertj.core.api.Assertions.assertThat;
+//import static org.mockito.Matchers.any;
+//import static org.mockito.Matchers.argThat;
+//import static org.mockito.Mockito.mock;
+//import static org.mockito.Mockito.never;
+//import static org.mockito.Mockito.times;
+//import static org.mockito.Mockito.verify;
+//import static org.mockito.Mockito.when;
+//
+//@RunWith(MockitoJUnitRunner.class)
+//public class DebtDecoratorTest {
+//
+//  static final int HOURS_IN_DAY = 8;
+//
+//  static final Long ONE_DAY_IN_MINUTES = 1L * HOURS_IN_DAY * 60;
+//
+//  @Mock
+//  DecoratorContext context;
+//
+//  @Mock
+//  Resource resource;
+//
+//  @Mock
+//  TechnicalDebtModel debtModel;
+//
+//  @Mock
+//  Issuable issuable;
+//
+//  @Mock
+//  ResourcePerspectives perspectives;
+//
+//  @Mock
+//  RuleFinder ruleFinder;
+//
+//  RuleKey ruleKey1 = RuleKey.of("repo1", "rule1");
+//  RuleKey ruleKey2 = RuleKey.of("repo2", "rule2");
+//  Rules rules;
+//
+//  DefaultCharacteristic efficiency = new DefaultCharacteristic().setKey("EFFICIENCY");
+//  DefaultCharacteristic memoryEfficiency = new DefaultCharacteristic().setKey("MEMORY_EFFICIENCY").setParent(efficiency);
+//
+//  DefaultCharacteristic reusability = new DefaultCharacteristic().setKey("REUSABILITY");
+//  DefaultCharacteristic modularity = new DefaultCharacteristic().setKey("MODULARITY").setParent(reusability);
+//
+//  DebtDecorator decorator;
+//
+//  @Before
+//  public void before() {
+//    when(perspectives.as(Issuable.class, resource)).thenReturn(issuable);
+//    RulesBuilder rulesBuilder = new RulesBuilder();
+//    rulesBuilder.add(ruleKey1).setName("rule1").setDebtSubCharacteristic("MEMORY_EFFICIENCY");
+//    rulesBuilder.add(ruleKey2).setName("rule2").setDebtSubCharacteristic("MODULARITY");
+//    rules = rulesBuilder.build();
+//
+//    when(ruleFinder.findByKey(ruleKey1)).thenReturn(org.sonar.api.rules.Rule.create(ruleKey1.repository(), ruleKey1.rule()));
+//    when(ruleFinder.findByKey(ruleKey2)).thenReturn(org.sonar.api.rules.Rule.create(ruleKey2.repository(), ruleKey2.rule()));
+//
+//    when(debtModel.characteristics()).thenReturn(newArrayList(efficiency, memoryEfficiency, reusability, modularity));
+//    when(debtModel.characteristicByKey("EFFICIENCY")).thenReturn(efficiency);
+//    when(debtModel.characteristicByKey("MEMORY_EFFICIENCY")).thenReturn(memoryEfficiency);
+//    when(debtModel.characteristicByKey("REUSABILITY")).thenReturn(reusability);
+//    when(debtModel.characteristicByKey("MODULARITY")).thenReturn(modularity);
+//
+//    decorator = new DebtDecorator(perspectives, debtModel, rules, ruleFinder);
+//  }
+//
+//  @Test
+//  public void generates_metrics() {
+//    assertThat(decorator.generatesMetrics()).hasSize(1);
+//  }
+//
+//  @Test
+//  public void execute_on_project() {
+//    assertThat(decorator.shouldExecuteOnProject(null)).isTrue();
+//  }
+//
+//  @Test
+//  public void not_save_if_measure_already_computed() {
+//    when(context.getMeasure(CoreMetrics.TECHNICAL_DEBT)).thenReturn(new Measure());
+//
+//    decorator.decorate(resource, context);
+//
+//    verify(context, never()).saveMeasure(argThat(new IsMeasure(CoreMetrics.TECHNICAL_DEBT)));
+//  }
+//
+//  @Test
+//  public void add_technical_debt_from_one_issue_and_no_parent() {
+//    Issue issue = createIssue("rule1", "repo1").setDebt(Duration.create(ONE_DAY_IN_MINUTES));
+//    when(issuable.issues()).thenReturn(newArrayList(issue));
+//
+//    decorator.decorate(resource, context);
+//
+//    verify(context).saveMeasure(CoreMetrics.TECHNICAL_DEBT, ONE_DAY_IN_MINUTES.doubleValue());
+//    verify(context).saveMeasure(argThat(new IsRuleMeasure(CoreMetrics.TECHNICAL_DEBT, ruleKey1, ONE_DAY_IN_MINUTES.doubleValue())));
+//  }
+//
+//  @Test
+//  public void add_technical_debt_from_one_issue_without_debt() {
+//    Issue issue = createIssue("rule1", "repo1").setDebt(null);
+//    when(issuable.issues()).thenReturn(newArrayList(issue));
+//
+//    decorator.decorate(resource, context);
+//
+//    verify(context).saveMeasure(CoreMetrics.TECHNICAL_DEBT, 0.0);
+//  }
+//
+//  @Test
+//  public void add_technical_debt_from_one_issue_and_propagate_to_parents() {
+//    Issue issue = createIssue("rule1", "repo1").setDebt(Duration.create(ONE_DAY_IN_MINUTES));
+//    when(issuable.issues()).thenReturn(newArrayList(issue));
+//
+//    decorator.decorate(resource, context);
+//
+//    verify(context).saveMeasure(CoreMetrics.TECHNICAL_DEBT, ONE_DAY_IN_MINUTES.doubleValue());
+//    verify(context).saveMeasure(argThat(new IsRuleMeasure(CoreMetrics.TECHNICAL_DEBT, ruleKey1, ONE_DAY_IN_MINUTES.doubleValue())));
+//    verify(context).saveMeasure(argThat(new IsCharacteristicMeasure(CoreMetrics.TECHNICAL_DEBT, efficiency, ONE_DAY_IN_MINUTES.doubleValue())));
+//    verify(context).saveMeasure(argThat(new IsCharacteristicMeasure(CoreMetrics.TECHNICAL_DEBT, memoryEfficiency, ONE_DAY_IN_MINUTES.doubleValue())));
+//  }
+//
+//  @Test
+//  public void add_technical_debt_from_issues() {
+//    Long technicalDebt1 = ONE_DAY_IN_MINUTES;
+//    Long technicalDebt2 = 2 * ONE_DAY_IN_MINUTES;
+//
+//    Issue issue1 = createIssue("rule1", "repo1").setDebt(Duration.create(technicalDebt1));
+//    Issue issue2 = createIssue("rule1", "repo1").setDebt(Duration.create(technicalDebt1));
+//    Issue issue3 = createIssue("rule2", "repo2").setDebt(Duration.create(technicalDebt2));
+//    Issue issue4 = createIssue("rule2", "repo2").setDebt(Duration.create(technicalDebt2));
+//    when(issuable.issues()).thenReturn(newArrayList(issue1, issue2, issue3, issue4));
+//
+//    decorator.decorate(resource, context);
+//
+//    verify(context).saveMeasure(CoreMetrics.TECHNICAL_DEBT, 6d * ONE_DAY_IN_MINUTES);
+//    verify(context).saveMeasure(argThat(new IsRuleMeasure(CoreMetrics.TECHNICAL_DEBT, ruleKey1, 2d * ONE_DAY_IN_MINUTES)));
+//    verify(context).saveMeasure(argThat(new IsRuleMeasure(CoreMetrics.TECHNICAL_DEBT, ruleKey2, 4d * ONE_DAY_IN_MINUTES)));
+//  }
+//
+//  @Test
+//  public void add_technical_debt_from_current_and_children_measures() {
+//    Issue issue1 = createIssue("rule1", "repo1").setDebt(Duration.create(ONE_DAY_IN_MINUTES));
+//    Issue issue2 = createIssue("rule1", "repo1").setDebt(Duration.create(ONE_DAY_IN_MINUTES));
+//    when(issuable.issues()).thenReturn(newArrayList(issue1, issue2));
+//
+//    when(context.getChildrenMeasures(any(MeasuresFilter.class))).thenReturn(Lists.<Measure>newArrayList(
+//      new RuleMeasure(CoreMetrics.TECHNICAL_DEBT,
+//        org.sonar.api.rules.Rule.create(ruleKey1.repository(), ruleKey1.rule()), null, null)
+//        .setValue(5d * ONE_DAY_IN_MINUTES)
+//      ));
+//    decorator.decorate(resource, context);
+//
+//    verify(context).saveMeasure(CoreMetrics.TECHNICAL_DEBT, 7d * ONE_DAY_IN_MINUTES);
+//    verify(context).saveMeasure(argThat(new IsRuleMeasure(CoreMetrics.TECHNICAL_DEBT, ruleKey1, 7d * ONE_DAY_IN_MINUTES)));
+//    verify(context).saveMeasure(argThat(new IsCharacteristicMeasure(CoreMetrics.TECHNICAL_DEBT, memoryEfficiency, 7d * ONE_DAY_IN_MINUTES)));
+//    verify(context).saveMeasure(argThat(new IsCharacteristicMeasure(CoreMetrics.TECHNICAL_DEBT, efficiency, 7d * ONE_DAY_IN_MINUTES)));
+//  }
+//
+//  @Test
+//  public void add_technical_debt_only_from_children_measures() {
+//    when(issuable.issues()).thenReturn(Collections.<Issue>emptyList());
+//
+//    when(context.getChildrenMeasures(any(MeasuresFilter.class))).thenReturn(Lists.<Measure>newArrayList(
+//      new RuleMeasure(CoreMetrics.TECHNICAL_DEBT,
+//        org.sonar.api.rules.Rule.create(ruleKey1.repository(), ruleKey1.rule())
+//        , null, null).setValue(5d * ONE_DAY_IN_MINUTES),
+//
+//      new RuleMeasure(CoreMetrics.TECHNICAL_DEBT,
+//        org.sonar.api.rules.Rule.create(ruleKey2.repository(), ruleKey2.rule())
+//        , null, null).setValue(10d * ONE_DAY_IN_MINUTES)
+//      ));
+//    decorator.decorate(resource, context);
+//
+//    verify(context).saveMeasure(CoreMetrics.TECHNICAL_DEBT, 15d * ONE_DAY_IN_MINUTES);
+//    verify(context).saveMeasure(argThat(new IsRuleMeasure(CoreMetrics.TECHNICAL_DEBT, ruleKey1, 5d * ONE_DAY_IN_MINUTES)));
+//    verify(context).saveMeasure(argThat(new IsRuleMeasure(CoreMetrics.TECHNICAL_DEBT, ruleKey2, 10d * ONE_DAY_IN_MINUTES)));
+//    verify(context).saveMeasure(argThat(new IsCharacteristicMeasure(CoreMetrics.TECHNICAL_DEBT, memoryEfficiency, 5d * ONE_DAY_IN_MINUTES)));
+//    verify(context).saveMeasure(argThat(new IsCharacteristicMeasure(CoreMetrics.TECHNICAL_DEBT, efficiency, 5d * ONE_DAY_IN_MINUTES)));
+//    verify(context).saveMeasure(argThat(new IsCharacteristicMeasure(CoreMetrics.TECHNICAL_DEBT, reusability, 10d * ONE_DAY_IN_MINUTES)));
+//    verify(context).saveMeasure(argThat(new IsCharacteristicMeasure(CoreMetrics.TECHNICAL_DEBT, modularity, 10d * ONE_DAY_IN_MINUTES)));
+//  }
+//
+//  @Test
+//  public void always_save_technical_debt_for_positive_values() {
+//    // for a project
+//    DecoratorContext context = mock(DecoratorContext.class);
+//    when(context.getResource()).thenReturn(new Project("foo"));
+//    decorator.saveCharacteristicMeasure(context, (Characteristic) null, 12.0, false);
+//    verify(context, times(1)).saveMeasure(new Measure(CoreMetrics.TECHNICAL_DEBT));
+//
+//    // or for a file
+//    context = mock(DecoratorContext.class);
+//    when(context.getResource()).thenReturn(File.create("foo"));
+//    decorator.saveCharacteristicMeasure(context, (Characteristic) null, 12.0, false);
+//    verify(context, times(1)).saveMeasure(new Measure(CoreMetrics.TECHNICAL_DEBT));
+//  }
+//
+//  @Test
+//  public void always_save_technical_debt_for_project_if_top_characteristic() {
+//    DecoratorContext context = mock(DecoratorContext.class);
+//    when(context.getResource()).thenReturn(new Project("foo"));
+//
+//    // this is a top characteristic
+//    DefaultCharacteristic rootCharacteristic = new DefaultCharacteristic().setKey("root");
+//
+//    decorator.saveCharacteristicMeasure(context, rootCharacteristic, 0.0, true);
+//    verify(context, times(1)).saveMeasure(new Measure(CoreMetrics.TECHNICAL_DEBT).setCharacteristic(rootCharacteristic));
+//  }
+//
+//  /**
+//   * SQALE-147
+//   */
+//  @Test
+//  public void never_save_technical_debt_for_project_if_not_top_characteristic() {
+//    DecoratorContext context = mock(DecoratorContext.class);
+//    when(context.getResource()).thenReturn(new Project("foo"));
+//
+//    DefaultCharacteristic rootCharacteristic = new DefaultCharacteristic().setKey("EFFICIENCY");
+//    DefaultCharacteristic characteristic = new DefaultCharacteristic().setKey("MEMORY_EFFICIENCY").setParent(rootCharacteristic);
+//
+//    decorator.saveCharacteristicMeasure(context, characteristic, 0.0, true);
+//    verify(context, never()).saveMeasure(any(Measure.class));
+//  }
+//
+//  @Test
+//  public void not_save_technical_debt_for_file_if_zero() {
+//    DecoratorContext context = mock(DecoratorContext.class);
+//    when(context.getResource()).thenReturn(File.create("foo"));
+//
+//    decorator.saveCharacteristicMeasure(context, null, 0.0, true);
+//    verify(context, never()).saveMeasure(new Measure(CoreMetrics.TECHNICAL_DEBT));
+//  }
+//
+//  private DefaultIssue createIssue(String ruleKey, String repositoryKey) {
+//    return new DefaultIssue().setRuleKey(RuleKey.of(repositoryKey, ruleKey));
+//  }
+//
+//  class IsCharacteristicMeasure extends ArgumentMatcher<Measure> {
+//    Metric metric = null;
+//    Characteristic characteristic = null;
+//    Double value = null;
+//
+//    public IsCharacteristicMeasure(Metric metric, Characteristic characteristic, Double value) {
+//      this.metric = metric;
+//      this.characteristic = characteristic;
+//      this.value = value;
+//    }
+//
+//    @Override
+//    public boolean matches(Object o) {
+//      if (!(o instanceof Measure)) {
+//        return false;
+//      }
+//      Measure m = (Measure) o;
+//      return ObjectUtils.equals(metric, m.getMetric()) &&
+//        ObjectUtils.equals(characteristic, m.getCharacteristic()) &&
+//        ObjectUtils.equals(value, m.getValue());
+//    }
+//
+//    @Override
+//    public void describeTo(Description description) {
+//      description.appendText(new StringBuilder()
+//        .append("value=").append(value).append(",")
+//        .append("characteristic=").append(characteristic.key()).append(",")
+//        .append("metric=").append(metric.getKey()).toString());
+//    }
+//  }
+//
+//  class IsRuleMeasure extends ArgumentMatcher<RuleMeasure> {
+//    Metric metric = null;
+//    RuleKey ruleKey = null;
+//    Double value = null;
+//
+//    public IsRuleMeasure(Metric metric, RuleKey ruleKey, Double value) {
+//      this.metric = metric;
+//      this.ruleKey = ruleKey;
+//      this.value = value;
+//    }
+//
+//    @Override
+//    public boolean matches(Object o) {
+//      if (!(o instanceof RuleMeasure)) {
+//        return false;
+//      }
+//      RuleMeasure m = (RuleMeasure) o;
+//      return ObjectUtils.equals(metric, m.getMetric()) &&
+//        ObjectUtils.equals(ruleKey, m.ruleKey()) &&
+//        ObjectUtils.equals(value, m.getValue());
+//    }
+//
+//    @Override
+//    public void describeTo(Description description) {
+//      description.appendText(ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE));
+//    }
+//  }
+//}
index 658cafcc62db6669eb51fb5e67d8a93a3eeb53b8..94204a3afbc6e4ed567bc29de5c0fa33d8fea9e1 100644 (file)
  */
 package org.sonar.batch.report;
 
+import java.io.File;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Date;
+import java.util.List;
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
@@ -30,23 +35,14 @@ import org.sonar.api.measures.Metric;
 import org.sonar.api.measures.Metric.Level;
 import org.sonar.api.measures.Metric.ValueType;
 import org.sonar.api.measures.MetricFinder;
-import org.sonar.api.measures.RuleMeasure;
 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.index.BatchComponentCache;
 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.Mockito.mock;
@@ -103,9 +99,6 @@ public class MeasuresPublisherTest {
     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)
@@ -117,7 +110,7 @@ public class MeasuresPublisherTest {
     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));
+    when(measureCache.byResource(sampleFile)).thenReturn(Arrays.asList(measure1, measure2, manual, rating, longMeasure, stringMeasure));
 
     File outputDir = temp.newFolder();
     BatchReportWriter writer = new BatchReportWriter(outputDir);
index 0575a850182a5c3de96b3f9e669952c827850d91..58dcf64ffdfc23a6b7f6ff1cfbab5442af194e17 100644 (file)
@@ -19,7 +19,8 @@
  */
 package org.sonar.batch.scan.measure;
 
-import org.sonar.batch.index.AbstractCachesTest;
+import java.util.Date;
+import java.util.Iterator;
 import org.apache.commons.lang.builder.EqualsBuilder;
 import org.junit.Before;
 import org.junit.Rule;
@@ -29,22 +30,15 @@ import org.sonar.api.batch.measure.MetricFinder;
 import org.sonar.api.measures.CoreMetrics;
 import org.sonar.api.measures.Measure;
 import org.sonar.api.measures.Metric.Level;
-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.rule.RuleKey;
-import org.sonar.api.rules.RulePriority;
 import org.sonar.api.technicaldebt.batch.Characteristic;
 import org.sonar.api.technicaldebt.batch.Requirement;
-import org.sonar.api.technicaldebt.batch.TechnicalDebtModel;
-import org.sonar.api.technicaldebt.batch.internal.DefaultCharacteristic;
+import org.sonar.batch.index.AbstractCachesTest;
 import org.sonar.batch.index.Cache.Entry;
 
-import java.util.Date;
-import java.util.Iterator;
-
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
@@ -55,8 +49,6 @@ public class MeasureCacheTest extends AbstractCachesTest {
 
   private MetricFinder metricFinder;
 
-  private TechnicalDebtModel techDebtModel;
-
   private MeasureCache measureCache;
 
   @Before
@@ -64,8 +56,7 @@ public class MeasureCacheTest extends AbstractCachesTest {
     super.start();
     metricFinder = mock(MetricFinder.class);
     when(metricFinder.findByKey(CoreMetrics.NCLOC_KEY)).thenReturn(CoreMetrics.NCLOC);
-    techDebtModel = mock(TechnicalDebtModel.class);
-    measureCache = new MeasureCache(caches, metricFinder, techDebtModel);
+    measureCache = new MeasureCache(caches, metricFinder);
   }
 
   @Test
@@ -89,13 +80,6 @@ public class MeasureCacheTest extends AbstractCachesTest {
 
     assertThat(measureCache.byResource(p)).hasSize(1);
     assertThat(measureCache.byResource(p).iterator().next()).isEqualTo(m);
-
-    Measure mRule = RuleMeasure.createForPriority(CoreMetrics.CRITICAL_VIOLATIONS, RulePriority.BLOCKER, 1.0);
-    measureCache.put(p, mRule);
-
-    assertThat(measureCache.entries()).hasSize(2);
-
-    assertThat(measureCache.byResource(p)).hasSize(2);
   }
 
   @Test
@@ -112,7 +96,7 @@ public class MeasureCacheTest extends AbstractCachesTest {
     for (int i = 0; i < 1_048_575; i++) {
       data.append("a");
     }
-    
+
     m.setData(data.toString());
 
     measureCache.put(p, m);
@@ -127,12 +111,6 @@ public class MeasureCacheTest extends AbstractCachesTest {
 
     assertThat(measureCache.byResource(p)).hasSize(1);
     assertThat(measureCache.byResource(p).iterator().next()).isEqualTo(m);
-
-    RuleMeasure mRule = RuleMeasure.createForPriority(CoreMetrics.CRITICAL_VIOLATIONS, RulePriority.BLOCKER, 1.0);
-    mRule.setRuleKey(RuleKey.of("repo", "rule"));
-    measureCache.put(p, mRule);
-
-    assertThat(measureCache.entries()).hasSize(2);
   }
 
   /**
@@ -166,11 +144,6 @@ public class MeasureCacheTest extends AbstractCachesTest {
     assertThat(measureCache.byResource(p)).hasSize(1);
     assertThat(measureCache.byResource(p).iterator().next()).isEqualTo(m);
 
-    RuleMeasure mRule = RuleMeasure.createForPriority(CoreMetrics.CRITICAL_VIOLATIONS, RulePriority.BLOCKER, 1.0);
-    mRule.setRuleKey(RuleKey.of("repo", "rule"));
-    measureCache.put(p, mRule);
-
-    assertThat(measureCache.entries()).hasSize(2);
   }
 
   @Test
@@ -203,17 +176,12 @@ public class MeasureCacheTest extends AbstractCachesTest {
     assertThat(measureCache.byResource(p)).hasSize(0);
 
     Measure m1 = new Measure(CoreMetrics.NCLOC, 1.0);
-    Measure m2 = new Measure(CoreMetrics.NCLOC, 1.0).setCharacteristic(new DefaultCharacteristic().setKey("charac"));
-    Measure m3 = new Measure(CoreMetrics.NCLOC, 1.0).setPersonId(2);
-    Measure m4 = new RuleMeasure(CoreMetrics.NCLOC, RuleKey.of("repo", "rule"), RulePriority.BLOCKER, null);
+    Measure m2 = new Measure(CoreMetrics.NCLOC, 1.0).setPersonId(2);
     measureCache.put(p, m1);
     measureCache.put(p, m2);
-    measureCache.put(p, m3);
-    measureCache.put(p, m4);
-
-    assertThat(measureCache.entries()).hasSize(4);
 
-    assertThat(measureCache.byResource(p)).hasSize(4);
+    assertThat(measureCache.entries()).hasSize(2);
+    assertThat(measureCache.byResource(p)).hasSize(2);
   }
 
   @Test
index 42530abf1320df5fe7e275aa896be2b0db786424..e3be32a43a0c9e112c40d38beb7449863ac1941c 100644 (file)
@@ -204,6 +204,10 @@ public final class MeasuresFilters {
     }
   }
 
+  /**
+   * @deprecated since 5.2. Useless by design because of Compute Engine
+   */
+  @Deprecated
   private abstract static class AbstractRuleMeasureFilter<M> extends MetricFilter<M> {
     protected AbstractRuleMeasureFilter(Metric metric) {
       super(metric);
@@ -232,6 +236,10 @@ public final class MeasuresFilters {
     }
   }
 
+  /**
+   * @deprecated since 5.2. Useless by design because of Compute Engine
+   */
+  @Deprecated
   private static class RuleFilter extends AbstractRuleMeasureFilter<RuleMeasure> {
     private RuleKey ruleKey;
 
index ca201e7ca060f7beafb9b6ce7e7a7b6f70d6445a..ba265ef413d1af66b908866240e06e48627e663f 100644 (file)
@@ -31,7 +31,9 @@ import javax.annotation.Nullable;
 
 /**
  * @since 1.10
+ * @deprecated since 5.2. Ignored by design because of Compute Engine.
  */
+@Deprecated
 public class RuleMeasure extends Measure {
 
   private RuleKey ruleKey;
diff --git a/sonar-plugin-api/src/test/java/org/sonar/api/test/IsRuleMeasure.java b/sonar-plugin-api/src/test/java/org/sonar/api/test/IsRuleMeasure.java
deleted file mode 100644 (file)
index 3f9f67c..0000000
+++ /dev/null
@@ -1,52 +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.test;
-
-import org.apache.commons.lang.ObjectUtils;
-import org.apache.commons.lang.math.NumberUtils;
-import org.mockito.ArgumentMatcher;
-import org.sonar.api.measures.Measure;
-import org.sonar.api.measures.Metric;
-import org.sonar.api.measures.RuleMeasure;
-import org.sonar.api.rules.Rule;
-
-public class IsRuleMeasure extends ArgumentMatcher<Measure> {
-
-  private Metric metric = null;
-  private Rule rule = null;
-  private Double value = null;
-
-  public IsRuleMeasure(Metric metric, Rule rule, Double value) {
-    this.metric = metric;
-    this.rule = rule;
-    this.value = value;
-  }
-
-  @Override
-  public boolean matches(Object o) {
-    if (!(o instanceof RuleMeasure)) {
-      return false;
-    }
-    RuleMeasure m = (RuleMeasure) o;
-    return ObjectUtils.equals(metric, m.getMetric()) &&
-      ObjectUtils.equals(rule.ruleKey(), m.ruleKey()) &&
-      NumberUtils.compare(value, m.getValue()) == 0;
-  }
-}