diff options
13 files changed, 273 insertions, 173 deletions
diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/technicaldebt/DebtDecorator.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/technicaldebt/DebtDecorator.java index e146e03a9df..d948742da26 100644 --- a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/technicaldebt/DebtDecorator.java +++ b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/technicaldebt/DebtDecorator.java @@ -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) { diff --git a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/technicaldebt/DebtDecoratorTest.java b/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/technicaldebt/DebtDecoratorTest.java index 457b72ad0d7..aff369faab5 100644 --- a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/technicaldebt/DebtDecoratorTest.java +++ b/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/technicaldebt/DebtDecoratorTest.java @@ -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())); diff --git a/sonar-batch/src/main/java/org/sonar/batch/issue/ModuleIssues.java b/sonar-batch/src/main/java/org/sonar/batch/issue/ModuleIssues.java index 106cf3bada2..751aa64eedd 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/issue/ModuleIssues.java +++ b/sonar-batch/src/main/java/org/sonar/batch/issue/ModuleIssues.java @@ -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); } diff --git a/sonar-batch/src/main/java/org/sonar/batch/rule/RulesProvider.java b/sonar-batch/src/main/java/org/sonar/batch/rule/RulesProvider.java index 5732f129663..2d0f1294e8d 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/rule/RulesProvider.java +++ b/sonar-batch/src/main/java/org/sonar/batch/rule/RulesProvider.java @@ -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); + } + } diff --git a/sonar-batch/src/test/java/org/sonar/batch/issue/ModuleIssuesTest.java b/sonar-batch/src/test/java/org/sonar/batch/issue/ModuleIssuesTest.java index 492b4061b1d..f5b920c3b3c 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/issue/ModuleIssuesTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/issue/ModuleIssuesTest.java @@ -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(); diff --git a/sonar-batch/src/test/java/org/sonar/batch/rule/RulesProviderTest.java b/sonar-batch/src/test/java/org/sonar/batch/rule/RulesProviderTest.java index 01108161c10..d87e6b3189b 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/rule/RulesProviderTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/rule/RulesProviderTest.java @@ -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 index 00000000000..60f3faccefe --- /dev/null +++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/rule/DebtRemediationFunction.java @@ -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(); + } +} diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/rule/Rule.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/rule/Rule.java index 3332c5a89da..27a75566c09 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/batch/rule/Rule.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/rule/Rule.java @@ -20,10 +20,8 @@ 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(); } diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/rule/internal/DefaultRule.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/rule/internal/DefaultRule.java index 13a3d3890eb..5b2db0d27b9 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/batch/rule/internal/DefaultRule.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/rule/internal/DefaultRule.java @@ -20,12 +20,11 @@ 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 diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/rule/internal/NewRule.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/rule/internal/NewRule.java index 1f67eeb4e96..c3506ff1b50 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/batch/rule/internal/NewRule.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/rule/internal/NewRule.java @@ -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 index f88baec8ff0..00000000000 --- a/sonar-plugin-api/src/main/java/org/sonar/api/rule/RemediationFunction.java +++ /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 index 00000000000..a377c4abb73 --- /dev/null +++ b/sonar-plugin-api/src/test/java/org/sonar/api/batch/rule/DebtRemediationFunctionTest.java @@ -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(); + } +} diff --git a/sonar-plugin-api/src/test/java/org/sonar/api/batch/rule/internal/RulesBuilderTest.java b/sonar-plugin-api/src/test/java/org/sonar/api/batch/rule/internal/RulesBuilderTest.java index a314191e3cb..881823e3cf6 100644 --- a/sonar-plugin-api/src/test/java/org/sonar/api/batch/rule/internal/RulesBuilderTest.java +++ b/sonar-plugin-api/src/test/java/org/sonar/api/batch/rule/internal/RulesBuilderTest.java @@ -20,11 +20,13 @@ 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(); } |