aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJulien Lancelot <julien.lancelot@sonarsource.com>2014-02-10 18:08:00 +0100
committerJulien Lancelot <julien.lancelot@sonarsource.com>2014-02-10 18:08:20 +0100
commit9ea9f3c3ea844683314926282da93ab743686806 (patch)
tree3530180c4aee2731e0fe8e33e9dcb527bc5490aa
parent59559f3f9f711e3c8468d2419caf944979e27580 (diff)
downloadsonarqube-9ea9f3c3ea844683314926282da93ab743686806.tar.gz
sonarqube-9ea9f3c3ea844683314926282da93ab743686806.zip
Merge WorkDayDuration with WorkUnit
-rw-r--r--plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/CorePlugin.java2
-rw-r--r--plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/IssueTrackingDecorator.java4
-rw-r--r--plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/technicaldebt/NewTechnicalDebtDecorator.java42
-rw-r--r--plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/technicaldebt/TechnicalDebtDecorator.java21
-rw-r--r--plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/issue/IssueTrackingDecoratorTest.java4
-rw-r--r--plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/technicaldebt/NewTechnicalDebtDecoratorTest.java23
-rw-r--r--plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/technicaldebt/TechnicalDebtDecoratorTest.java47
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/scan/ProjectScanContainer.java30
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/technicaldebt/TechnicalDebtCalculator.java58
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/issue/ModuleIssuesTest.java6
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/technicaldebt/TechnicalDebtCalculatorTest.java39
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/technicaldebt/TechnicalDebtModelLoaderTest.java4
-rw-r--r--sonar-core/src/main/java/org/sonar/core/issue/IssueUpdater.java14
-rw-r--r--sonar-core/src/main/java/org/sonar/core/issue/db/IssueDto.java4
-rw-r--r--sonar-core/src/main/java/org/sonar/core/technicaldebt/TechnicalDebtConverter.java90
-rw-r--r--sonar-core/src/test/java/org/sonar/core/issue/IssueUpdaterTest.java22
-rw-r--r--sonar-core/src/test/java/org/sonar/core/issue/db/IssueDtoTest.java48
-rw-r--r--sonar-core/src/test/java/org/sonar/core/issue/db/IssueStorageTest.java6
-rw-r--r--sonar-core/src/test/java/org/sonar/core/technicaldebt/DefaultTechnicalDebtManagerTest.java8
-rw-r--r--sonar-core/src/test/java/org/sonar/core/technicaldebt/DefaultTechnicalDebtModelTest.java4
-rw-r--r--sonar-core/src/test/java/org/sonar/core/technicaldebt/TechnicalDebtConverterTest.java85
-rw-r--r--sonar-core/src/test/java/org/sonar/core/technicaldebt/TechnicalDebtModelSynchronizerTest.java4
-rw-r--r--sonar-core/src/test/java/org/sonar/core/technicaldebt/TechnicalDebtXMLImporterTest.java2
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/CoreProperties.java5
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/issue/internal/DefaultIssue.java7
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/issue/internal/WorkDayDuration.java113
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/technicaldebt/batch/internal/DefaultRequirement.java4
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/utils/WorkUnit.java191
-rw-r--r--sonar-plugin-api/src/test/java/org/sonar/api/issue/internal/DefaultIssueTest.java5
-rw-r--r--sonar-plugin-api/src/test/java/org/sonar/api/issue/internal/WorkDayDurationTest.java73
-rw-r--r--sonar-plugin-api/src/test/java/org/sonar/api/technicaldebt/batch/internal/DefaultRequirementTest.java8
-rw-r--r--sonar-plugin-api/src/test/java/org/sonar/api/technicaldebt/server/internal/DefaultCharacteristicTest.java12
-rw-r--r--sonar-plugin-api/src/test/java/org/sonar/api/utils/WorkUnitTest.java53
-rw-r--r--sonar-server/src/main/java/org/sonar/server/issue/IssueChangelogFormatter.java6
-rw-r--r--sonar-server/src/main/java/org/sonar/server/issue/ws/IssueShowWsHandler.java9
-rw-r--r--sonar-server/src/main/java/org/sonar/server/platform/Platform.java6
-rw-r--r--sonar-server/src/main/java/org/sonar/server/technicaldebt/DebtFormatter.java4
-rw-r--r--sonar-server/src/main/java/org/sonar/server/technicaldebt/DebtService.java8
-rw-r--r--sonar-server/src/test/java/org/sonar/server/issue/DefaultIssueFinderTest.java6
-rw-r--r--sonar-server/src/test/java/org/sonar/server/issue/IssueChangelogFormatterTest.java8
-rw-r--r--sonar-server/src/test/java/org/sonar/server/issue/ws/IssueShowWsHandlerTest.java13
-rw-r--r--sonar-server/src/test/java/org/sonar/server/technicaldebt/DebtFormatterTest.java15
-rw-r--r--sonar-server/src/test/java/org/sonar/server/technicaldebt/DebtServiceTest.java6
43 files changed, 479 insertions, 640 deletions
diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/CorePlugin.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/CorePlugin.java
index 7bc015f104d..a4539278b05 100644
--- a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/CorePlugin.java
+++ b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/CorePlugin.java
@@ -25,7 +25,6 @@ import org.sonar.api.checks.NoSonarFilter;
import org.sonar.api.config.PropertyDefinition;
import org.sonar.api.resources.Qualifiers;
import org.sonar.batch.components.PastSnapshotFinder;
-import org.sonar.core.technicaldebt.TechnicalDebtConverter;
import org.sonar.core.timemachine.Periods;
import org.sonar.plugins.core.batch.IndexProjectPostJob;
import org.sonar.plugins.core.charts.DistributionAreaChart;
@@ -290,7 +289,6 @@ public final class CorePlugin extends SonarPlugin {
NewFalsePositiveNotificationDispatcher.newMetadata(),
// technical debt
- TechnicalDebtConverter.class,
TechnicalDebtDecorator.class,
NewTechnicalDebtDecorator.class,
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 90603e96ce7..3c568ae78f9 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
@@ -31,7 +31,6 @@ import org.sonar.api.issue.Issuable;
import org.sonar.api.issue.Issue;
import org.sonar.api.issue.internal.DefaultIssue;
import org.sonar.api.issue.internal.IssueChangeContext;
-import org.sonar.api.issue.internal.WorkDayDuration;
import org.sonar.api.profiles.RulesProfile;
import org.sonar.api.resources.Project;
import org.sonar.api.resources.Resource;
@@ -40,6 +39,7 @@ import org.sonar.api.rules.ActiveRule;
import org.sonar.api.rules.Rule;
import org.sonar.api.rules.RuleFinder;
import org.sonar.api.utils.KeyValueFormat;
+import org.sonar.api.utils.WorkUnit;
import org.sonar.batch.issue.IssueCache;
import org.sonar.batch.scan.LastSnapshots;
import org.sonar.core.issue.IssueUpdater;
@@ -178,7 +178,7 @@ public class IssueTrackingDecorator implements Decorator {
updater.setPastMessage(issue, ref.getMessage(), changeContext);
updater.setPastEffortToFix(issue, ref.getEffortToFix(), changeContext);
Long technicalDebt = ref.getTechnicalDebt();
- WorkDayDuration previousTechnicalDebt = technicalDebt != null ? WorkDayDuration.fromLong(technicalDebt) : null;
+ WorkUnit previousTechnicalDebt = technicalDebt != null ? WorkUnit.fromLong(technicalDebt) : null;
updater.setPastTechnicalDebt(issue, previousTechnicalDebt, changeContext);
}
}
diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/technicaldebt/NewTechnicalDebtDecorator.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/technicaldebt/NewTechnicalDebtDecorator.java
index 641d659c25e..cd540b55525 100644
--- a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/technicaldebt/NewTechnicalDebtDecorator.java
+++ b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/technicaldebt/NewTechnicalDebtDecorator.java
@@ -24,23 +24,24 @@ import com.google.common.base.Function;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Ordering;
import org.apache.commons.lang.time.DateUtils;
+import org.sonar.api.CoreProperties;
import org.sonar.api.batch.*;
import org.sonar.api.component.ResourcePerspectives;
+import org.sonar.api.config.Settings;
import org.sonar.api.issue.Issuable;
import org.sonar.api.issue.Issue;
import org.sonar.api.issue.internal.DefaultIssue;
import org.sonar.api.issue.internal.FieldDiffs;
-import org.sonar.api.issue.internal.WorkDayDuration;
import org.sonar.api.measures.CoreMetrics;
import org.sonar.api.measures.Measure;
import org.sonar.api.measures.MeasureUtils;
import org.sonar.api.measures.Metric;
import org.sonar.api.resources.Project;
import org.sonar.api.resources.Resource;
+import org.sonar.api.utils.WorkUnit;
import org.sonar.batch.components.Period;
import org.sonar.batch.components.TimeMachineConfiguration;
import org.sonar.core.issue.IssueUpdater;
-import org.sonar.core.technicaldebt.TechnicalDebtConverter;
import javax.annotation.Nullable;
@@ -56,12 +57,13 @@ public final class NewTechnicalDebtDecorator implements Decorator {
private final ResourcePerspectives perspectives;
private final TimeMachineConfiguration timeMachineConfiguration;
- private final TechnicalDebtConverter technicalDebtConverter;
- public NewTechnicalDebtDecorator(ResourcePerspectives perspectives, TimeMachineConfiguration timeMachineConfiguration, TechnicalDebtConverter technicalDebtConverter) {
+ private final int hoursInDay;
+
+ public NewTechnicalDebtDecorator(ResourcePerspectives perspectives, TimeMachineConfiguration timeMachineConfiguration, Settings settings) {
this.perspectives = perspectives;
this.timeMachineConfiguration = timeMachineConfiguration;
- this.technicalDebtConverter = technicalDebtConverter;
+ this.hoursInDay = settings.getInt(CoreProperties.HOURS_IN_DAY);
}
public boolean shouldExecuteOnProject(Project project) {
@@ -98,32 +100,34 @@ public final class NewTechnicalDebtDecorator implements Decorator {
private Double calculateNewTechnicalDebtValue(Collection<Issue> issues, @Nullable Date periodDate) {
double value = 0;
for (Issue issue : issues) {
- WorkDayDuration currentTechnicalDebt = ((DefaultIssue) issue).technicalDebt();
+ double currentTechnicalDebtValue = 0d;
+ WorkUnit currentTechnicalDebt = ((DefaultIssue) issue).technicalDebt();
+ if (currentTechnicalDebt != null) {
+ currentTechnicalDebtValue = currentTechnicalDebt.toDays(hoursInDay);
+ }
Date periodDatePlusOneSecond = periodDate != null ? DateUtils.addSeconds(periodDate, 1) : null;
if (isAfter(issue.creationDate(), periodDatePlusOneSecond)) {
- value += technicalDebtConverter.toDays(currentTechnicalDebt);
+ value += currentTechnicalDebtValue;
} else {
- value += calculateNewTechnicalDebtValueFromChangelog(currentTechnicalDebt, issue, periodDate);
+ value += calculateNewTechnicalDebtValueFromChangelog(currentTechnicalDebtValue, issue, periodDate);
}
}
return value;
}
- private double calculateNewTechnicalDebtValueFromChangelog(WorkDayDuration currentTechnicalDebt, Issue issue, Date periodDate) {
- double currentTechnicalDebtValue = technicalDebtConverter.toDays(currentTechnicalDebt);
-
+ private double calculateNewTechnicalDebtValueFromChangelog(double currentTechnicalDebtValue, Issue issue, Date periodDate) {
List<FieldDiffs> changelog = technicalDebtHistory(issue);
for (Iterator<FieldDiffs> iterator = changelog.iterator(); iterator.hasNext(); ) {
FieldDiffs diff = iterator.next();
Date date = diff.creationDate();
if (isLesserOrEqual(date, periodDate)) {
// return new value from the change that is just before the period date
- return currentTechnicalDebtValue - technicalDebtConverter.toDays(newValue(diff));
+ return currentTechnicalDebtValue - newValue(diff).toDays(hoursInDay);
}
if (!iterator.hasNext()) {
// return old value from the change that is just after the period date when there's no more element in changelog
- return currentTechnicalDebtValue - technicalDebtConverter.toDays(oldValue(diff));
+ return currentTechnicalDebtValue - oldValue(diff).toDays(hoursInDay);
}
}
// Return 0 when no changelog
@@ -155,24 +159,24 @@ public final class NewTechnicalDebtDecorator implements Decorator {
return diffs;
}
- private WorkDayDuration newValue(FieldDiffs fieldDiffs) {
+ private WorkUnit newValue(FieldDiffs fieldDiffs) {
for (Map.Entry<String, FieldDiffs.Diff> entry : fieldDiffs.diffs().entrySet()) {
if (entry.getKey().equals(IssueUpdater.TECHNICAL_DEBT)) {
Long newValue = entry.getValue().newValueLong();
- return newValue != null ? WorkDayDuration.fromLong(newValue) : null;
+ return newValue != null ? WorkUnit.fromLong(newValue) : WorkUnit.fromLong(0);
}
}
- return null;
+ return WorkUnit.fromLong(0);
}
- private WorkDayDuration oldValue(FieldDiffs fieldDiffs) {
+ private WorkUnit oldValue(FieldDiffs fieldDiffs) {
for (Map.Entry<String, FieldDiffs.Diff> entry : fieldDiffs.diffs().entrySet()) {
if (entry.getKey().equals(IssueUpdater.TECHNICAL_DEBT)) {
Long value = entry.getValue().oldValueLong();
- return value != null ? WorkDayDuration.fromLong(value) : null;
+ return value != null ? WorkUnit.fromLong(value) : WorkUnit.fromLong(0);
}
}
- return null;
+ return WorkUnit.fromLong(0);
}
private boolean isAfter(@Nullable Date currentDate, @Nullable Date pastDate) {
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 2cbc2ce8285..44eb76e6ba1 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
@@ -30,6 +30,7 @@ import org.sonar.api.PropertyType;
import org.sonar.api.batch.*;
import org.sonar.api.component.ResourcePerspectives;
import org.sonar.api.config.PropertyDefinition;
+import org.sonar.api.config.Settings;
import org.sonar.api.issue.Issuable;
import org.sonar.api.issue.Issue;
import org.sonar.api.issue.internal.DefaultIssue;
@@ -40,7 +41,7 @@ import org.sonar.api.resources.ResourceUtils;
import org.sonar.api.technicaldebt.batch.Characteristic;
import org.sonar.api.technicaldebt.batch.Requirement;
import org.sonar.api.technicaldebt.batch.TechnicalDebtModel;
-import org.sonar.core.technicaldebt.TechnicalDebtConverter;
+import org.sonar.api.utils.WorkUnit;
import java.util.Arrays;
import java.util.Collection;
@@ -60,12 +61,13 @@ public final class TechnicalDebtDecorator implements Decorator {
private final ResourcePerspectives perspectives;
private final TechnicalDebtModel model;
- private final TechnicalDebtConverter converter;
- public TechnicalDebtDecorator(ResourcePerspectives perspectives, TechnicalDebtModel model, TechnicalDebtConverter converter) {
+ private final int hoursInDay;
+
+ public TechnicalDebtDecorator(ResourcePerspectives perspectives, TechnicalDebtModel model, Settings settings) {
this.perspectives = perspectives;
this.model = model;
- this.converter = converter;
+ this.hoursInDay = settings.getInt(CoreProperties.HOURS_IN_DAY);
}
public boolean shouldExecuteOnProject(Project project) {
@@ -168,8 +170,13 @@ public final class TechnicalDebtDecorator implements Decorator {
private double computeTechnicalDebt(Metric metric, DecoratorContext context, Requirement requirement, Collection<Issue> issues) {
double value = 0.0;
if (issues != null) {
- for (Issue issue : issues){
- value += converter.toDays(((DefaultIssue) issue).technicalDebt());
+ for (Issue issue : issues) {
+ WorkUnit debt = ((DefaultIssue) issue).technicalDebt();
+ if (debt != null) {
+ value += debt.toDays(hoursInDay);
+ } else {
+ value += 0d;
+ }
}
}
@@ -200,7 +207,7 @@ public final class TechnicalDebtDecorator implements Decorator {
public static List<PropertyDefinition> definitions() {
return ImmutableList.of(
- PropertyDefinition.builder(TechnicalDebtConverter.PROPERTY_HOURS_IN_DAY)
+ PropertyDefinition.builder(CoreProperties.HOURS_IN_DAY)
.name("Number of working hours in a day")
.type(PropertyType.INTEGER)
.defaultValue("8")
diff --git a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/issue/IssueTrackingDecoratorTest.java b/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/issue/IssueTrackingDecoratorTest.java
index 9a573b3d62a..0cb689bb9d8 100644
--- a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/issue/IssueTrackingDecoratorTest.java
+++ b/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/issue/IssueTrackingDecoratorTest.java
@@ -29,7 +29,6 @@ import org.sonar.api.component.ResourcePerspectives;
import org.sonar.api.issue.Issue;
import org.sonar.api.issue.internal.DefaultIssue;
import org.sonar.api.issue.internal.IssueChangeContext;
-import org.sonar.api.issue.internal.WorkDayDuration;
import org.sonar.api.profiles.RulesProfile;
import org.sonar.api.resources.File;
import org.sonar.api.resources.Project;
@@ -37,6 +36,7 @@ import org.sonar.api.resources.Resource;
import org.sonar.api.rule.RuleKey;
import org.sonar.api.rules.Rule;
import org.sonar.api.rules.RuleFinder;
+import org.sonar.api.utils.WorkUnit;
import org.sonar.batch.issue.IssueCache;
import org.sonar.batch.scan.LastSnapshots;
import org.sonar.core.issue.IssueUpdater;
@@ -520,7 +520,7 @@ public class IssueTrackingDecoratorTest extends AbstractDaoTestCase {
verify(updater).setPastLine(eq(issue), eq(10));
verify(updater).setPastMessage(eq(issue), eq("Message"), any(IssueChangeContext.class));
verify(updater).setPastEffortToFix(eq(issue), eq(1.5), any(IssueChangeContext.class));
- verify(updater).setPastTechnicalDebt(eq(issue), eq(WorkDayDuration.of(1, 0, 0)), any(IssueChangeContext.class));
+ verify(updater).setPastTechnicalDebt(eq(issue), eq(new WorkUnit.Builder().setMinutes(1).build()), any(IssueChangeContext.class));
}
@Test
diff --git a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/technicaldebt/NewTechnicalDebtDecoratorTest.java b/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/technicaldebt/NewTechnicalDebtDecoratorTest.java
index 2dfc4b3df36..4b968938136 100644
--- a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/technicaldebt/NewTechnicalDebtDecoratorTest.java
+++ b/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/technicaldebt/NewTechnicalDebtDecoratorTest.java
@@ -27,21 +27,22 @@ import org.junit.runner.RunWith;
import org.mockito.ArgumentMatcher;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
+import org.sonar.api.CoreProperties;
import org.sonar.api.batch.DecoratorContext;
import org.sonar.api.component.ResourcePerspectives;
+import org.sonar.api.config.Settings;
import org.sonar.api.issue.Issuable;
import org.sonar.api.issue.Issue;
import org.sonar.api.issue.internal.DefaultIssue;
import org.sonar.api.issue.internal.FieldDiffs;
-import org.sonar.api.issue.internal.WorkDayDuration;
import org.sonar.api.measures.CoreMetrics;
import org.sonar.api.measures.Measure;
import org.sonar.api.measures.Metric;
import org.sonar.api.resources.Resource;
import org.sonar.api.test.IsMeasure;
+import org.sonar.api.utils.WorkUnit;
import org.sonar.batch.components.Period;
import org.sonar.batch.components.TimeMachineConfiguration;
-import org.sonar.core.technicaldebt.TechnicalDebtConverter;
import java.util.Date;
@@ -67,9 +68,6 @@ public class NewTechnicalDebtDecoratorTest {
@Mock
DecoratorContext context;
- @Mock
- TechnicalDebtConverter technicalDebtConverter;
-
Date rightNow;
Date elevenDaysAgo;
Date tenDaysAgo;
@@ -77,15 +75,14 @@ public class NewTechnicalDebtDecoratorTest {
Date fiveDaysAgo;
Date fourDaysAgo;
- WorkDayDuration oneDaysDebt = WorkDayDuration.of(0, 0, 1);
- WorkDayDuration twoDaysDebt = WorkDayDuration.of(0, 0, 2);
- WorkDayDuration fiveDaysDebt = WorkDayDuration.of(0, 0, 5);
+ WorkUnit oneDaysDebt = new WorkUnit.Builder().setDays(1).build();
+ WorkUnit twoDaysDebt = new WorkUnit.Builder().setDays(2).build();
+ WorkUnit fiveDaysDebt = new WorkUnit.Builder().setDays(5).build();
@Before
public void setup() {
- when(technicalDebtConverter.toDays(oneDaysDebt)).thenReturn(1d);
- when(technicalDebtConverter.toDays(twoDaysDebt)).thenReturn(2d);
- when(technicalDebtConverter.toDays(fiveDaysDebt)).thenReturn(5d);
+ Settings settings = new Settings();
+ settings.setProperty(CoreProperties.HOURS_IN_DAY, "8");
ResourcePerspectives perspectives = mock(ResourcePerspectives.class);
when(perspectives.as(Issuable.class, resource)).thenReturn(issuable);
@@ -99,7 +96,7 @@ public class NewTechnicalDebtDecoratorTest {
when(timeMachineConfiguration.periods()).thenReturn(newArrayList(new Period(1, fiveDaysAgo), new Period(2, tenDaysAgo)));
- decorator = new NewTechnicalDebtDecorator(perspectives, timeMachineConfiguration, technicalDebtConverter);
+ decorator = new NewTechnicalDebtDecorator(perspectives, timeMachineConfiguration, settings);
}
@Test
@@ -328,7 +325,7 @@ public class NewTechnicalDebtDecoratorTest {
verify(context, never()).saveMeasure(argThat(new IsMeasure(CoreMetrics.NEW_TECHNICAL_DEBT)));
}
- private Long fromWorkDayDuration(WorkDayDuration workDayDuration){
+ private Long fromWorkDayDuration(WorkUnit workDayDuration) {
return workDayDuration.toLong();
}
diff --git a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/technicaldebt/TechnicalDebtDecoratorTest.java b/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/technicaldebt/TechnicalDebtDecoratorTest.java
index eb5376d47f0..3c13be9a8a3 100644
--- a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/technicaldebt/TechnicalDebtDecoratorTest.java
+++ b/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/technicaldebt/TechnicalDebtDecoratorTest.java
@@ -28,12 +28,13 @@ import org.junit.runner.RunWith;
import org.mockito.ArgumentMatcher;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
+import org.sonar.api.CoreProperties;
import org.sonar.api.batch.DecoratorContext;
import org.sonar.api.component.ResourcePerspectives;
+import org.sonar.api.config.Settings;
import org.sonar.api.issue.Issuable;
import org.sonar.api.issue.Issue;
import org.sonar.api.issue.internal.DefaultIssue;
-import org.sonar.api.issue.internal.WorkDayDuration;
import org.sonar.api.measures.CoreMetrics;
import org.sonar.api.measures.Measure;
import org.sonar.api.measures.MeasuresFilter;
@@ -48,7 +49,7 @@ import org.sonar.api.technicaldebt.batch.TechnicalDebtModel;
import org.sonar.api.technicaldebt.batch.internal.DefaultCharacteristic;
import org.sonar.api.technicaldebt.batch.internal.DefaultRequirement;
import org.sonar.api.test.IsMeasure;
-import org.sonar.core.technicaldebt.TechnicalDebtConverter;
+import org.sonar.api.utils.WorkUnit;
import java.util.List;
@@ -67,9 +68,6 @@ public class TechnicalDebtDecoratorTest {
Resource resource;
@Mock
- TechnicalDebtConverter converter;
-
- @Mock
TechnicalDebtModel defaultTechnicalDebtModel;
@Mock
@@ -82,7 +80,10 @@ public class TechnicalDebtDecoratorTest {
ResourcePerspectives perspectives = mock(ResourcePerspectives.class);
when(perspectives.as(Issuable.class, resource)).thenReturn(issuable);
- decorator = new TechnicalDebtDecorator(perspectives, defaultTechnicalDebtModel, converter);
+ Settings settings = new Settings();
+ settings.setProperty(CoreProperties.HOURS_IN_DAY, "8");
+
+ decorator = new TechnicalDebtDecorator(perspectives, defaultTechnicalDebtModel, settings);
}
@Test
@@ -128,8 +129,7 @@ public class TechnicalDebtDecoratorTest {
@Test
public void add_technical_debt_from_one_issue_and_no_parent() throws Exception {
- WorkDayDuration technicalDebt = mock(WorkDayDuration.class);
- when(converter.toDays(technicalDebt)).thenReturn(1.0);
+ WorkUnit technicalDebt = new WorkUnit.Builder().setDays(1).build();
Issue issue = createIssue("rule1", "repo1").setTechnicalDebt(technicalDebt);
when(issuable.issues()).thenReturn(newArrayList(issue));
@@ -145,9 +145,22 @@ public class TechnicalDebtDecoratorTest {
}
@Test
+ public void add_technical_debt_from_one_issue_without_debt() throws Exception {
+ Issue issue = createIssue("rule1", "repo1").setTechnicalDebt(null);
+ when(issuable.issues()).thenReturn(newArrayList(issue));
+
+ Requirement requirement = mock(Requirement.class);
+ when(defaultTechnicalDebtModel.requirementsByRule(RuleKey.of("repo1", "rule1"))).thenReturn(requirement);
+ doReturn(newArrayList(requirement)).when(defaultTechnicalDebtModel).requirements();
+
+ decorator.decorate(resource, context);
+
+ verify(context).saveMeasure(argThat(new IsCharacteristicMeasure(CoreMetrics.TECHNICAL_DEBT, 0.0)));
+ }
+
+ @Test
public void add_technical_debt_from_one_issue_and_propagate_to_parents() throws Exception {
- WorkDayDuration technicalDebt = mock(WorkDayDuration.class);
- when(converter.toDays(technicalDebt)).thenReturn(1.0);
+ WorkUnit technicalDebt = new WorkUnit.Builder().setDays(1).build();
Issue issue = createIssue("rule1", "repo1").setTechnicalDebt(technicalDebt);
when(issuable.issues()).thenReturn(newArrayList(issue));
@@ -170,11 +183,8 @@ public class TechnicalDebtDecoratorTest {
@Test
public void add_technical_debt_from_issues() throws Exception {
- WorkDayDuration technicalDebt1 = mock(WorkDayDuration.class);
- when(converter.toDays(technicalDebt1)).thenReturn(1.0);
-
- WorkDayDuration technicalDebt2 = mock(WorkDayDuration.class);
- when(converter.toDays(technicalDebt2)).thenReturn(2.0);
+ WorkUnit technicalDebt1 = new WorkUnit.Builder().setDays(1).build();
+ WorkUnit technicalDebt2 = new WorkUnit.Builder().setDays(2).build();
Issue issue1 = createIssue("rule1", "repo1").setTechnicalDebt(technicalDebt1);
Issue issue2 = createIssue("rule1", "repo1").setTechnicalDebt(technicalDebt1);
@@ -202,11 +212,10 @@ public class TechnicalDebtDecoratorTest {
@Test
public void add_technical_debt_from_children_measures() throws Exception {
- WorkDayDuration technicalDebt1 = mock(WorkDayDuration.class);
- when(converter.toDays(technicalDebt1)).thenReturn(1.0);
+ WorkUnit technicalDebt = new WorkUnit.Builder().setDays(1).build();
- Issue issue1 = createIssue("rule1", "repo1").setTechnicalDebt(technicalDebt1);
- Issue issue2 = createIssue("rule1", "repo1").setTechnicalDebt(technicalDebt1);
+ Issue issue1 = createIssue("rule1", "repo1").setTechnicalDebt(technicalDebt);
+ Issue issue2 = createIssue("rule1", "repo1").setTechnicalDebt(technicalDebt);
when(issuable.issues()).thenReturn(newArrayList(issue1, issue2));
DefaultCharacteristic rootCharacteristic = new DefaultCharacteristic().setKey("rootCharacteristic");
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 285e29b5652..821de088059 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
@@ -35,32 +35,10 @@ 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.bootstrap.*;
import org.sonar.batch.components.PeriodsDefinition;
-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.ResourceKeyMigration;
-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.index.*;
+import org.sonar.batch.issue.*;
import org.sonar.batch.phases.GraphPersister;
import org.sonar.batch.profiling.PhasesSumUpTimeProfiler;
import org.sonar.batch.scan.filesystem.InputFileCache;
@@ -77,7 +55,6 @@ 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.test.TestPlanBuilder;
import org.sonar.core.test.TestPlanPerspectiveLoader;
import org.sonar.core.test.TestableBuilder;
@@ -177,7 +154,6 @@ public class ProjectScanContainer extends ComponentContainer {
// technical debt
TechnicalDebtModelLoader.class,
- TechnicalDebtConverter.class,
TechnicalDebtCalculator.class,
new TechnicalDebtModelProvider(),
diff --git a/sonar-batch/src/main/java/org/sonar/batch/technicaldebt/TechnicalDebtCalculator.java b/sonar-batch/src/main/java/org/sonar/batch/technicaldebt/TechnicalDebtCalculator.java
index 996cd321c99..3cfefd8af44 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/technicaldebt/TechnicalDebtCalculator.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/technicaldebt/TechnicalDebtCalculator.java
@@ -21,35 +21,39 @@ package org.sonar.batch.technicaldebt;
import com.google.common.base.Objects;
import org.sonar.api.BatchExtension;
+import org.sonar.api.CoreProperties;
+import org.sonar.api.config.Settings;
import org.sonar.api.issue.Issue;
-import org.sonar.api.issue.internal.WorkDayDuration;
import org.sonar.api.technicaldebt.batch.Requirement;
import org.sonar.api.technicaldebt.batch.TechnicalDebtModel;
import org.sonar.api.technicaldebt.batch.internal.DefaultRequirement;
import org.sonar.api.utils.WorkUnit;
-import org.sonar.core.technicaldebt.TechnicalDebtConverter;
/**
* Computes the remediation cost based on the quality and analysis models.
*/
public class TechnicalDebtCalculator implements BatchExtension {
- private final TechnicalDebtConverter converter;
+ private int hoursInDay;
+
private TechnicalDebtModel model;
- public TechnicalDebtCalculator(TechnicalDebtModel model, TechnicalDebtConverter converter) {
+ public TechnicalDebtCalculator(TechnicalDebtModel model, Settings settings) {
this.model = model;
- this.converter = converter;
+ this.hoursInDay = settings.getInt(CoreProperties.HOURS_IN_DAY);
}
- public WorkDayDuration calculTechnicalDebt(Issue issue) {
+ /**
+ * Get the technical debt from the requirement
+ */
+ public WorkUnit calculTechnicalDebt(Issue issue) {
Requirement requirement = model.requirementsByRule(issue.ruleKey());
if (requirement != null) {
if (requirement.function().equals(DefaultRequirement.CONSTANT_ISSUE) && issue.effortToFix() != null) {
- throw new IllegalArgumentException("Requirement for '"+ issue.ruleKey() +"' can not use 'Constant/issue' remediation function " +
+ throw new IllegalArgumentException("Requirement for '" + issue.ruleKey() + "' can not use 'Constant/issue' remediation function " +
"because this rule does not have a fixed remediation cost.");
}
- return converter.fromMinutes(calculTechnicalDebt(requirement, issue));
+ return fromMinutes(calculTechnicalDebt(requirement, issue));
}
return null;
}
@@ -58,11 +62,45 @@ public class TechnicalDebtCalculator implements BatchExtension {
long effortToFix = Objects.firstNonNull(issue.effortToFix(), 1L).longValue();
WorkUnit factorUnit = requirement.factor();
- long factor = factorUnit != null ? converter.toMinutes(factorUnit) : 0L;
+ long factor = factorUnit != null ? toMinutes(factorUnit) : 0L;
WorkUnit offsetUnit = requirement.offset();
- long offset = offsetUnit != null ? converter.toMinutes(offsetUnit) : 0L;
+ long offset = offsetUnit != null ? toMinutes(offsetUnit) : 0L;
return effortToFix * factor + offset;
}
+
+ private long toMinutes(WorkUnit factor) {
+ if (factor.days() > 0) {
+ return Double.valueOf(factor.days() * hoursInDay * 60d).longValue();
+ } else if (factor.hours() > 0) {
+ return Double.valueOf(factor.hours() * 60d).longValue();
+ } else {
+ return Double.valueOf(factor.minutes()).longValue();
+ }
+ }
+
+ private WorkUnit 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 new WorkUnit.Builder().setDays(days).setHours(hours).setMinutes(minutes).build();
+ }
}
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 667de9f373a..532d056a306 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
@@ -27,7 +27,6 @@ import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import org.sonar.api.issue.internal.DefaultIssue;
-import org.sonar.api.issue.internal.WorkDayDuration;
import org.sonar.api.profiles.RulesProfile;
import org.sonar.api.resources.JavaFile;
import org.sonar.api.resources.Project;
@@ -36,6 +35,7 @@ import org.sonar.api.rule.RuleKey;
import org.sonar.api.rule.Severity;
import org.sonar.api.rules.*;
import org.sonar.api.utils.MessageException;
+import org.sonar.api.utils.WorkUnit;
import org.sonar.batch.technicaldebt.TechnicalDebtCalculator;
import java.util.Calendar;
@@ -284,14 +284,14 @@ public class ModuleIssuesTest {
.setRuleKey(SQUID_RULE_KEY)
.setSeverity(Severity.CRITICAL);
- when(technicalDebtCalculator.calculTechnicalDebt(issue)).thenReturn(WorkDayDuration.of(10, 0, 0));
+ when(technicalDebtCalculator.calculTechnicalDebt(issue)).thenReturn(new WorkUnit.Builder().setDays(10).build());
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().technicalDebt()).isEqualTo(WorkDayDuration.of(10, 0, 0));
+ assertThat(argument.getValue().technicalDebt()).isEqualTo(new WorkUnit.Builder().setDays(10).build());
}
}
diff --git a/sonar-batch/src/test/java/org/sonar/batch/technicaldebt/TechnicalDebtCalculatorTest.java b/sonar-batch/src/test/java/org/sonar/batch/technicaldebt/TechnicalDebtCalculatorTest.java
index ccb9554d225..684f4426353 100644
--- a/sonar-batch/src/test/java/org/sonar/batch/technicaldebt/TechnicalDebtCalculatorTest.java
+++ b/sonar-batch/src/test/java/org/sonar/batch/technicaldebt/TechnicalDebtCalculatorTest.java
@@ -25,16 +25,18 @@ import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.runners.MockitoJUnitRunner;
+import org.sonar.api.CoreProperties;
+import org.sonar.api.config.Settings;
import org.sonar.api.issue.internal.DefaultIssue;
import org.sonar.api.rule.RuleKey;
import org.sonar.api.technicaldebt.batch.TechnicalDebtModel;
import org.sonar.api.technicaldebt.batch.internal.DefaultRequirement;
import org.sonar.api.utils.WorkUnit;
-import org.sonar.core.technicaldebt.TechnicalDebtConverter;
import static org.fest.assertions.Assertions.assertThat;
import static org.fest.assertions.Fail.fail;
-import static org.mockito.Mockito.*;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
@RunWith(MockitoJUnitRunner.class)
public class TechnicalDebtCalculatorTest {
@@ -42,20 +44,17 @@ public class TechnicalDebtCalculatorTest {
@Mock
TechnicalDebtModel model;
- @Mock
- TechnicalDebtConverter converter;
-
- WorkUnit tenMinutes = WorkUnit.create(10d, WorkUnit.MINUTES);
- WorkUnit fiveMinutes = WorkUnit.create(5d, WorkUnit.MINUTES);
+ WorkUnit tenMinutes = new WorkUnit.Builder().setMinutes(10).build();
+ WorkUnit fiveMinutes = new WorkUnit.Builder().setMinutes(5).build();
TechnicalDebtCalculator remediationCostCalculator;
@Before
public void before() {
- when(converter.toMinutes(tenMinutes)).thenReturn(10l);
- when(converter.toMinutes(fiveMinutes)).thenReturn(5l);
+ Settings settings = new Settings();
+ settings.setProperty(CoreProperties.HOURS_IN_DAY, 8);
- remediationCostCalculator = new TechnicalDebtCalculator(model, converter);
+ remediationCostCalculator = new TechnicalDebtCalculator(model, settings);
}
@Test
@@ -69,9 +68,7 @@ public class TechnicalDebtCalculatorTest {
Mockito.when(requirement.offset()).thenReturn(fiveMinutes);
when(model.requirementsByRule(ruleKey)).thenReturn(requirement);
- remediationCostCalculator.calculTechnicalDebt(issue);
-
- verify(converter).fromMinutes(10l + 5l);
+ assertThat(remediationCostCalculator.calculTechnicalDebt(issue)).isEqualTo(new WorkUnit.Builder().setMinutes(15).build());
}
@Test
@@ -85,9 +82,7 @@ public class TechnicalDebtCalculatorTest {
Mockito.when(requirement.offset()).thenReturn(fiveMinutes);
when(model.requirementsByRule(ruleKey)).thenReturn(requirement);
- remediationCostCalculator.calculTechnicalDebt(issue);
-
- verify(converter).fromMinutes(10l * 2 + 5l);
+ assertThat(remediationCostCalculator.calculTechnicalDebt(issue)).isEqualTo(new WorkUnit.Builder().setMinutes((10 * 2) + 5).build());
}
@Test
@@ -101,9 +96,7 @@ public class TechnicalDebtCalculatorTest {
Mockito.when(requirement.offset()).thenReturn(null);
when(model.requirementsByRule(ruleKey)).thenReturn(requirement);
- remediationCostCalculator.calculTechnicalDebt(issue);
-
- verify(converter).fromMinutes(10l * 2 + 0l);
+ assertThat(remediationCostCalculator.calculTechnicalDebt(issue)).isEqualTo(new WorkUnit.Builder().setMinutes(10 * 2).build());
}
@Test
@@ -117,9 +110,7 @@ public class TechnicalDebtCalculatorTest {
Mockito.when(requirement.offset()).thenReturn(fiveMinutes);
when(model.requirementsByRule(ruleKey)).thenReturn(requirement);
- remediationCostCalculator.calculTechnicalDebt(issue);
-
- verify(converter).fromMinutes(0l + 5l);
+ assertThat(remediationCostCalculator.calculTechnicalDebt(issue)).isEqualTo(new WorkUnit.Builder().setMinutes(5).build());
}
@Test
@@ -129,7 +120,6 @@ public class TechnicalDebtCalculatorTest {
when(model.requirementsByRule(ruleKey)).thenReturn(null);
assertThat(remediationCostCalculator.calculTechnicalDebt(issue)).isNull();
- verify(converter, never()).fromMinutes(anyLong());
}
@Test
@@ -144,13 +134,12 @@ public class TechnicalDebtCalculatorTest {
when(model.requirementsByRule(ruleKey)).thenReturn(requirement);
try {
- remediationCostCalculator.calculTechnicalDebt(issue);
+ assertThat(remediationCostCalculator.calculTechnicalDebt(issue)).isEqualTo(new WorkUnit.Builder().setMinutes(15).build());
fail();
} catch (Exception e) {
assertThat(e).isInstanceOf(IllegalArgumentException.class)
.hasMessage("Requirement for 'squid:AvoidCycle' can not use 'Constant/issue' remediation function because this rule does not have a fixed remediation cost.");
}
- verifyZeroInteractions(converter);
}
}
diff --git a/sonar-batch/src/test/java/org/sonar/batch/technicaldebt/TechnicalDebtModelLoaderTest.java b/sonar-batch/src/test/java/org/sonar/batch/technicaldebt/TechnicalDebtModelLoaderTest.java
index cb1ecab4b73..b60bb584426 100644
--- a/sonar-batch/src/test/java/org/sonar/batch/technicaldebt/TechnicalDebtModelLoaderTest.java
+++ b/sonar-batch/src/test/java/org/sonar/batch/technicaldebt/TechnicalDebtModelLoaderTest.java
@@ -108,8 +108,8 @@ public class TechnicalDebtModelLoaderTest {
DefaultRequirement requirement = result.requirementsByRule(ruleKey);
assertThat(requirement.ruleKey()).isEqualTo(ruleKey);
assertThat(requirement.function()).isEqualTo("linear");
- assertThat(requirement.factor()).isEqualTo(WorkUnit.create(2d, WorkUnit.DAYS));
- assertThat(requirement.offset()).isEqualTo(WorkUnit.create(0d, WorkUnit.DEFAULT_UNIT));
+ assertThat(requirement.factor()).isEqualTo(new WorkUnit.Builder().setDays(2).build());
+ assertThat(requirement.offset()).isEqualTo(new WorkUnit.Builder().setDays(0).build());
}
}
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 9cbd6c92045..538104db87c 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,8 +28,8 @@ 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.issue.internal.WorkDayDuration;
import org.sonar.api.user.User;
+import org.sonar.api.utils.WorkUnit;
import javax.annotation.Nullable;
@@ -85,7 +85,7 @@ public class IssueUpdater implements BatchComponent, ServerComponent {
public boolean assign(DefaultIssue issue, @Nullable User user, IssueChangeContext context) {
String sanitizedAssignee = null;
- if(user != null) {
+ if (user != null) {
sanitizedAssignee = StringUtils.defaultIfBlank(user.login(), null);
}
if (!Objects.equal(sanitizedAssignee, issue.assignee())) {
@@ -200,8 +200,8 @@ public class IssueUpdater implements BatchComponent, ServerComponent {
return setEffortToFix(issue, currentEffort, context);
}
- public boolean setTechnicalDebt(DefaultIssue issue, @Nullable WorkDayDuration value, IssueChangeContext context) {
- WorkDayDuration oldValue = issue.technicalDebt();
+ public boolean setTechnicalDebt(DefaultIssue issue, @Nullable WorkUnit value, IssueChangeContext context) {
+ WorkUnit oldValue = issue.technicalDebt();
if (!Objects.equal(value, oldValue)) {
issue.setTechnicalDebt(value);
issue.setFieldChange(context, TECHNICAL_DEBT, oldValue != null ? oldValue.toLong() : null, value != null ? value.toLong() : null);
@@ -212,8 +212,8 @@ public class IssueUpdater implements BatchComponent, ServerComponent {
return false;
}
- public boolean setPastTechnicalDebt(DefaultIssue issue, @Nullable WorkDayDuration previousTechnicalDebt, IssueChangeContext context) {
- WorkDayDuration currentTechnicalDebt = issue.technicalDebt();
+ public boolean setPastTechnicalDebt(DefaultIssue issue, @Nullable WorkUnit previousTechnicalDebt, IssueChangeContext context) {
+ WorkUnit currentTechnicalDebt = issue.technicalDebt();
issue.setTechnicalDebt(previousTechnicalDebt);
return setTechnicalDebt(issue, currentTechnicalDebt, context);
}
@@ -232,7 +232,7 @@ public class IssueUpdater implements BatchComponent, ServerComponent {
public boolean plan(DefaultIssue issue, @Nullable ActionPlan actionPlan, IssueChangeContext context) {
String sanitizedActionPlanKey = null;
- if(actionPlan != null) {
+ if (actionPlan != null) {
sanitizedActionPlanKey = StringUtils.defaultIfBlank(actionPlan.key(), null);
}
if (!Objects.equal(sanitizedActionPlanKey, issue.actionPlanKey())) {
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 1574dcc9ff5..3e34ad2c738 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
@@ -24,9 +24,9 @@ import com.google.common.base.Preconditions;
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.issue.internal.WorkDayDuration;
import org.sonar.api.rule.RuleKey;
import org.sonar.api.utils.KeyValueFormat;
+import org.sonar.api.utils.WorkUnit;
import javax.annotation.CheckForNull;
import javax.annotation.Nullable;
@@ -422,7 +422,7 @@ public final class IssueDto implements Serializable {
issue.setResolution(resolution);
issue.setMessage(message);
issue.setEffortToFix(effortToFix);
- issue.setTechnicalDebt(technicalDebt != null ? WorkDayDuration.fromLong(technicalDebt) : null);
+ issue.setTechnicalDebt(technicalDebt != null ? WorkUnit.fromLong(technicalDebt) : null);
issue.setLine(line);
issue.setSeverity(severity);
issue.setReporter(reporter);
diff --git a/sonar-core/src/main/java/org/sonar/core/technicaldebt/TechnicalDebtConverter.java b/sonar-core/src/main/java/org/sonar/core/technicaldebt/TechnicalDebtConverter.java
deleted file mode 100644
index 7191034e8e6..00000000000
--- a/sonar-core/src/main/java/org/sonar/core/technicaldebt/TechnicalDebtConverter.java
+++ /dev/null
@@ -1,90 +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.apache.commons.lang.StringUtils;
-import org.sonar.api.BatchComponent;
-import org.sonar.api.ServerComponent;
-import org.sonar.api.config.Settings;
-import org.sonar.api.issue.internal.WorkDayDuration;
-import org.sonar.api.utils.WorkUnit;
-
-import javax.annotation.Nullable;
-
-public class TechnicalDebtConverter implements BatchComponent, ServerComponent {
-
- public static final String PROPERTY_HOURS_IN_DAY = "sonar.technicalDebt.hoursInDay";
-
- private int hoursInDay;
-
- public TechnicalDebtConverter(Settings settings) {
- this.hoursInDay = settings.getInt(PROPERTY_HOURS_IN_DAY);
- }
-
- public long toMinutes(WorkUnit factor) {
- if (StringUtils.equals(WorkUnit.DAYS, factor.getUnit())) {
- return Double.valueOf(factor.getValue() * hoursInDay * 60d).longValue();
-
- } else if (StringUtils.equals(WorkUnit.HOURS, factor.getUnit())) {
- return Double.valueOf(factor.getValue() * 60d).longValue();
-
- } else if (StringUtils.equals(WorkUnit.MINUTES, factor.getUnit())) {
- return Double.valueOf(factor.getValue()).longValue();
-
- } else {
- throw new IllegalArgumentException("Unknown remediation factor unit: " + factor.getUnit());
- }
- }
-
- public double toDays(@Nullable WorkDayDuration technicalDebt) {
- if (technicalDebt == null) {
- return 0d;
- }
- double resultDays = technicalDebt.days();
- resultDays += Double.valueOf(technicalDebt.hours()) / hoursInDay;
- resultDays += Double.valueOf(technicalDebt.minutes()) / (hoursInDay * 60.0);
- return resultDays;
- }
-
- public WorkDayDuration 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 WorkDayDuration.of(minutes, hours, days);
- }
-
-}
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 0533e9c157b..3a78a443010 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,8 +24,8 @@ 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.issue.internal.WorkDayDuration;
import org.sonar.api.user.User;
+import org.sonar.api.utils.WorkUnit;
import org.sonar.core.user.DefaultUser;
import java.util.Date;
@@ -366,42 +366,42 @@ public class IssueUpdaterTest {
@Test
public void set_past_technical_debt() throws Exception {
- issue.setTechnicalDebt(WorkDayDuration.of(15, 0, 0));
- WorkDayDuration previousDebt = WorkDayDuration.of(10, 0, 0);
+ issue.setTechnicalDebt(new WorkUnit.Builder().setDays(15).build());
+ WorkUnit previousDebt = new WorkUnit.Builder().setDays(10).build();
boolean updated = updater.setPastTechnicalDebt(issue, previousDebt, context);
assertThat(updated).isTrue();
- assertThat(issue.technicalDebt()).isEqualTo(WorkDayDuration.of(15, 0, 0));
+ assertThat(issue.technicalDebt()).isEqualTo(new WorkUnit.Builder().setDays(15).build());
assertThat(issue.mustSendNotifications()).isFalse();
FieldDiffs.Diff diff = issue.currentChange().get(TECHNICAL_DEBT);
- assertThat(diff.oldValue()).isEqualTo(WorkDayDuration.of(10, 0, 0).toLong());
- assertThat(diff.newValue()).isEqualTo(WorkDayDuration.of(15, 0, 0).toLong());
+ assertThat(diff.oldValue()).isEqualTo(new WorkUnit.Builder().setDays(10).build().toLong());
+ assertThat(diff.newValue()).isEqualTo(new WorkUnit.Builder().setDays(15).build().toLong());
}
@Test
public void set_past_technical_debt_without_previous_value() throws Exception {
- issue.setTechnicalDebt(WorkDayDuration.of(15, 0, 0));
+ issue.setTechnicalDebt(new WorkUnit.Builder().setDays(15).build());
boolean updated = updater.setPastTechnicalDebt(issue, null, context);
assertThat(updated).isTrue();
- assertThat(issue.technicalDebt()).isEqualTo(WorkDayDuration.of(15, 0, 0));
+ assertThat(issue.technicalDebt()).isEqualTo(new WorkUnit.Builder().setDays(15).build());
assertThat(issue.mustSendNotifications()).isFalse();
FieldDiffs.Diff diff = issue.currentChange().get(TECHNICAL_DEBT);
assertThat(diff.oldValue()).isNull();
- assertThat(diff.newValue()).isEqualTo(WorkDayDuration.of(15, 0, 0).toLong());
+ assertThat(diff.newValue()).isEqualTo(new WorkUnit.Builder().setDays(15).build().toLong());
}
@Test
public void set_past_technical_debt_with_null_new_value() throws Exception {
issue.setTechnicalDebt(null);
- WorkDayDuration previousDebt = WorkDayDuration.of(10, 0, 0);
+ WorkUnit previousDebt = new WorkUnit.Builder().setDays(10).build();
boolean updated = updater.setPastTechnicalDebt(issue, previousDebt, context);
assertThat(updated).isTrue();
assertThat(issue.technicalDebt()).isNull();
assertThat(issue.mustSendNotifications()).isFalse();
FieldDiffs.Diff diff = issue.currentChange().get(TECHNICAL_DEBT);
- assertThat(diff.oldValue()).isEqualTo(WorkDayDuration.of(10, 0, 0).toLong());
+ assertThat(diff.oldValue()).isEqualTo(new WorkUnit.Builder().setDays(10).build().toLong());
assertThat(diff.newValue()).isNull();
}
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 484ad84f2a8..e87ffb98153 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,7 +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.issue.internal.WorkDayDuration;
+import org.sonar.api.utils.WorkUnit;
import java.util.Calendar;
import java.util.Date;
@@ -56,28 +56,28 @@ public class IssueDtoTest {
Date closedAt = DateUtils.addDays(new Date(), -1);
IssueDto dto = new IssueDto()
- .setKee("100")
- .setRuleId(1)
- .setRuleKey_unit_test_only("squid", "AvoidCycle")
- .setComponentKey_unit_test_only("org.sonar.sample:Sample")
- .setRootComponentKey_unit_test_only("org.sonar.sample")
- .setComponentId(1l)
- .setRootComponentId(1l)
- .setStatus(Issue.STATUS_CLOSED)
- .setResolution(Issue.RESOLUTION_FALSE_POSITIVE)
- .setEffortToFix(15.0)
- .setTechnicalDebt(101010L)
- .setLine(6)
- .setSeverity("BLOCKER")
- .setMessage("message")
- .setManualSeverity(true)
- .setReporter("arthur")
- .setAssignee("perceval")
- .setIssueAttributes("key=value")
- .setAuthorLogin("pierre")
- .setIssueCreationDate(createdAt)
- .setIssueUpdateDate(updatedAt)
- .setIssueCloseDate(closedAt);
+ .setKee("100")
+ .setRuleId(1)
+ .setRuleKey_unit_test_only("squid", "AvoidCycle")
+ .setComponentKey_unit_test_only("org.sonar.sample:Sample")
+ .setRootComponentKey_unit_test_only("org.sonar.sample")
+ .setComponentId(1l)
+ .setRootComponentId(1l)
+ .setStatus(Issue.STATUS_CLOSED)
+ .setResolution(Issue.RESOLUTION_FALSE_POSITIVE)
+ .setEffortToFix(15.0)
+ .setTechnicalDebt(101010L)
+ .setLine(6)
+ .setSeverity("BLOCKER")
+ .setMessage("message")
+ .setManualSeverity(true)
+ .setReporter("arthur")
+ .setAssignee("perceval")
+ .setIssueAttributes("key=value")
+ .setAuthorLogin("pierre")
+ .setIssueCreationDate(createdAt)
+ .setIssueUpdateDate(updatedAt)
+ .setIssueCloseDate(closedAt);
DefaultIssue issue = dto.toDefaultIssue();
assertThat(issue.key()).isEqualTo("100");
@@ -87,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.technicalDebt()).isEqualTo(WorkDayDuration.of(10, 10, 10));
+ assertThat(issue.technicalDebt()).isEqualTo(new WorkUnit.Builder().setDays(10).setHours(10).setMinutes(10).build());
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/IssueStorageTest.java b/sonar-core/src/test/java/org/sonar/core/issue/db/IssueStorageTest.java
index 1c6281c837a..5c8b3487f8e 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
@@ -23,12 +23,12 @@ import org.junit.Test;
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.issue.internal.WorkDayDuration;
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.utils.DateUtils;
+import org.sonar.api.utils.WorkUnit;
import org.sonar.core.persistence.AbstractDaoTestCase;
import org.sonar.core.persistence.MyBatis;
@@ -54,7 +54,7 @@ public class IssueStorageTest extends AbstractDaoTestCase {
.setRuleKey(RuleKey.of("squid", "AvoidCycle"))
.setLine(5000)
- .setTechnicalDebt(WorkDayDuration.of(10, 0, 0))
+ .setTechnicalDebt(new WorkUnit.Builder().setMinutes(10).build())
.setReporter("emmerik")
.setResolution("OPEN")
.setStatus("OPEN")
@@ -88,7 +88,7 @@ public class IssueStorageTest extends AbstractDaoTestCase {
// updated fields
.setLine(5000)
- .setTechnicalDebt(WorkDayDuration.of(10, 0, 0))
+ .setTechnicalDebt(new WorkUnit.Builder().setMinutes(10).build())
.setChecksum("FFFFF")
.setAuthorLogin("simon")
.setAssignee("loic")
diff --git a/sonar-core/src/test/java/org/sonar/core/technicaldebt/DefaultTechnicalDebtManagerTest.java b/sonar-core/src/test/java/org/sonar/core/technicaldebt/DefaultTechnicalDebtManagerTest.java
index a69517c7c99..69877f81898 100644
--- a/sonar-core/src/test/java/org/sonar/core/technicaldebt/DefaultTechnicalDebtManagerTest.java
+++ b/sonar-core/src/test/java/org/sonar/core/technicaldebt/DefaultTechnicalDebtManagerTest.java
@@ -89,8 +89,8 @@ public class DefaultTechnicalDebtManagerTest {
assertThat(result.rootId()).isEqualTo(1);
assertThat(result.ruleKey()).isEqualTo(RuleKey.of("repo", "key"));
assertThat(result.function()).isEqualTo("linear");
- assertThat(result.factor()).isEqualTo(WorkUnit.create(30.0, WorkUnit.MINUTES));
- assertThat(result.offset()).isEqualTo(WorkUnit.create());
+ assertThat(result.factor()).isEqualTo(new WorkUnit.Builder().setMinutes(30).build());
+ assertThat(result.offset()).isEqualTo(new WorkUnit.Builder().setDays(0).build());
}
@Test
@@ -149,8 +149,8 @@ public class DefaultTechnicalDebtManagerTest {
assertThat(result.rootId()).isEqualTo(1);
assertThat(result.ruleKey()).isEqualTo(RuleKey.of("repo", "key"));
assertThat(result.function()).isEqualTo("linear");
- assertThat(result.factor()).isEqualTo(WorkUnit.create(30.0, WorkUnit.MINUTES));
- assertThat(result.offset()).isEqualTo(WorkUnit.create());
+ assertThat(result.factor()).isEqualTo(new WorkUnit.Builder().setMinutes(30).build());
+ assertThat(result.offset()).isEqualTo(new WorkUnit.Builder().setDays(0).build());
}
@Test
diff --git a/sonar-core/src/test/java/org/sonar/core/technicaldebt/DefaultTechnicalDebtModelTest.java b/sonar-core/src/test/java/org/sonar/core/technicaldebt/DefaultTechnicalDebtModelTest.java
index dcf61654fc3..4177c144c64 100644
--- a/sonar-core/src/test/java/org/sonar/core/technicaldebt/DefaultTechnicalDebtModelTest.java
+++ b/sonar-core/src/test/java/org/sonar/core/technicaldebt/DefaultTechnicalDebtModelTest.java
@@ -92,8 +92,8 @@ public class DefaultTechnicalDebtModelTest {
.setCharacteristic(characteristic)
.setRuleKey(ruleKey)
.setFunction("linear")
- .setFactor(WorkUnit.create(2d, WorkUnit.HOURS))
- .setOffset(WorkUnit.create(0d, WorkUnit.HOURS));
+ .setFactor(new WorkUnit.Builder().setHours(2).build())
+ .setOffset(new WorkUnit.Builder().setHours(0).build());
sqaleModel.addRootCharacteristic(rootCharacteristic);
diff --git a/sonar-core/src/test/java/org/sonar/core/technicaldebt/TechnicalDebtConverterTest.java b/sonar-core/src/test/java/org/sonar/core/technicaldebt/TechnicalDebtConverterTest.java
deleted file mode 100644
index c196320b193..00000000000
--- a/sonar-core/src/test/java/org/sonar/core/technicaldebt/TechnicalDebtConverterTest.java
+++ /dev/null
@@ -1,85 +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.Before;
-import org.junit.Test;
-import org.sonar.api.config.Settings;
-import org.sonar.api.issue.internal.WorkDayDuration;
-import org.sonar.api.utils.WorkUnit;
-
-import static org.fest.assertions.Assertions.assertThat;
-
-
-public class TechnicalDebtConverterTest {
-
- private TechnicalDebtConverter converter;
-
- @Before
- public void before(){
- Settings settings = new Settings();
- settings.setProperty(TechnicalDebtConverter.PROPERTY_HOURS_IN_DAY, "12");
-
- converter = new TechnicalDebtConverter(settings);
- }
-
- @Test
- public void concert_work_unit_to_minutes() {
- assertThat(converter.toMinutes(WorkUnit.create(2.0, WorkUnit.DAYS))).isEqualTo(2 * 12 * 60L);
- assertThat(converter.toMinutes(WorkUnit.create(6.0, WorkUnit.HOURS))).isEqualTo(6 * 60L);
- assertThat(converter.toMinutes(WorkUnit.create(60.0, WorkUnit.MINUTES))).isEqualTo(60L);
- }
-
- @Test
- public void convert_simple_values() {
- checkValues(converter.fromMinutes(15L), 15, 0, 0);
- checkValues(converter.fromMinutes(120L), 0, 2, 0);
- checkValues(converter.fromMinutes(720L), 0, 0, 1);
- }
-
- @Test
- public void convert_complex_values() {
- checkValues(converter.fromMinutes(70L), 10, 1, 0);
- checkValues(converter.fromMinutes(730L), 10, 0, 1);
- checkValues(converter.fromMinutes(790L), 10, 1, 1);
- }
-
- @Test
- public void convert_technical_debt_to_days() {
- assertThat(converter.toDays(WorkDayDuration.of(0, 0, 6))).isEqualTo(6.0);
- assertThat(converter.toDays(WorkDayDuration.of(0, 6, 0))).isEqualTo(0.5);
- assertThat(converter.toDays(WorkDayDuration.of(360, 0, 0))).isEqualTo(0.5);
- assertThat(converter.toDays(WorkDayDuration.of(45, 0, 0))).isEqualTo(0.0625);
-
- assertThat(converter.toDays(WorkDayDuration.of(45, 6, 1))).isEqualTo(1.5625);
- }
-
- @Test
- public void return_zero_if_null_when_convert_technical_debt_to_days() {
- assertThat(converter.toDays((WorkDayDuration) null)).isEqualTo(0.0);
- }
-
- private void checkValues(WorkDayDuration technicalDebt, int expectedMinutes, int expectedHours, int expectedDays) {
- assertThat(technicalDebt.minutes()).isEqualTo(expectedMinutes);
- assertThat(technicalDebt.hours()).isEqualTo(expectedHours);
- assertThat(technicalDebt.days()).isEqualTo(expectedDays);
- }
-
-}
diff --git a/sonar-core/src/test/java/org/sonar/core/technicaldebt/TechnicalDebtModelSynchronizerTest.java b/sonar-core/src/test/java/org/sonar/core/technicaldebt/TechnicalDebtModelSynchronizerTest.java
index e037a48280f..17e4bee2e8a 100644
--- a/sonar-core/src/test/java/org/sonar/core/technicaldebt/TechnicalDebtModelSynchronizerTest.java
+++ b/sonar-core/src/test/java/org/sonar/core/technicaldebt/TechnicalDebtModelSynchronizerTest.java
@@ -142,7 +142,7 @@ public class TechnicalDebtModelSynchronizerTest {
RuleKey ruleKey = RuleKey.of("checkstyle", "import");
when(ruleCache.getByRuleKey(ruleKey)).thenReturn(rule);
new DefaultRequirement().setRuleKey(ruleKey)
- .setFunction("linear").setFactor(WorkUnit.create(30.0, WorkUnit.MINUTES)).setCharacteristic(javaCharacteristic).setRootCharacteristic(javaRootCharacteristic);
+ .setFunction("linear").setFactor(new WorkUnit.Builder().setMinutes(30).build()).setCharacteristic(javaCharacteristic).setRootCharacteristic(javaRootCharacteristic);
Reader javaModelReader = mock(Reader.class);
when(xmlImporter.importXML(eq(javaModelReader), any(ValidationMessages.class), eq(ruleCache))).thenReturn(javaModel);
@@ -195,7 +195,7 @@ public class TechnicalDebtModelSynchronizerTest {
// New requirement
new DefaultRequirement().setRuleKey(ruleKey2)
- .setFunction("linear").setFactor(WorkUnit.create(1.0, WorkUnit.HOURS)).setCharacteristic(javaCharacteristic).setRootCharacteristic(javaRootCharacteristic);
+ .setFunction("linear").setFactor(new WorkUnit.Builder().setHours(1).build()).setCharacteristic(javaCharacteristic).setRootCharacteristic(javaRootCharacteristic);
Reader javaModelReader = mock(Reader.class);
when(technicalDebtModelRepository.createReaderForXMLFile("java")).thenReturn(javaModelReader);
diff --git a/sonar-core/src/test/java/org/sonar/core/technicaldebt/TechnicalDebtXMLImporterTest.java b/sonar-core/src/test/java/org/sonar/core/technicaldebt/TechnicalDebtXMLImporterTest.java
index 1670422d435..d614d7588a0 100644
--- a/sonar-core/src/test/java/org/sonar/core/technicaldebt/TechnicalDebtXMLImporterTest.java
+++ b/sonar-core/src/test/java/org/sonar/core/technicaldebt/TechnicalDebtXMLImporterTest.java
@@ -189,7 +189,7 @@ public class TechnicalDebtXMLImporterTest {
}
private void checkXmlCorrectlyImported(DefaultTechnicalDebtModel sqale, ValidationMessages messages) {
- checkXmlCorrectlyImported(sqale, WorkUnit.create(), messages);
+ checkXmlCorrectlyImported(sqale, new WorkUnit.Builder().setDays(0).build(), messages);
}
private void checkXmlCorrectlyImported(DefaultTechnicalDebtModel sqale, WorkUnit offset, ValidationMessages messages) {
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/CoreProperties.java b/sonar-plugin-api/src/main/java/org/sonar/api/CoreProperties.java
index d0a38dbdc84..5e0795830d0 100644
--- a/sonar-plugin-api/src/main/java/org/sonar/api/CoreProperties.java
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/CoreProperties.java
@@ -543,4 +543,9 @@ public interface CoreProperties {
* @since 4.2
*/
String CORE_AUTHENTICATOR_LOCAL_USERS = "sonar.security.localUsers";
+
+ /**
+ * @since 4.0
+ */
+ String HOURS_IN_DAY = "sonar.technicalDebt.hoursInDay";
}
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 10155076963..dcb7e1a7beb 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
@@ -33,6 +33,7 @@ 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.utils.WorkUnit;
import javax.annotation.CheckForNull;
import javax.annotation.Nullable;
@@ -58,7 +59,7 @@ public class DefaultIssue implements Issue {
private String message;
private Integer line;
private Double effortToFix;
- private WorkDayDuration technicalDebt;
+ private WorkUnit technicalDebt;
private String status;
private String resolution;
private String reporter;
@@ -195,11 +196,11 @@ public class DefaultIssue implements Issue {
* Elapsed time to fix the issue
*/
@CheckForNull
- public WorkDayDuration technicalDebt() {
+ public WorkUnit technicalDebt() {
return technicalDebt;
}
- public DefaultIssue setTechnicalDebt(@Nullable WorkDayDuration t) {
+ public DefaultIssue setTechnicalDebt(@Nullable WorkUnit t) {
this.technicalDebt = t;
return this;
}
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/issue/internal/WorkDayDuration.java b/sonar-plugin-api/src/main/java/org/sonar/api/issue/internal/WorkDayDuration.java
deleted file mode 100644
index a2acecf56f8..00000000000
--- a/sonar-plugin-api/src/main/java/org/sonar/api/issue/internal/WorkDayDuration.java
+++ /dev/null
@@ -1,113 +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.api.issue.internal;
-
-import java.io.Serializable;
-
-public class WorkDayDuration 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 WorkDayDuration(int minutes, int hours, int days) {
- this.minutes = minutes;
- this.hours = hours;
- this.days = days;
- }
-
- private WorkDayDuration(long durationInLong) {
- long time = durationInLong;
- 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 WorkDayDuration of(int minutes, int hours, int days) {
- return new WorkDayDuration(minutes, hours, days);
- }
-
- public static WorkDayDuration fromLong(long durationInLong) {
- return new WorkDayDuration(durationInLong);
- }
-
- public long toLong() {
- return days * DAY + hours * HOUR + minutes * MINUTE;
- }
-
- public int days() {
- return days;
- }
-
- public int hours() {
- return hours;
- }
-
- public int minutes() {
- return minutes;
- }
-
- @Override
- public boolean equals(Object o) {
- if (this == o) {
- return true;
- }
- if (o == null || getClass() != o.getClass()) {
- return false;
- }
- WorkDayDuration workDayDuration = (WorkDayDuration) o;
- if (days != workDayDuration.days) {
- return false;
- }
- if (hours != workDayDuration.hours) {
- return false;
- }
- if (minutes != workDayDuration.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;
- }
-
-}
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/technicaldebt/batch/internal/DefaultRequirement.java b/sonar-plugin-api/src/main/java/org/sonar/api/technicaldebt/batch/internal/DefaultRequirement.java
index 66f4778c5e4..8f80e3fc8ec 100644
--- a/sonar-plugin-api/src/main/java/org/sonar/api/technicaldebt/batch/internal/DefaultRequirement.java
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/technicaldebt/batch/internal/DefaultRequirement.java
@@ -47,8 +47,8 @@ public class DefaultRequirement implements Requirement {
private Date updatedAt;
public DefaultRequirement() {
- this.factor = WorkUnit.create(0d, WorkUnit.DEFAULT_UNIT);
- this.offset = WorkUnit.create(0d, WorkUnit.DEFAULT_UNIT);
+ this.factor = new WorkUnit.Builder().setDays(0).build();
+ this.offset = new WorkUnit.Builder().setDays(0).build();
}
public Integer id() {
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/utils/WorkUnit.java b/sonar-plugin-api/src/main/java/org/sonar/api/utils/WorkUnit.java
index 61a5aeec2a7..2686663765c 100644
--- a/sonar-plugin-api/src/main/java/org/sonar/api/utils/WorkUnit.java
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/utils/WorkUnit.java
@@ -26,30 +26,42 @@ import org.apache.commons.lang.builder.ToStringStyle;
import javax.annotation.Nullable;
-public final class WorkUnit {
+import java.io.Serializable;
+
+/**
+ * @since 4.0
+ */
+public final class WorkUnit implements Serializable {
public static final String DAYS = "d";
public static final String MINUTES = "mn";
public static final String HOURS = "h";
public static final String DEFAULT_UNIT = DAYS;
- private static final String[] UNITS = {DAYS, MINUTES, HOURS};
public static final double DEFAULT_VALUE = 0.0;
- private double value = 0d;
- private String unit = DEFAULT_UNIT;
+ private static final String[] UNITS = {DAYS, MINUTES, HOURS};
- WorkUnit(double value, String unit) {
- this.value = value;
- this.unit = unit;
- }
+ private static final int DAY = 10000;
+ private static final int HOUR = 100;
+ private static final int MINUTE = 1;
- public double getValue() {
- return value;
+ private int days;
+ private int hours;
+ private int minutes;
+
+ private WorkUnit(int days, int hours, int minutes) {
+ this.minutes = minutes;
+ this.hours = hours;
+ this.days = days;
}
- public String getUnit() {
- return unit;
+ /**
+ * @deprecated since 4.2.
+ */
+ @Deprecated
+ public static WorkUnit create() {
+ return create(0d, DEFAULT_UNIT);
}
public static WorkUnit create(@Nullable Double value, @Nullable String unit) {
@@ -57,15 +69,114 @@ public final class WorkUnit {
if (!ArrayUtils.contains(UNITS, defaultIfEmptyUnit)) {
throw new IllegalArgumentException("Unit can not be: " + defaultIfEmptyUnit + ". Possible values are " + ArrayUtils.toString(UNITS));
}
- double d = value != null ? value : DEFAULT_VALUE;
+ Double d = value != null ? value : DEFAULT_VALUE;
if (d < 0.0) {
throw new IllegalArgumentException("Value can not be negative: " + d);
}
- return new WorkUnit(d, defaultIfEmptyUnit);
+
+ int days = 0;
+ int hours = 0;
+ int minutes = 0;
+ if (DAYS.equals(unit)) {
+ days = d.intValue();
+ } else if (HOURS.equals(unit)) {
+ hours = d.intValue();
+ } else if (MINUTES.equals(unit)) {
+ minutes = d.intValue();
+ }
+ return new WorkUnit(days, hours, minutes);
}
- public static WorkUnit create() {
- return create(0d, DEFAULT_UNIT);
+ public double getValue() {
+ if (days > 0) {
+ return days + (hours / 24) + (minutes / 60 / 24);
+ } else if (hours > 0) {
+ return hours + (minutes / 60);
+ } else {
+ return minutes;
+ }
+ }
+
+ public String getUnit() {
+ if (days > 0) {
+ return DAYS;
+ } else if (hours > 0) {
+ return HOURS;
+ } else {
+ return MINUTES;
+ }
+ }
+
+ /**
+ * @since 4.2
+ */
+ public int days() {
+ return days;
+ }
+
+ /**
+ * @since 4.2
+ */
+ public int hours() {
+ return hours;
+ }
+
+ /**
+ * @since 4.2
+ */
+ public int minutes() {
+ return minutes;
+ }
+
+ /**
+ *
+ * @since 4.2
+ */
+ public static WorkUnit fromLong(long durationInLong) {
+ Builder builder = new Builder();
+
+ long time = durationInLong;
+ Long currentTime = time / DAY;
+ if (currentTime > 0) {
+ builder.setDays(currentTime.intValue());
+ time = time - (currentTime * DAY);
+ }
+
+ currentTime = time / HOUR;
+ if (currentTime > 0) {
+ builder.setHours(currentTime.intValue());
+ time = time - (currentTime * HOUR);
+ }
+
+ currentTime = time / MINUTE;
+ if (currentTime > 0) {
+ builder.setMinutes(currentTime.intValue());
+ }
+
+ return builder.build();
+ }
+
+ /**
+ * Return the duration using the following format DDHHMM, where DD is the number of days, HH is the number of months, and MM the number of minutes.
+ * For instance, 5 days and 2 hours will return 050200.
+ *
+ * @since 4.2
+ */
+ public long toLong() {
+ return days * DAY + hours * HOUR + minutes * MINUTE;
+ }
+
+ /**
+ * Return the duration in number of days.
+ * For instance, 5 days and 4 hours will return 5.5 hours (if hoursIndDay is 8).
+ *
+ * @since 4.2
+ */
+ public double toDays(int hoursInDay) {
+ double resultDays = days;
+ resultDays += (double) hours / hoursInDay;
+ resultDays += (double) minutes / (hoursInDay * 60.0);
+ return resultDays;
}
@Override
@@ -76,26 +187,24 @@ public final class WorkUnit {
if (o == null || getClass() != o.getClass()) {
return false;
}
-
- WorkUnit workUnit = (WorkUnit) o;
-
- if (Double.compare(workUnit.value, value) != 0) {
+ WorkUnit workDayDuration = (WorkUnit) o;
+ if (days != workDayDuration.days) {
return false;
}
- if (!unit.equals(workUnit.unit)) {
+ if (hours != workDayDuration.hours) {
+ return false;
+ }
+ if (minutes != workDayDuration.minutes) {
return false;
}
-
return true;
}
@Override
public int hashCode() {
- int result;
- long temp;
- temp = Double.doubleToLongBits(value);
- result = (int) (temp ^ (temp >>> 32));
- result = 31 * result + unit.hashCode();
+ int result = Integer.valueOf(days).hashCode();
+ result = 29 * result + Integer.valueOf(hours).hashCode();
+ result = 27 * result + Integer.valueOf(minutes).hashCode();
return result;
}
@@ -103,4 +212,32 @@ public final class WorkUnit {
public String toString() {
return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE);
}
+
+ /**
+ * @since 4.2
+ */
+ public static class Builder {
+ private int days;
+ private int hours;
+ private int minutes;
+
+ public Builder setDays(int days) {
+ this.days = days;
+ return this;
+ }
+
+ public Builder setHours(int hours) {
+ this.hours = hours;
+ return this;
+ }
+
+ public Builder setMinutes(int minutes) {
+ this.minutes = minutes;
+ return this;
+ }
+
+ public WorkUnit build() {
+ return new WorkUnit(days, hours, minutes);
+ }
+ }
}
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 0e464d40ec5..1b385766ac4 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.utils.WorkUnit;
import java.text.SimpleDateFormat;
import java.util.List;
@@ -49,7 +50,7 @@ public class DefaultIssueTest {
.setMessage("a message")
.setLine(7)
.setEffortToFix(1.2d)
- .setTechnicalDebt(WorkDayDuration.of(1, 0, 0))
+ .setTechnicalDebt(new WorkUnit.Builder().setDays(1).build())
.setActionPlanKey("BCDE")
.setStatus(Issue.STATUS_CLOSED)
.setResolution(Issue.RESOLUTION_FIXED)
@@ -77,7 +78,7 @@ public class DefaultIssueTest {
assertThat(issue.message()).isEqualTo("a message");
assertThat(issue.line()).isEqualTo(7);
assertThat(issue.effortToFix()).isEqualTo(1.2d);
- assertThat(issue.technicalDebt()).isEqualTo(WorkDayDuration.of(1, 0, 0));
+ assertThat(issue.technicalDebt()).isEqualTo(new WorkUnit.Builder().setDays(1).build());
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/issue/internal/WorkDayDurationTest.java b/sonar-plugin-api/src/test/java/org/sonar/api/issue/internal/WorkDayDurationTest.java
deleted file mode 100644
index ccff88c8624..00000000000
--- a/sonar-plugin-api/src/test/java/org/sonar/api/issue/internal/WorkDayDurationTest.java
+++ /dev/null
@@ -1,73 +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.api.issue.internal;
-
-import org.junit.Test;
-
-import static org.fest.assertions.Assertions.assertThat;
-
-public class WorkDayDurationTest {
-
- @Test
- public void from_long_on_simple_values(){
- checkTimes(WorkDayDuration.fromLong(1L), 0, 0, 1);
- checkTimes(WorkDayDuration.fromLong(100L), 0, 1, 0);
- checkTimes(WorkDayDuration.fromLong(10000L), 1, 0, 0);
- }
-
- @Test
- public void from_long_on_complex_values(){
- checkTimes(WorkDayDuration.fromLong(10101L), 1, 1, 1);
- checkTimes(WorkDayDuration.fromLong(101L), 0, 1, 1);
- checkTimes(WorkDayDuration.fromLong(10001L), 1, 0, 1);
- checkTimes(WorkDayDuration.fromLong(10100L), 1, 1, 0);
-
- checkTimes(WorkDayDuration.fromLong(112233L), 11, 22, 33);
- }
-
- @Test
- public void to_long(){
- assertThat(WorkDayDuration.of(1, 1, 1).toLong()).isEqualTo(10101L);
- }
-
- @Test
- public void test_equals_and_hashCode() throws Exception {
- WorkDayDuration oneMinute = WorkDayDuration.fromLong(1L);
- WorkDayDuration oneHours = WorkDayDuration.fromLong(100L);
- WorkDayDuration oneDay = WorkDayDuration.fromLong(10000L);
-
- assertThat(oneMinute).isEqualTo(oneMinute);
- assertThat(oneMinute).isEqualTo(WorkDayDuration.fromLong(1L));
- assertThat(oneHours).isEqualTo(WorkDayDuration.fromLong(100L));
- assertThat(oneDay).isEqualTo(WorkDayDuration.fromLong(10000L));
-
- assertThat(oneMinute).isNotEqualTo(oneHours);
- assertThat(oneHours).isNotEqualTo(oneDay);
-
- assertThat(oneMinute.hashCode()).isEqualTo(oneMinute.hashCode());
- }
-
- private void checkTimes(WorkDayDuration 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-plugin-api/src/test/java/org/sonar/api/technicaldebt/batch/internal/DefaultRequirementTest.java b/sonar-plugin-api/src/test/java/org/sonar/api/technicaldebt/batch/internal/DefaultRequirementTest.java
index 3c8c246165f..f3bda181038 100644
--- a/sonar-plugin-api/src/test/java/org/sonar/api/technicaldebt/batch/internal/DefaultRequirementTest.java
+++ b/sonar-plugin-api/src/test/java/org/sonar/api/technicaldebt/batch/internal/DefaultRequirementTest.java
@@ -47,8 +47,8 @@ public class DefaultRequirementTest {
.setCharacteristic(characteristic)
.setRootCharacteristic(root)
.setFunction("linear_offset")
- .setFactor(WorkUnit.create(2.0, "mn"))
- .setOffset(WorkUnit.create(1.0, "h"))
+ .setFactor(new WorkUnit.Builder().setMinutes(2).build())
+ .setOffset(new WorkUnit.Builder().setHours(1).build())
.setCreatedAt(new SimpleDateFormat("yyyy-MM-dd").parse("2013-08-19"))
.setUpdatedAt(new SimpleDateFormat("yyyy-MM-dd").parse("2013-08-19"));
@@ -57,8 +57,8 @@ public class DefaultRequirementTest {
assertThat(requirement.characteristic()).isEqualTo(characteristic);
assertThat(requirement.rootCharacteristic()).isEqualTo(root);
assertThat(requirement.function()).isEqualTo("linear_offset");
- assertThat(requirement.factor()).isEqualTo(WorkUnit.create(2.0, "mn"));
- assertThat(requirement.offset()).isEqualTo(WorkUnit.create(1.0, "h"));
+ assertThat(requirement.factor()).isEqualTo(new WorkUnit.Builder().setMinutes(2).build());
+ assertThat(requirement.offset()).isEqualTo(new WorkUnit.Builder().setHours(1).build());
assertThat(requirement.createdAt()).isEqualTo(new SimpleDateFormat("yyyy-MM-dd").parse("2013-08-19"));
assertThat(requirement.updatedAt()).isEqualTo(new SimpleDateFormat("yyyy-MM-dd").parse("2013-08-19"));
}
diff --git a/sonar-plugin-api/src/test/java/org/sonar/api/technicaldebt/server/internal/DefaultCharacteristicTest.java b/sonar-plugin-api/src/test/java/org/sonar/api/technicaldebt/server/internal/DefaultCharacteristicTest.java
index 3217dde1a7b..72835e0705b 100644
--- a/sonar-plugin-api/src/test/java/org/sonar/api/technicaldebt/server/internal/DefaultCharacteristicTest.java
+++ b/sonar-plugin-api/src/test/java/org/sonar/api/technicaldebt/server/internal/DefaultCharacteristicTest.java
@@ -56,8 +56,8 @@ public class DefaultCharacteristicTest {
.setId(1)
.setRuleKey(RuleKey.of("repo", "rule"))
.setFunction("linear_offset")
- .setFactor(WorkUnit.create(2.0, "mn"))
- .setOffset(WorkUnit.create(1.0, "h"))
+ .setFactor(new WorkUnit.Builder().setMinutes(2).build())
+ .setOffset(new WorkUnit.Builder().setHours(1).build())
.setRootId(3)
.setParentId(2);
@@ -67,8 +67,8 @@ public class DefaultCharacteristicTest {
assertThat(requirement.order()).isNull();
assertThat(requirement.ruleKey()).isEqualTo(RuleKey.of("repo", "rule"));
assertThat(requirement.function()).isEqualTo("linear_offset");
- assertThat(requirement.factor()).isEqualTo(WorkUnit.create(2.0, "mn"));
- assertThat(requirement.offset()).isEqualTo(WorkUnit.create(1.0, "h"));
+ assertThat(requirement.factor()).isEqualTo(new WorkUnit.Builder().setMinutes(2).build());
+ assertThat(requirement.offset()).isEqualTo(new WorkUnit.Builder().setHours(1).build());
assertThat(requirement.parentId()).isEqualTo(2);
assertThat(requirement.rootId()).isEqualTo(3);
}
@@ -92,8 +92,8 @@ public class DefaultCharacteristicTest {
.setId(1)
.setRuleKey(RuleKey.of("repo", "rule"))
.setFunction("linear_offset")
- .setFactor(WorkUnit.create(2.0, "mn"))
- .setOffset(WorkUnit.create(1.0, "h"))
+ .setFactor(new WorkUnit.Builder().setMinutes(2).build())
+ .setOffset(new WorkUnit.Builder().setHours(1).build())
.setRootId(3)
.setParentId(2);
diff --git a/sonar-plugin-api/src/test/java/org/sonar/api/utils/WorkUnitTest.java b/sonar-plugin-api/src/test/java/org/sonar/api/utils/WorkUnitTest.java
index 108f7aa57c2..c77e0b8bbf6 100644
--- a/sonar-plugin-api/src/test/java/org/sonar/api/utils/WorkUnitTest.java
+++ b/sonar-plugin-api/src/test/java/org/sonar/api/utils/WorkUnitTest.java
@@ -36,18 +36,10 @@ public class WorkUnitTest {
@Test
public void create_default() throws Exception {
WorkUnit workUnit = WorkUnit.create();
- assertThat(workUnit.getUnit()).isEqualTo("d");
assertThat(workUnit.getValue()).isEqualTo(0.0);
}
@Test
- public void test_equals() throws Exception {
- assertThat(WorkUnit.create(2.0, "mn")).isEqualTo(WorkUnit.create(2.0, "mn"));
- assertThat(WorkUnit.create(3.0, "mn")).isNotEqualTo(WorkUnit.create(2.0, "mn"));
- assertThat(WorkUnit.create(2.0, "h")).isNotEqualTo(WorkUnit.create(2.0, "mn"));
- }
-
- @Test
public void fail_with_bad_unit() throws Exception {
try {
WorkUnit.create(2.0, "z");
@@ -65,4 +57,49 @@ public class WorkUnitTest {
}
}
+ @Test
+ public void from_long_on_simple_values() {
+ checkTimes(WorkUnit.fromLong(1L), 0, 0, 1);
+ checkTimes(WorkUnit.fromLong(100L), 0, 1, 0);
+ checkTimes(WorkUnit.fromLong(10000L), 1, 0, 0);
+ }
+
+ @Test
+ public void from_long_on_complex_values() {
+ checkTimes(WorkUnit.fromLong(10101L), 1, 1, 1);
+ checkTimes(WorkUnit.fromLong(101L), 0, 1, 1);
+ checkTimes(WorkUnit.fromLong(10001L), 1, 0, 1);
+ checkTimes(WorkUnit.fromLong(10100L), 1, 1, 0);
+
+ checkTimes(WorkUnit.fromLong(112233L), 11, 22, 33);
+ }
+
+ @Test
+ public void to_long() {
+ assertThat(new WorkUnit.Builder().setDays(1).setHours(1).setMinutes(1).build().toLong()).isEqualTo(10101L);
+ }
+
+ @Test
+ public void test_equals_and_hashCode() throws Exception {
+ WorkUnit oneMinute = WorkUnit.fromLong(1L);
+ WorkUnit oneHours = WorkUnit.fromLong(100L);
+ WorkUnit oneDay = WorkUnit.fromLong(10000L);
+
+ assertThat(oneMinute).isEqualTo(oneMinute);
+ assertThat(oneMinute).isEqualTo(WorkUnit.fromLong(1L));
+ assertThat(oneHours).isEqualTo(WorkUnit.fromLong(100L));
+ assertThat(oneDay).isEqualTo(WorkUnit.fromLong(10000L));
+
+ assertThat(oneMinute).isNotEqualTo(oneHours);
+ assertThat(oneHours).isNotEqualTo(oneDay);
+
+ assertThat(oneMinute.hashCode()).isEqualTo(oneMinute.hashCode());
+ }
+
+ private void checkTimes(WorkUnit 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/IssueChangelogFormatter.java b/sonar-server/src/main/java/org/sonar/server/issue/IssueChangelogFormatter.java
index 56d38affc15..d92ea0f1cee 100644
--- a/sonar-server/src/main/java/org/sonar/server/issue/IssueChangelogFormatter.java
+++ b/sonar-server/src/main/java/org/sonar/server/issue/IssueChangelogFormatter.java
@@ -21,7 +21,7 @@ package org.sonar.server.issue;
import org.sonar.api.ServerComponent;
import org.sonar.api.issue.internal.FieldDiffs;
-import org.sonar.api.issue.internal.WorkDayDuration;
+import org.sonar.api.utils.WorkUnit;
import org.sonar.core.i18n.DefaultI18n;
import org.sonar.core.issue.IssueUpdater;
import org.sonar.server.technicaldebt.DebtFormatter;
@@ -74,10 +74,10 @@ public class IssueChangelogFormatter implements ServerComponent {
String oldValueString = oldValue != null && !"".equals(oldValue) ? oldValue.toString() : null;
if (IssueUpdater.TECHNICAL_DEBT.equals(key)) {
if (newValueString != null) {
- newValueString = debtFormatter.format(locale, WorkDayDuration.fromLong(Long.parseLong(newValueString)));
+ newValueString = debtFormatter.format(locale, WorkUnit.fromLong(Long.parseLong(newValueString)));
}
if (oldValueString != null) {
- oldValueString = debtFormatter.format(locale, WorkDayDuration.fromLong(Long.parseLong(oldValueString)));
+ oldValueString = debtFormatter.format(locale, WorkUnit.fromLong(Long.parseLong(oldValueString)));
}
}
return new IssueChangelogDiffFormat(oldValueString, newValueString);
diff --git a/sonar-server/src/main/java/org/sonar/server/issue/ws/IssueShowWsHandler.java b/sonar-server/src/main/java/org/sonar/server/issue/ws/IssueShowWsHandler.java
index 856a4a38c51..096ca6e2255 100644
--- a/sonar-server/src/main/java/org/sonar/server/issue/ws/IssueShowWsHandler.java
+++ b/sonar-server/src/main/java/org/sonar/server/issue/ws/IssueShowWsHandler.java
@@ -25,13 +25,13 @@ import org.sonar.api.issue.*;
import org.sonar.api.issue.action.Action;
import org.sonar.api.issue.internal.DefaultIssue;
import org.sonar.api.issue.internal.FieldDiffs;
-import org.sonar.api.issue.internal.WorkDayDuration;
import org.sonar.api.server.ws.Request;
import org.sonar.api.server.ws.RequestHandler;
import org.sonar.api.server.ws.Response;
import org.sonar.api.technicaldebt.server.Characteristic;
import org.sonar.api.user.User;
import org.sonar.api.utils.DateUtils;
+import org.sonar.api.utils.WorkUnit;
import org.sonar.api.utils.text.JsonWriter;
import org.sonar.api.web.UserRole;
import org.sonar.core.issue.workflow.Transition;
@@ -47,6 +47,7 @@ import org.sonar.server.user.UserSession;
import javax.annotation.CheckForNull;
import javax.annotation.Nullable;
+
import java.util.Arrays;
import java.util.Date;
import java.util.List;
@@ -100,7 +101,7 @@ public class IssueShowWsHandler implements RequestHandler {
Component project = result.project(issue);
String actionPlanKey = issue.actionPlanKey();
ActionPlan actionPlan = result.actionPlan(issue);
- WorkDayDuration technicalDebt = issue.technicalDebt();
+ WorkUnit technicalDebt = issue.technicalDebt();
Date updateDate = issue.updateDate();
Date closeDate = issue.closeDate();
@@ -114,7 +115,7 @@ public class IssueShowWsHandler implements RequestHandler {
.prop("rule", issue.ruleKey().toString())
.prop("ruleName", result.rule(issue).getName())
.prop("line", issue.line())
- .prop("message",issue.message())
+ .prop("message", issue.message())
.prop("resolution", issue.resolution())
.prop("status", issue.status())
.prop("severity", issue.severity())
@@ -147,7 +148,7 @@ public class IssueShowWsHandler implements RequestHandler {
}
@CheckForNull
- private Characteristic findCharacteristicById(@Nullable Integer id){
+ private Characteristic findCharacteristicById(@Nullable Integer id) {
if (id != null) {
return technicalDebtManager.findCharacteristicById(id);
}
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 513be22291e..85bc93c8f53 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,10 @@ import org.sonar.core.profiling.Profiling;
import org.sonar.core.purge.PurgeProfiler;
import org.sonar.core.resource.DefaultResourcePermissions;
import org.sonar.core.rule.DefaultRuleFinder;
-import org.sonar.core.technicaldebt.*;
+import org.sonar.core.technicaldebt.DefaultTechnicalDebtManager;
+import org.sonar.core.technicaldebt.TechnicalDebtModelRepository;
+import org.sonar.core.technicaldebt.TechnicalDebtModelSynchronizer;
+import org.sonar.core.technicaldebt.TechnicalDebtXMLImporter;
import org.sonar.core.test.TestPlanPerspectiveLoader;
import org.sonar.core.test.TestablePerspectiveLoader;
import org.sonar.core.timemachine.Periods;
@@ -365,7 +368,6 @@ public final class Platform {
servicesContainer.addSingleton(TechnicalDebtModelSynchronizer.class);
servicesContainer.addSingleton(TechnicalDebtModelRepository.class);
servicesContainer.addSingleton(TechnicalDebtXMLImporter.class);
- servicesContainer.addSingleton(TechnicalDebtConverter.class);
servicesContainer.addSingleton(DebtFormatter.class);
servicesContainer.addSingleton(DefaultTechnicalDebtManager.class);
diff --git a/sonar-server/src/main/java/org/sonar/server/technicaldebt/DebtFormatter.java b/sonar-server/src/main/java/org/sonar/server/technicaldebt/DebtFormatter.java
index 5a44a0f432e..faa2f8b7175 100644
--- a/sonar-server/src/main/java/org/sonar/server/technicaldebt/DebtFormatter.java
+++ b/sonar-server/src/main/java/org/sonar/server/technicaldebt/DebtFormatter.java
@@ -21,7 +21,7 @@
package org.sonar.server.technicaldebt;
import org.sonar.api.ServerComponent;
-import org.sonar.api.issue.internal.WorkDayDuration;
+import org.sonar.api.utils.WorkUnit;
import org.sonar.core.i18n.DefaultI18n;
import java.util.Locale;
@@ -34,7 +34,7 @@ public class DebtFormatter implements ServerComponent {
this.defaultI18n = defaultI18n;
}
- public String format(Locale locale, WorkDayDuration technicalDebt) {
+ public String format(Locale locale, WorkUnit technicalDebt) {
StringBuilder message = new StringBuilder();
if (technicalDebt.days() > 0) {
message.append(defaultI18n.message(locale, "issue.technical_debt.x_days", null, technicalDebt.days()));
diff --git a/sonar-server/src/main/java/org/sonar/server/technicaldebt/DebtService.java b/sonar-server/src/main/java/org/sonar/server/technicaldebt/DebtService.java
index fe89ec33b3b..cb079c12dae 100644
--- a/sonar-server/src/main/java/org/sonar/server/technicaldebt/DebtService.java
+++ b/sonar-server/src/main/java/org/sonar/server/technicaldebt/DebtService.java
@@ -21,8 +21,8 @@
package org.sonar.server.technicaldebt;
import org.sonar.api.ServerComponent;
-import org.sonar.api.issue.internal.WorkDayDuration;
import org.sonar.api.technicaldebt.server.Characteristic;
+import org.sonar.api.utils.WorkUnit;
import org.sonar.core.technicaldebt.DefaultTechnicalDebtManager;
import org.sonar.server.user.UserSession;
@@ -40,12 +40,12 @@ public class DebtService implements ServerComponent {
this.finder = finder;
}
- public String format(WorkDayDuration technicalDebt) {
+ public String format(WorkUnit technicalDebt) {
return debtFormatter.format(UserSession.get().locale(), technicalDebt);
}
- public WorkDayDuration toTechnicalDebt(String technicalDebtInLong) {
- return WorkDayDuration.fromLong(Long.parseLong(technicalDebtInLong));
+ public WorkUnit toTechnicalDebt(String technicalDebtInLong) {
+ return WorkUnit.fromLong(Long.parseLong(technicalDebtInLong));
}
public List<Characteristic> findRootCharacteristics() {
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 9b43022c7d1..754a06a61b5 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
@@ -28,10 +28,10 @@ import org.sonar.api.issue.Issue;
import org.sonar.api.issue.IssueQuery;
import org.sonar.api.issue.IssueQueryResult;
import org.sonar.api.issue.internal.DefaultIssue;
-import org.sonar.api.issue.internal.WorkDayDuration;
import org.sonar.api.rules.Rule;
import org.sonar.api.user.User;
import org.sonar.api.user.UserFinder;
+import org.sonar.api.utils.WorkUnit;
import org.sonar.core.component.ComponentDto;
import org.sonar.core.issue.DefaultActionPlan;
import org.sonar.core.issue.db.IssueChangeDao;
@@ -270,7 +270,7 @@ public class DefaultIssueFinderTest {
when(userFinder.findByLogins(anyListOf(String.class))).thenReturn(Lists.<User>newArrayList(
new DefaultUser().setLogin("perceval").setName("Perceval"),
new DefaultUser().setLogin("arthur").setName("Roi Arthur")
- ));
+ ));
IssueQuery query = IssueQuery.builder().build();
@@ -322,7 +322,7 @@ public class DefaultIssueFinderTest {
assertThat(results.issues()).hasSize(1);
DefaultIssue result = (DefaultIssue) results.issues().iterator().next();
- assertThat(result.technicalDebt()).isEqualTo(WorkDayDuration.of(10, 0, 0));
+ assertThat(result.technicalDebt()).isEqualTo(new WorkUnit.Builder().setMinutes(10).build());
}
}
diff --git a/sonar-server/src/test/java/org/sonar/server/issue/IssueChangelogFormatterTest.java b/sonar-server/src/test/java/org/sonar/server/issue/IssueChangelogFormatterTest.java
index ff90a7cc425..bb84b7a2b8f 100644
--- a/sonar-server/src/test/java/org/sonar/server/issue/IssueChangelogFormatterTest.java
+++ b/sonar-server/src/test/java/org/sonar/server/issue/IssueChangelogFormatterTest.java
@@ -25,7 +25,7 @@ import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import org.sonar.api.issue.internal.FieldDiffs;
-import org.sonar.api.issue.internal.WorkDayDuration;
+import org.sonar.api.utils.WorkUnit;
import org.sonar.core.i18n.DefaultI18n;
import org.sonar.server.technicaldebt.DebtFormatter;
@@ -130,8 +130,8 @@ public class IssueChangelogFormatterTest {
FieldDiffs diffs = new FieldDiffs();
diffs.setDiff("technicalDebt", "500", "10000");
- when(debtFormatter.format(DEFAULT_LOCALE, WorkDayDuration.of(0, 5, 0))).thenReturn("5 hours");
- when(debtFormatter.format(DEFAULT_LOCALE, WorkDayDuration.of(0, 0, 1))).thenReturn("1 days");
+ when(debtFormatter.format(DEFAULT_LOCALE, new WorkUnit.Builder().setHours(5).build())).thenReturn("5 hours");
+ when(debtFormatter.format(DEFAULT_LOCALE, new WorkUnit.Builder().setDays(1).build())).thenReturn("1 days");
when(i18n.message(DEFAULT_LOCALE, "issue.changelog.field.technicalDebt", null)).thenReturn("Technical Debt");
when(i18n.message(DEFAULT_LOCALE, "issue.changelog.changed_to", null, "Technical Debt", "1 days")).thenReturn("Technical Debt changed to 1 days");
@@ -148,7 +148,7 @@ public class IssueChangelogFormatterTest {
FieldDiffs diffs = new FieldDiffs();
diffs.setDiff("technicalDebt", null, "10000");
- when(debtFormatter.format(DEFAULT_LOCALE, WorkDayDuration.of(0, 0, 1))).thenReturn("1 days");
+ when(debtFormatter.format(DEFAULT_LOCALE, new WorkUnit.Builder().setDays(1).build())).thenReturn("1 days");
when(i18n.message(DEFAULT_LOCALE, "issue.changelog.field.technicalDebt", null)).thenReturn("Technical Debt");
when(i18n.message(DEFAULT_LOCALE, "issue.changelog.changed_to", null, "Technical Debt", "1 days")).thenReturn("Technical Debt changed to 1 days");
diff --git a/sonar-server/src/test/java/org/sonar/server/issue/ws/IssueShowWsHandlerTest.java b/sonar-server/src/test/java/org/sonar/server/issue/ws/IssueShowWsHandlerTest.java
index aa2ec681d0b..73bdd1ba656 100644
--- a/sonar-server/src/test/java/org/sonar/server/issue/ws/IssueShowWsHandlerTest.java
+++ b/sonar-server/src/test/java/org/sonar/server/issue/ws/IssueShowWsHandlerTest.java
@@ -35,7 +35,6 @@ import org.sonar.api.issue.action.Action;
import org.sonar.api.issue.internal.DefaultIssue;
import org.sonar.api.issue.internal.DefaultIssueComment;
import org.sonar.api.issue.internal.FieldDiffs;
-import org.sonar.api.issue.internal.WorkDayDuration;
import org.sonar.api.rule.RuleKey;
import org.sonar.api.rules.Rule;
import org.sonar.api.server.ws.WsTester;
@@ -43,6 +42,7 @@ import org.sonar.api.technicaldebt.server.Characteristic;
import org.sonar.api.technicaldebt.server.internal.DefaultCharacteristic;
import org.sonar.api.user.User;
import org.sonar.api.utils.DateUtils;
+import org.sonar.api.utils.WorkUnit;
import org.sonar.api.web.UserRole;
import org.sonar.core.issue.DefaultActionPlan;
import org.sonar.core.issue.DefaultIssueQueryResult;
@@ -209,9 +209,8 @@ public class IssueShowWsHandlerTest {
@Test
public void show_issue_with_technical_debt() throws Exception {
- WorkDayDuration technicalDebt = WorkDayDuration.of(1, 2, 0);
- Issue issue = createStandardIssue()
- .setTechnicalDebt(technicalDebt);
+ WorkUnit technicalDebt = new WorkUnit.Builder().setHours(2).setMinutes(1).build();
+ Issue issue = createStandardIssue().setTechnicalDebt(technicalDebt);
issues.add(issue);
when(debtFormatter.format(any(Locale.class), eq(technicalDebt))).thenReturn("2 hours 1 minutes");
@@ -223,9 +222,9 @@ public class IssueShowWsHandlerTest {
@Test
public void show_issue_with_characteristics() throws Exception {
- WorkDayDuration technicalDebt = WorkDayDuration.of(1, 2, 0);
- Issue issue = createStandardIssue()
- .setTechnicalDebt(technicalDebt);
+ WorkUnit technicalDebt = new WorkUnit.Builder().setHours(2).setMinutes(1).build();
+ ;
+ Issue issue = createStandardIssue().setTechnicalDebt(technicalDebt);
issues.add(issue);
Characteristic requirement = new DefaultCharacteristic().setId(5).setParentId(2).setRootId(1);
diff --git a/sonar-server/src/test/java/org/sonar/server/technicaldebt/DebtFormatterTest.java b/sonar-server/src/test/java/org/sonar/server/technicaldebt/DebtFormatterTest.java
index f7249fb21b5..c9f12afd90e 100644
--- a/sonar-server/src/test/java/org/sonar/server/technicaldebt/DebtFormatterTest.java
+++ b/sonar-server/src/test/java/org/sonar/server/technicaldebt/DebtFormatterTest.java
@@ -21,7 +21,7 @@
package org.sonar.server.technicaldebt;
import org.junit.Test;
-import org.sonar.api.issue.internal.WorkDayDuration;
+import org.sonar.api.utils.WorkUnit;
import org.sonar.core.i18n.DefaultI18n;
import java.util.Locale;
@@ -43,14 +43,13 @@ public class DebtFormatterTest {
when(i18n.message(DEFAULT_LOCALE, "issue.technical_debt.x_hours", null, 2)).thenReturn("2 hours");
when(i18n.message(DEFAULT_LOCALE, "issue.technical_debt.x_minutes", null, 1)).thenReturn("1 minutes");
- assertThat(formatter.format(DEFAULT_LOCALE, WorkDayDuration.of(0, 0, 5))).isEqualTo("5 days");
- assertThat(formatter.format(DEFAULT_LOCALE, WorkDayDuration.of(0, 2, 0))).isEqualTo("2 hours");
- assertThat(formatter.format(DEFAULT_LOCALE, WorkDayDuration.of(1, 0, 0))).isEqualTo("1 minutes");
+ assertThat(formatter.format(DEFAULT_LOCALE, new WorkUnit.Builder().setDays(5).build())).isEqualTo("5 days");
+ assertThat(formatter.format(DEFAULT_LOCALE, new WorkUnit.Builder().setHours(2).build())).isEqualTo("2 hours");
+ assertThat(formatter.format(DEFAULT_LOCALE, new WorkUnit.Builder().setMinutes(1).build())).isEqualTo("1 minutes");
- assertThat(formatter.format(DEFAULT_LOCALE, WorkDayDuration.of(0, 2, 5))).isEqualTo("5 days 2 hours");
- assertThat(formatter.format(DEFAULT_LOCALE, WorkDayDuration.of(1, 2, 0))).isEqualTo("2 hours 1 minutes");
- assertThat(formatter.format(DEFAULT_LOCALE, WorkDayDuration.of(1, 2, 5))).isEqualTo("5 days 2 hours");
+ assertThat(formatter.format(DEFAULT_LOCALE, new WorkUnit.Builder().setDays(5).setHours(2).build())).isEqualTo("5 days 2 hours");
+ assertThat(formatter.format(DEFAULT_LOCALE, new WorkUnit.Builder().setHours(2).setMinutes(1).build())).isEqualTo("2 hours 1 minutes");
+ assertThat(formatter.format(DEFAULT_LOCALE, new WorkUnit.Builder().setDays(5).setHours(2).setMinutes(10).build())).isEqualTo("5 days 2 hours");
}
-
}
diff --git a/sonar-server/src/test/java/org/sonar/server/technicaldebt/DebtServiceTest.java b/sonar-server/src/test/java/org/sonar/server/technicaldebt/DebtServiceTest.java
index 586444b6f5e..75684adf2db 100644
--- a/sonar-server/src/test/java/org/sonar/server/technicaldebt/DebtServiceTest.java
+++ b/sonar-server/src/test/java/org/sonar/server/technicaldebt/DebtServiceTest.java
@@ -20,9 +20,9 @@
package org.sonar.server.technicaldebt;
import org.junit.Test;
-import org.sonar.api.issue.internal.WorkDayDuration;
import org.sonar.api.technicaldebt.server.Characteristic;
import org.sonar.api.technicaldebt.server.internal.DefaultCharacteristic;
+import org.sonar.api.utils.WorkUnit;
import org.sonar.core.technicaldebt.DefaultTechnicalDebtManager;
import java.util.List;
@@ -42,14 +42,14 @@ public class DebtServiceTest {
@Test
public void format() {
- WorkDayDuration technicalDebt = WorkDayDuration.of(5, 0, 0);
+ WorkUnit technicalDebt = new WorkUnit.Builder().setMinutes(5).build();
service.format(technicalDebt);
verify(debtFormatter).format(any(Locale.class), eq(technicalDebt));
}
@Test
public void to_technical_debt() {
- assertThat(service.toTechnicalDebt("500")).isEqualTo(WorkDayDuration.of(0, 5, 0));
+ assertThat(service.toTechnicalDebt("500")).isEqualTo(new WorkUnit.Builder().setHours(5).build());
}
@Test