diff options
author | Julien Lancelot <julien.lancelot@gmail.com> | 2013-10-07 13:35:09 +0200 |
---|---|---|
committer | Julien Lancelot <julien.lancelot@gmail.com> | 2013-10-07 13:35:09 +0200 |
commit | eb61eba8a4e2dead826feca34b22ca8fc5fa0ffb (patch) | |
tree | 63fb2bccde71e2134d0a99a6e1b3f2f1692f3f75 | |
parent | a559fa67ec15486009e7dccdb79d6f488699dbc2 (diff) | |
download | sonarqube-eb61eba8a4e2dead826feca34b22ca8fc5fa0ffb.tar.gz sonarqube-eb61eba8a4e2dead826feca34b22ca8fc5fa0ffb.zip |
SONAR-4716 Replace remediation cost by technical debt in issue
65 files changed, 654 insertions, 331 deletions
diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/IssueTrackingDecorator.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/IssueTrackingDecorator.java index b42bff38ae4..90ea63bd8e7 100644 --- a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/IssueTrackingDecorator.java +++ b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/IssueTrackingDecorator.java @@ -38,6 +38,7 @@ import org.sonar.api.resources.ResourceUtils; import org.sonar.api.rules.ActiveRule; import org.sonar.api.rules.Rule; import org.sonar.api.rules.RuleFinder; +import org.sonar.api.technicaldebt.TechnicalDebt; import org.sonar.api.utils.KeyValueFormat; import org.sonar.batch.issue.IssueCache; import org.sonar.batch.scan.LastSnapshots; @@ -166,7 +167,7 @@ public class IssueTrackingDecorator implements Decorator { updater.setPastLine(issue, ref.getLine()); updater.setPastMessage(issue, ref.getMessage(), changeContext); updater.setPastEffortToFix(issue, ref.getEffortToFix(), changeContext); - updater.setPastRemediationCost(issue, ref.getRemediationCost(), changeContext); + updater.setPastTechnicalDebt(issue, TechnicalDebt.fromLong(ref.getTechnicalDebt()), changeContext); } } diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/technicaldebt/TechnicalDebtDecorator.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/technicaldebt/TechnicalDebtDecorator.java index 0d13f9f6b24..0000fe95f25 100644 --- a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/technicaldebt/TechnicalDebtDecorator.java +++ b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/technicaldebt/TechnicalDebtDecorator.java @@ -32,8 +32,8 @@ import org.sonar.api.resources.Resource; import org.sonar.api.resources.ResourceUtils; import org.sonar.core.technicaldebt.TechnicalDebtCalculator; import org.sonar.core.technicaldebt.TechnicalDebtCharacteristic; +import org.sonar.core.technicaldebt.TechnicalDebtConverter; import org.sonar.core.technicaldebt.TechnicalDebtRequirement; -import org.sonar.core.technicaldebt.WorkUnitConverter; import java.util.Arrays; import java.util.List; @@ -111,7 +111,7 @@ public final class TechnicalDebtDecorator implements Decorator { private static List<PropertyDefinition> definitions() { return ImmutableList.of( - PropertyDefinition.builder(WorkUnitConverter.PROPERTY_HOURS_IN_DAY) + PropertyDefinition.builder(TechnicalDebtConverter.PROPERTY_HOURS_IN_DAY) .name("Number of working hours in a day") .defaultValue("8") .category(CoreProperties.CATEGORY_TECHNICAL_DEBT) diff --git a/plugins/sonar-core-plugin/src/main/resources/org/sonar/l10n/core.properties b/plugins/sonar-core-plugin/src/main/resources/org/sonar/l10n/core.properties index 0d03bf4ef1d..4b60157db4b 100644 --- a/plugins/sonar-core-plugin/src/main/resources/org/sonar/l10n/core.properties +++ b/plugins/sonar-core-plugin/src/main/resources/org/sonar/l10n/core.properties @@ -114,7 +114,6 @@ resolution=Resolution result=Result results=Results x_results={0} results -remediationCost=Remediation Cost review=Review reviews=Reviews review_verb=Review @@ -528,9 +527,9 @@ issue.component_deleted=Removed issue.changelog.changed_to={0} changed to {1} issue.changelog.was=was {0} issue.changelog.removed={0} removed -issue.remedation_cost.x_days={0} days -issue.remedation_cost.x_hours={0} hours -issue.remedation_cost.x_minutes={0} minutes +issue.technical_debt.x_days={0} days +issue.technical_debt.x_hours={0} hours +issue.technical_debt.x_minutes={0} minutes #------------------------------------------------------------------------------ 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 a3f695151f0..e22ac73c46f 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 @@ -82,7 +82,7 @@ public class ModuleIssues { if (issue.severity() == null) { issue.setSeverity(activeRule.getSeverity().name()); } - issue.setRemediationCost(technicalDebtCalculator.cost(issue)); + issue.setTechnicalDebt(technicalDebtCalculator.calculTechnicalDebt(issue)); if (filters.accept(issue, violation)) { cache.put(issue); diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/ProjectScanContainer.java b/sonar-batch/src/main/java/org/sonar/batch/scan/ProjectScanContainer.java index 0615528efa0..a425e6386da 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/scan/ProjectScanContainer.java +++ b/sonar-batch/src/main/java/org/sonar/batch/scan/ProjectScanContainer.java @@ -33,30 +33,9 @@ import org.sonar.batch.DefaultFileLinesContextFactory; import org.sonar.batch.DefaultResourceCreationLock; import org.sonar.batch.ProjectConfigurator; import org.sonar.batch.ProjectTree; -import org.sonar.batch.bootstrap.BootstrapSettings; -import org.sonar.batch.bootstrap.ExtensionInstaller; -import org.sonar.batch.bootstrap.ExtensionMatcher; -import org.sonar.batch.bootstrap.ExtensionUtils; -import org.sonar.batch.bootstrap.MetricProvider; -import org.sonar.batch.index.Caches; -import org.sonar.batch.index.ComponentDataCache; -import org.sonar.batch.index.ComponentDataPersister; -import org.sonar.batch.index.DefaultIndex; -import org.sonar.batch.index.DefaultPersistenceManager; -import org.sonar.batch.index.DefaultResourcePersister; -import org.sonar.batch.index.DependencyPersister; -import org.sonar.batch.index.EventPersister; -import org.sonar.batch.index.LinkPersister; -import org.sonar.batch.index.MeasurePersister; -import org.sonar.batch.index.MemoryOptimizer; -import org.sonar.batch.index.ResourceCache; -import org.sonar.batch.index.SnapshotCache; -import org.sonar.batch.index.SourcePersister; -import org.sonar.batch.issue.DefaultProjectIssues; -import org.sonar.batch.issue.DeprecatedViolations; -import org.sonar.batch.issue.IssueCache; -import org.sonar.batch.issue.IssuePersister; -import org.sonar.batch.issue.ScanIssueStorage; +import org.sonar.batch.bootstrap.*; +import org.sonar.batch.index.*; +import org.sonar.batch.issue.*; import org.sonar.batch.phases.GraphPersister; import org.sonar.batch.profiling.PhasesSumUpTimeProfiler; import org.sonar.batch.scan.filesystem.HashBuilder; @@ -70,13 +49,9 @@ import org.sonar.core.issue.IssueUpdater; import org.sonar.core.issue.workflow.FunctionExecutor; import org.sonar.core.issue.workflow.IssueWorkflow; import org.sonar.core.notification.DefaultNotificationManager; +import org.sonar.core.technicaldebt.TechnicalDebtConverter; import org.sonar.core.technicaldebt.TechnicalDebtModel; -import org.sonar.core.technicaldebt.WorkUnitConverter; -import org.sonar.core.technicaldebt.functions.ConstantFunction; -import org.sonar.core.technicaldebt.functions.Functions; -import org.sonar.core.technicaldebt.functions.LinearFunction; -import org.sonar.core.technicaldebt.functions.LinearWithOffsetFunction; -import org.sonar.core.technicaldebt.functions.LinearWithThresholdFunction; +import org.sonar.core.technicaldebt.functions.*; import org.sonar.core.test.TestPlanBuilder; import org.sonar.core.test.TestPlanPerspectiveLoader; import org.sonar.core.test.TestableBuilder; @@ -169,7 +144,7 @@ public class ProjectScanContainer extends ComponentContainer { // technical debt TechnicalDebtModel.class, - WorkUnitConverter.class, + TechnicalDebtConverter.class, ConstantFunction.class, LinearFunction.class, LinearWithOffsetFunction.class, 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 0097856a211..3f5e939fd9d 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 @@ -34,6 +34,7 @@ import org.sonar.api.rules.ActiveRule; import org.sonar.api.rules.Rule; import org.sonar.api.rules.RulePriority; import org.sonar.api.rules.Violation; +import org.sonar.api.technicaldebt.TechnicalDebt; import org.sonar.core.technicaldebt.TechnicalDebtCalculator; import java.util.Calendar; @@ -200,14 +201,14 @@ public class ModuleIssuesTest { .setRuleKey(SQUID_RULE_KEY) .setSeverity(Severity.CRITICAL); - when(technicalDebtCalculator.cost(issue)).thenReturn(10L); + when(technicalDebtCalculator.calculTechnicalDebt(issue)).thenReturn(TechnicalDebt.of(10, 0, 0)); when(filters.accept(issue, null)).thenReturn(true); moduleIssues.initAndAddIssue(issue); ArgumentCaptor<DefaultIssue> argument = ArgumentCaptor.forClass(DefaultIssue.class); verify(cache).put(argument.capture()); - assertThat(argument.getValue().remediationCost()).isEqualTo(10L); + assertThat(argument.getValue().technicalDebt()).isEqualTo(TechnicalDebt.of(10, 0, 0)); } } diff --git a/sonar-core/src/main/java/org/sonar/core/issue/IssueUpdater.java b/sonar-core/src/main/java/org/sonar/core/issue/IssueUpdater.java index ad834ed8ff2..6149cb65b6c 100644 --- a/sonar-core/src/main/java/org/sonar/core/issue/IssueUpdater.java +++ b/sonar-core/src/main/java/org/sonar/core/issue/IssueUpdater.java @@ -28,6 +28,7 @@ import org.sonar.api.issue.ActionPlan; import org.sonar.api.issue.internal.DefaultIssue; import org.sonar.api.issue.internal.DefaultIssueComment; import org.sonar.api.issue.internal.IssueChangeContext; +import org.sonar.api.technicaldebt.TechnicalDebt; import org.sonar.api.user.User; import javax.annotation.Nullable; @@ -47,7 +48,6 @@ public class IssueUpdater implements BatchComponent, ServerComponent { public static final String STATUS = "status"; public static final String AUTHOR = "author"; public static final String ACTION_PLAN = "actionPlan"; - public static final String REMEDIATION_COST = "remediationCost"; public boolean setSeverity(DefaultIssue issue, String severity, IssueChangeContext context) { if (issue.manualSeverity()) { @@ -199,23 +199,21 @@ public class IssueUpdater implements BatchComponent, ServerComponent { return setEffortToFix(issue, currentEffort, context); } - public boolean setRemediationCost(DefaultIssue issue, @Nullable Long value, IssueChangeContext context) { - Long oldValue = issue.remediationCost(); + public boolean setTechnicalDebt(DefaultIssue issue, @Nullable TechnicalDebt value, IssueChangeContext context) { + TechnicalDebt oldValue = issue.technicalDebt(); if (!Objects.equal(value, oldValue)) { - issue.setRemediationCost(value); + issue.setTechnicalDebt(value); issue.setUpdateDate(context.date()); issue.setChanged(true); - issue.setFieldChange(context, REMEDIATION_COST, oldValue, value); return true; } return false; } - public boolean setPastRemediationCost(DefaultIssue issue, @Nullable Long previousRemediationCost, IssueChangeContext context) { - Long currentRemediationCost = issue.remediationCost(); - issue.setRemediationCost(previousRemediationCost); - return setRemediationCost(issue, currentRemediationCost, context); - + public boolean setPastTechnicalDebt(DefaultIssue issue, @Nullable TechnicalDebt previousTechnicalDebt, IssueChangeContext context) { + TechnicalDebt currentTechnicalDebt = issue.technicalDebt(); + issue.setTechnicalDebt(previousTechnicalDebt); + return setTechnicalDebt(issue, currentTechnicalDebt, context); } public boolean setAttribute(DefaultIssue issue, String key, @Nullable String value, IssueChangeContext context) { diff --git a/sonar-core/src/main/java/org/sonar/core/issue/db/IssueDto.java b/sonar-core/src/main/java/org/sonar/core/issue/db/IssueDto.java index fabdee98933..4452f482b14 100644 --- a/sonar-core/src/main/java/org/sonar/core/issue/db/IssueDto.java +++ b/sonar-core/src/main/java/org/sonar/core/issue/db/IssueDto.java @@ -25,6 +25,7 @@ import org.apache.commons.lang.builder.ToStringBuilder; import org.apache.commons.lang.builder.ToStringStyle; import org.sonar.api.issue.internal.DefaultIssue; import org.sonar.api.rule.RuleKey; +import org.sonar.api.technicaldebt.TechnicalDebt; import org.sonar.api.utils.KeyValueFormat; import javax.annotation.CheckForNull; @@ -48,7 +49,7 @@ public final class IssueDto implements Serializable { private String message; private Integer line; private Double effortToFix; - private Long remediationCost; + private Long technicalDebt; private String status; private String resolution; private String checksum; @@ -183,12 +184,12 @@ public final class IssueDto implements Serializable { } @CheckForNull - public Long getRemediationCost() { - return remediationCost; + public Long getTechnicalDebt() { + return technicalDebt; } - public IssueDto setRemediationCost(@Nullable Long remediationCost) { - this.remediationCost = remediationCost; + public IssueDto setTechnicalDebt(@Nullable Long technicalDebt) { + this.technicalDebt = technicalDebt; return this; } @@ -367,7 +368,7 @@ public final class IssueDto implements Serializable { .setLine(issue.line()) .setMessage(issue.message()) .setEffortToFix(issue.effortToFix()) - .setRemediationCost(issue.remediationCost()) + .setTechnicalDebt(issue.technicalDebt() != null ? issue.technicalDebt().toLong() : null) .setResolution(issue.resolution()) .setStatus(issue.status()) .setSeverity(issue.severity()) @@ -396,7 +397,7 @@ public final class IssueDto implements Serializable { .setLine(issue.line()) .setMessage(issue.message()) .setEffortToFix(issue.effortToFix()) - .setRemediationCost(issue.remediationCost()) + .setTechnicalDebt(issue.technicalDebt() != null ? issue.technicalDebt().toLong() : null) .setResolution(issue.resolution()) .setStatus(issue.status()) .setSeverity(issue.severity()) @@ -421,7 +422,7 @@ public final class IssueDto implements Serializable { issue.setResolution(resolution); issue.setMessage(message); issue.setEffortToFix(effortToFix); - issue.setRemediationCost(remediationCost); + issue.setTechnicalDebt(technicalDebt != null ? TechnicalDebt.fromLong(technicalDebt) : null); issue.setLine(line); issue.setSeverity(severity); issue.setReporter(reporter); diff --git a/sonar-core/src/main/java/org/sonar/core/technicaldebt/RemediationCostTimeUnit.java b/sonar-core/src/main/java/org/sonar/core/technicaldebt/RemediationCostTimeUnit.java deleted file mode 100644 index 67ae89e0159..00000000000 --- a/sonar-core/src/main/java/org/sonar/core/technicaldebt/RemediationCostTimeUnit.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * SonarQube, open source software quality management tool. - * Copyright (C) 2008-2013 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.core.technicaldebt; - -public class RemediationCostTimeUnit { - - private long days; - private long hours; - private long minutes; - - private static final int ONE_HOUR_IN_MINUTE = 60; - - private RemediationCostTimeUnit(long input, int hoursInDay) { - int oneWorkingDay = hoursInDay * ONE_HOUR_IN_MINUTE; - if (input >= oneWorkingDay) { - long nbDays = input / oneWorkingDay; - this.days = nbDays; - input = input - (nbDays * oneWorkingDay); - } - - if (input >= ONE_HOUR_IN_MINUTE) { - long nbHours = input / ONE_HOUR_IN_MINUTE; - this.hours = nbHours; - input = input - (nbHours * ONE_HOUR_IN_MINUTE); - } - - this.minutes = input; - } - - public static RemediationCostTimeUnit of(Long time, int hoursInDay) { - return new RemediationCostTimeUnit(time, hoursInDay); - } - - public long days() { - return days; - } - - public long hours() { - return hours; - } - - public long minutes() { - return minutes; - } - -} diff --git a/sonar-core/src/main/java/org/sonar/core/technicaldebt/TechnicalDebtCalculator.java b/sonar-core/src/main/java/org/sonar/core/technicaldebt/TechnicalDebtCalculator.java index fb540c66419..edbf8bd2b79 100644 --- a/sonar-core/src/main/java/org/sonar/core/technicaldebt/TechnicalDebtCalculator.java +++ b/sonar-core/src/main/java/org/sonar/core/technicaldebt/TechnicalDebtCalculator.java @@ -32,6 +32,7 @@ import org.sonar.api.measures.Measure; import org.sonar.api.measures.MeasuresFilters; import org.sonar.api.measures.Metric; import org.sonar.api.rules.Violation; +import org.sonar.api.technicaldebt.TechnicalDebt; import org.sonar.core.technicaldebt.functions.Functions; import java.util.Collection; @@ -48,17 +49,19 @@ public class TechnicalDebtCalculator implements BatchExtension { private Map<TechnicalDebtRequirement, Double> requirementCosts = Maps.newHashMap(); private Functions functions; + private final TechnicalDebtConverter converter; private TechnicalDebtModel technicalDebtModel; - public TechnicalDebtCalculator(TechnicalDebtModel technicalDebtModel, Functions functions) { + public TechnicalDebtCalculator(TechnicalDebtModel technicalDebtModel, Functions functions, TechnicalDebtConverter converter) { this.technicalDebtModel = technicalDebtModel; this.functions = functions; + this.converter = converter; } - public Long cost(Issue issue) { + public TechnicalDebt calculTechnicalDebt(Issue issue) { TechnicalDebtRequirement requirement = technicalDebtModel.getRequirementByRule(issue.ruleKey().repository(), issue.ruleKey().rule()); if (requirement != null) { - return functions.costInMinutes(requirement, issue); + return converter.fromMinutes(functions.costInMinutes(requirement, issue)); } return null; } @@ -72,7 +75,7 @@ public class TechnicalDebtCalculator implements BatchExtension { // the total cost is: cost(violations) for (TechnicalDebtRequirement requirement : technicalDebtModel.getAllRequirements()) { List<Violation> violations = violationsByRequirement.get(requirement); - double allViolationsCost = computeRemediationCost(CoreMetrics.TECHNICAL_DEBT, context, requirement, violations); + double allViolationsCost = computeTechnicalDebt(CoreMetrics.TECHNICAL_DEBT, context, requirement, violations); updateRequirementCosts(requirement, allViolationsCost); } } @@ -112,7 +115,7 @@ public class TechnicalDebtCalculator implements BatchExtension { propagateCostInParents(requirement.getParent(), cost); } - private double computeRemediationCost(Metric metric, DecoratorContext context, TechnicalDebtRequirement requirement, Collection<Violation> violations) { + private double computeTechnicalDebt(Metric metric, DecoratorContext context, TechnicalDebtRequirement requirement, Collection<Violation> violations) { double cost = 0.0; if (violations != null) { cost = functions.costInHours(requirement, violations); diff --git a/sonar-core/src/main/java/org/sonar/core/technicaldebt/WorkUnitConverter.java b/sonar-core/src/main/java/org/sonar/core/technicaldebt/TechnicalDebtConverter.java index 3c3d26154e1..0b0f977e084 100644 --- a/sonar-core/src/main/java/org/sonar/core/technicaldebt/WorkUnitConverter.java +++ b/sonar-core/src/main/java/org/sonar/core/technicaldebt/TechnicalDebtConverter.java @@ -23,14 +23,15 @@ import org.apache.commons.lang.StringUtils; import org.sonar.api.BatchComponent; import org.sonar.api.ServerComponent; import org.sonar.api.config.Settings; +import org.sonar.api.technicaldebt.TechnicalDebt; -public final class WorkUnitConverter implements BatchComponent, ServerComponent { +public class TechnicalDebtConverter implements BatchComponent, ServerComponent { public static final String PROPERTY_HOURS_IN_DAY = "sonar.technicalDebt.hoursInDay"; private int hoursInDay; - public WorkUnitConverter(Settings settings) { + public TechnicalDebtConverter(Settings settings) { this.hoursInDay = settings.getInt(PROPERTY_HOURS_IN_DAY); } @@ -64,8 +65,28 @@ public final class WorkUnitConverter implements BatchComponent, ServerComponent } } - public RemediationCostTimeUnit toRemediationCostTimeUnit(long minutes){ - return RemediationCostTimeUnit.of(minutes, hoursInDay); + public TechnicalDebt fromMinutes(Long inMinutes){ + int oneHourInMinute = 60; + int days = 0; + int hours = 0; + int minutes = 0; + + int oneWorkingDay = hoursInDay * oneHourInMinute; + if (inMinutes >= oneWorkingDay) { + Long nbDays = inMinutes / oneWorkingDay; + days = nbDays.shortValue(); + inMinutes = inMinutes - (nbDays * oneWorkingDay); + } + + if (inMinutes >= oneHourInMinute) { + Long nbHours = inMinutes / oneHourInMinute; + hours = nbHours.shortValue(); + inMinutes = inMinutes - (nbHours * oneHourInMinute); + } + + minutes = inMinutes.shortValue(); + + return TechnicalDebt.of(minutes, hours, days); } } diff --git a/sonar-core/src/main/java/org/sonar/core/technicaldebt/functions/AbstractFunction.java b/sonar-core/src/main/java/org/sonar/core/technicaldebt/functions/AbstractFunction.java index c07a7c4b181..86146993b1b 100644 --- a/sonar-core/src/main/java/org/sonar/core/technicaldebt/functions/AbstractFunction.java +++ b/sonar-core/src/main/java/org/sonar/core/technicaldebt/functions/AbstractFunction.java @@ -21,20 +21,20 @@ package org.sonar.core.technicaldebt.functions; import org.sonar.api.issue.Issue; import org.sonar.api.rules.Violation; +import org.sonar.core.technicaldebt.TechnicalDebtConverter; import org.sonar.core.technicaldebt.TechnicalDebtRequirement; -import org.sonar.core.technicaldebt.WorkUnitConverter; import java.util.Collection; public abstract class AbstractFunction implements Function { - private WorkUnitConverter converter; + private TechnicalDebtConverter converter; - public AbstractFunction(WorkUnitConverter converter) { + public AbstractFunction(TechnicalDebtConverter converter) { this.converter = converter; } - protected WorkUnitConverter getConverter() { + protected TechnicalDebtConverter getConverter() { return converter; } diff --git a/sonar-core/src/main/java/org/sonar/core/technicaldebt/functions/ConstantFunction.java b/sonar-core/src/main/java/org/sonar/core/technicaldebt/functions/ConstantFunction.java index b347c6838bd..7f92e8604b7 100644 --- a/sonar-core/src/main/java/org/sonar/core/technicaldebt/functions/ConstantFunction.java +++ b/sonar-core/src/main/java/org/sonar/core/technicaldebt/functions/ConstantFunction.java @@ -21,8 +21,8 @@ package org.sonar.core.technicaldebt.functions; import org.sonar.api.issue.Issue; import org.sonar.api.rules.Violation; +import org.sonar.core.technicaldebt.TechnicalDebtConverter; import org.sonar.core.technicaldebt.TechnicalDebtRequirement; -import org.sonar.core.technicaldebt.WorkUnitConverter; import java.util.Collection; @@ -30,7 +30,7 @@ public final class ConstantFunction extends AbstractFunction { public static final String FUNCTION_CONSTANT_RESOURCE = "constant_resource"; - public ConstantFunction(WorkUnitConverter converter) { + public ConstantFunction(TechnicalDebtConverter converter) { super(converter); } diff --git a/sonar-core/src/main/java/org/sonar/core/technicaldebt/functions/LinearFunction.java b/sonar-core/src/main/java/org/sonar/core/technicaldebt/functions/LinearFunction.java index 2453437ddff..d351372576b 100644 --- a/sonar-core/src/main/java/org/sonar/core/technicaldebt/functions/LinearFunction.java +++ b/sonar-core/src/main/java/org/sonar/core/technicaldebt/functions/LinearFunction.java @@ -21,8 +21,8 @@ package org.sonar.core.technicaldebt.functions; import org.sonar.api.issue.Issue; import org.sonar.api.rules.Violation; +import org.sonar.core.technicaldebt.TechnicalDebtConverter; import org.sonar.core.technicaldebt.TechnicalDebtRequirement; -import org.sonar.core.technicaldebt.WorkUnitConverter; import java.util.Collection; @@ -32,7 +32,7 @@ public class LinearFunction extends AbstractFunction { public static final double DEFAULT_VIOLATION_COST = 1.0; - public LinearFunction(WorkUnitConverter converter) { + public LinearFunction(TechnicalDebtConverter converter) { super(converter); } diff --git a/sonar-core/src/main/java/org/sonar/core/technicaldebt/functions/LinearWithOffsetFunction.java b/sonar-core/src/main/java/org/sonar/core/technicaldebt/functions/LinearWithOffsetFunction.java index 931ff24798e..890dc779ec3 100644 --- a/sonar-core/src/main/java/org/sonar/core/technicaldebt/functions/LinearWithOffsetFunction.java +++ b/sonar-core/src/main/java/org/sonar/core/technicaldebt/functions/LinearWithOffsetFunction.java @@ -20,8 +20,8 @@ package org.sonar.core.technicaldebt.functions; import org.sonar.api.rules.Violation; +import org.sonar.core.technicaldebt.TechnicalDebtConverter; import org.sonar.core.technicaldebt.TechnicalDebtRequirement; -import org.sonar.core.technicaldebt.WorkUnitConverter; import java.util.Collection; @@ -29,7 +29,7 @@ public final class LinearWithOffsetFunction extends LinearFunction { public static final String FUNCTION_LINEAR_WITH_OFFSET = "linear_offset"; - public LinearWithOffsetFunction(WorkUnitConverter converter) { + public LinearWithOffsetFunction(TechnicalDebtConverter converter) { super(converter); } diff --git a/sonar-core/src/main/java/org/sonar/core/technicaldebt/functions/LinearWithThresholdFunction.java b/sonar-core/src/main/java/org/sonar/core/technicaldebt/functions/LinearWithThresholdFunction.java index 9530b11843f..f8fc198556e 100644 --- a/sonar-core/src/main/java/org/sonar/core/technicaldebt/functions/LinearWithThresholdFunction.java +++ b/sonar-core/src/main/java/org/sonar/core/technicaldebt/functions/LinearWithThresholdFunction.java @@ -20,8 +20,8 @@ package org.sonar.core.technicaldebt.functions; import org.sonar.api.rules.Violation; +import org.sonar.core.technicaldebt.TechnicalDebtConverter; import org.sonar.core.technicaldebt.TechnicalDebtRequirement; -import org.sonar.core.technicaldebt.WorkUnitConverter; import java.util.Collection; @@ -29,7 +29,7 @@ public final class LinearWithThresholdFunction extends LinearFunction { public static final String FUNCTION_LINEAR_WITH_THRESHOLD = "linear_threshold"; - public LinearWithThresholdFunction(WorkUnitConverter converter) { + public LinearWithThresholdFunction(TechnicalDebtConverter converter) { super(converter); } diff --git a/sonar-core/src/main/resources/org/sonar/core/issue/db/IssueMapper.xml b/sonar-core/src/main/resources/org/sonar/core/issue/db/IssueMapper.xml index 80e9e375cb1..9cc0a285dcd 100644 --- a/sonar-core/src/main/resources/org/sonar/core/issue/db/IssueMapper.xml +++ b/sonar-core/src/main/resources/org/sonar/core/issue/db/IssueMapper.xml @@ -16,7 +16,7 @@ i.message as message, i.line as line, i.effort_to_fix as effortToFix, - i.remediation_cost as remediationCost, + i.technical_debt as technicalDebt, i.status as status, i.resolution as resolution, i.checksum as checksum, @@ -62,11 +62,11 @@ <insert id="insert" parameterType="Issue" useGeneratedKeys="false" keyProperty="id"> INSERT INTO issues (kee, component_id, root_component_id, rule_id, action_plan_key, severity, manual_severity, - message, line, effort_to_fix, remediation_cost, status, + message, line, effort_to_fix, technical_debt, status, resolution, checksum, reporter, assignee, author_login, issue_attributes, issue_creation_date, issue_update_date, issue_close_date, created_at, updated_at) VALUES (#{kee}, #{componentId}, #{rootComponentId}, #{ruleId}, #{actionPlanKey}, #{severity}, #{manualSeverity}, - #{message}, #{line}, #{effortToFix}, #{remediationCost}, #{status}, + #{message}, #{line}, #{effortToFix}, #{technicalDebt}, #{status}, #{resolution}, #{checksum}, #{reporter}, #{assignee}, #{authorLogin}, #{issueAttributes}, #{issueCreationDate}, #{issueUpdateDate}, #{issueCloseDate}, #{createdAt}, #{updatedAt}) </insert> @@ -82,7 +82,7 @@ message=#{message}, line=#{line}, effort_to_fix=#{effortToFix}, - remediation_cost=#{remediationCost}, + technical_debt=#{technicalDebt}, status=#{status}, resolution=#{resolution}, checksum=#{checksum}, @@ -108,7 +108,7 @@ message=#{message}, line=#{line}, effort_to_fix=#{effortToFix}, - remediation_cost=#{remediationCost}, + technical_debt=#{technicalDebt}, status=#{status}, resolution=#{resolution}, checksum=#{checksum}, @@ -148,7 +148,7 @@ i.message as message, i.line as line, i.effort_to_fix as effortToFix, - i.remediation_cost as remediationCost, + i.technical_debt as technicalDebt, i.status as status, i.resolution as resolution, i.checksum as checksum, diff --git a/sonar-core/src/main/resources/org/sonar/core/persistence/schema-h2.ddl b/sonar-core/src/main/resources/org/sonar/core/persistence/schema-h2.ddl index 4f201802db7..5551481cb82 100644 --- a/sonar-core/src/main/resources/org/sonar/core/persistence/schema-h2.ddl +++ b/sonar-core/src/main/resources/org/sonar/core/persistence/schema-h2.ddl @@ -477,7 +477,7 @@ CREATE TABLE "ISSUES" ( "MESSAGE" VARCHAR(4000), "LINE" INTEGER, "EFFORT_TO_FIX" DOUBLE, - "REMEDIATION_COST" INTEGER, + "TECHNICAL_DEBT" INTEGER, "STATUS" VARCHAR(20), "RESOLUTION" VARCHAR(20), "CHECKSUM" VARCHAR(1000), diff --git a/sonar-core/src/test/java/org/sonar/core/issue/IssueUpdaterTest.java b/sonar-core/src/test/java/org/sonar/core/issue/IssueUpdaterTest.java index 07e0e8f3977..345b7a513ec 100644 --- a/sonar-core/src/test/java/org/sonar/core/issue/IssueUpdaterTest.java +++ b/sonar-core/src/test/java/org/sonar/core/issue/IssueUpdaterTest.java @@ -24,6 +24,7 @@ import org.sonar.api.issue.ActionPlan; import org.sonar.api.issue.internal.DefaultIssue; import org.sonar.api.issue.internal.FieldDiffs; import org.sonar.api.issue.internal.IssueChangeContext; +import org.sonar.api.technicaldebt.TechnicalDebt; import org.sonar.api.user.User; import org.sonar.core.user.DefaultUser; @@ -364,15 +365,13 @@ public class IssueUpdaterTest { } @Test - public void set_past_remediation_cost() throws Exception { - issue.setRemediationCost(15l); - boolean updated = updater.setPastRemediationCost(issue, 10l, context); + public void set_past_technical_debt() throws Exception { + issue.setTechnicalDebt(TechnicalDebt.of(15, 0, 0)); + TechnicalDebt previousDebt = TechnicalDebt.of(10, 0, 0); + boolean updated = updater.setPastTechnicalDebt(issue, previousDebt, context); assertThat(updated).isTrue(); - assertThat(issue.remediationCost()).isEqualTo(15L); + assertThat(issue.technicalDebt()).isEqualTo(TechnicalDebt.of(15, 0, 0)); - FieldDiffs.Diff diff = issue.currentChange().get("remediationCost"); - assertThat(diff.oldValue()).isEqualTo(10L); - assertThat(diff.newValue()).isEqualTo(15L); assertThat(issue.mustSendNotifications()).isFalse(); } diff --git a/sonar-core/src/test/java/org/sonar/core/issue/db/IssueDtoTest.java b/sonar-core/src/test/java/org/sonar/core/issue/db/IssueDtoTest.java index 4add1b46497..6b9249417e4 100644 --- a/sonar-core/src/test/java/org/sonar/core/issue/db/IssueDtoTest.java +++ b/sonar-core/src/test/java/org/sonar/core/issue/db/IssueDtoTest.java @@ -25,6 +25,7 @@ import org.junit.Test; import org.junit.rules.ExpectedException; import org.sonar.api.issue.Issue; import org.sonar.api.issue.internal.DefaultIssue; +import org.sonar.api.technicaldebt.TechnicalDebt; import java.util.Calendar; import java.util.Date; @@ -65,7 +66,7 @@ public class IssueDtoTest { .setStatus(Issue.STATUS_CLOSED) .setResolution(Issue.RESOLUTION_FALSE_POSITIVE) .setEffortToFix(15.0) - .setRemediationCost(500L) + .setTechnicalDebt(101010L) .setLine(6) .setSeverity("BLOCKER") .setMessage("message") @@ -86,7 +87,7 @@ public class IssueDtoTest { assertThat(issue.status()).isEqualTo(Issue.STATUS_CLOSED); assertThat(issue.resolution()).isEqualTo(Issue.RESOLUTION_FALSE_POSITIVE); assertThat(issue.effortToFix()).isEqualTo(15.0); - assertThat(issue.remediationCost()).isEqualTo(500L); + assertThat(issue.technicalDebt()).isEqualTo(TechnicalDebt.of(10, 10, 10)); assertThat(issue.line()).isEqualTo(6); assertThat(issue.severity()).isEqualTo("BLOCKER"); assertThat(issue.message()).isEqualTo("message"); diff --git a/sonar-core/src/test/java/org/sonar/core/issue/db/IssueMapperTest.java b/sonar-core/src/test/java/org/sonar/core/issue/db/IssueMapperTest.java index 3397cd4e4a2..58736049267 100644 --- a/sonar-core/src/test/java/org/sonar/core/issue/db/IssueMapperTest.java +++ b/sonar-core/src/test/java/org/sonar/core/issue/db/IssueMapperTest.java @@ -54,7 +54,7 @@ public class IssueMapperTest extends AbstractDaoTestCase { dto.setKee("ABCDE"); dto.setLine(500); dto.setEffortToFix(3.14); - dto.setRemediationCost(10L); + dto.setTechnicalDebt(10L); dto.setResolution("FIXED"); dto.setStatus("RESOLVED"); dto.setSeverity("BLOCKER"); @@ -89,7 +89,7 @@ public class IssueMapperTest extends AbstractDaoTestCase { dto.setKee("ABCDE"); dto.setLine(500); dto.setEffortToFix(3.14); - dto.setRemediationCost(10L); + dto.setTechnicalDebt(10L); dto.setResolution("FIXED"); dto.setStatus("RESOLVED"); dto.setSeverity("BLOCKER"); @@ -124,7 +124,7 @@ public class IssueMapperTest extends AbstractDaoTestCase { dto.setKee("ABCDE"); dto.setLine(500); dto.setEffortToFix(3.14); - dto.setRemediationCost(10L); + dto.setTechnicalDebt(10L); dto.setResolution("FIXED"); dto.setStatus("RESOLVED"); dto.setSeverity("BLOCKER"); @@ -162,7 +162,7 @@ public class IssueMapperTest extends AbstractDaoTestCase { dto.setKee("ABCDE"); dto.setLine(500); dto.setEffortToFix(3.14); - dto.setRemediationCost(10L); + dto.setTechnicalDebt(10L); dto.setResolution("FIXED"); dto.setStatus("RESOLVED"); dto.setSeverity("BLOCKER"); diff --git a/sonar-core/src/test/java/org/sonar/core/issue/db/IssueStorageTest.java b/sonar-core/src/test/java/org/sonar/core/issue/db/IssueStorageTest.java index b39bb5ba413..b33f56b286a 100644 --- a/sonar-core/src/test/java/org/sonar/core/issue/db/IssueStorageTest.java +++ b/sonar-core/src/test/java/org/sonar/core/issue/db/IssueStorageTest.java @@ -27,6 +27,7 @@ import org.sonar.api.rule.RuleKey; import org.sonar.api.rules.Rule; import org.sonar.api.rules.RuleFinder; import org.sonar.api.rules.RuleQuery; +import org.sonar.api.technicaldebt.TechnicalDebt; import org.sonar.api.utils.DateUtils; import org.sonar.core.persistence.AbstractDaoTestCase; import org.sonar.core.persistence.MyBatis; @@ -53,7 +54,7 @@ public class IssueStorageTest extends AbstractDaoTestCase { .setRuleKey(RuleKey.of("squid", "AvoidCycle")) .setLine(5000) - .setRemediationCost(10L) + .setTechnicalDebt(TechnicalDebt.of(10, 0, 0)) .setReporter("emmerik") .setResolution("OPEN") .setStatus("OPEN") @@ -87,7 +88,7 @@ public class IssueStorageTest extends AbstractDaoTestCase { // updated fields .setLine(5000) - .setRemediationCost(10L) + .setTechnicalDebt(TechnicalDebt.of(10, 0, 0)) .setChecksum("FFFFF") .setAuthorLogin("simon") .setAssignee("loic") diff --git a/sonar-core/src/test/java/org/sonar/core/technicaldebt/RemediationCostTimeUnitTest.java b/sonar-core/src/test/java/org/sonar/core/technicaldebt/RemediationCostTimeUnitTest.java deleted file mode 100644 index ab611144e6c..00000000000 --- a/sonar-core/src/test/java/org/sonar/core/technicaldebt/RemediationCostTimeUnitTest.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * SonarQube, open source software quality management tool. - * Copyright (C) 2008-2013 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.core.technicaldebt; - -import org.junit.Test; - -import static org.fest.assertions.Assertions.assertThat; - -public class RemediationCostTimeUnitTest { - - private static final int HOURS_IN_DAY = 8; - - @Test - public void convert_simple_values() { - checkTimes(RemediationCostTimeUnit.of(15L, HOURS_IN_DAY), 15L, 0L, 0L); - checkTimes(RemediationCostTimeUnit.of(120L, HOURS_IN_DAY), 0L, 2L, 0L); - checkTimes(RemediationCostTimeUnit.of(480L, HOURS_IN_DAY), 0L, 0L, 1L); - } - - @Test - public void convert_complex_values() { - checkTimes(RemediationCostTimeUnit.of(70L, HOURS_IN_DAY), 10L, 1L, 0L); - checkTimes(RemediationCostTimeUnit.of(490L, HOURS_IN_DAY), 10L, 0L, 1L); - checkTimes(RemediationCostTimeUnit.of(550L, HOURS_IN_DAY), 10L, 1L, 1L); - } - - private void checkTimes(RemediationCostTimeUnit remediationCostTimeUnit, Long expectedMinutes, Long expectedHours, Long expectedDays ) { - assertThat(remediationCostTimeUnit.minutes()).isEqualTo(expectedMinutes); - assertThat(remediationCostTimeUnit.hours()).isEqualTo(expectedHours); - assertThat(remediationCostTimeUnit.days()).isEqualTo(expectedDays); - } - -} diff --git a/sonar-core/src/test/java/org/sonar/core/technicaldebt/TechnicalDebtCalculatorTest.java b/sonar-core/src/test/java/org/sonar/core/technicaldebt/TechnicalDebtCalculatorTest.java index eed0940f08c..c310b4c87f2 100644 --- a/sonar-core/src/test/java/org/sonar/core/technicaldebt/TechnicalDebtCalculatorTest.java +++ b/sonar-core/src/test/java/org/sonar/core/technicaldebt/TechnicalDebtCalculatorTest.java @@ -52,12 +52,14 @@ public class TechnicalDebtCalculatorTest { private TechnicalDebtModel technicalDebtModel; private Functions functions; private TechnicalDebtCalculator remediationCostCalculator; + private TechnicalDebtConverter converter; @Before public void initMocks() { technicalDebtModel = mock(TechnicalDebtModel.class); functions = mock(Functions.class); - remediationCostCalculator = new TechnicalDebtCalculator(technicalDebtModel, functions); + converter = mock(TechnicalDebtConverter.class); + remediationCostCalculator = new TechnicalDebtCalculator(technicalDebtModel, functions, converter); } @Test @@ -150,22 +152,22 @@ public class TechnicalDebtCalculatorTest { } @Test - public void cost_from_one_issue() throws Exception { + public void technical_debt_from_one_issue() throws Exception { DefaultIssue issue = new DefaultIssue().setKey("ABCDE").setRuleKey(RuleKey.of("squid", "AvoidCycle")); TechnicalDebtRequirement requirement = mock(TechnicalDebtRequirement.class); - stub(technicalDebtModel.getRequirementByRule("squid", "AvoidCycle")).toReturn(requirement); - + when(technicalDebtModel.getRequirementByRule("squid", "AvoidCycle")).thenReturn(requirement); when(functions.costInMinutes(eq(requirement), eq(issue))).thenReturn(10L); - assertThat(remediationCostCalculator.cost(issue)).isEqualTo(10L); + remediationCostCalculator.calculTechnicalDebt(issue); + verify(functions).costInMinutes(eq(requirement), eq(issue)); } @Test - public void no_cost_from_one_issue_if_reauirement_not_found() throws Exception { + public void no_technical_debt_from_one_issue_if_reauirement_not_found() throws Exception { DefaultIssue issue = new DefaultIssue().setKey("ABCDE").setRuleKey(RuleKey.of("squid", "AvoidCycle")); - stub(technicalDebtModel.getRequirementByRule("squid", "AvoidCycle")).toReturn(null); + when(technicalDebtModel.getRequirementByRule("squid", "AvoidCycle")).thenReturn(null); - assertThat(remediationCostCalculator.cost(issue)).isNull(); + assertThat(remediationCostCalculator.calculTechnicalDebt(issue)).isNull(); verify(functions, never()).costInMinutes(any(TechnicalDebtRequirement.class), any(Issue.class)); } diff --git a/sonar-core/src/test/java/org/sonar/core/technicaldebt/WorkUnitConverterTest.java b/sonar-core/src/test/java/org/sonar/core/technicaldebt/TechnicalDebtConverterTest.java index 890e84ee312..fe86eb80dbf 100644 --- a/sonar-core/src/test/java/org/sonar/core/technicaldebt/WorkUnitConverterTest.java +++ b/sonar-core/src/test/java/org/sonar/core/technicaldebt/TechnicalDebtConverterTest.java @@ -19,21 +19,29 @@ */ package org.sonar.core.technicaldebt; +import org.fest.assertions.Assertions; +import org.junit.Before; import org.junit.Test; import org.sonar.api.config.Settings; +import org.sonar.api.technicaldebt.TechnicalDebt; import static org.hamcrest.Matchers.is; import static org.junit.Assert.assertThat; -public class WorkUnitConverterTest { +public class TechnicalDebtConverterTest { - @Test - public void convert_to_days() { + private TechnicalDebtConverter converter; + + @Before + public void before(){ Settings settings = new Settings(); - settings.setProperty(WorkUnitConverter.PROPERTY_HOURS_IN_DAY, "12"); + settings.setProperty(TechnicalDebtConverter.PROPERTY_HOURS_IN_DAY, "12"); - WorkUnitConverter converter = new WorkUnitConverter(settings); + converter = new TechnicalDebtConverter(settings); + } + @Test + public void convert_to_days() { assertThat(converter.toDays(WorkUnit.create(6.0, WorkUnit.DAYS)), is(6.0)); assertThat(converter.toDays(WorkUnit.create(6.0, WorkUnit.HOURS)), is(6.0 / 12.0)); assertThat(converter.toDays(WorkUnit.create(60.0, WorkUnit.MINUTES)), is(1.0 / 12.0)); @@ -41,14 +49,29 @@ public class WorkUnitConverterTest { @Test public void concert_to_minutes() { - Settings settings = new Settings(); - settings.setProperty(WorkUnitConverter.PROPERTY_HOURS_IN_DAY, "12"); - - WorkUnitConverter converter = new WorkUnitConverter(settings); - assertThat(converter.toMinutes(WorkUnit.create(2.0, WorkUnit.DAYS)), is(2 * 12 * 60L)); assertThat(converter.toMinutes(WorkUnit.create(6.0, WorkUnit.HOURS)), is(6 * 60L)); assertThat(converter.toMinutes(WorkUnit.create(60.0, WorkUnit.MINUTES)), is(60L)); } + @Test + public void convert_simple_values() { + checkValues(converter.fromMinutes(15L), 15L, 0L, 0L); + checkValues(converter.fromMinutes(120L), 0L, 2L, 0L); + checkValues(converter.fromMinutes(720L), 0L, 0L, 1L); + } + + @Test + public void convert_complex_values() { + checkValues(converter.fromMinutes(70L), 10L, 1L, 0L); + checkValues(converter.fromMinutes(730L), 10L, 0L, 1L); + checkValues(converter.fromMinutes(790L), 10L, 1L, 1L); + } + + private void checkValues(TechnicalDebt technicalDebt, Long expectedMinutes, Long expectedHours, Long expectedDays) { + Assertions.assertThat(technicalDebt.minutes()).isEqualTo(expectedMinutes); + Assertions.assertThat(technicalDebt.hours()).isEqualTo(expectedHours); + Assertions.assertThat(technicalDebt.days()).isEqualTo(expectedDays); + } + } diff --git a/sonar-core/src/test/java/org/sonar/core/technicaldebt/functions/ConstantFunctionTest.java b/sonar-core/src/test/java/org/sonar/core/technicaldebt/functions/ConstantFunctionTest.java index 9bd97a1a6a3..1a377123164 100644 --- a/sonar-core/src/test/java/org/sonar/core/technicaldebt/functions/ConstantFunctionTest.java +++ b/sonar-core/src/test/java/org/sonar/core/technicaldebt/functions/ConstantFunctionTest.java @@ -29,9 +29,9 @@ import org.sonar.api.config.Settings; import org.sonar.api.issue.internal.DefaultIssue; import org.sonar.api.rules.Rule; import org.sonar.api.rules.Violation; +import org.sonar.core.technicaldebt.TechnicalDebtConverter; import org.sonar.core.technicaldebt.TechnicalDebtRequirement; import org.sonar.core.technicaldebt.WorkUnit; -import org.sonar.core.technicaldebt.WorkUnitConverter; import java.util.Collection; import java.util.Collections; @@ -46,7 +46,7 @@ public class ConstantFunctionTest { @Before public void before() { - function = new ConstantFunction(new WorkUnitConverter(new Settings())); + function = new ConstantFunction(new TechnicalDebtConverter(new Settings())); requirement = Mockito.mock(TechnicalDebtRequirement.class); Mockito.when(requirement.getRemediationFactor()).thenReturn(WorkUnit.createInDays(3.14)); } diff --git a/sonar-core/src/test/java/org/sonar/core/technicaldebt/functions/LinearFunctionTest.java b/sonar-core/src/test/java/org/sonar/core/technicaldebt/functions/LinearFunctionTest.java index 077ebe8f6aa..1b2193298ac 100644 --- a/sonar-core/src/test/java/org/sonar/core/technicaldebt/functions/LinearFunctionTest.java +++ b/sonar-core/src/test/java/org/sonar/core/technicaldebt/functions/LinearFunctionTest.java @@ -26,9 +26,9 @@ import org.sonar.api.config.Settings; import org.sonar.api.issue.internal.DefaultIssue; import org.sonar.api.rules.Rule; import org.sonar.api.rules.Violation; +import org.sonar.core.technicaldebt.TechnicalDebtConverter; import org.sonar.core.technicaldebt.TechnicalDebtRequirement; import org.sonar.core.technicaldebt.WorkUnit; -import org.sonar.core.technicaldebt.WorkUnitConverter; import java.util.Collection; import java.util.Collections; @@ -45,8 +45,8 @@ public class LinearFunctionTest { @Before public void before() { Settings settings = new Settings(); - settings.setProperty(WorkUnitConverter.PROPERTY_HOURS_IN_DAY, 8); - function = new LinearFunction(new WorkUnitConverter(settings)); + settings.setProperty(TechnicalDebtConverter.PROPERTY_HOURS_IN_DAY, 8); + function = new LinearFunction(new TechnicalDebtConverter(settings)); requirement = mock(TechnicalDebtRequirement.class); when(requirement.getRemediationFactor()).thenReturn(WorkUnit.createInDays(3.14)); diff --git a/sonar-core/src/test/java/org/sonar/core/technicaldebt/functions/LinearWithOffsetFunctionTest.java b/sonar-core/src/test/java/org/sonar/core/technicaldebt/functions/LinearWithOffsetFunctionTest.java index b4aa70153a2..1a0b6c03521 100644 --- a/sonar-core/src/test/java/org/sonar/core/technicaldebt/functions/LinearWithOffsetFunctionTest.java +++ b/sonar-core/src/test/java/org/sonar/core/technicaldebt/functions/LinearWithOffsetFunctionTest.java @@ -28,9 +28,9 @@ import org.mockito.Mockito; import org.sonar.api.config.Settings; import org.sonar.api.rules.Rule; import org.sonar.api.rules.Violation; +import org.sonar.core.technicaldebt.TechnicalDebtConverter; import org.sonar.core.technicaldebt.TechnicalDebtRequirement; import org.sonar.core.technicaldebt.WorkUnit; -import org.sonar.core.technicaldebt.WorkUnitConverter; import java.util.Collection; import java.util.Collections; @@ -38,7 +38,7 @@ import java.util.Collections; public class LinearWithOffsetFunctionTest { private TechnicalDebtRequirement requirement; - private Function function = new LinearWithOffsetFunction(new WorkUnitConverter(new Settings())); + private Function function = new LinearWithOffsetFunction(new TechnicalDebtConverter(new Settings())); @Before public void before() { diff --git a/sonar-core/src/test/java/org/sonar/core/technicaldebt/functions/LinearWithThresholdFunctionTest.java b/sonar-core/src/test/java/org/sonar/core/technicaldebt/functions/LinearWithThresholdFunctionTest.java index 7445fad7f92..86c71479c05 100644 --- a/sonar-core/src/test/java/org/sonar/core/technicaldebt/functions/LinearWithThresholdFunctionTest.java +++ b/sonar-core/src/test/java/org/sonar/core/technicaldebt/functions/LinearWithThresholdFunctionTest.java @@ -28,9 +28,9 @@ import org.mockito.Mockito; import org.sonar.api.config.Settings; import org.sonar.api.rules.Rule; import org.sonar.api.rules.Violation; +import org.sonar.core.technicaldebt.TechnicalDebtConverter; import org.sonar.core.technicaldebt.TechnicalDebtRequirement; import org.sonar.core.technicaldebt.WorkUnit; -import org.sonar.core.technicaldebt.WorkUnitConverter; import java.util.Collection; import java.util.Collections; @@ -38,7 +38,7 @@ import java.util.Collections; public class LinearWithThresholdFunctionTest { private TechnicalDebtRequirement requirement; - private Function function = new LinearWithThresholdFunction(new WorkUnitConverter(new Settings())); + private Function function = new LinearWithThresholdFunction(new TechnicalDebtConverter(new Settings())); @Before public void before() { diff --git a/sonar-core/src/test/resources/org/sonar/core/issue/db/IssueMapperTest/testInsert-result.xml b/sonar-core/src/test/resources/org/sonar/core/issue/db/IssueMapperTest/testInsert-result.xml index 4e0b18c0de6..3d736381a9e 100644 --- a/sonar-core/src/test/resources/org/sonar/core/issue/db/IssueMapperTest/testInsert-result.xml +++ b/sonar-core/src/test/resources/org/sonar/core/issue/db/IssueMapperTest/testInsert-result.xml @@ -10,7 +10,7 @@ message="the message" line="500" effort_to_fix="3.14" - remediation_cost="10" + technical_debt="10" status="RESOLVED" resolution="FIXED" checksum="123456789" @@ -25,4 +25,4 @@ updated_at="2013-05-22" action_plan_key="current_sprint" /> -</dataset>
\ No newline at end of file +</dataset> diff --git a/sonar-core/src/test/resources/org/sonar/core/issue/db/IssueMapperTest/testUpdate-result.xml b/sonar-core/src/test/resources/org/sonar/core/issue/db/IssueMapperTest/testUpdate-result.xml index 4dbc84fdd59..8016cfac576 100644 --- a/sonar-core/src/test/resources/org/sonar/core/issue/db/IssueMapperTest/testUpdate-result.xml +++ b/sonar-core/src/test/resources/org/sonar/core/issue/db/IssueMapperTest/testUpdate-result.xml @@ -10,7 +10,7 @@ message="the message" line="500" effort_to_fix="3.14" - remediation_cost="10" + technical_debt="10" status="RESOLVED" resolution="FIXED" checksum="123456789" @@ -25,4 +25,4 @@ updated_at="2013-05-22" action_plan_key="current_sprint" /> -</dataset>
\ No newline at end of file +</dataset> diff --git a/sonar-core/src/test/resources/org/sonar/core/issue/db/IssueMapperTest/testUpdate.xml b/sonar-core/src/test/resources/org/sonar/core/issue/db/IssueMapperTest/testUpdate.xml index 00a1b052c40..4c6f701dc2c 100644 --- a/sonar-core/src/test/resources/org/sonar/core/issue/db/IssueMapperTest/testUpdate.xml +++ b/sonar-core/src/test/resources/org/sonar/core/issue/db/IssueMapperTest/testUpdate.xml @@ -10,7 +10,7 @@ message="old" line="[null]" effort_to_fix="[null]" - remediation_cost="[null]" + technical_debt="[null]" status="OPEN" resolution="[null]" checksum="[null]" @@ -25,4 +25,4 @@ updated_at="2009-01-01" action_plan_key="[null]" /> -</dataset>
\ No newline at end of file +</dataset> diff --git a/sonar-core/src/test/resources/org/sonar/core/issue/db/IssueMapperTest/updateBeforeSelectedDate_with_conflict-result.xml b/sonar-core/src/test/resources/org/sonar/core/issue/db/IssueMapperTest/updateBeforeSelectedDate_with_conflict-result.xml index 027e5f65c5b..5163092c424 100644 --- a/sonar-core/src/test/resources/org/sonar/core/issue/db/IssueMapperTest/updateBeforeSelectedDate_with_conflict-result.xml +++ b/sonar-core/src/test/resources/org/sonar/core/issue/db/IssueMapperTest/updateBeforeSelectedDate_with_conflict-result.xml @@ -11,7 +11,7 @@ message="old" line="[null]" effort_to_fix="[null]" - remediation_cost="[null]" + technical_debt="[null]" status="OPEN" resolution="[null]" checksum="[null]" @@ -26,4 +26,4 @@ updated_at="2013-06-01" action_plan_key="[null]" /> -</dataset>
\ No newline at end of file +</dataset> diff --git a/sonar-core/src/test/resources/org/sonar/core/issue/db/IssueMapperTest/updateBeforeSelectedDate_with_conflict.xml b/sonar-core/src/test/resources/org/sonar/core/issue/db/IssueMapperTest/updateBeforeSelectedDate_with_conflict.xml index fb218f4ab13..d2a7e749e78 100644 --- a/sonar-core/src/test/resources/org/sonar/core/issue/db/IssueMapperTest/updateBeforeSelectedDate_with_conflict.xml +++ b/sonar-core/src/test/resources/org/sonar/core/issue/db/IssueMapperTest/updateBeforeSelectedDate_with_conflict.xml @@ -10,7 +10,7 @@ message="old" line="[null]" effort_to_fix="[null]" - remediation_cost="[null]" + technical_debt="[null]" status="OPEN" resolution="[null]" checksum="[null]" @@ -25,4 +25,4 @@ updated_at="2013-06-01" action_plan_key="[null]" /> -</dataset>
\ No newline at end of file +</dataset> diff --git a/sonar-core/src/test/resources/org/sonar/core/issue/db/IssueStorageTest/should_insert_new_issues-result.xml b/sonar-core/src/test/resources/org/sonar/core/issue/db/IssueStorageTest/should_insert_new_issues-result.xml index 81c7d21c464..7d211f38c01 100644 --- a/sonar-core/src/test/resources/org/sonar/core/issue/db/IssueStorageTest/should_insert_new_issues-result.xml +++ b/sonar-core/src/test/resources/org/sonar/core/issue/db/IssueStorageTest/should_insert_new_issues-result.xml @@ -4,7 +4,7 @@ author_login="[null]" checksum="[null]" effort_to_fix="[null]" - remediation_cost="10" + technical_debt="10" message="[null]" line="5000" component_id="100" diff --git a/sonar-core/src/test/resources/org/sonar/core/issue/db/IssueStorageTest/should_resolve_conflicts_on_updates-result.xml b/sonar-core/src/test/resources/org/sonar/core/issue/db/IssueStorageTest/should_resolve_conflicts_on_updates-result.xml index 9c2a8fcbee9..76e711ccf7b 100644 --- a/sonar-core/src/test/resources/org/sonar/core/issue/db/IssueStorageTest/should_resolve_conflicts_on_updates-result.xml +++ b/sonar-core/src/test/resources/org/sonar/core/issue/db/IssueStorageTest/should_resolve_conflicts_on_updates-result.xml @@ -15,7 +15,7 @@ author_login="[null]" checksum="FFFFF" effort_to_fix="[null]" - remediation_cost="[null]" + technical_debt="[null]" message="[null]" line="444" component_id="100" @@ -30,4 +30,4 @@ issue_update_date="2013-05-18 00:00:00.0" issue_close_date="[null]" /> -</dataset>
\ No newline at end of file +</dataset> diff --git a/sonar-core/src/test/resources/org/sonar/core/issue/db/IssueStorageTest/should_resolve_conflicts_on_updates.xml b/sonar-core/src/test/resources/org/sonar/core/issue/db/IssueStorageTest/should_resolve_conflicts_on_updates.xml index a31dd9baa6e..18c1d52c639 100644 --- a/sonar-core/src/test/resources/org/sonar/core/issue/db/IssueStorageTest/should_resolve_conflicts_on_updates.xml +++ b/sonar-core/src/test/resources/org/sonar/core/issue/db/IssueStorageTest/should_resolve_conflicts_on_updates.xml @@ -17,7 +17,7 @@ author_login="[null]" checksum="FFFFF" effort_to_fix="[null]" - remediation_cost="[null]" + technical_debt="[null]" message="[null]" line="1" component_id="100" @@ -32,4 +32,4 @@ issue_update_date="2013-05-18 00:00:00.0" issue_close_date="[null]" /> -</dataset>
\ No newline at end of file +</dataset> diff --git a/sonar-core/src/test/resources/org/sonar/core/issue/db/IssueStorageTest/should_update_issues-result.xml b/sonar-core/src/test/resources/org/sonar/core/issue/db/IssueStorageTest/should_update_issues-result.xml index 07fe401b3ca..d3b9baa9d07 100644 --- a/sonar-core/src/test/resources/org/sonar/core/issue/db/IssueStorageTest/should_update_issues-result.xml +++ b/sonar-core/src/test/resources/org/sonar/core/issue/db/IssueStorageTest/should_update_issues-result.xml @@ -9,7 +9,7 @@ author_login="simon" checksum="FFFFF" effort_to_fix="[null]" - remediation_cost="10" + technical_debt="10" message="[null]" line="5000" component_id="100" diff --git a/sonar-core/src/test/resources/org/sonar/core/issue/db/IssueStorageTest/should_update_issues.xml b/sonar-core/src/test/resources/org/sonar/core/issue/db/IssueStorageTest/should_update_issues.xml index 8f73107f0e9..edab1651a43 100644 --- a/sonar-core/src/test/resources/org/sonar/core/issue/db/IssueStorageTest/should_update_issues.xml +++ b/sonar-core/src/test/resources/org/sonar/core/issue/db/IssueStorageTest/should_update_issues.xml @@ -9,7 +9,7 @@ author_login="simon" checksum="FFFFF" effort_to_fix="[null]" - remediation_cost="[null]" + technical_debt="[null]" message="[null]" line="3000" component_id="100" @@ -24,4 +24,4 @@ issue_update_date="2010-02-02" issue_close_date="[null]" /> -</dataset>
\ No newline at end of file +</dataset> diff --git a/sonar-core/src/test/resources/org/sonar/core/purge/PurgeDaoTest/should_delete_all_closed_issues-result.xml b/sonar-core/src/test/resources/org/sonar/core/purge/PurgeDaoTest/should_delete_all_closed_issues-result.xml index 354b35fcf13..43ff5c4d598 100644 --- a/sonar-core/src/test/resources/org/sonar/core/purge/PurgeDaoTest/should_delete_all_closed_issues-result.xml +++ b/sonar-core/src/test/resources/org/sonar/core/purge/PurgeDaoTest/should_delete_all_closed_issues-result.xml @@ -18,7 +18,7 @@ status="CLOSED" issue_close_date="2010-01-01" resolution="FIXED" line="200" severity="BLOCKER" reporter="perceval" assignee="arthur" rule_id="500" manual_severity="[false]" - message="[null]" action_plan_key="[null]" effort_to_fix="[null]" remediation_cost="[null]" issue_attributes="[null]" checksum="[null]" author_login="[null]" + message="[null]" action_plan_key="[null]" effort_to_fix="[null]" technical_debt="[null]" issue_attributes="[null]" checksum="[null]" author_login="[null]" updated_at="[null]" issue_creation_date="2013-04-16" issue_update_date="2013-04-16" created_at="2013-04-16"/> <issue_changes id="1" kee="[null]" issue_key="ISSUE-1" created_at="[null]" updated_at="[null]" user_login="admin" change_type="comment" change_data="abc"/> @@ -28,7 +28,7 @@ status="CLOSED" issue_close_date="2010-01-01" resolution="FIXED" line="200" severity="BLOCKER" reporter="perceval" assignee="arthur" rule_id="500" manual_severity="[false]" - message="[null]" action_plan_key="[null]" effort_to_fix="[null]" remediation_cost="[null]" issue_attributes="[null]" checksum="[null]" author_login="[null]" + message="[null]" action_plan_key="[null]" effort_to_fix="[null]" technical_debt="[null]" issue_attributes="[null]" checksum="[null]" author_login="[null]" updated_at="[null]" issue_creation_date="2013-04-16" issue_update_date="2013-04-16" created_at="2013-04-16"/> <issue_changes id="2" kee="[null]" issue_key="ISSUE-2" created_at="[null]" updated_at="[null]" user_login="admin" change_type="comment" change_data="abc"/> --> @@ -40,7 +40,7 @@ status="OPEN" issue_close_date="[null]" resolution="[null]" line="200" severity="BLOCKER" reporter="perceval" assignee="arthur" rule_id="500" manual_severity="[false]" - message="[null]" action_plan_key="[null]" effort_to_fix="[null]" remediation_cost="[null]" issue_attributes="[null]" checksum="[null]" author_login="[null]" + message="[null]" action_plan_key="[null]" effort_to_fix="[null]" technical_debt="[null]" issue_attributes="[null]" checksum="[null]" author_login="[null]" updated_at="[null]" issue_creation_date="2013-04-16" issue_update_date="2013-04-16" created_at="2013-04-16"/> <issue_changes id="3" kee="[null]" issue_key="ISSUE-3" created_at="[null]" updated_at="[null]" user_login="admin" change_type="comment" change_data="abc"/> @@ -51,7 +51,7 @@ status="OPEN" issue_close_date="[null]" resolution="[null]" line="200" severity="BLOCKER" reporter="perceval" assignee="arthur" rule_id="500" manual_severity="[false]" - message="[null]" action_plan_key="[null]" effort_to_fix="[null]" remediation_cost="[null]" issue_attributes="[null]" checksum="[null]" author_login="[null]" + message="[null]" action_plan_key="[null]" effort_to_fix="[null]" technical_debt="[null]" issue_attributes="[null]" checksum="[null]" author_login="[null]" updated_at="[null]" issue_creation_date="2013-04-16" issue_update_date="2013-04-16" created_at="2013-04-16"/> <issue_changes id="4" kee="[null]" issue_key="ISSUE-4" created_at="[null]" updated_at="[null]" user_login="admin" change_type="comment" change_data="abc"/> @@ -62,8 +62,8 @@ status="CLOSED" issue_close_date="2025-01-01" resolution="FIXED" line="200" severity="BLOCKER" reporter="perceval" assignee="arthur" rule_id="500" manual_severity="[false]" - message="[null]" action_plan_key="[null]" effort_to_fix="[null]" remediation_cost="[null]" issue_attributes="[null]" checksum="[null]" author_login="[null]" + message="[null]" action_plan_key="[null]" effort_to_fix="[null]" technical_debt="[null]" issue_attributes="[null]" checksum="[null]" author_login="[null]" updated_at="[null]" issue_creation_date="2013-04-16" issue_update_date="2013-04-16" created_at="2013-04-16"/> <issue_changes id="5" kee="[null]" issue_key="ISSUE-5" created_at="[null]" updated_at="[null]" user_login="admin" change_type="comment" change_data="abc"/> --> -</dataset>
\ No newline at end of file +</dataset> diff --git a/sonar-core/src/test/resources/org/sonar/core/purge/PurgeDaoTest/should_delete_all_closed_issues.xml b/sonar-core/src/test/resources/org/sonar/core/purge/PurgeDaoTest/should_delete_all_closed_issues.xml index 9ab34cc61fe..2bb55c7d6c4 100644 --- a/sonar-core/src/test/resources/org/sonar/core/purge/PurgeDaoTest/should_delete_all_closed_issues.xml +++ b/sonar-core/src/test/resources/org/sonar/core/purge/PurgeDaoTest/should_delete_all_closed_issues.xml @@ -12,7 +12,7 @@ status="CLOSED" issue_close_date="2010-01-01" resolution="FIXED" line="200" severity="BLOCKER" reporter="perceval" assignee="arthur" rule_id="500" manual_severity="[false]" - message="[null]" action_plan_key="[null]" effort_to_fix="[null]" remediation_cost="[null]" issue_attributes="[null]" checksum="[null]" author_login="[null]" + message="[null]" action_plan_key="[null]" effort_to_fix="[null]" technical_debt="[null]" issue_attributes="[null]" checksum="[null]" author_login="[null]" updated_at="[null]" issue_creation_date="2013-04-16" issue_update_date="2013-04-16" created_at="2013-04-16"/> <issue_changes id="1" kee="[null]" issue_key="ISSUE-1" created_at="[null]" updated_at="[null]" user_login="admin" change_type="comment" change_data="abc"/> @@ -22,7 +22,7 @@ status="CLOSED" issue_close_date="2010-01-01" resolution="FIXED" line="200" severity="BLOCKER" reporter="perceval" assignee="arthur" rule_id="500" manual_severity="[false]" - message="[null]" action_plan_key="[null]" effort_to_fix="[null]" remediation_cost="[null]" issue_attributes="[null]" checksum="[null]" author_login="[null]" + message="[null]" action_plan_key="[null]" effort_to_fix="[null]" technical_debt="[null]" issue_attributes="[null]" checksum="[null]" author_login="[null]" updated_at="[null]" issue_creation_date="2013-04-16" issue_update_date="2013-04-16" created_at="2013-04-16"/> <issue_changes id="2" kee="[null]" issue_key="ISSUE-2" created_at="[null]" updated_at="[null]" user_login="admin" change_type="comment" change_data="abc"/> @@ -34,7 +34,7 @@ status="OPEN" issue_close_date="[null]" resolution="[null]" line="200" severity="BLOCKER" reporter="perceval" assignee="arthur" rule_id="500" manual_severity="[false]" - message="[null]" action_plan_key="[null]" effort_to_fix="[null]" remediation_cost="[null]" issue_attributes="[null]" checksum="[null]" author_login="[null]" + message="[null]" action_plan_key="[null]" effort_to_fix="[null]" technical_debt="[null]" issue_attributes="[null]" checksum="[null]" author_login="[null]" updated_at="[null]" issue_creation_date="2013-04-16" issue_update_date="2013-04-16" created_at="2013-04-16"/> <issue_changes id="3" kee="[null]" issue_key="ISSUE-3" created_at="[null]" updated_at="[null]" user_login="admin" change_type="comment" change_data="abc"/> @@ -45,7 +45,7 @@ status="OPEN" issue_close_date="[null]" resolution="[null]" line="200" severity="BLOCKER" reporter="perceval" assignee="arthur" rule_id="500" manual_severity="[false]" - message="[null]" action_plan_key="[null]" effort_to_fix="[null]" remediation_cost="[null]" issue_attributes="[null]" checksum="[null]" author_login="[null]" + message="[null]" action_plan_key="[null]" effort_to_fix="[null]" technical_debt="[null]" issue_attributes="[null]" checksum="[null]" author_login="[null]" updated_at="[null]" issue_creation_date="2013-04-16" issue_update_date="2013-04-16" created_at="2013-04-16"/> <issue_changes id="4" kee="[null]" issue_key="ISSUE-4" created_at="[null]" updated_at="[null]" user_login="admin" change_type="comment" change_data="abc"/> @@ -55,8 +55,8 @@ status="CLOSED" issue_close_date="2025-01-01" resolution="FIXED" line="200" severity="BLOCKER" reporter="perceval" assignee="arthur" rule_id="500" manual_severity="[false]" - message="[null]" action_plan_key="[null]" effort_to_fix="[null]" remediation_cost="[null]" issue_attributes="[null]" checksum="[null]" author_login="[null]" + message="[null]" action_plan_key="[null]" effort_to_fix="[null]" technical_debt="[null]" issue_attributes="[null]" checksum="[null]" author_login="[null]" updated_at="[null]" issue_creation_date="2013-04-16" issue_update_date="2013-04-16" created_at="2013-04-16"/> <issue_changes id="5" kee="[null]" issue_key="ISSUE-5" created_at="[null]" updated_at="[null]" user_login="admin" change_type="comment" change_data="abc"/> -</dataset>
\ No newline at end of file +</dataset> diff --git a/sonar-core/src/test/resources/org/sonar/core/purge/PurgeDaoTest/should_delete_old_closed_issues-result.xml b/sonar-core/src/test/resources/org/sonar/core/purge/PurgeDaoTest/should_delete_old_closed_issues-result.xml index d931b3848fd..65bd0a71c55 100644 --- a/sonar-core/src/test/resources/org/sonar/core/purge/PurgeDaoTest/should_delete_old_closed_issues-result.xml +++ b/sonar-core/src/test/resources/org/sonar/core/purge/PurgeDaoTest/should_delete_old_closed_issues-result.xml @@ -13,7 +13,7 @@ status="CLOSED" issue_close_date="2010-01-01" resolution="FIXED" line="200" severity="BLOCKER" reporter="perceval" assignee="arthur" rule_id="500" manual_severity="[false]" - message="[null]" action_plan_key="[null]" effort_to_fix="[null]" remediation_cost="[null]" issue_attributes="[null]" checksum="[null]" author_login="[null]" + message="[null]" action_plan_key="[null]" effort_to_fix="[null]" technical_debt="[null]" issue_attributes="[null]" checksum="[null]" author_login="[null]" updated_at="[null]" issue_creation_date="2013-04-16" issue_update_date="2013-04-16" created_at="2013-04-16"/> <issue_changes id="1" kee="[null]" issue_key="ISSUE-1" created_at="[null]" updated_at="[null]" user_login="admin" change_type="comment" change_data="abc"/> @@ -23,7 +23,7 @@ status="CLOSED" issue_close_date="2010-01-01" resolution="FIXED" line="200" severity="BLOCKER" reporter="perceval" assignee="arthur" rule_id="500" manual_severity="[false]" - message="[null]" action_plan_key="[null]" effort_to_fix="[null]" remediation_cost="[null]" issue_attributes="[null]" checksum="[null]" author_login="[null]" + message="[null]" action_plan_key="[null]" effort_to_fix="[null]" technical_debt="[null]" issue_attributes="[null]" checksum="[null]" author_login="[null]" updated_at="[null]" issue_creation_date="2013-04-16" issue_update_date="2013-04-16" created_at="2013-04-16"/> <issue_changes id="2" kee="[null]" issue_key="ISSUE-2" created_at="[null]" updated_at="[null]" user_login="admin" change_type="comment" change_data="abc"/> --> @@ -35,7 +35,7 @@ status="OPEN" issue_close_date="[null]" resolution="[null]" line="200" severity="BLOCKER" reporter="perceval" assignee="arthur" rule_id="500" manual_severity="[false]" - message="[null]" action_plan_key="[null]" effort_to_fix="[null]" remediation_cost="[null]" issue_attributes="[null]" checksum="[null]" author_login="[null]" + message="[null]" action_plan_key="[null]" effort_to_fix="[null]" technical_debt="[null]" issue_attributes="[null]" checksum="[null]" author_login="[null]" updated_at="[null]" issue_creation_date="2013-04-16" issue_update_date="2013-04-16" created_at="2013-04-16"/> <issue_changes id="3" kee="[null]" issue_key="ISSUE-3" created_at="[null]" updated_at="[null]" user_login="admin" change_type="comment" change_data="abc"/> @@ -46,7 +46,7 @@ status="OPEN" issue_close_date="[null]" resolution="[null]" line="200" severity="BLOCKER" reporter="perceval" assignee="arthur" rule_id="500" manual_severity="[false]" - message="[null]" action_plan_key="[null]" effort_to_fix="[null]" remediation_cost="[null]" issue_attributes="[null]" checksum="[null]" author_login="[null]" + message="[null]" action_plan_key="[null]" effort_to_fix="[null]" technical_debt="[null]" issue_attributes="[null]" checksum="[null]" author_login="[null]" updated_at="[null]" issue_creation_date="2013-04-16" issue_update_date="2013-04-16" created_at="2013-04-16"/> <issue_changes id="4" kee="[null]" issue_key="ISSUE-4" created_at="[null]" updated_at="[null]" user_login="admin" change_type="comment" change_data="abc"/> @@ -56,8 +56,8 @@ status="CLOSED" issue_close_date="2025-01-01" resolution="FIXED" line="200" severity="BLOCKER" reporter="perceval" assignee="arthur" rule_id="500" manual_severity="[false]" - message="[null]" action_plan_key="[null]" effort_to_fix="[null]" remediation_cost="[null]" issue_attributes="[null]" checksum="[null]" author_login="[null]" + message="[null]" action_plan_key="[null]" effort_to_fix="[null]" technical_debt="[null]" issue_attributes="[null]" checksum="[null]" author_login="[null]" updated_at="[null]" issue_creation_date="2013-04-16" issue_update_date="2013-04-16" created_at="2013-04-16"/> <issue_changes id="5" kee="[null]" issue_key="ISSUE-5" created_at="[null]" updated_at="[null]" user_login="admin" change_type="comment" change_data="abc"/> -</dataset>
\ No newline at end of file +</dataset> diff --git a/sonar-core/src/test/resources/org/sonar/core/purge/PurgeDaoTest/should_delete_old_closed_issues.xml b/sonar-core/src/test/resources/org/sonar/core/purge/PurgeDaoTest/should_delete_old_closed_issues.xml index 27af8b156b0..127261b47f3 100644 --- a/sonar-core/src/test/resources/org/sonar/core/purge/PurgeDaoTest/should_delete_old_closed_issues.xml +++ b/sonar-core/src/test/resources/org/sonar/core/purge/PurgeDaoTest/should_delete_old_closed_issues.xml @@ -12,7 +12,7 @@ status="CLOSED" issue_close_date="2010-01-01" resolution="FIXED" line="200" severity="BLOCKER" reporter="perceval" assignee="arthur" rule_id="500" manual_severity="[false]" - message="[null]" action_plan_key="[null]" effort_to_fix="[null]" remediation_cost="[null]" issue_attributes="[null]" checksum="[null]" author_login="[null]" + message="[null]" action_plan_key="[null]" effort_to_fix="[null]" technical_debt="[null]" issue_attributes="[null]" checksum="[null]" author_login="[null]" updated_at="[null]" issue_creation_date="2013-04-16" issue_update_date="2013-04-16" created_at="2013-04-16"/> <issue_changes id="1" kee="[null]" issue_key="ISSUE-1" created_at="[null]" updated_at="[null]" user_login="admin" change_type="comment" change_data="abc"/> @@ -22,7 +22,7 @@ status="CLOSED" issue_close_date="2010-01-01" resolution="FIXED" line="200" severity="BLOCKER" reporter="perceval" assignee="arthur" rule_id="500" manual_severity="[false]" - message="[null]" action_plan_key="[null]" effort_to_fix="[null]" remediation_cost="[null]" issue_attributes="[null]" checksum="[null]" author_login="[null]" + message="[null]" action_plan_key="[null]" effort_to_fix="[null]" technical_debt="[null]" issue_attributes="[null]" checksum="[null]" author_login="[null]" updated_at="[null]" issue_creation_date="2013-04-16" issue_update_date="2013-04-16" created_at="2013-04-16"/> <issue_changes id="2" kee="[null]" issue_key="ISSUE-2" created_at="[null]" updated_at="[null]" user_login="admin" change_type="comment" change_data="abc"/> @@ -34,7 +34,7 @@ status="OPEN" issue_close_date="[null]" resolution="[null]" line="200" severity="BLOCKER" reporter="perceval" assignee="arthur" rule_id="500" manual_severity="[false]" - message="[null]" action_plan_key="[null]" effort_to_fix="[null]" remediation_cost="[null]" issue_attributes="[null]" checksum="[null]" author_login="[null]" + message="[null]" action_plan_key="[null]" effort_to_fix="[null]" technical_debt="[null]" issue_attributes="[null]" checksum="[null]" author_login="[null]" updated_at="[null]" issue_creation_date="2013-04-16" issue_update_date="2013-04-16" created_at="2013-04-16"/> <issue_changes id="3" kee="[null]" issue_key="ISSUE-3" created_at="[null]" updated_at="[null]" user_login="admin" change_type="comment" change_data="abc"/> @@ -45,7 +45,7 @@ status="OPEN" issue_close_date="[null]" resolution="[null]" line="200" severity="BLOCKER" reporter="perceval" assignee="arthur" rule_id="500" manual_severity="[false]" - message="[null]" action_plan_key="[null]" effort_to_fix="[null]" remediation_cost="[null]" issue_attributes="[null]" checksum="[null]" author_login="[null]" + message="[null]" action_plan_key="[null]" effort_to_fix="[null]" technical_debt="[null]" issue_attributes="[null]" checksum="[null]" author_login="[null]" updated_at="[null]" issue_creation_date="2013-04-16" issue_update_date="2013-04-16" created_at="2013-04-16"/> <issue_changes id="4" kee="[null]" issue_key="ISSUE-4" created_at="[null]" updated_at="[null]" user_login="admin" change_type="comment" change_data="abc"/> @@ -55,8 +55,8 @@ status="CLOSED" issue_close_date="2025-01-01" resolution="FIXED" line="200" severity="BLOCKER" reporter="perceval" assignee="arthur" rule_id="500" manual_severity="[false]" - message="[null]" action_plan_key="[null]" effort_to_fix="[null]" remediation_cost="[null]" issue_attributes="[null]" checksum="[null]" author_login="[null]" + message="[null]" action_plan_key="[null]" effort_to_fix="[null]" technical_debt="[null]" issue_attributes="[null]" checksum="[null]" author_login="[null]" updated_at="[null]" issue_creation_date="2013-04-16" issue_update_date="2013-04-16" created_at="2013-04-16"/> <issue_changes id="5" kee="[null]" issue_key="ISSUE-5" created_at="[null]" updated_at="[null]" user_login="admin" change_type="comment" change_data="abc"/> -</dataset>
\ No newline at end of file +</dataset> diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/issue/Issue.java b/sonar-plugin-api/src/main/java/org/sonar/api/issue/Issue.java index 847d1d65eca..20b30dc88e2 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/issue/Issue.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/issue/Issue.java @@ -21,8 +21,10 @@ package org.sonar.api.issue; import com.google.common.collect.ImmutableList; import org.sonar.api.rule.RuleKey; +import org.sonar.api.technicaldebt.TechnicalDebt; import javax.annotation.CheckForNull; + import java.io.Serializable; import java.util.Date; import java.util.List; @@ -105,7 +107,7 @@ public interface Issue extends Serializable { * Elapsed time in minutes to fix the issue */ @CheckForNull - Long remediationCost(); + TechnicalDebt technicalDebt(); /** * See constant values in {@link Issue}. diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/issue/internal/DefaultIssue.java b/sonar-plugin-api/src/main/java/org/sonar/api/issue/internal/DefaultIssue.java index a195ab4ea80..ae160327e42 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/issue/internal/DefaultIssue.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/issue/internal/DefaultIssue.java @@ -34,9 +34,11 @@ import org.sonar.api.issue.Issue; import org.sonar.api.issue.IssueComment; import org.sonar.api.rule.RuleKey; import org.sonar.api.rule.Severity; +import org.sonar.api.technicaldebt.TechnicalDebt; import javax.annotation.CheckForNull; import javax.annotation.Nullable; + import java.io.Serializable; import java.util.*; @@ -56,7 +58,7 @@ public class DefaultIssue implements Issue { private String message; private Integer line; private Double effortToFix; - private Long remediationCost; + private TechnicalDebt technicalDebt; private String status; private String resolution; private String reporter; @@ -187,12 +189,12 @@ public class DefaultIssue implements Issue { } @CheckForNull - public Long remediationCost() { - return remediationCost; + public TechnicalDebt technicalDebt() { + return technicalDebt; } - public DefaultIssue setRemediationCost(@Nullable Long r) { - this.remediationCost = r; + public DefaultIssue setTechnicalDebt(@Nullable TechnicalDebt t) { + this.technicalDebt = t; return this; } diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/technicaldebt/TechnicalDebt.java b/sonar-plugin-api/src/main/java/org/sonar/api/technicaldebt/TechnicalDebt.java new file mode 100644 index 00000000000..51f5c8f70c8 --- /dev/null +++ b/sonar-plugin-api/src/main/java/org/sonar/api/technicaldebt/TechnicalDebt.java @@ -0,0 +1,117 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2013 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.technicaldebt; + +import java.io.Serializable; + +public class TechnicalDebt implements Serializable { + + private static final int DAY = 10000; + private static final int HOUR = 100; + private static final int MINUTE = 1; + + private int days; + private int hours; + private int minutes; + + private TechnicalDebt(int minutes, int hours, int days) { + this.minutes = minutes; + this.hours = hours; + this.days = days; + } + + private TechnicalDebt(long technicalDebtInLong) { + long time = technicalDebtInLong; + Long currentTime = time / DAY; + if (currentTime > 0) { + this.days = currentTime.intValue(); + time = time - (currentTime * DAY); + } + + currentTime = time / HOUR; + if (currentTime > 0) { + this.hours = currentTime.intValue(); + time = time - (currentTime * HOUR); + } + + currentTime = time / MINUTE; + if (currentTime > 0) { + this.minutes = currentTime.intValue(); + } + } + + public static TechnicalDebt of(int minutes, int hours, int days) { + return new TechnicalDebt(minutes, hours, days); + } + + public static TechnicalDebt fromLong(long technicalDebtInLong) { + return new TechnicalDebt(technicalDebtInLong); + } + + public long toLong() { + return days * DAY + hours * HOUR + minutes * MINUTE; + } + + public long days() { + return days; + } + + public long hours() { + return hours; + } + + public long minutes() { + return minutes; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + TechnicalDebt technicalDebt = (TechnicalDebt) o; + if (days != technicalDebt.days) { + return false; + } + if (hours != technicalDebt.hours) { + return false; + } + if (minutes != technicalDebt.minutes) { + return false; + } + return true; + } + + @Override + public int hashCode() { + int result = Integer.valueOf(days).hashCode(); + result = 29 * result + Integer.valueOf(hours).hashCode(); + result = 27 * result + Integer.valueOf(minutes).hashCode(); + return result; + } + + @Override + public String toString() { + return super.toString(); + } +} diff --git a/sonar-plugin-api/src/test/java/org/sonar/api/issue/internal/DefaultIssueTest.java b/sonar-plugin-api/src/test/java/org/sonar/api/issue/internal/DefaultIssueTest.java index 32f164eb4e7..93fba1ecc52 100644 --- a/sonar-plugin-api/src/test/java/org/sonar/api/issue/internal/DefaultIssueTest.java +++ b/sonar-plugin-api/src/test/java/org/sonar/api/issue/internal/DefaultIssueTest.java @@ -25,6 +25,7 @@ import org.junit.Test; import org.sonar.api.issue.Issue; import org.sonar.api.issue.IssueComment; import org.sonar.api.rule.RuleKey; +import org.sonar.api.technicaldebt.TechnicalDebt; import java.text.SimpleDateFormat; import java.util.List; @@ -48,7 +49,7 @@ public class DefaultIssueTest { .setMessage("a message") .setLine(7) .setEffortToFix(1.2d) - .setRemediationCost(1L) + .setTechnicalDebt(TechnicalDebt.of(1, 0, 0)) .setActionPlanKey("BCDE") .setStatus(Issue.STATUS_CLOSED) .setResolution(Issue.RESOLUTION_FIXED) @@ -76,7 +77,7 @@ public class DefaultIssueTest { assertThat(issue.message()).isEqualTo("a message"); assertThat(issue.line()).isEqualTo(7); assertThat(issue.effortToFix()).isEqualTo(1.2d); - assertThat(issue.remediationCost()).isEqualTo(1L); + assertThat(issue.technicalDebt()).isEqualTo(TechnicalDebt.of(1, 0, 0)); assertThat(issue.actionPlanKey()).isEqualTo("BCDE"); assertThat(issue.status()).isEqualTo(Issue.STATUS_CLOSED); assertThat(issue.resolution()).isEqualTo(Issue.RESOLUTION_FIXED); diff --git a/sonar-plugin-api/src/test/java/org/sonar/api/technicaldebt/TechnicalDebtTest.java b/sonar-plugin-api/src/test/java/org/sonar/api/technicaldebt/TechnicalDebtTest.java new file mode 100644 index 00000000000..5a51722c98e --- /dev/null +++ b/sonar-plugin-api/src/test/java/org/sonar/api/technicaldebt/TechnicalDebtTest.java @@ -0,0 +1,73 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2013 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.technicaldebt; + +import org.junit.Test; + +import static org.fest.assertions.Assertions.assertThat; + +public class TechnicalDebtTest { + + @Test + public void from_long_on_simple_values(){ + checkTimes(TechnicalDebt.fromLong(1L), 0, 0, 1); + checkTimes(TechnicalDebt.fromLong(100L), 0, 1, 0); + checkTimes(TechnicalDebt.fromLong(10000L), 1, 0, 0); + } + + @Test + public void from_long_on_complex_values(){ + checkTimes(TechnicalDebt.fromLong(10101L), 1, 1, 1); + checkTimes(TechnicalDebt.fromLong(101L), 0, 1, 1); + checkTimes(TechnicalDebt.fromLong(10001L), 1, 0, 1); + checkTimes(TechnicalDebt.fromLong(10100L), 1, 1, 0); + + checkTimes(TechnicalDebt.fromLong(112233L), 11, 22, 33); + } + + @Test + public void to_long(){ + assertThat(TechnicalDebt.of(1, 1, 1).toLong()).isEqualTo(10101L); + } + + @Test + public void test_equals_and_hashCode() throws Exception { + TechnicalDebt oneMinute = TechnicalDebt.fromLong(1L); + TechnicalDebt oneHours = TechnicalDebt.fromLong(100L); + TechnicalDebt oneDay = TechnicalDebt.fromLong(10000L); + + assertThat(oneMinute).isEqualTo(oneMinute); + assertThat(oneMinute).isEqualTo(TechnicalDebt.fromLong(1L)); + assertThat(oneHours).isEqualTo(TechnicalDebt.fromLong(100L)); + assertThat(oneDay).isEqualTo(TechnicalDebt.fromLong(10000L)); + + assertThat(oneMinute).isNotEqualTo(oneHours); + assertThat(oneHours).isNotEqualTo(oneDay); + + assertThat(oneMinute.hashCode()).isEqualTo(oneMinute.hashCode()); + } + + private void checkTimes(TechnicalDebt technicalDebt, int expectedDays, int expectedHours, int expectedMinutes){ + assertThat(technicalDebt.days()).isEqualTo(expectedDays); + assertThat(technicalDebt.hours()).isEqualTo(expectedHours); + assertThat(technicalDebt.minutes()).isEqualTo(expectedMinutes); + } + +} diff --git a/sonar-server/src/main/java/org/sonar/server/issue/InternalRubyIssueService.java b/sonar-server/src/main/java/org/sonar/server/issue/InternalRubyIssueService.java index 8dde854e09b..de33721f1bb 100644 --- a/sonar-server/src/main/java/org/sonar/server/issue/InternalRubyIssueService.java +++ b/sonar-server/src/main/java/org/sonar/server/issue/InternalRubyIssueService.java @@ -43,8 +43,6 @@ import org.sonar.core.issue.workflow.Transition; import org.sonar.core.resource.ResourceDao; import org.sonar.core.resource.ResourceDto; import org.sonar.core.resource.ResourceQuery; -import org.sonar.core.technicaldebt.RemediationCostTimeUnit; -import org.sonar.core.technicaldebt.WorkUnitConverter; import org.sonar.server.exceptions.BadRequestException; import org.sonar.server.user.UserSession; import org.sonar.server.util.RubyUtils; @@ -83,14 +81,12 @@ public class InternalRubyIssueService implements ServerComponent { private final ActionService actionService; private final IssueFilterService issueFilterService; private final IssueBulkChangeService issueBulkChangeService; - private final WorkUnitConverter workUnitConverter; public InternalRubyIssueService(IssueService issueService, IssueCommentService commentService, IssueChangelogService changelogService, ActionPlanService actionPlanService, IssueStatsFinder issueStatsFinder, ResourceDao resourceDao, ActionService actionService, - IssueFilterService issueFilterService, IssueBulkChangeService issueBulkChangeService, - WorkUnitConverter workUnitConverter) { + IssueFilterService issueFilterService, IssueBulkChangeService issueBulkChangeService) { this.issueService = issueService; this.commentService = commentService; this.changelogService = changelogService; @@ -100,7 +96,6 @@ public class InternalRubyIssueService implements ServerComponent { this.actionService = actionService; this.issueFilterService = issueFilterService; this.issueBulkChangeService = issueBulkChangeService; - this.workUnitConverter = workUnitConverter; } public IssueStatsFinder.IssueStatsResult findIssueAssignees(Map<String, Object> params) { @@ -626,14 +621,4 @@ public class InternalRubyIssueService implements ServerComponent { } } - @CheckForNull - public RemediationCostTimeUnit remediationCost(Issue issue) { - Long remediationCost = issue.remediationCost(); - if (remediationCost != null) { - return workUnitConverter.toRemediationCostTimeUnit(issue.remediationCost()); - } else { - return null; - } - } - } diff --git a/sonar-server/src/main/java/org/sonar/server/platform/Platform.java b/sonar-server/src/main/java/org/sonar/server/platform/Platform.java index 152cbff94ac..c3fe96f1505 100644 --- a/sonar-server/src/main/java/org/sonar/server/platform/Platform.java +++ b/sonar-server/src/main/java/org/sonar/server/platform/Platform.java @@ -58,7 +58,7 @@ import org.sonar.core.qualitymodel.DefaultModelFinder; import org.sonar.core.resource.DefaultResourcePermissions; import org.sonar.core.rule.DefaultRuleFinder; import org.sonar.core.source.HtmlSourceDecorator; -import org.sonar.core.technicaldebt.WorkUnitConverter; +import org.sonar.core.technicaldebt.TechnicalDebtConverter; import org.sonar.core.test.TestPlanPerspectiveLoader; import org.sonar.core.test.TestablePerspectiveLoader; import org.sonar.core.timemachine.Periods; @@ -302,7 +302,7 @@ public final class Platform { servicesContainer.addSingleton(TechnicalDebtManager.class); servicesContainer.addSingleton(TechnicalDebtModelFinder.class); servicesContainer.addSingleton(XMLImporter.class); - servicesContainer.addSingleton(WorkUnitConverter.class); + servicesContainer.addSingleton(TechnicalDebtConverter.class); // text servicesContainer.addSingleton(MacroInterpreter.class); diff --git a/sonar-server/src/main/java/org/sonar/server/technicaldebt/RubyDebtService.java b/sonar-server/src/main/java/org/sonar/server/technicaldebt/RubyDebtService.java new file mode 100644 index 00000000000..526011b3650 --- /dev/null +++ b/sonar-server/src/main/java/org/sonar/server/technicaldebt/RubyDebtService.java @@ -0,0 +1,27 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2013 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.technicaldebt; + +import org.sonar.api.ServerComponent; + +public class RubyDebtService implements ServerComponent { + + +} diff --git a/sonar-server/src/main/webapp/WEB-INF/app/models/issue.rb b/sonar-server/src/main/webapp/WEB-INF/app/models/issue.rb index 4b908bcc8e9..11d03ddd820 100644 --- a/sonar-server/src/main/webapp/WEB-INF/app/models/issue.rb +++ b/sonar-server/src/main/webapp/WEB-INF/app/models/issue.rb @@ -32,7 +32,7 @@ class Issue hash[:message] = issue.message if issue.message hash[:line] = issue.line.to_i if issue.line hash[:effortToFix] = issue.effortToFix.to_f if issue.effortToFix - hash[:remediationCost] = issue.remediationCost.to_i if issue.remediationCost + hash[:technicalDebt] = technical_debt_to_hash(issue.technicalDebt) if issue.technicalDebt hash[:reporter] = issue.reporter if issue.reporter hash[:assignee] = issue.assignee if issue.assignee hash[:author] = issue.authorLogin if issue.authorLogin @@ -56,4 +56,12 @@ class Issue } end + def self.technical_debt_to_hash(technical_debt) + { + :days => technical_debt.days(), + :hours => technical_debt.hours(), + :minutes => technical_debt.minutes() + } + end + end diff --git a/sonar-server/src/main/webapp/WEB-INF/app/views/issue/_issue.html.erb b/sonar-server/src/main/webapp/WEB-INF/app/views/issue/_issue.html.erb index eaaa91a7084..dc23a963e63 100644 --- a/sonar-server/src/main/webapp/WEB-INF/app/views/issue/_issue.html.erb +++ b/sonar-server/src/main/webapp/WEB-INF/app/views/issue/_issue.html.erb @@ -36,23 +36,21 @@ <span><%= message('issue.authorLogin') -%> <%= issue.authorLogin -%></span> <% end %> - <% if issue.remediationCost %> + <% if issue.technicalDebt %> <img src="<%= ApplicationController.root_context -%>/images/sep12.png"/> - <% remediaction_cost_time_unit = Internal.issues.remediationCost(issue) - if remediaction_cost_time_unit - days = remediaction_cost_time_unit.days - hours = remediaction_cost_time_unit.hours - minutes = remediaction_cost_time_unit.minutes + <% technical_debt = issue.technicalDebt + days = technical_debt.days + hours = technical_debt.hours + minutes = technical_debt.minutes message = '' - message += message('issue.remedation_cost.x_days', :params => days) + ' ' if days > 0 - message += message('issue.remedation_cost.x_hours', :params => hours) + ' ' if hours > 0 + message += message('issue.technical_debt.x_days', :params => days) + ' ' if days > 0 + message += message('issue.technical_debt.x_hours', :params => hours) + ' ' if hours > 0 # Do not display minutes if days is not null to not have too much information - message += message('issue.remedation_cost.x_minutes', :params => minutes) if minutes > 0 && days == 0 + message += message('issue.technical_debt.x_minutes', :params => minutes) if minutes > 0 && days == 0 %> <span><%= message -%></span> - <% end %> <% end %> </div> diff --git a/sonar-server/src/main/webapp/WEB-INF/db/migrate/442_add_remediation_cost_to_issue.rb b/sonar-server/src/main/webapp/WEB-INF/db/migrate/442_add_technical_debt_to_issue.rb index 2a5825554f4..de74c3098f5 100644 --- a/sonar-server/src/main/webapp/WEB-INF/db/migrate/442_add_remediation_cost_to_issue.rb +++ b/sonar-server/src/main/webapp/WEB-INF/db/migrate/442_add_technical_debt_to_issue.rb @@ -23,10 +23,10 @@ # SONAR-4716 # -class AddRemediationCostToIssue < ActiveRecord::Migration +class AddTechnicalDebtToIssue < ActiveRecord::Migration def self.up - add_column 'issues', 'remediation_cost', :integer, :null => true + add_column 'issues', 'technical_debt', :integer, :null => true end end diff --git a/sonar-server/src/test/java/org/sonar/server/issue/DefaultIssueFinderTest.java b/sonar-server/src/test/java/org/sonar/server/issue/DefaultIssueFinderTest.java index 1ed91d8bbbf..5dbff1a591a 100644 --- a/sonar-server/src/test/java/org/sonar/server/issue/DefaultIssueFinderTest.java +++ b/sonar-server/src/test/java/org/sonar/server/issue/DefaultIssueFinderTest.java @@ -29,6 +29,7 @@ import org.sonar.api.issue.IssueQuery; import org.sonar.api.issue.IssueQueryResult; import org.sonar.api.issue.internal.DefaultIssue; import org.sonar.api.rules.Rule; +import org.sonar.api.technicaldebt.TechnicalDebt; import org.sonar.api.user.User; import org.sonar.api.user.UserFinder; import org.sonar.core.component.ComponentDto; @@ -285,4 +286,26 @@ public class DefaultIssueFinderTest { assertThat(results.actionPlans()).isEmpty(); } + @Test + public void should_find_issue_with_technical_debt() { + IssueQuery query = IssueQuery.builder().build(); + + IssueDto issue = new IssueDto().setId(1L).setRuleId(50).setComponentId(123l).setRootComponentId(100l) + .setComponentKey_unit_test_only("Action.java") + .setRootComponentKey_unit_test_only("struts") + .setRuleKey_unit_test_only("squid", "AvoidCycle") + .setStatus("OPEN").setResolution("OPEN") + .setTechnicalDebt(10L) + ; + List<IssueDto> dtoList = newArrayList(issue); + when(issueDao.selectByIds(anyCollection(), any(SqlSession.class))).thenReturn(dtoList); + + IssueQueryResult results = finder.find(query); + verify(issueDao).selectIssueIds(eq(query), anyInt(), any(SqlSession.class)); + + assertThat(results.issues()).hasSize(1); + DefaultIssue result = (DefaultIssue) results.issues().iterator().next(); + assertThat(result.technicalDebt()).isEqualTo(TechnicalDebt.of(10, 0, 0)); + } + } diff --git a/sonar-server/src/test/java/org/sonar/server/issue/InternalRubyIssueServiceTest.java b/sonar-server/src/test/java/org/sonar/server/issue/InternalRubyIssueServiceTest.java index 658b3155ec4..eb3fc3c561d 100644 --- a/sonar-server/src/test/java/org/sonar/server/issue/InternalRubyIssueServiceTest.java +++ b/sonar-server/src/test/java/org/sonar/server/issue/InternalRubyIssueServiceTest.java @@ -64,7 +64,7 @@ public class InternalRubyIssueServiceTest { ResourceDto project = new ResourceDto().setKey("org.sonar.Sample"); when(resourceDao.getResource(any(ResourceQuery.class))).thenReturn(project); service = new InternalRubyIssueService(issueService, commentService, changelogService, actionPlanService, issueStatsFinder, resourceDao, actionService, - issueFilterService, issueBulkChangeService, null); + issueFilterService, issueBulkChangeService); } @Test diff --git a/sonar-server/src/test/java/org/sonar/server/technicaldebt/RubyDebtServiceTest.java b/sonar-server/src/test/java/org/sonar/server/technicaldebt/RubyDebtServiceTest.java new file mode 100644 index 00000000000..65a9f7753e3 --- /dev/null +++ b/sonar-server/src/test/java/org/sonar/server/technicaldebt/RubyDebtServiceTest.java @@ -0,0 +1,43 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2013 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.technicaldebt; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.runners.MockitoJUnitRunner; + +@RunWith(MockitoJUnitRunner.class) +public class RubyDebtServiceTest { + + + private RubyDebtService service; + + @Before + public void before() { + service = new RubyDebtService(); + } + + @Test + public void test(){ + + } + +} diff --git a/sonar-ws-client/src/main/java/org/sonar/wsclient/issue/Issue.java b/sonar-ws-client/src/main/java/org/sonar/wsclient/issue/Issue.java index c88a9a228e0..8f81332bb86 100644 --- a/sonar-ws-client/src/main/java/org/sonar/wsclient/issue/Issue.java +++ b/sonar-ws-client/src/main/java/org/sonar/wsclient/issue/Issue.java @@ -20,6 +20,7 @@ package org.sonar.wsclient.issue; import javax.annotation.CheckForNull; + import java.util.Date; import java.util.List; import java.util.Map; @@ -52,7 +53,7 @@ public interface Issue { Double effortToFix(); @CheckForNull - Long remediationCost(); + TechnicalDebt technicalDebt(); String status(); diff --git a/sonar-ws-client/src/main/java/org/sonar/wsclient/issue/TechnicalDebt.java b/sonar-ws-client/src/main/java/org/sonar/wsclient/issue/TechnicalDebt.java new file mode 100644 index 00000000000..c2014b0dfe5 --- /dev/null +++ b/sonar-ws-client/src/main/java/org/sonar/wsclient/issue/TechnicalDebt.java @@ -0,0 +1,31 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2013 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.wsclient.issue; + +/** + * @since 4.0 + */ +public interface TechnicalDebt { + + int days(); + int minutes(); + int hours(); + +} diff --git a/sonar-ws-client/src/main/java/org/sonar/wsclient/issue/internal/DefaultIssue.java b/sonar-ws-client/src/main/java/org/sonar/wsclient/issue/internal/DefaultIssue.java index 2f83632ab17..50c74c34a08 100644 --- a/sonar-ws-client/src/main/java/org/sonar/wsclient/issue/internal/DefaultIssue.java +++ b/sonar-ws-client/src/main/java/org/sonar/wsclient/issue/internal/DefaultIssue.java @@ -21,9 +21,11 @@ package org.sonar.wsclient.issue.internal; import org.sonar.wsclient.issue.Issue; import org.sonar.wsclient.issue.IssueComment; +import org.sonar.wsclient.issue.TechnicalDebt; import org.sonar.wsclient.unmarshallers.JsonUtils; import javax.annotation.CheckForNull; + import java.util.*; /** @@ -76,8 +78,12 @@ public class DefaultIssue implements Issue { } @CheckForNull - public Long remediationCost() { - return JsonUtils.getLong(json, "remediationCost"); + public TechnicalDebt technicalDebt() { + Map technicalDebt = (Map) json.get("technicalDebt"); + if (technicalDebt != null) { + return new DefaultTechnicalDebt(technicalDebt); + } + return null; } public String status() { diff --git a/sonar-ws-client/src/main/java/org/sonar/wsclient/issue/internal/DefaultTechnicalDebt.java b/sonar-ws-client/src/main/java/org/sonar/wsclient/issue/internal/DefaultTechnicalDebt.java new file mode 100644 index 00000000000..c82ceb13a41 --- /dev/null +++ b/sonar-ws-client/src/main/java/org/sonar/wsclient/issue/internal/DefaultTechnicalDebt.java @@ -0,0 +1,49 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2013 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.wsclient.issue.internal; + +import org.sonar.wsclient.issue.TechnicalDebt; +import org.sonar.wsclient.unmarshallers.JsonUtils; + +import java.util.Map; + +/** + * @since 4.0 + */ +public class DefaultTechnicalDebt implements TechnicalDebt { + private final Map json; + + DefaultTechnicalDebt(Map json) { + this.json = json; + } + + public int days() { + return JsonUtils.getInteger(json, "days"); + } + + public int hours() { + return JsonUtils.getInteger(json, "hours"); + } + + public int minutes() { + return JsonUtils.getInteger(json, "minutes"); + } + +} diff --git a/sonar-ws-client/src/test/java/org/sonar/wsclient/issue/internal/DefaultIssueClientTest.java b/sonar-ws-client/src/test/java/org/sonar/wsclient/issue/internal/DefaultIssueClientTest.java index 96140bd593a..b01badc4bdc 100644 --- a/sonar-ws-client/src/test/java/org/sonar/wsclient/issue/internal/DefaultIssueClientTest.java +++ b/sonar-ws-client/src/test/java/org/sonar/wsclient/issue/internal/DefaultIssueClientTest.java @@ -34,6 +34,7 @@ import static org.fest.assertions.Fail.fail; import static org.fest.assertions.MapAssert.entry; public class DefaultIssueClientTest { + @Rule public MockHttpServerInterceptor httpServer = new MockHttpServerInterceptor(); diff --git a/sonar-ws-client/src/test/java/org/sonar/wsclient/issue/internal/IssueJsonParserTest.java b/sonar-ws-client/src/test/java/org/sonar/wsclient/issue/internal/IssueJsonParserTest.java index 4e95e9dcbe0..42e517cd069 100644 --- a/sonar-ws-client/src/test/java/org/sonar/wsclient/issue/internal/IssueJsonParserTest.java +++ b/sonar-ws-client/src/test/java/org/sonar/wsclient/issue/internal/IssueJsonParserTest.java @@ -51,7 +51,7 @@ public class IssueJsonParserTest { assertThat(first.assignee()).isEqualTo("karadoc"); assertThat(first.message()).isEqualTo("the message"); assertThat(first.effortToFix()).isEqualTo(4.2); - assertThat(first.remediationCost()).isEqualTo(10L); + assertThat(first.technicalDebt()).isNull(); assertThat(first.reporter()).isEqualTo("perceval"); assertThat(first.author()).isEqualTo("pirlouis"); assertThat(first.actionPlan()).isEqualTo("9450b10c-e725-48b8-bf01-acdec751c491"); @@ -67,7 +67,7 @@ public class IssueJsonParserTest { assertThat(second.key()).isEqualTo("FGHIJ"); assertThat(second.line()).isNull(); assertThat(second.effortToFix()).isNull(); - assertThat(second.remediationCost()).isNull(); + assertThat(second.technicalDebt()).isNull(); assertThat(second.reporter()).isNull(); assertThat(second.author()).isNull(); assertThat(second.attribute("JIRA")).isNull(); @@ -197,6 +197,18 @@ public class IssueJsonParserTest { } @Test + public void should_parse_technical_debt() throws Exception { + String json = IOUtils.toString(getClass().getResourceAsStream("/org/sonar/wsclient/issue/internal/IssueJsonParserTest/issue-with-technical-debt.json")); + Issues issues = new IssueJsonParser().parseIssues(json); + assertThat(issues.size()).isEqualTo(1); + + Issue issue = issues.list().get(0); + assertThat(issue.technicalDebt().days()).isEqualTo(3); + assertThat(issue.technicalDebt().hours()).isEqualTo(0); + assertThat(issue.technicalDebt().minutes()).isEqualTo(10); + } + + @Test public void should_parse_bulk_change() throws Exception { String json = IOUtils.toString(getClass().getResourceAsStream("/org/sonar/wsclient/issue/internal/IssueJsonParserTest/bulk-change.json")); BulkChange bulkChange = new IssueJsonParser().parseBulkChange(json); diff --git a/sonar-ws-client/src/test/resources/org/sonar/wsclient/issue/internal/IssueJsonParserTest/issue-with-technical-debt.json b/sonar-ws-client/src/test/resources/org/sonar/wsclient/issue/internal/IssueJsonParserTest/issue-with-technical-debt.json new file mode 100644 index 00000000000..cda81fc2262 --- /dev/null +++ b/sonar-ws-client/src/test/resources/org/sonar/wsclient/issue/internal/IssueJsonParserTest/issue-with-technical-debt.json @@ -0,0 +1,33 @@ +{ + "issues": [ + { + "key": "ABCDE", + "component": "Action.java", + "project": "struts", + "rule": "squid:CycleBetweenPackages", + "severity": "CRITICAL", + "status": "OPEN", + "technicalDebt": { + "days": 3, + "hours": 0, + "minutes": 10 + } + } + ], + "rules": [ + { + + "key": "squid:CycleBetweenPackages", + "name": "Avoid cycle between java packages", + "desc": "<p>\nWhen several packages are involved in a cycle (package A > package B > package C > package A where \">\" means \"depends upon\"),\nthat means that those packages are highly coupled and that there is no way to reuse/extract one of those packages without importing all the other packages.\nSuch cycle could quickly increase the effort required to maintain an application and to embrace business change.\nSonar not only detect cycles between packages but also determines what is the minimum effort to break those cycles.\nThis rule log a violation on each source file having an outgoing dependency to be but in order to break a cycle.\n</p>\n" + + } + ], + "paging": { + "pageIndex": 1, + "pageSize": 100, + "total": 2, + "pages": 1 + }, + "maxResultsReached": false +} diff --git a/sonar-ws-client/src/test/resources/org/sonar/wsclient/issue/internal/IssueJsonParserTest/search.json b/sonar-ws-client/src/test/resources/org/sonar/wsclient/issue/internal/IssueJsonParserTest/search.json index e1f131c2f96..8a944880826 100644 --- a/sonar-ws-client/src/test/resources/org/sonar/wsclient/issue/internal/IssueJsonParserTest/search.json +++ b/sonar-ws-client/src/test/resources/org/sonar/wsclient/issue/internal/IssueJsonParserTest/search.json @@ -11,7 +11,6 @@ "status": "OPEN", "assignee": "karadoc", "effortToFix": 4.2, - "remediationCost": 10, "message": "the message", "title": "the title", "reporter": "perceval", @@ -55,4 +54,4 @@ "pages": 1 }, "maxResultsReached": true -}
\ No newline at end of file +} |