]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-5056 Create DebtRemediationFunction API on batch side
authorJulien Lancelot <julien.lancelot@sonarsource.com>
Mon, 17 Mar 2014 13:13:22 +0000 (14:13 +0100)
committerJulien Lancelot <julien.lancelot@sonarsource.com>
Mon, 17 Mar 2014 13:13:31 +0000 (14:13 +0100)
13 files changed:
plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/technicaldebt/DebtDecorator.java
plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/technicaldebt/DebtDecoratorTest.java
sonar-batch/src/main/java/org/sonar/batch/issue/ModuleIssues.java
sonar-batch/src/main/java/org/sonar/batch/rule/RulesProvider.java
sonar-batch/src/test/java/org/sonar/batch/issue/ModuleIssuesTest.java
sonar-batch/src/test/java/org/sonar/batch/rule/RulesProviderTest.java
sonar-plugin-api/src/main/java/org/sonar/api/batch/rule/DebtRemediationFunction.java [new file with mode: 0644]
sonar-plugin-api/src/main/java/org/sonar/api/batch/rule/Rule.java
sonar-plugin-api/src/main/java/org/sonar/api/batch/rule/internal/DefaultRule.java
sonar-plugin-api/src/main/java/org/sonar/api/batch/rule/internal/NewRule.java
sonar-plugin-api/src/main/java/org/sonar/api/rule/RemediationFunction.java [deleted file]
sonar-plugin-api/src/test/java/org/sonar/api/batch/rule/DebtRemediationFunctionTest.java [new file with mode: 0644]
sonar-plugin-api/src/test/java/org/sonar/api/batch/rule/internal/RulesBuilderTest.java

index e146e03a9df0723b00e2bae3955c6d27057f6679..d948742da26925e0707597e89e5464ba9e8a7f68 100644 (file)
@@ -121,7 +121,7 @@ public final class DebtDecorator implements Decorator {
     if (debt != null) {
       Rule rule = rules.find(ruleKey);
       if (rule != null) {
-        String characteristicKey = rule.characteristic();
+        String characteristicKey = rule.debtCharacteristic();
         if (characteristicKey != null) {
           Characteristic characteristic = model.characteristicByKey(characteristicKey);
           if (characteristic != null) {
index 457b72ad0d7b021d1869f51a5cc5e81d12b2e0ab..aff369faab5d16a114026c80b3179c6a623d1da9 100644 (file)
@@ -98,8 +98,8 @@ public class DebtDecoratorTest {
   public void before() throws Exception {
     when(perspectives.as(Issuable.class, resource)).thenReturn(issuable);
     RulesBuilder rulesBuilder = new RulesBuilder();
-    rulesBuilder.add(ruleKey1).setName("rule1").setCharacteristic("MEMORY_EFFICIENCY");
-    rulesBuilder.add(ruleKey2).setName("rule2").setCharacteristic("MODULARITY");
+    rulesBuilder.add(ruleKey1).setName("rule1").setDebtCharacteristic("MEMORY_EFFICIENCY");
+    rulesBuilder.add(ruleKey2).setName("rule2").setDebtCharacteristic("MODULARITY");
     rules = rulesBuilder.build();
 
     when(ruleFinder.findByKey(ruleKey1)).thenReturn(org.sonar.api.rules.Rule.create(ruleKey1.repository(), ruleKey1.rule()));
index 106cf3bada223ef0456290171370bdee80451d83..751aa64eedd6bd2d528784544dbd14754f597285 100644 (file)
@@ -21,13 +21,9 @@ package org.sonar.batch.issue;
 
 import com.google.common.base.Objects;
 import com.google.common.base.Strings;
-import org.sonar.api.batch.rule.ActiveRule;
-import org.sonar.api.batch.rule.ActiveRules;
-import org.sonar.api.batch.rule.Rule;
-import org.sonar.api.batch.rule.Rules;
+import org.sonar.api.batch.rule.*;
 import org.sonar.api.issue.internal.DefaultIssue;
 import org.sonar.api.resources.Project;
-import org.sonar.api.rule.RemediationFunction;
 import org.sonar.api.rule.RuleKey;
 import org.sonar.api.rules.Violation;
 import org.sonar.api.utils.Duration;
@@ -111,25 +107,25 @@ public class ModuleIssues {
     if (issue.severity() == null) {
       issue.setSeverity(activeRule.severity());
     }
-    if (rule.characteristic() != null) {
+    if (rule.debtCharacteristic() != null) {
       issue.setDebt(calculateDebt(rule, issue.effortToFix()));
     }
   }
 
   private Duration calculateDebt(Rule rule, @Nullable Double effortToFix) {
-    if (RemediationFunction.CONSTANT_ISSUE.equals(rule.function()) && effortToFix != null) {
+    DebtRemediationFunction function = rule.debtRemediationFunction();
+    if (DebtRemediationFunction.Type.CONSTANT_ISSUE.equals(function.type()) && effortToFix != null) {
       throw new IllegalArgumentException("Rule '" + rule.key() + "' can not use 'Constant/issue' remediation function " +
         "because this rule does not have a fixed remediation cost.");
     }
     Duration result = Duration.create(0);
-    Duration factor = rule.factor();
-    Duration offset = rule.offset();
+    Duration factor = function.factor();
+    Duration offset = function.offset();
 
     if (factor != null) {
       int effortToFixValue = Objects.firstNonNull(effortToFix, 1).intValue();
       result = factor.multiply(effortToFixValue);
     }
-
     if (offset != null) {
       result = result.add(offset);
     }
index 5732f129663e460aa4414f14e0bbac5b25ef64a9..2d0f1294e8d8e28be486c89ef0767b3ebfcca698 100644 (file)
@@ -25,10 +25,10 @@ import com.google.common.collect.ListMultimap;
 import org.picocontainer.injectors.ProviderAdapter;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+import org.sonar.api.batch.rule.DebtRemediationFunction;
 import org.sonar.api.batch.rule.Rules;
 import org.sonar.api.batch.rule.internal.NewRule;
 import org.sonar.api.batch.rule.internal.RulesBuilder;
-import org.sonar.api.rule.RemediationFunction;
 import org.sonar.api.rule.RuleKey;
 import org.sonar.api.rule.RuleStatus;
 import org.sonar.api.technicaldebt.batch.Characteristic;
@@ -80,8 +80,8 @@ public class RulesProvider extends ProviderAdapter {
       // TODO should we set metadata ?
 
       if (ruleDto.hasCharacteristic()) {
-        newRule.setCharacteristic(characteristic(ruleDto, ruleKey, debtModel).key());
-        setFunction(ruleDto, newRule, ruleKey, durations);
+        newRule.setDebtCharacteristic(effectiveCharacteristic(ruleDto, ruleKey, debtModel).key());
+        newRule.setDebtRemediationFunction(effectiveFunction(ruleDto, ruleKey, newRule, durations));
       }
 
       for (RuleParamDto ruleParamDto : paramDtosByRuleId.get(ruleDto.getId())) {
@@ -92,27 +92,7 @@ public class RulesProvider extends ProviderAdapter {
     return rulesBuilder.build();
   }
 
-  private void setFunction(RuleDto ruleDto, NewRule newRule, RuleKey ruleKey, Durations durations) {
-    String function = ruleDto.getRemediationFunction();
-    String factor = ruleDto.getRemediationFactor();
-    String offset = ruleDto.getRemediationOffset();
-
-    String defaultFunction = ruleDto.getDefaultRemediationFunction();
-    String defaultFactor = ruleDto.getDefaultRemediationFactor();
-    String defaultOffset = ruleDto.getDefaultRemediationOffset();
-
-    if (function != null) {
-      newRule.setFunction(function(function, ruleKey));
-      newRule.setFactor(factor != null ? durations.decode(factor) : null);
-      newRule.setOffset(offset != null ? durations.decode(offset) : null);
-    } else {
-      newRule.setFunction(function(defaultFunction, ruleKey));
-      newRule.setFactor(defaultFactor != null ? durations.decode(defaultFactor) : null);
-      newRule.setOffset(defaultOffset != null ? durations.decode(defaultOffset) : null);
-    }
-  }
-
-  private Characteristic characteristic(RuleDto ruleDto, RuleKey ruleKey, TechnicalDebtModel debtModel) {
+  private Characteristic effectiveCharacteristic(RuleDto ruleDto, RuleKey ruleKey, TechnicalDebtModel debtModel) {
     Integer characteristicId = ruleDto.getCharacteristicId();
     Integer defaultCharacteristicId = ruleDto.getDefaultCharacteristicId();
     Integer effectiveCharacteristicId = characteristicId != null ? characteristicId : defaultCharacteristicId;
@@ -123,10 +103,22 @@ public class RulesProvider extends ProviderAdapter {
     return characteristic;
   }
 
-  private RemediationFunction function(@Nullable String function, RuleKey ruleKey) {
-    if (function == null) {
+  private DebtRemediationFunction effectiveFunction(RuleDto ruleDto, RuleKey ruleKey, NewRule newRule, Durations durations) {
+    String function = ruleDto.getRemediationFunction();
+    String defaultFunction = ruleDto.getDefaultRemediationFunction();
+    if (function != null) {
+      return createDebtRemediationFunction(function, ruleDto.getRemediationFactor(), ruleDto.getRemediationOffset(), durations);
+    } else if (defaultFunction != null) {
+      return createDebtRemediationFunction(ruleDto.getDefaultRemediationFunction(), ruleDto.getDefaultRemediationFactor(), ruleDto.getDefaultRemediationOffset(), durations);
+    } else {
       throw new IllegalStateException(String.format("Remediation function should not be null on rule '%s'", ruleKey));
     }
-    return RemediationFunction.valueOf(function);
   }
+
+  private DebtRemediationFunction createDebtRemediationFunction(String function, @Nullable String factor, @Nullable String offset, Durations durations) {
+    return DebtRemediationFunction.create(DebtRemediationFunction.Type.valueOf(function),
+      factor != null ? durations.decode(factor) : null,
+      offset != null ? durations.decode(offset) : null);
+  }
+
 }
index 492b4061b1db6b536d68cfdd352fcf19930cea85..f5b920c3b3cee565fce53c0f79c639ef372705ea 100644 (file)
@@ -26,13 +26,13 @@ import org.junit.runner.RunWith;
 import org.mockito.ArgumentCaptor;
 import org.mockito.Mock;
 import org.mockito.runners.MockitoJUnitRunner;
+import org.sonar.api.batch.rule.DebtRemediationFunction;
 import org.sonar.api.batch.rule.internal.ActiveRulesBuilder;
 import org.sonar.api.batch.rule.internal.RulesBuilder;
 import org.sonar.api.issue.internal.DefaultIssue;
 import org.sonar.api.resources.JavaFile;
 import org.sonar.api.resources.Project;
 import org.sonar.api.resources.Resource;
-import org.sonar.api.rule.RemediationFunction;
 import org.sonar.api.rule.RuleKey;
 import org.sonar.api.rule.Severity;
 import org.sonar.api.rules.RulePriority;
@@ -250,9 +250,8 @@ public class ModuleIssuesTest {
   public void set_debt_with_linear_function() throws Exception {
     ruleBuilder.add(SQUID_RULE_KEY)
       .setName(SQUID_RULE_NAME)
-      .setCharacteristic("COMPILER_RELATED_PORTABILITY")
-      .setFunction(RemediationFunction.LINEAR)
-      .setFactor(Duration.create(10L));
+      .setDebtCharacteristic("COMPILER_RELATED_PORTABILITY")
+      .setDebtRemediationFunction(DebtRemediationFunction.createLinear(Duration.create(10L)));
     activeRulesBuilder.activate(SQUID_RULE_KEY).setSeverity(Severity.INFO);
     initModuleIssues();
 
@@ -277,10 +276,8 @@ public class ModuleIssuesTest {
   public void set_debt_with_linear_with_offset_function() throws Exception {
     ruleBuilder.add(SQUID_RULE_KEY)
       .setName(SQUID_RULE_NAME)
-      .setCharacteristic("COMPILER_RELATED_PORTABILITY")
-      .setFunction(RemediationFunction.LINEAR_OFFSET)
-      .setFactor(Duration.create(10L))
-      .setOffset(Duration.create(25L));
+      .setDebtCharacteristic("COMPILER_RELATED_PORTABILITY")
+      .setDebtRemediationFunction(DebtRemediationFunction.createLinearWithOffset(Duration.create(10L), Duration.create(25L)));
     activeRulesBuilder.activate(SQUID_RULE_KEY).setSeverity(Severity.INFO);
     initModuleIssues();
 
@@ -305,9 +302,8 @@ public class ModuleIssuesTest {
   public void set_debt_with_constant_issue_function() throws Exception {
     ruleBuilder.add(SQUID_RULE_KEY)
       .setName(SQUID_RULE_NAME)
-      .setCharacteristic("COMPILER_RELATED_PORTABILITY")
-      .setFunction(RemediationFunction.CONSTANT_ISSUE)
-      .setOffset(Duration.create(10L));
+      .setDebtCharacteristic("COMPILER_RELATED_PORTABILITY")
+      .setDebtRemediationFunction(DebtRemediationFunction.createConstantPerIssue(Duration.create(10L)));
     activeRulesBuilder.activate(SQUID_RULE_KEY).setSeverity(Severity.INFO);
     initModuleIssues();
 
@@ -332,9 +328,8 @@ public class ModuleIssuesTest {
   public void fail_to_set_debt_with_constant_issue_function_when_effort_to_fix_is_set() throws Exception {
     ruleBuilder.add(SQUID_RULE_KEY)
       .setName(SQUID_RULE_NAME)
-      .setCharacteristic("COMPILER_RELATED_PORTABILITY")
-      .setFunction(RemediationFunction.CONSTANT_ISSUE)
-      .setOffset(Duration.create(25L));
+      .setDebtCharacteristic("COMPILER_RELATED_PORTABILITY")
+      .setDebtRemediationFunction(DebtRemediationFunction.createConstantPerIssue(Duration.create(25L)));
     activeRulesBuilder.activate(SQUID_RULE_KEY).setSeverity(Severity.INFO);
     initModuleIssues();
 
index 01108161c10723ce58604e79e82f85625fb656d3..d87e6b3189b747e6baeb1ab723139a7d983741d4 100644 (file)
@@ -25,11 +25,11 @@ import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
 import org.mockito.runners.MockitoJUnitRunner;
+import org.sonar.api.batch.rule.DebtRemediationFunction;
 import org.sonar.api.batch.rule.Rule;
 import org.sonar.api.batch.rule.RuleParam;
 import org.sonar.api.batch.rule.Rules;
 import org.sonar.api.config.Settings;
-import org.sonar.api.rule.RemediationFunction;
 import org.sonar.api.rule.RuleKey;
 import org.sonar.api.rule.Severity;
 import org.sonar.api.technicaldebt.batch.internal.DefaultCharacteristic;
@@ -111,10 +111,8 @@ public class RulesProviderTest extends AbstractDaoTestCase {
     Rules rules = provider.provide(ruleDao, debtModel, durations);
 
     Rule rule = rules.find(RuleKey.of("checkstyle", "AvoidNull"));
-    assertThat(rule.characteristic()).isEqualTo("EFFICIENCY");
-    assertThat(rule.function()).isEqualTo(RemediationFunction.LINEAR_OFFSET);
-    assertThat(rule.factor()).isEqualTo(Duration.decode("5d", 8));
-    assertThat(rule.offset()).isEqualTo(Duration.decode("10h", 8));
+    assertThat(rule.debtCharacteristic()).isEqualTo("EFFICIENCY");
+    assertThat(rule.debtRemediationFunction()).isEqualTo(DebtRemediationFunction.createLinearWithOffset(Duration.decode("5d", 8), Duration.decode("10h", 8)));
   }
 
   @Test
@@ -124,10 +122,8 @@ public class RulesProviderTest extends AbstractDaoTestCase {
     Rules rules = provider.provide(ruleDao, debtModel, durations);
 
     Rule rule = rules.find(RuleKey.of("checkstyle", "AvoidNull"));
-    assertThat(rule.characteristic()).isEqualTo("PORTABILITY");
-    assertThat(rule.function()).isEqualTo(RemediationFunction.LINEAR);
-    assertThat(rule.factor()).isEqualTo(Duration.decode("2h", 8));
-    assertThat(rule.offset()).isNull();
+    assertThat(rule.debtCharacteristic()).isEqualTo("PORTABILITY");
+    assertThat(rule.debtRemediationFunction()).isEqualTo(DebtRemediationFunction.createLinear(Duration.decode("2h", 8)));
   }
 
   @Test
@@ -138,10 +134,8 @@ public class RulesProviderTest extends AbstractDaoTestCase {
 
     // As both default columns and user columns on debt are set, user debt columns should be used
     Rule rule = rules.find(RuleKey.of("checkstyle", "AvoidNull"));
-    assertThat(rule.characteristic()).isEqualTo("PORTABILITY");
-    assertThat(rule.function()).isEqualTo(RemediationFunction.LINEAR);
-    assertThat(rule.factor()).isEqualTo(Duration.decode("2h", 8));
-    assertThat(rule.offset()).isNull();
+    assertThat(rule.debtCharacteristic()).isEqualTo("PORTABILITY");
+    assertThat(rule.debtRemediationFunction()).isEqualTo(DebtRemediationFunction.createLinear(Duration.decode("2h", 8)));
   }
 
   @Test
@@ -152,10 +146,8 @@ public class RulesProviderTest extends AbstractDaoTestCase {
 
     // As both default columns and user columns on debt are set, user debt columns should be used
     Rule rule = rules.find(RuleKey.of("checkstyle", "AvoidNull"));
-    assertThat(rule.characteristic()).isEqualTo("PORTABILITY");
-    assertThat(rule.function()).isEqualTo(RemediationFunction.LINEAR);
-    assertThat(rule.factor()).isEqualTo(Duration.decode("2h", 8));
-    assertThat(rule.offset()).isNull();
+    assertThat(rule.debtCharacteristic()).isEqualTo("PORTABILITY");
+    assertThat(rule.debtRemediationFunction()).isEqualTo(DebtRemediationFunction.createLinear(Duration.decode("2h", 8)));
   }
 
   @Test
@@ -166,10 +158,8 @@ public class RulesProviderTest extends AbstractDaoTestCase {
 
     // As both default columns and user columns on debt are set, user debt columns should be used
     Rule rule = rules.find(RuleKey.of("checkstyle", "AvoidNull"));
-    assertThat(rule.characteristic()).isEqualTo("PORTABILITY");
-    assertThat(rule.function()).isEqualTo(RemediationFunction.LINEAR);
-    assertThat(rule.factor()).isEqualTo(Duration.decode("2h", 8));
-    assertThat(rule.offset()).isNull();
+    assertThat(rule.debtCharacteristic()).isEqualTo("PORTABILITY");
+    assertThat(rule.debtRemediationFunction()).isEqualTo(DebtRemediationFunction.createLinear(Duration.decode("2h", 8)));
   }
 
   @Test
@@ -179,10 +169,8 @@ public class RulesProviderTest extends AbstractDaoTestCase {
     Rules rules = provider.provide(ruleDao, debtModel, durations);
 
     Rule rule = rules.find(RuleKey.of("checkstyle", "AvoidNull"));
-    assertThat(rule.characteristic()).isNull();
-    assertThat(rule.function()).isNull();
-    assertThat(rule.factor()).isNull();
-    assertThat(rule.offset()).isNull();
+    assertThat(rule.debtCharacteristic()).isNull();
+    assertThat(rule.debtRemediationFunction()).isNull();
   }
 
   @Test
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/rule/DebtRemediationFunction.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/rule/DebtRemediationFunction.java
new file mode 100644 (file)
index 0000000..60f3fac
--- /dev/null
@@ -0,0 +1,115 @@
+/*
+ * 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.batch.rule;
+
+import org.apache.commons.lang.builder.ReflectionToStringBuilder;
+import org.apache.commons.lang.builder.ToStringStyle;
+import org.sonar.api.utils.Duration;
+
+import javax.annotation.CheckForNull;
+import javax.annotation.Nullable;
+
+/**
+ * @since 4.3
+ */
+public class DebtRemediationFunction {
+
+  public static enum Type {
+    LINEAR, LINEAR_OFFSET, CONSTANT_ISSUE
+  }
+
+  private Type type;
+  private Duration factor;
+  private Duration offset;
+
+  private DebtRemediationFunction(Type type, @Nullable Duration factor, @Nullable Duration offset) {
+    this.type = type;
+    this.factor = factor;
+    this.offset = offset;
+  }
+
+  public static DebtRemediationFunction create(Type type, @Nullable Duration factor, @Nullable Duration offset) {
+    return new DebtRemediationFunction(type, factor, offset);
+  }
+
+  public static DebtRemediationFunction createLinear(Duration factor) {
+    return new DebtRemediationFunction(Type.LINEAR, factor, null);
+  }
+
+  public static DebtRemediationFunction createLinearWithOffset(Duration factor, Duration offset) {
+    return new DebtRemediationFunction(Type.LINEAR_OFFSET, factor, offset);
+  }
+
+  public static DebtRemediationFunction createConstantPerIssue(Duration offset) {
+    return new DebtRemediationFunction(Type.CONSTANT_ISSUE, null, offset);
+  }
+
+  public Type type() {
+    return type;
+  }
+
+  @CheckForNull
+  public Duration factor() {
+    return factor;
+  }
+
+  @CheckForNull
+  public Duration offset() {
+    return offset;
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) {
+      return true;
+    }
+    if (o == null || getClass() != o.getClass()) {
+      return false;
+    }
+
+    DebtRemediationFunction that = (DebtRemediationFunction) o;
+
+    if (type != that.type) {
+      return false;
+    }
+    if (factor != null ? !factor.equals(that.factor) : that.factor != null) {
+      return false;
+    }
+    if (offset != null ? !offset.equals(that.offset) : that.offset != null) {
+      return false;
+    }
+
+    return true;
+  }
+
+  @Override
+  public int hashCode() {
+    int result = type.hashCode();
+    result = 31 * result + (factor != null ? factor.hashCode() : 0);
+    result = 31 * result + (offset != null ? offset.hashCode() : 0);
+    return result;
+  }
+
+  @Override
+  public String toString() {
+    return new ReflectionToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE).toString();
+  }
+}
index 3332c5a89dadae3c25d50042ce80463e4635a834..27a75566c0973a31ffc4e6afbd606bc940c46b84 100644 (file)
 package org.sonar.api.batch.rule;
 
 import com.google.common.annotations.Beta;
-import org.sonar.api.rule.RemediationFunction;
 import org.sonar.api.rule.RuleKey;
 import org.sonar.api.rule.RuleStatus;
-import org.sonar.api.utils.Duration;
 
 import javax.annotation.CheckForNull;
 
@@ -60,30 +58,14 @@ public interface Rule {
    * @since 4.3
    */
   @CheckForNull
-  String characteristic();
+  String debtCharacteristic();
 
   /**
-   * Remediation function : one of LINEAR, LINEAR_OFFSET or CONSTANT_ISSUE.
+   * Remediation function : one of LINEAR (with a factor), LINEAR_OFFSET (with a factor and an offset) or CONSTANT_ISSUE (with an offset)
    *
    * @since 4.3
    */
   @CheckForNull
-  RemediationFunction function();
-
-  /**
-   * Remediation factor duration (used for LINEAR function).
-   *
-   * @since 4.3
-   */
-  @CheckForNull
-  Duration factor();
-
-  /**
-   * Remediation offset duration (used for LINEAR_OFFSET or CONSTANT_ISSUE function).
-   *
-   * @since 4.3
-   */
-  @CheckForNull
-  Duration offset();
+  DebtRemediationFunction debtRemediationFunction();
 
 }
index 13a3d3890eba57c336a037d0f81b90a10ea4bdbe..5b2db0d27b9f73d4dfb507ea90c4dba2b0784d92 100644 (file)
 package org.sonar.api.batch.rule.internal;
 
 import com.google.common.collect.ImmutableMap;
+import org.sonar.api.batch.rule.DebtRemediationFunction;
 import org.sonar.api.batch.rule.Rule;
 import org.sonar.api.batch.rule.RuleParam;
-import org.sonar.api.rule.RemediationFunction;
 import org.sonar.api.rule.RuleKey;
 import org.sonar.api.rule.RuleStatus;
-import org.sonar.api.utils.Duration;
 
 import javax.annotation.CheckForNull;
 import javax.annotation.concurrent.Immutable;
@@ -38,10 +37,9 @@ public class DefaultRule implements Rule {
 
   private final RuleKey key;
   private final Integer id;
-  private final String name, severity, description, metadata, characteristic;
+  private final String name, severity, description, metadata, debtCharacteristic;
   private final RuleStatus status;
-  private final RemediationFunction function;
-  private final Duration factor, offset;
+  private final DebtRemediationFunction debtRemediationFunction;
 
   private final Map<String, RuleParam> params;
 
@@ -53,10 +51,8 @@ public class DefaultRule implements Rule {
     this.description = newRule.description;
     this.metadata = newRule.metadata;
     this.status = newRule.status;
-    this.characteristic = newRule.characteristic;
-    this.function = newRule.function;
-    this.factor = newRule.factor;
-    this.offset = newRule.offset;
+    this.debtCharacteristic = newRule.debtCharacteristic;
+    this.debtRemediationFunction = newRule.debtRemediationFunction;
 
     ImmutableMap.Builder<String, RuleParam> builder = ImmutableMap.builder();
     for (NewRuleParam newRuleParam : newRule.params.values()) {
@@ -101,23 +97,13 @@ public class DefaultRule implements Rule {
   }
 
   @Override
-  public String characteristic() {
-    return characteristic;
+  public String debtCharacteristic() {
+    return debtCharacteristic;
   }
 
   @Override
-  public RemediationFunction function() {
-    return function;
-  }
-
-  @Override
-  public Duration factor() {
-    return factor;
-  }
-
-  @Override
-  public Duration offset() {
-    return offset;
+  public DebtRemediationFunction debtRemediationFunction() {
+    return debtRemediationFunction;
   }
 
   @Override
index 1f67eeb4e9632f461f5e141c436fc3233fe40f5c..c3506ff1b50c5132198ce283791a557b00b4e582 100644 (file)
@@ -21,11 +21,10 @@ package org.sonar.api.batch.rule.internal;
 
 import org.apache.commons.lang.ObjectUtils;
 import org.apache.commons.lang.StringUtils;
-import org.sonar.api.rule.RemediationFunction;
+import org.sonar.api.batch.rule.DebtRemediationFunction;
 import org.sonar.api.rule.RuleKey;
 import org.sonar.api.rule.RuleStatus;
 import org.sonar.api.rule.Severity;
-import org.sonar.api.utils.Duration;
 
 import javax.annotation.Nullable;
 
@@ -38,9 +37,8 @@ public class NewRule {
 
   final RuleKey key;
   Integer id;
-  String name, description, severity = DEFAULT_SEVERITY, metadata, characteristic;
-  RemediationFunction function;
-  Duration factor, offset;
+  String name, description, severity = DEFAULT_SEVERITY, metadata, debtCharacteristic;
+  DebtRemediationFunction debtRemediationFunction;
   RuleStatus status = RuleStatus.defaultStatus();
   Map<String, NewRuleParam> params = new HashMap<String, NewRuleParam>();
 
@@ -69,7 +67,7 @@ public class NewRule {
   }
 
   public NewRule setStatus(@Nullable RuleStatus s) {
-    this.status = (RuleStatus)ObjectUtils.defaultIfNull(s, RuleStatus.defaultStatus());
+    this.status = (RuleStatus) ObjectUtils.defaultIfNull(s, RuleStatus.defaultStatus());
     return this;
   }
 
@@ -78,23 +76,13 @@ public class NewRule {
     return this;
   }
 
-  public NewRule setCharacteristic(@Nullable String c) {
-    this.characteristic = c;
+  public NewRule setDebtCharacteristic(@Nullable String c) {
+    this.debtCharacteristic = c;
     return this;
   }
 
-  public NewRule setFunction(@Nullable RemediationFunction f) {
-    this.function = f;
-    return this;
-  }
-
-  public NewRule setFactor(@Nullable Duration f) {
-    this.factor = f;
-    return this;
-  }
-
-  public NewRule setOffset(@Nullable Duration o) {
-    this.offset = o;
+  public NewRule setDebtRemediationFunction(@Nullable DebtRemediationFunction f) {
+    this.debtRemediationFunction = f;
     return this;
   }
 
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/rule/RemediationFunction.java b/sonar-plugin-api/src/main/java/org/sonar/api/rule/RemediationFunction.java
deleted file mode 100644 (file)
index f88baec..0000000
+++ /dev/null
@@ -1,30 +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.rule;
-
-/**
- * List of availables remediation function
- *
- * @since 4.3
- */
-public enum RemediationFunction {
-  LINEAR, LINEAR_OFFSET, CONSTANT_ISSUE
-}
diff --git a/sonar-plugin-api/src/test/java/org/sonar/api/batch/rule/DebtRemediationFunctionTest.java b/sonar-plugin-api/src/test/java/org/sonar/api/batch/rule/DebtRemediationFunctionTest.java
new file mode 100644 (file)
index 0000000..a377c4a
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ * 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.batch.rule;
+
+import org.junit.Test;
+import org.sonar.api.server.rule.DebtRemediationFunction;
+
+import static org.fest.assertions.Assertions.assertThat;
+
+public class DebtRemediationFunctionTest {
+
+  @Test
+  public void create_linear() throws Exception {
+    org.sonar.api.server.rule.DebtRemediationFunction function = org.sonar.api.server.rule.DebtRemediationFunction.createLinear("10h");
+    assertThat(function.type()).isEqualTo(org.sonar.api.server.rule.DebtRemediationFunction.Type.LINEAR);
+    assertThat(function.factor()).isEqualTo("10h");
+    assertThat(function.offset()).isNull();
+  }
+
+  @Test
+  public void create_linear_with_offset() throws Exception {
+    org.sonar.api.server.rule.DebtRemediationFunction function = org.sonar.api.server.rule.DebtRemediationFunction.createLinearWithOffset("10h", "5min");
+    assertThat(function.type()).isEqualTo(org.sonar.api.server.rule.DebtRemediationFunction.Type.LINEAR_OFFSET);
+    assertThat(function.factor()).isEqualTo("10h");
+    assertThat(function.offset()).isEqualTo("5min");
+  }
+
+  @Test
+  public void create_constant_per_issue() throws Exception {
+    org.sonar.api.server.rule.DebtRemediationFunction function = org.sonar.api.server.rule.DebtRemediationFunction.createConstantPerIssue("10h");
+    assertThat(function.type()).isEqualTo(org.sonar.api.server.rule.DebtRemediationFunction.Type.CONSTANT_ISSUE);
+    assertThat(function.factor()).isNull();
+    assertThat(function.offset()).isEqualTo("10h");
+  }
+
+  @Test
+  public void test_equals_and_hashcode() throws Exception {
+    org.sonar.api.server.rule.DebtRemediationFunction function = org.sonar.api.server.rule.DebtRemediationFunction.createLinearWithOffset("10h", "5min");
+    org.sonar.api.server.rule.DebtRemediationFunction functionWithSameValue = org.sonar.api.server.rule.DebtRemediationFunction.createLinearWithOffset("10h", "5min");
+    org.sonar.api.server.rule.DebtRemediationFunction functionWithDifferentType = org.sonar.api.server.rule.DebtRemediationFunction.createConstantPerIssue("5min");
+
+    assertThat(function).isEqualTo(function);
+    assertThat(function).isEqualTo(functionWithSameValue);
+    assertThat(function).isNotEqualTo(functionWithDifferentType);
+    assertThat(function).isNotEqualTo(org.sonar.api.server.rule.DebtRemediationFunction.createLinearWithOffset("11h", "5min"));
+    assertThat(function).isNotEqualTo(org.sonar.api.server.rule.DebtRemediationFunction.createLinearWithOffset("10h", "6min"));
+    assertThat(function).isNotEqualTo(org.sonar.api.server.rule.DebtRemediationFunction.createLinear("10h"));
+    assertThat(function).isNotEqualTo(org.sonar.api.server.rule.DebtRemediationFunction.createConstantPerIssue("6min"));
+
+    assertThat(function.hashCode()).isEqualTo(function.hashCode());
+    assertThat(function.hashCode()).isEqualTo(functionWithSameValue.hashCode());
+    assertThat(function.hashCode()).isNotEqualTo(functionWithDifferentType.hashCode());
+  }
+
+  @Test
+  public void test_to_string() throws Exception {
+    assertThat(DebtRemediationFunction.createLinearWithOffset("10h", "5min").toString()).isNotNull();
+  }
+}
index a314191e3cbec7ef3924c2f86d55efa1b0a1fe55..881823e3cf628754375dd1f8e29ecc3662e7a8d8 100644 (file)
 package org.sonar.api.batch.rule.internal;
 
 import org.junit.Test;
+import org.sonar.api.batch.rule.DebtRemediationFunction;
 import org.sonar.api.batch.rule.Rule;
 import org.sonar.api.batch.rule.Rules;
 import org.sonar.api.rule.RuleKey;
 import org.sonar.api.rule.RuleStatus;
 import org.sonar.api.rule.Severity;
+import org.sonar.api.utils.Duration;
 
 import static org.fest.assertions.Assertions.assertThat;
 import static org.fest.assertions.Fail.fail;
@@ -46,6 +48,8 @@ public class RulesBuilderTest {
     newSquid1.setMetadata("foo=bar");
     newSquid1.setSeverity(Severity.CRITICAL);
     newSquid1.setStatus(RuleStatus.BETA);
+    newSquid1.setDebtCharacteristic("COMPILER");
+    newSquid1.setDebtRemediationFunction(DebtRemediationFunction.create(DebtRemediationFunction.Type.LINEAR_OFFSET, Duration.create(10), Duration.create(60)));
     newSquid1.addParam("min");
     newSquid1.addParam("max").setDescription("Maximum");
     // most simple rule
@@ -67,6 +71,11 @@ public class RulesBuilderTest {
     assertThat(squid1.metadata()).isEqualTo("foo=bar");
     assertThat(squid1.status()).isEqualTo(RuleStatus.BETA);
     assertThat(squid1.severity()).isEqualTo(Severity.CRITICAL);
+    assertThat(squid1.debtCharacteristic()).isEqualTo("COMPILER");
+    assertThat(squid1.debtRemediationFunction().type()).isEqualTo(DebtRemediationFunction.Type.LINEAR_OFFSET);
+    assertThat(squid1.debtRemediationFunction().factor()).isEqualTo(Duration.create(10));
+    assertThat(squid1.debtRemediationFunction().offset()).isEqualTo(Duration.create(60));
+    assertThat(squid1.debtCharacteristic()).isEqualTo("COMPILER");
     assertThat(squid1.params()).hasSize(2);
     assertThat(squid1.param("min").key()).isEqualTo("min");
     assertThat(squid1.param("min").description()).isNull();
@@ -80,6 +89,8 @@ public class RulesBuilderTest {
     assertThat(squid2.metadata()).isNull();
     assertThat(squid2.status()).isEqualTo(RuleStatus.defaultStatus());
     assertThat(squid2.severity()).isEqualTo(Severity.defaultSeverity());
+    assertThat(squid2.debtCharacteristic()).isNull();
+    assertThat(squid2.debtRemediationFunction()).isNull();
     assertThat(squid2.params()).isEmpty();
   }